blob: e0ee69b1321325b0e569581ac8dc4a1f939f0f0a [file] [log] [blame]
// OpenSTA, Static Timing Analyzer
// Copyright (c) 2022, 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 "ConcreteNetwork.hh"
#include "DisallowCopyAssign.hh"
#include "PatternMatch.hh"
#include "Report.hh"
#include "Liberty.hh"
#include "PortDirection.hh"
#include "ConcreteLibrary.hh"
#include "Network.hh"
namespace sta {
static void
makeChildNetwork(Instance *proto,
Instance *parent,
ConcreteBindingTbl *parent_bindings,
NetworkReader *network);
static void
makeClonePins(Instance *proto,
Instance *clone,
Instance *clone_view,
ConcreteBindingTbl *bindings,
Instance *parent,
ConcreteBindingTbl *parent_bindings,
NetworkReader *network);
NetworkReader *
makeConcreteNetwork()
{
return new ConcreteNetwork;
}
class ConcreteInstanceChildIterator : public InstanceChildIterator
{
public:
explicit ConcreteInstanceChildIterator(ConcreteInstanceChildMap *map);
bool hasNext();
Instance *next();
private:
ConcreteInstanceChildMap::ConstIterator iter_;
};
ConcreteInstanceChildIterator::
ConcreteInstanceChildIterator(ConcreteInstanceChildMap *map) :
iter_(map)
{
}
bool
ConcreteInstanceChildIterator::hasNext()
{
return iter_.hasNext();
}
Instance *
ConcreteInstanceChildIterator::next()
{
return reinterpret_cast<Instance*>(iter_.next());
}
class ConcreteInstanceNetIterator : public InstanceNetIterator
{
public:
explicit ConcreteInstanceNetIterator(ConcreteInstanceNetMap *nets);
bool hasNext();
Net *next();
private:
DISALLOW_COPY_AND_ASSIGN(ConcreteInstanceNetIterator);
void findNext();
ConcreteInstanceNetMap::Iterator iter_;
ConcreteNet *next_;
};
ConcreteInstanceNetIterator::
ConcreteInstanceNetIterator(ConcreteInstanceNetMap *nets):
iter_(nets),
next_(nullptr)
{
findNext();
}
bool
ConcreteInstanceNetIterator::hasNext()
{
return next_ != nullptr;
}
// Skip nets that have been merged.
void
ConcreteInstanceNetIterator::findNext()
{
while (iter_.hasNext()) {
next_ = iter_.next();
if (next_->mergedInto() == nullptr)
return;
}
next_ = nullptr;
}
Net *
ConcreteInstanceNetIterator::next()
{
ConcreteNet *next = next_;
findNext();
return reinterpret_cast<Net*>(next);
}
////////////////////////////////////////////////////////////////
class ConcreteInstancePinIterator : public InstancePinIterator
{
public:
ConcreteInstancePinIterator(const ConcreteInstance *inst,
int pin_count);
bool hasNext();
Pin *next();
private:
DISALLOW_COPY_AND_ASSIGN(ConcreteInstancePinIterator);
void findNext();
ConcretePin **pins_;
int pin_count_;
int pin_index_;
ConcretePin *next_;
};
ConcreteInstancePinIterator::
ConcreteInstancePinIterator(const ConcreteInstance *inst,
int pin_count) :
pins_(inst->pins_),
pin_count_(pin_count),
pin_index_(0)
{
findNext();
}
bool
ConcreteInstancePinIterator::hasNext()
{
return next_ != nullptr;
}
Pin *
ConcreteInstancePinIterator::next()
{
ConcretePin *next = next_;
findNext();
return reinterpret_cast<Pin*>(next);
}
// Skip over missing pins.
void
ConcreteInstancePinIterator::findNext()
{
while (pin_index_ < pin_count_) {
next_ = pins_[pin_index_++];
if (next_)
return;
}
next_ = nullptr;
}
////////////////////////////////////////////////////////////////
class ConcreteNetPinIterator : public NetPinIterator
{
public:
explicit ConcreteNetPinIterator(const ConcreteNet *net);
bool hasNext();
Pin *next();
private:
DISALLOW_COPY_AND_ASSIGN(ConcreteNetPinIterator);
ConcretePin *next_;
};
ConcreteNetPinIterator::ConcreteNetPinIterator(const ConcreteNet *net) :
next_(net->pins_)
{
}
bool
ConcreteNetPinIterator::hasNext()
{
return next_ != nullptr;
}
Pin *
ConcreteNetPinIterator::next()
{
ConcretePin *next = next_;
next_ = next_->net_next_;
return reinterpret_cast<Pin*>(next);
}
////////////////////////////////////////////////////////////////
class ConcreteNetTermIterator : public NetTermIterator
{
public:
explicit ConcreteNetTermIterator(const ConcreteNet *net);
bool hasNext();
Term *next();
private:
DISALLOW_COPY_AND_ASSIGN(ConcreteNetTermIterator);
ConcreteTerm *next_;
};
ConcreteNetTermIterator::ConcreteNetTermIterator(const ConcreteNet *net) :
next_(net->terms_)
{
}
bool
ConcreteNetTermIterator::hasNext()
{
return next_ != nullptr;
}
Term *
ConcreteNetTermIterator::next()
{
ConcreteTerm *next = next_;
next_ = next_->net_next_;
return reinterpret_cast<Term*>(next);
}
////////////////////////////////////////////////////////////////
ConcreteNetwork::ConcreteNetwork() :
NetworkReader(),
top_instance_(nullptr),
link_func_(nullptr)
{
}
ConcreteNetwork::~ConcreteNetwork()
{
clear();
}
void
ConcreteNetwork::clear()
{
deleteTopInstance();
deleteCellNetworkViews();
library_seq_.deleteContentsClear();
library_map_.clear();
Network::clear();
}
void
ConcreteNetwork::deleteTopInstance()
{
if (top_instance_) {
deleteInstance(top_instance_);
top_instance_ = nullptr;
}
}
void
ConcreteNetwork::deleteCellNetworkViews()
{
CellNetworkViewMap::Iterator view_iter(cell_network_view_map_);
while (view_iter.hasNext()) {
Instance *view = view_iter.next();
if (view)
deleteInstance(view);
}
cell_network_view_map_.clear();
}
Instance *
ConcreteNetwork::topInstance() const
{
return top_instance_;
}
////////////////////////////////////////////////////////////////
class ConcreteLibraryIterator1 : public Iterator<Library*>
{
public:
explicit ConcreteLibraryIterator1(const ConcreteLibrarySeq &lib_seq_);
virtual bool hasNext();
virtual Library *next();
private:
DISALLOW_COPY_AND_ASSIGN(ConcreteLibraryIterator1);
ConcreteLibraryIterator iter_;
};
ConcreteLibraryIterator1::ConcreteLibraryIterator1(const ConcreteLibrarySeq &lib_seq_):
iter_(lib_seq_)
{
}
bool
ConcreteLibraryIterator1::hasNext()
{
return iter_.hasNext();
}
Library *
ConcreteLibraryIterator1::next()
{
return reinterpret_cast<Library*>(iter_.next());
}
LibraryIterator *
ConcreteNetwork::libraryIterator() const
{
return new ConcreteLibraryIterator1(library_seq_);
}
////////////////////////////////////////////////////////////////
class ConcreteLibertyLibraryIterator : public Iterator<LibertyLibrary*>
{
public:
explicit ConcreteLibertyLibraryIterator(const ConcreteNetwork *network);
virtual ~ConcreteLibertyLibraryIterator();
virtual bool hasNext();
virtual LibertyLibrary *next();
private:
DISALLOW_COPY_AND_ASSIGN(ConcreteLibertyLibraryIterator);
void findNext();
ConcreteLibrarySeq::ConstIterator iter_;
LibertyLibrary *next_;
};
ConcreteLibertyLibraryIterator::
ConcreteLibertyLibraryIterator(const ConcreteNetwork *network):
iter_(network->library_seq_),
next_(nullptr)
{
findNext();
}
ConcreteLibertyLibraryIterator::~ConcreteLibertyLibraryIterator()
{
}
bool
ConcreteLibertyLibraryIterator::hasNext()
{
return next_ != nullptr;
}
LibertyLibrary *
ConcreteLibertyLibraryIterator::next()
{
LibertyLibrary *next = next_;
findNext();
return next;
}
void
ConcreteLibertyLibraryIterator::findNext()
{
next_ = nullptr;
while (iter_.hasNext()) {
ConcreteLibrary *lib = iter_.next();
if (lib->isLiberty()) {
LibertyLibrary *liberty = static_cast<LibertyLibrary*>(lib);
if (liberty) {
next_ = liberty;
break;
}
}
}
}
LibertyLibraryIterator *
ConcreteNetwork::libertyLibraryIterator() const
{
return new ConcreteLibertyLibraryIterator(this);
}
////////////////////////////////////////////////////////////////
Library *
ConcreteNetwork::makeLibrary(const char *name,
const char *filename)
{
ConcreteLibrary *library = new ConcreteLibrary(name, filename, false);
addLibrary(library);
return reinterpret_cast<Library*>(library);
}
LibertyLibrary *
ConcreteNetwork::makeLibertyLibrary(const char *name,
const char *filename)
{
LibertyLibrary *library = new LibertyLibrary(name, filename);
addLibrary(library);
return library;
}
void
ConcreteNetwork::addLibrary(ConcreteLibrary *library)
{
library_seq_.push_back(library);
library_map_[library->name()] = library;
}
Library *
ConcreteNetwork::findLibrary(const char *name)
{
return reinterpret_cast<Library*>(library_map_.findKey(name));
}
void
ConcreteNetwork::deleteLibrary(Library *library)
{
ConcreteLibrary *clib = reinterpret_cast<ConcreteLibrary*>(library);
library_map_.erase(clib->name());
library_seq_.eraseObject(clib);
delete clib;
}
const char *
ConcreteNetwork::name(const Library *library) const
{
const ConcreteLibrary *clib =
reinterpret_cast<const ConcreteLibrary*>(library);
return clib->name();
}
LibertyLibrary *
ConcreteNetwork::findLiberty(const char *name)
{
ConcreteLibrary *lib = library_map_.findKey(name);
if (lib) {
if (lib->isLiberty())
return static_cast<LibertyLibrary*>(lib);
// Potential name conflict
else {
for (ConcreteLibrary *lib : library_seq_) {
if (stringEq(lib->name(), name)
&& lib->isLiberty())
return static_cast<LibertyLibrary*>(lib);
}
}
}
return nullptr;
}
LibertyLibrary *
ConcreteNetwork::libertyLibrary(Library *library) const
{
ConcreteLibrary *lib = reinterpret_cast<ConcreteLibrary*>(library);
return static_cast<LibertyLibrary*>(lib);
}
Cell *
ConcreteNetwork::makeCell(Library *library,
const char *name,
bool is_leaf,
const char *filename)
{
ConcreteLibrary *clib = reinterpret_cast<ConcreteLibrary*>(library);
return reinterpret_cast<Cell*>(clib->makeCell(name, is_leaf, filename));
}
Cell *
ConcreteNetwork::findCell(const Library *library,
const char *name) const
{
const ConcreteLibrary *clib =
reinterpret_cast<const ConcreteLibrary*>(library);
return reinterpret_cast<Cell*>(clib->findCell(name));
}
Cell *
ConcreteNetwork::findAnyCell(const char *name)
{
ConcreteLibrarySeq::Iterator lib_iter(library_seq_);
while (lib_iter.hasNext()) {
ConcreteLibrary *lib = lib_iter.next();
ConcreteCell *cell = lib->findCell(name);
if (cell)
return reinterpret_cast<Cell*>(cell);
}
return nullptr;
}
void
ConcreteNetwork::findCellsMatching(const Library *library,
const PatternMatch *pattern,
CellSeq *cells) const
{
const ConcreteLibrary *clib =
reinterpret_cast<const ConcreteLibrary*>(library);
clib->findCellsMatching(pattern, cells);
}
void
ConcreteNetwork::deleteCell(Cell *cell)
{
ConcreteCell *ccell = reinterpret_cast<ConcreteCell*>(cell);
ConcreteLibrary *clib = ccell->library();
clib->deleteCell(ccell);
}
////////////////////////////////////////////////////////////////
const char *
ConcreteNetwork::name(const Cell *cell) const
{
const ConcreteCell *ccell = reinterpret_cast<const ConcreteCell*>(cell);
return ccell->name();
}
void
ConcreteNetwork::setName(Cell *cell,
const char *name)
{
ConcreteCell *ccell = reinterpret_cast<ConcreteCell*>(cell);
ccell->setName(name);
}
void
ConcreteNetwork::setIsLeaf(Cell *cell,
bool is_leaf)
{
ConcreteCell *ccell = reinterpret_cast<ConcreteCell*>(cell);
ccell->setIsLeaf(is_leaf);
}
Library *
ConcreteNetwork::library(const Cell *cell) const
{
const ConcreteCell *ccell = reinterpret_cast<const ConcreteCell*>(cell);
return reinterpret_cast<Library*>(ccell->library());
}
LibertyCell *
ConcreteNetwork::libertyCell(Cell *cell) const
{
ConcreteCell *ccell = reinterpret_cast<ConcreteCell*>(cell);
return ccell->libertyCell();
}
const LibertyCell *
ConcreteNetwork::libertyCell(const Cell *cell) const
{
const ConcreteCell *ccell = reinterpret_cast<const ConcreteCell*>(cell);
return ccell->libertyCell();
}
Cell *
ConcreteNetwork::cell(LibertyCell *cell) const
{
return reinterpret_cast<Cell*>(cell);
}
const Cell *
ConcreteNetwork::cell(const LibertyCell *cell) const
{
return reinterpret_cast<const Cell*>(cell);
}
const char *
ConcreteNetwork::filename(const Cell *cell)
{
const ConcreteCell *ccell = reinterpret_cast<const ConcreteCell*>(cell);
return ccell->filename();
}
Port *
ConcreteNetwork::findPort(const Cell *cell,
const char *name) const
{
const ConcreteCell *ccell = reinterpret_cast<const ConcreteCell*>(cell);
return reinterpret_cast<Port*>(ccell->findPort(name));
}
void
ConcreteNetwork::findPortsMatching(const Cell *cell,
const PatternMatch *pattern,
PortSeq *ports) const
{
const ConcreteCell *ccell = reinterpret_cast<const ConcreteCell*>(cell);
ccell->findPortsMatching(pattern, ports);
}
bool
ConcreteNetwork::isLeaf(const Cell *cell) const
{
const ConcreteCell *ccell = reinterpret_cast<const ConcreteCell*>(cell);
return ccell->isLeaf();
}
Port *
ConcreteNetwork::makePort(Cell *cell,
const char *name)
{
ConcreteCell *ccell = reinterpret_cast<ConcreteCell*>(cell);
ConcretePort *port = ccell->makePort(name);
return reinterpret_cast<Port*>(port);
}
Port *
ConcreteNetwork::makeBusPort(Cell *cell,
const char *name,
int from_index,
int to_index)
{
ConcreteCell *ccell = reinterpret_cast<ConcreteCell*>(cell);
ConcretePort *port = ccell->makeBusPort(name, from_index, to_index);
return reinterpret_cast<Port*>(port);
}
void
ConcreteNetwork::groupBusPorts(Cell *cell,
std::function<bool(const char*)> port_msb_first)
{
Library *lib = library(cell);
ConcreteLibrary *clib = reinterpret_cast<ConcreteLibrary*>(lib);
ConcreteCell *ccell = reinterpret_cast<ConcreteCell*>(cell);
ccell->groupBusPorts(clib->busBrktLeft(), clib->busBrktRight(), port_msb_first);
}
Port *
ConcreteNetwork::makeBundlePort(Cell *cell,
const char *name,
PortSeq *members)
{
ConcreteCell *ccell = reinterpret_cast<ConcreteCell*>(cell);
ConcretePortSeq *cmembers = reinterpret_cast<ConcretePortSeq*>(members);
ConcretePort *port = ccell->makeBundlePort(name, cmembers);
return reinterpret_cast<Port*>(port);
}
void
ConcreteNetwork::setDirection(Port *port,
PortDirection *dir)
{
ConcretePort *cport = reinterpret_cast<ConcretePort*>(port);
cport->setDirection(dir);
}
////////////////////////////////////////////////////////////////
class ConcreteCellPortIterator1 : public CellPortIterator
{
public:
explicit ConcreteCellPortIterator1(const ConcreteCell *cell);
~ConcreteCellPortIterator1();
virtual bool hasNext() { return iter_->hasNext(); }
virtual Port *next();
private:
DISALLOW_COPY_AND_ASSIGN(ConcreteCellPortIterator1);
ConcreteCellPortIterator *iter_;
};
ConcreteCellPortIterator1::ConcreteCellPortIterator1(const ConcreteCell *cell):
iter_(cell->portIterator())
{
}
ConcreteCellPortIterator1::~ConcreteCellPortIterator1()
{
delete iter_;
}
Port *
ConcreteCellPortIterator1::next()
{
return reinterpret_cast<Port*>(iter_->next());
}
CellPortIterator *
ConcreteNetwork::portIterator(const Cell *cell) const
{
const ConcreteCell *ccell = reinterpret_cast<const ConcreteCell*>(cell);
return new ConcreteCellPortIterator1(ccell);
}
////////////////////////////////////////////////////////////////
class ConcreteCellPortBitIterator1 : public CellPortIterator
{
public:
explicit ConcreteCellPortBitIterator1(const ConcreteCell *cell);
~ConcreteCellPortBitIterator1();
virtual bool hasNext() { return iter_->hasNext(); }
virtual Port *next();
private:
DISALLOW_COPY_AND_ASSIGN(ConcreteCellPortBitIterator1);
ConcreteCellPortBitIterator *iter_;
};
ConcreteCellPortBitIterator1::ConcreteCellPortBitIterator1(const ConcreteCell *cell):
iter_(cell->portBitIterator())
{
}
ConcreteCellPortBitIterator1::~ConcreteCellPortBitIterator1()
{
delete iter_;
}
Port *
ConcreteCellPortBitIterator1::next()
{
return reinterpret_cast<Port*>(iter_->next());
}
CellPortBitIterator *
ConcreteNetwork::portBitIterator(const Cell *cell) const
{
const ConcreteCell *ccell = reinterpret_cast<const ConcreteCell*>(cell);
return new ConcreteCellPortBitIterator1(ccell);
}
int
ConcreteNetwork::portBitCount(const Cell *cell) const
{
const ConcreteCell *ccell = reinterpret_cast<const ConcreteCell*>(cell);
return ccell->portBitCount();
}
////////////////////////////////////////////////////////////////
const char *
ConcreteNetwork::name(const Port *port) const
{
const ConcretePort *cport = reinterpret_cast<const ConcretePort*>(port);
return cport->name();
}
Cell *
ConcreteNetwork::cell(const Port *port) const
{
const ConcretePort *cport = reinterpret_cast<const ConcretePort*>(port);
return cport->cell();
}
LibertyPort *
ConcreteNetwork::libertyPort(const Port *port) const
{
const ConcretePort *cport = reinterpret_cast<const ConcretePort*>(port);
return cport->libertyPort();
}
PortDirection *
ConcreteNetwork::direction(const Port *port) const
{
const ConcretePort *cport = reinterpret_cast<const ConcretePort*>(port);
return cport->direction();
}
bool
ConcreteNetwork::isBundle(const Port *port) const
{
const ConcretePort *cport = reinterpret_cast<const ConcretePort*>(port);
return cport->isBundle();
}
bool
ConcreteNetwork::isBus(const Port *port) const
{
const ConcretePort *cport = reinterpret_cast<const ConcretePort*>(port);
return cport->isBus();
}
const char *
ConcreteNetwork::busName(const Port *port) const
{
const ConcretePort *cport = reinterpret_cast<const ConcretePort*>(port);
return cport->busName();
}
int
ConcreteNetwork::size(const Port *port) const
{
const ConcretePort *cport = reinterpret_cast<const ConcretePort*>(port);
return cport->size();
}
int
ConcreteNetwork::fromIndex(const Port *port) const
{
const ConcretePort *cport = reinterpret_cast<const ConcretePort*>(port);
return cport->fromIndex();
}
int
ConcreteNetwork::toIndex(const Port *port) const
{
const ConcretePort *cport = reinterpret_cast<const ConcretePort*>(port);
return cport->toIndex();
}
Port *
ConcreteNetwork::findBusBit(const Port *port,
int index) const
{
const ConcretePort *cport = reinterpret_cast<const ConcretePort*>(port);
return reinterpret_cast<Port*>(cport->findBusBit(index));
}
Port *
ConcreteNetwork::findMember(const Port *port,
int index) const
{
const ConcretePort *cport = reinterpret_cast<const ConcretePort*>(port);
return reinterpret_cast<Port*>(cport->findMember(index));
}
bool
ConcreteNetwork::hasMembers(const Port *port) const
{
const ConcretePort *cport = reinterpret_cast<const ConcretePort*>(port);
return cport->hasMembers();
}
////////////////////////////////////////////////////////////////
class ConcretePortMemberIterator1 : public PortMemberIterator
{
public:
explicit ConcretePortMemberIterator1(const ConcretePort *port);
~ConcretePortMemberIterator1();
virtual bool hasNext() { return iter_->hasNext(); }
virtual Port *next();
private:
DISALLOW_COPY_AND_ASSIGN(ConcretePortMemberIterator1);
ConcretePortMemberIterator *iter_;
};
ConcretePortMemberIterator1::ConcretePortMemberIterator1(const ConcretePort *
port) :
iter_(port->memberIterator())
{
}
ConcretePortMemberIterator1::~ConcretePortMemberIterator1()
{
delete iter_;
}
Port *
ConcretePortMemberIterator1::next()
{
return reinterpret_cast<Port*>(iter_->next());
}
PortMemberIterator *
ConcreteNetwork::memberIterator(const Port *port) const
{
const ConcretePort *cport = reinterpret_cast<const ConcretePort*>(port);
return new ConcretePortMemberIterator1(cport);
}
////////////////////////////////////////////////////////////////
const char *
ConcreteNetwork::name(const Instance *instance) const
{
const ConcreteInstance *inst =
reinterpret_cast<const ConcreteInstance*>(instance);
return inst->name();
}
Cell *
ConcreteNetwork::cell(const Instance *instance) const
{
const ConcreteInstance *inst =
reinterpret_cast<const ConcreteInstance*>(instance);
return inst->cell();
}
Instance *
ConcreteNetwork::parent(const Instance *instance) const
{
const ConcreteInstance *inst =
reinterpret_cast<const ConcreteInstance*>(instance);
return reinterpret_cast<Instance*>(inst->parent());
}
bool
ConcreteNetwork::isLeaf(const Instance *instance) const
{
const ConcreteInstance *inst =
reinterpret_cast<const ConcreteInstance*>(instance);
ConcreteCell *ccell = reinterpret_cast<ConcreteCell*>(inst->cell());
return ccell->isLeaf();
}
Instance *
ConcreteNetwork::findChild(const Instance *parent,
const char *name) const
{
const ConcreteInstance *inst =
reinterpret_cast<const ConcreteInstance*>(parent);
return inst->findChild(name);
}
Pin *
ConcreteNetwork::findPin(const Instance *instance,
const char *port_name) const
{
const ConcreteInstance *inst =
reinterpret_cast<const ConcreteInstance*>(instance);
return reinterpret_cast<Pin*>(inst->findPin(port_name));
}
Pin *
ConcreteNetwork::findPin(const Instance *instance,
const Port *port) const
{
const ConcreteInstance *inst =
reinterpret_cast<const ConcreteInstance*>(instance);
return reinterpret_cast<Pin*>(inst->findPin(port));
}
Net *
ConcreteNetwork::findNet(const Instance *instance,
const char *net_name) const
{
const ConcreteInstance *inst =
reinterpret_cast<const ConcreteInstance*>(instance);
return reinterpret_cast<Net*>(inst->findNet(net_name));
}
void
ConcreteNetwork::findInstNetsMatching(const Instance *instance,
const PatternMatch *pattern,
NetSeq *nets) const
{
const ConcreteInstance *inst =
reinterpret_cast<const ConcreteInstance*>(instance);
inst->findNetsMatching(pattern, nets);
}
////////////////////////////////////////////////////////////////
InstanceChildIterator *
ConcreteNetwork::childIterator(const Instance *instance) const
{
const ConcreteInstance *inst =
reinterpret_cast<const ConcreteInstance*>(instance);
return inst->childIterator();
}
InstancePinIterator *
ConcreteNetwork::pinIterator(const Instance *instance) const
{
const ConcreteInstance *inst =
reinterpret_cast<const ConcreteInstance*>(instance);
ConcreteCell *cell = reinterpret_cast<ConcreteCell*>(inst->cell());
int pin_count = cell->portBitCount();
return new ConcreteInstancePinIterator(inst, pin_count);
}
InstanceNetIterator *
ConcreteNetwork::netIterator(const Instance *instance) const
{
const ConcreteInstance *inst =
reinterpret_cast<const ConcreteInstance*>(instance);
return inst->netIterator();
}
////////////////////////////////////////////////////////////////
Instance *
ConcreteNetwork::instance(const Pin *pin) const
{
const ConcretePin *cpin = reinterpret_cast<const ConcretePin*>(pin);
return reinterpret_cast<Instance*>(cpin->instance());
}
Net *
ConcreteNetwork::net(const Pin *pin) const
{
const ConcretePin *cpin = reinterpret_cast<const ConcretePin*>(pin);
return reinterpret_cast<Net*>(cpin->net());
}
Term *
ConcreteNetwork::term(const Pin *pin) const
{
const ConcretePin *cpin = reinterpret_cast<const ConcretePin*>(pin);
return reinterpret_cast<Term*>(cpin->term());
}
Port *
ConcreteNetwork::port(const Pin *pin) const
{
const ConcretePin *cpin = reinterpret_cast<const ConcretePin*>(pin);
return reinterpret_cast<Port*>(cpin->port());
}
PortDirection *
ConcreteNetwork::direction(const Pin *pin) const
{
const ConcretePin *cpin = reinterpret_cast<const ConcretePin*>(pin);
const ConcretePort *cport = cpin->port();
return cport->direction();
}
VertexId
ConcreteNetwork::vertexId(const Pin *pin) const
{
const ConcretePin *cpin = reinterpret_cast<const ConcretePin*>(pin);
return cpin->vertexId();
}
void
ConcreteNetwork::setVertexId(Pin *pin,
VertexId id)
{
ConcretePin *cpin = reinterpret_cast<ConcretePin*>(pin);
cpin->setVertexId(id);
}
////////////////////////////////////////////////////////////////
Net *
ConcreteNetwork::net(const Term *term) const
{
const ConcreteTerm *cterm = reinterpret_cast<const ConcreteTerm*>(term);
return reinterpret_cast<Net*>(cterm->net());
}
Pin *
ConcreteNetwork::pin(const Term *term) const
{
const ConcreteTerm *cterm = reinterpret_cast<const ConcreteTerm*>(term);
return reinterpret_cast<Pin*>(cterm->pin());
}
////////////////////////////////////////////////////////////////
const char *
ConcreteNetwork::name(const Net *net) const
{
const ConcreteNet *cnet = reinterpret_cast<const ConcreteNet*>(net);
return cnet->name();
}
Instance *
ConcreteNetwork::instance(const Net *net) const
{
const ConcreteNet *cnet = reinterpret_cast<const ConcreteNet*>(net);
return reinterpret_cast<Instance*>(cnet->instance());
}
bool
ConcreteNetwork::isPower(const Net *net) const
{
return constant_nets_[int(LogicValue::one)].hasKey(const_cast<Net*>(net));
}
bool
ConcreteNetwork::isGround(const Net *net) const
{
return constant_nets_[int(LogicValue::zero)].hasKey(const_cast<Net*>(net));
}
NetPinIterator *
ConcreteNetwork::pinIterator(const Net *net) const
{
const ConcreteNet *cnet = reinterpret_cast<const ConcreteNet*>(net);
return new ConcreteNetPinIterator(cnet);
}
NetTermIterator *
ConcreteNetwork::termIterator(const Net *net) const
{
const ConcreteNet *cnet = reinterpret_cast<const ConcreteNet*>(net);
return new ConcreteNetTermIterator(cnet);
}
void
ConcreteNetwork::mergeInto(Net *net,
Net *into_net)
{
ConcreteNet *cnet = reinterpret_cast<ConcreteNet*>(net);
ConcreteNet *cinto_net = reinterpret_cast<ConcreteNet*>(into_net);
cnet->mergeInto(cinto_net);
clearNetDrvrPinMap();
}
Net *
ConcreteNetwork::mergedInto(Net *net)
{
ConcreteNet *cnet = reinterpret_cast<ConcreteNet*>(net);
return reinterpret_cast<Net*>(cnet->mergedInto());
}
////////////////////////////////////////////////////////////////
Cell *
ConcreteInstance::cell() const
{
return reinterpret_cast<Cell*>(cell_);
}
Instance *
ConcreteNetwork::makeInstance(Cell *cell,
const char *name,
Instance *parent)
{
ConcreteCell *ccell = reinterpret_cast<ConcreteCell*>(cell);
return makeConcreteInstance(ccell, name, parent);
}
Instance *
ConcreteNetwork::makeInstance(LibertyCell *cell,
const char *name,
Instance *parent)
{
return makeConcreteInstance(cell, name, parent);
}
Instance *
ConcreteNetwork::makeConcreteInstance(ConcreteCell *cell,
const char *name,
Instance *parent)
{
ConcreteInstance *cparent =
reinterpret_cast<ConcreteInstance*>(parent);
ConcreteInstance *inst = new ConcreteInstance(cell, name, cparent);
if (parent)
cparent->addChild(inst);
return reinterpret_cast<Instance*>(inst);
}
void
ConcreteNetwork::makePins(Instance *inst)
{
CellPortBitIterator *port_iterator = portBitIterator(cell(inst));
while (port_iterator->hasNext()) {
Port *port = port_iterator->next();
makePin(inst, port, nullptr);
}
delete port_iterator;
}
void
ConcreteNetwork::replaceCell(Instance *inst,
Cell *cell)
{
ConcreteCell *ccell = reinterpret_cast<ConcreteCell*>(cell);
int port_count = ccell->portBitCount();
ConcreteInstance *cinst = reinterpret_cast<ConcreteInstance*>(inst);
// Port count picked from Instance instead of Target cells-Dinesh A
ConcreteCell *instcell = reinterpret_cast<ConcreteCell*>(cinst->cell());
int inst_port_count = instcell->portBitCount();
ConcretePin **pins = cinst->pins_;
ConcretePin **rpins = new ConcretePin*[port_count];
for (int i = 0; i < port_count; i++)
rpins[i] = pins[inst_port_count-1];
for (int i = 0; i < inst_port_count; i++) {
ConcretePin *cpin = pins[i];
if (cpin) {
ConcretePort *pin_cport = reinterpret_cast<ConcretePort*>(cpin->port());
ConcretePort *cport = ccell->findPort(pin_cport->name());
if (cport) {
rpins[cport->pinIndex()] = cpin;
cpin->port_ = cport;
}
}
}
delete [] pins;
cinst->pins_ = rpins;
cinst->setCell(ccell);
}
void
ConcreteNetwork::deleteInstance(Instance *inst)
{
ConcreteInstance *cinst = reinterpret_cast<ConcreteInstance*>(inst);
// Delete nets first (so children pin deletes are not required).
ConcreteInstanceNetMap::Iterator net_iter(cinst->nets_);
while (net_iter.hasNext()) {
ConcreteNet *cnet = net_iter.next();
Net *net = reinterpret_cast<Net*>(cnet);
// Delete terminals connected to net.
NetTermIterator *term_iter = termIterator(net);
while (term_iter->hasNext()) {
ConcreteTerm *term = reinterpret_cast<ConcreteTerm*>(term_iter->next());
delete term;
}
delete term_iter;
deleteNet(net);
}
// Delete children.
InstanceChildIterator *child_iter = childIterator(inst);
while (child_iter->hasNext()) {
Instance *child = child_iter->next();
deleteInstance(child);
}
delete child_iter;
InstancePinIterator *pin_iter = pinIterator(inst);
while (pin_iter->hasNext()) {
Pin *pin = pin_iter->next();
deletePin(pin);
}
delete pin_iter;
Instance *parent_inst = parent(inst);
if (parent_inst) {
ConcreteInstance *cparent =
reinterpret_cast<ConcreteInstance*>(parent_inst);
cparent->deleteChild(cinst);
}
delete cinst;
}
Pin *
ConcreteNetwork::makePin(Instance *inst,
Port *port,
Net *net)
{
ConcreteInstance *cinst = reinterpret_cast<ConcreteInstance*>(inst);
ConcretePort *cport = reinterpret_cast<ConcretePort*>(port);
ConcreteNet *cnet = reinterpret_cast<ConcreteNet*>(net);
ConcretePin *cpin = new ConcretePin(cinst, cport, cnet);
cinst->addPin(cpin);
if (cnet)
connectNetPin(cnet, cpin);
return reinterpret_cast<Pin*>(cpin);
}
Term *
ConcreteNetwork::makeTerm(Pin *pin,
Net *net)
{
ConcretePin *cpin = reinterpret_cast<ConcretePin*>(pin);
ConcreteNet *cnet = reinterpret_cast<ConcreteNet*>(net);
ConcreteTerm *cterm = new ConcreteTerm(cpin, cnet);
if (cnet)
cnet->addTerm(cterm);
cpin->term_ = cterm;
return reinterpret_cast<Term*>(cterm);
}
Pin *
ConcreteNetwork::connect(Instance *inst,
LibertyPort *port,
Net *net)
{
return connect(inst, reinterpret_cast<Port*>(port), net);
}
Pin *
ConcreteNetwork::connect(Instance *inst,
Port *port,
Net *net)
{
ConcreteNet *cnet = reinterpret_cast<ConcreteNet*>(net);
ConcreteInstance *cinst = reinterpret_cast<ConcreteInstance*>(inst);
ConcretePort *cport = reinterpret_cast<ConcretePort*>(port);
ConcretePin *cpin = cinst->findPin(port);
if (cpin) {
ConcreteNet *prev_net = cpin->net_;
if (prev_net)
disconnectNetPin(prev_net, cpin);
}
else {
cpin = new ConcretePin(cinst, cport, cnet);
cinst->addPin(cpin);
}
if (inst == top_instance_) {
// makeTerm
ConcreteTerm *cterm = new ConcreteTerm(cpin, cnet);
cnet->addTerm(cterm);
cpin->term_ = cterm;
cpin->net_ = nullptr;
}
else {
cpin->net_ = cnet;
connectNetPin(cnet, cpin);
}
return reinterpret_cast<Pin*>(cpin);
}
void
ConcreteNetwork::connectNetPin(ConcreteNet *cnet,
ConcretePin *cpin)
{
cnet->addPin(cpin);
// If there are no terminals the net does not span hierarchy levels
// and it is safe to incrementally update the drivers.
Pin *pin = reinterpret_cast<Pin*>(cpin);
if (isDriver(pin)) {
if (cnet->terms_ == nullptr) {
Net *net = reinterpret_cast<Net*>(cnet);
PinSet *drvrs = net_drvr_pin_map_.findKey(net);
if (drvrs)
drvrs->insert(pin);
}
else
clearNetDrvrPinMap();
}
}
void
ConcreteNetwork::disconnectPin(Pin *pin)
{
ConcretePin *cpin = reinterpret_cast<ConcretePin*>(pin);
if (reinterpret_cast<Instance*>(cpin->instance()) == top_instance_) {
ConcreteTerm *cterm = cpin->term_;
if (cterm) {
ConcreteNet *cnet = cterm->net_;
if (cnet) {
cnet->deleteTerm(cterm);
clearNetDrvrPinMap();
}
cpin->term_ = nullptr;
delete cterm;
}
}
else {
ConcreteNet *cnet = cpin->net();
if (cnet)
disconnectNetPin(cnet, cpin);
cpin->net_ = nullptr;
}
}
void
ConcreteNetwork::disconnectNetPin(ConcreteNet *cnet,
ConcretePin *cpin)
{
cnet->deletePin(cpin);
Pin *pin = reinterpret_cast<Pin*>(cpin);
if (isDriver(pin)) {
ConcreteNet *cnet = cpin->net();
// If there are no terminals the net does not span hierarchy levels
// and it is safe to incrementally update the drivers.
if (cnet->terms_ == nullptr) {
Net *net = reinterpret_cast<Net*>(cnet);
PinSet *drvrs = net_drvr_pin_map_.findKey(net);
if (drvrs)
drvrs->erase(pin);
}
else
clearNetDrvrPinMap();
}
}
void
ConcreteNetwork::deletePin(Pin *pin)
{
ConcretePin *cpin = reinterpret_cast<ConcretePin*>(pin);
ConcreteNet *cnet = cpin->net();
if (cnet)
disconnectNetPin(cnet, cpin);
ConcreteInstance *cinst =
reinterpret_cast<ConcreteInstance*>(cpin->instance());
if (cinst)
cinst->deletePin(cpin);
delete cpin;
}
Net *
ConcreteNetwork::makeNet(const char *name,
Instance *parent)
{
ConcreteInstance *cparent = reinterpret_cast<ConcreteInstance*>(parent);
ConcreteNet *net = new ConcreteNet(name, cparent);
cparent->addNet(net);
return reinterpret_cast<Net*>(net);
}
void
ConcreteNetwork::deleteNet(Net *net)
{
ConcreteNet *cnet = reinterpret_cast<ConcreteNet*>(net);
ConcreteNetPinIterator pin_iter(cnet);
while (pin_iter.hasNext()) {
ConcretePin *pin = reinterpret_cast<ConcretePin*>(pin_iter.next());
// Do NOT use net->disconnectPin because it would be N^2
// to delete all of the pins from the net.
pin->net_ = nullptr;
}
constant_nets_[int(LogicValue::zero)].erase(net);
constant_nets_[int(LogicValue::one)].erase(net);
PinSet *drvrs = net_drvr_pin_map_.findKey(net);
if (drvrs) {
delete drvrs;
net_drvr_pin_map_.erase(net);
}
ConcreteInstance *cinst =
reinterpret_cast<ConcreteInstance*>(cnet->instance());
cinst->deleteNet(cnet);
delete cnet;
}
void
ConcreteNetwork::clearConstantNets()
{
constant_nets_[int(LogicValue::zero)].clear();
constant_nets_[int(LogicValue::one)].clear();
}
void
ConcreteNetwork::addConstantNet(Net *net,
LogicValue value)
{
if (value == LogicValue::zero
|| value == LogicValue::one)
constant_nets_[int(value)].insert(net);
}
ConstantPinIterator *
ConcreteNetwork::constantPinIterator()
{
return new NetworkConstantPinIterator(this,
constant_nets_[int(LogicValue::zero)],
constant_nets_[int(LogicValue::one)]);
}
////////////////////////////////////////////////////////////////
// Optimized version of Network::visitConnectedPins.
void
ConcreteNetwork::visitConnectedPins(const Net *net,
PinVisitor &visitor,
ConstNetSet &visited_nets) const
{
if (!visited_nets.hasKey(net)) {
visited_nets.insert(net);
// Search up from net terminals.
const ConcreteNet *cnet = reinterpret_cast<const ConcreteNet*>(net);
for (ConcreteTerm *term = cnet->terms_; term; term = term->net_next_) {
ConcretePin *above_pin = term->pin_;
if (above_pin) {
ConcreteNet *above_net = above_pin->net_;
if (above_net)
visitConnectedPins(reinterpret_cast<Net*>(above_net),
visitor, visited_nets);
else
visitor(reinterpret_cast<Pin*>(above_pin));
}
}
// Search down from net pins.
for (ConcretePin *pin = cnet->pins_; pin; pin = pin->net_next_) {
visitor(reinterpret_cast<Pin*>(pin));
ConcreteTerm *below_term = pin->term_;
if (below_term) {
ConcreteNet *below_net = below_term->net_;
if (below_net)
visitConnectedPins(reinterpret_cast<Net*>(below_net),
visitor, visited_nets);
}
}
}
}
////////////////////////////////////////////////////////////////
ConcreteInstance::ConcreteInstance(ConcreteCell *cell,
const char *name,
ConcreteInstance *parent) :
cell_(cell),
name_(stringCopy(name)),
parent_(parent),
children_(nullptr),
nets_(nullptr)
{
initPins();
}
void
ConcreteInstance::initPins()
{
int pin_count = reinterpret_cast<ConcreteCell*>(cell_)->portBitCount();
if (pin_count) {
pins_ = new ConcretePin*[pin_count];
for (int i = 0; i < pin_count; i++)
pins_[i] = nullptr;
}
else
pins_ = nullptr;
}
ConcreteInstance::~ConcreteInstance()
{
stringDelete(name_);
delete [] pins_;
delete children_;
delete nets_;
}
Instance *
ConcreteInstance::findChild(const char *name) const
{
if (children_)
return reinterpret_cast<Instance*>(children_->findKey(name));
else
return nullptr;
}
ConcretePin *
ConcreteInstance::findPin(const char *port_name) const
{
ConcreteCell *ccell = reinterpret_cast<ConcreteCell*>(cell_);
const ConcretePort *cport =
reinterpret_cast<const ConcretePort*>(ccell->findPort(port_name));
if (cport
&& !cport->isBus())
return pins_[cport->pinIndex()];
else
return nullptr;
}
ConcretePin *
ConcreteInstance::findPin(const Port *port) const
{
const ConcretePort *cport = reinterpret_cast<const ConcretePort*>(port);
return pins_[cport->pinIndex()];
}
ConcreteNet *
ConcreteInstance::findNet(const char *net_name) const
{
ConcreteNet *net = nullptr;
if (nets_) {
net = nets_->findKey(net_name);
// Follow merge pointer to surviving net.
if (net) {
while (net->mergedInto())
net = net->mergedInto();
}
}
return net;
}
void
ConcreteInstance::findNetsMatching(const PatternMatch *pattern,
NetSeq *nets) const
{
if (pattern->hasWildcards()) {
ConcreteInstanceNetMap::Iterator net_iter(nets_);
while (net_iter.hasNext()) {
const char *net_name;
ConcreteNet *cnet;
net_iter.next(net_name, cnet);
if (pattern->match(net_name))
nets->push_back(reinterpret_cast<Net*>(cnet));
}
}
else {
ConcreteNet *cnet = findNet(pattern->pattern());
if (cnet)
nets->push_back(reinterpret_cast<Net*>(cnet));
}
}
InstanceNetIterator *
ConcreteInstance::netIterator() const
{
return reinterpret_cast<InstanceNetIterator*>
(new ConcreteInstanceNetIterator(nets_));
}
InstanceChildIterator *
ConcreteInstance::childIterator() const
{
return new ConcreteInstanceChildIterator(children_);
}
void
ConcreteInstance::addChild(ConcreteInstance *child)
{
if (children_ == nullptr)
children_ = new ConcreteInstanceChildMap;
(*children_)[child->name()] = child;
}
void
ConcreteInstance::deleteChild(ConcreteInstance *child)
{
children_->erase(child->name());
}
void
ConcreteInstance::addPin(ConcretePin *pin)
{
ConcretePort *cport = reinterpret_cast<ConcretePort *>(pin->port());
pins_[cport->pinIndex()] = pin;
}
void
ConcreteInstance::deletePin(ConcretePin *pin)
{
ConcretePort *cport = reinterpret_cast<ConcretePort *>(pin->port());
pins_[cport->pinIndex()] = nullptr;
}
void
ConcreteInstance::addNet(ConcreteNet *net)
{
if (nets_ == nullptr)
nets_ = new ConcreteInstanceNetMap;
(*nets_)[net->name()] = net;
}
void
ConcreteInstance::addNet(const char *name,
ConcreteNet *net)
{
if (nets_ == nullptr)
nets_ = new ConcreteInstanceNetMap;
(*nets_)[name] = net;
}
void
ConcreteInstance::deleteNet(ConcreteNet *net)
{
nets_->erase(net->name());
}
void
ConcreteInstance::setCell(ConcreteCell *cell)
{
cell_ = cell;
}
////////////////////////////////////////////////////////////////
ConcretePin::ConcretePin(ConcreteInstance *instance,
ConcretePort *port,
ConcreteNet *net) :
instance_(instance),
port_(port),
net_(net),
term_(nullptr),
net_next_(nullptr),
net_prev_(nullptr),
vertex_id_(vertex_id_null)
{
}
const char *
ConcretePin::name() const
{
return port_->name();
}
void
ConcretePin::setVertexId(VertexId id)
{
vertex_id_ = id;
}
////////////////////////////////////////////////////////////////
const char *
ConcreteTerm::name() const
{
ConcretePin *cpin = reinterpret_cast<ConcretePin*>(pin_);
const ConcretePort *cport =
reinterpret_cast<const ConcretePort*>(cpin->port());
return cport->name();
}
ConcreteTerm::ConcreteTerm(ConcretePin *pin,
ConcreteNet *net) :
pin_(pin),
net_(net),
net_next_(nullptr)
{
}
////////////////////////////////////////////////////////////////
ConcreteNet::ConcreteNet(const char *name,
ConcreteInstance *instance) :
name_(stringCopy(name)),
instance_(instance),
pins_(nullptr),
terms_(nullptr),
merged_into_(nullptr)
{
}
ConcreteNet::~ConcreteNet()
{
stringDelete(name_);
}
// Merged nets are kept around to serve as name aliases.
// Only Instance::findNet and InstanceNetIterator need to know
// the net has been merged.
void
ConcreteNet::mergeInto(ConcreteNet *net)
{
ConcreteNetPinIterator pin_iter(this);
while (pin_iter.hasNext()) {
Pin *pin = pin_iter.next();
ConcretePin *cpin = reinterpret_cast<ConcretePin*>(pin);
net->addPin(cpin);
cpin->net_ = net;
}
pins_ = nullptr;
ConcreteNetTermIterator term_iter(this);
while (term_iter.hasNext()) {
Term *term = term_iter.next();
ConcreteTerm *cterm = reinterpret_cast<ConcreteTerm*>(term);
net->addTerm(cterm);
cterm->net_ = net;
}
terms_ = nullptr;
// Leave name map pointing to merged net because otherwise a top
// level merged net has no pointer to it and it is leaked.
merged_into_ = net;
}
void
ConcreteNet::addPin(ConcretePin *pin)
{
if (pins_)
pins_->net_prev_ = pin;
pin->net_next_ = pins_;
pin->net_prev_ = nullptr;
pins_ = pin;
}
void
ConcreteNet::deletePin(ConcretePin *pin)
{
ConcretePin *prev = pin->net_prev_;
ConcretePin *next = pin->net_next_;
if (prev)
prev->net_next_ = next;
if (next)
next->net_prev_ = prev;
if (pins_ == pin)
pins_ = next;
}
void
ConcreteNet::addTerm(ConcreteTerm *term)
{
ConcreteTerm *next = terms_;
terms_ = term;
term->net_next_ = next;
}
void
ConcreteNet::deleteTerm(ConcreteTerm *term)
{
ConcreteTerm *net_prev_term = nullptr;
for (ConcreteTerm *net_term=terms_;net_term;net_term=net_term->net_next_) {
if (net_term == term) {
if (net_prev_term)
net_prev_term->net_next_ = term->net_next_;
else
terms_ = term->net_next_;
break;
}
net_prev_term = net_term;
}
}
////////////////////////////////////////////////////////////////
typedef Map<Net*, Net*> BindingMap;
// Binding table used for linking/expanding network.
class ConcreteBindingTbl
{
public:
explicit ConcreteBindingTbl(NetworkEdit *network);
Net *ensureBinding(Net *proto_net,
Instance *parent);
Net *find(Net *net);
void bind(Net *proto_net,
Net *clone_net);
private:
DISALLOW_COPY_AND_ASSIGN(ConcreteBindingTbl);
BindingMap map_;
NetworkEdit *network_;
};
void
ConcreteNetwork::setCellNetworkView(Cell *cell,
Instance *inst)
{
cell_network_view_map_[cell] = inst;
}
Instance *
ConcreteNetwork::cellNetworkView(Cell *cell)
{
return cell_network_view_map_.findKey(cell);
}
void
ConcreteNetwork::readNetlistBefore()
{
clearConstantNets();
deleteTopInstance();
clearNetDrvrPinMap();
}
void
ConcreteNetwork::setTopInstance(Instance *top_inst)
{
if (top_instance_) {
deleteInstance(top_instance_);
clearConstantNets();
clearNetDrvrPinMap();
}
top_instance_ = top_inst;
}
void
ConcreteNetwork::setLinkFunc(LinkNetworkFunc *link)
{
link_func_ = link;
}
bool
ConcreteNetwork::linkNetwork(const char *top_cell_name,
bool make_black_boxes,
Report *report)
{
if (link_func_) {
clearConstantNets();
deleteTopInstance();
top_instance_ = link_func_(top_cell_name, make_black_boxes, report, this);
return top_instance_ != nullptr;
}
else {
report->error(8, "cell type %s can not be linked.", top_cell_name);
return false;
}
}
Instance *
linkReaderNetwork(Cell *top_cell,
bool, Report *,
NetworkReader *network)
{
Instance *view = network->cellNetworkView(top_cell);
if (view) {
// Seed the recursion for expansion with the top level instance.
Instance *top_instance = network->makeInstance(top_cell, "", nullptr);
ConcreteBindingTbl bindings(network);
makeClonePins(view, top_instance, view, &bindings, nullptr, nullptr, network);
InstanceChildIterator *child_iter = network->childIterator(view);
while (child_iter->hasNext()) {
Instance *child = child_iter->next();
makeChildNetwork(child, top_instance, &bindings, network);
}
delete child_iter;
network->deleteCellNetworkViews();
return top_instance;
}
return nullptr;
}
static void
makeChildNetwork(Instance *proto,
Instance *parent,
ConcreteBindingTbl *parent_bindings,
NetworkReader *network)
{
Cell *proto_cell = network->cell(proto);
Instance *clone = network->makeInstance(proto_cell, network->name(proto),
parent);
if (network->isLeaf(proto_cell))
makeClonePins(proto, clone, nullptr, nullptr, parent, parent_bindings, network);
else {
// Recurse if this isn't a leaf cell.
ConcreteBindingTbl bindings(network);
Instance *clone_view = network->cellNetworkView(proto_cell);
makeClonePins(proto, clone, clone_view, &bindings, parent,
parent_bindings, network);
if (clone_view) {
InstanceChildIterator *child_iter = network->childIterator(clone_view);
while (child_iter->hasNext()) {
Instance *child = child_iter->next();
makeChildNetwork(child, clone, &bindings, network);
}
delete child_iter;
}
}
}
static void
makeClonePins(Instance *proto,
Instance *clone,
Instance *clone_view,
ConcreteBindingTbl *bindings,
Instance *parent,
ConcreteBindingTbl *parent_bindings,
NetworkReader *network)
{
InstancePinIterator *proto_pin_iter = network->pinIterator(proto);
while (proto_pin_iter->hasNext()) {
Pin *proto_pin = proto_pin_iter->next();
Net *proto_net = network->net(proto_pin);
Port *proto_port = network->port(proto_pin);
Net *clone_net = nullptr;
if (proto_net && parent_bindings)
clone_net = parent_bindings->ensureBinding(proto_net, parent);
Pin *clone_pin = network->connect(clone, proto_port, clone_net);
if (clone_view) {
Pin *clone_proto_pin = network->findPin(clone_view, proto_port);
Net *clone_proto_net = network->net(clone_proto_pin);
Net *clone_child_net = nullptr;
if (clone_proto_net)
clone_child_net = bindings->ensureBinding(clone_proto_net, clone);
network->makeTerm(clone_pin, clone_child_net);
}
}
delete proto_pin_iter;
}
////////////////////////////////////////////////////////////////
ConcreteBindingTbl::ConcreteBindingTbl(NetworkEdit *network) :
network_(network)
{
}
// Follow the merged_into pointers rather than update the
// binding tables up the call tree when nodes are merged
// because the name changes up the hierarchy.
Net *
ConcreteBindingTbl::find(Net *proto_net)
{
ConcreteNet *net = reinterpret_cast<ConcreteNet*>(map_.findKey(proto_net));
while (net && net->mergedInto())
net = net->mergedInto();
return reinterpret_cast<Net*>(net);
}
void
ConcreteBindingTbl::bind(Net *proto_net,
Net *net)
{
map_[proto_net] = net;
}
Net *
ConcreteBindingTbl::ensureBinding(Net *proto_net,
Instance *parent)
{
Net *net = find(proto_net);
if (net == nullptr) {
net = network_->makeNet(network_->name(proto_net), parent);
map_[proto_net] = net;
}
return net;
}
} // namespace