2018-09-28 17:54:21 +02:00
|
|
|
// OpenSTA, Static Timing Analyzer
|
2025-01-22 02:54:33 +01:00
|
|
|
// Copyright (c) 2025, Parallax Software, Inc.
|
2018-09-28 17:54:21 +02:00
|
|
|
//
|
|
|
|
|
// 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
|
2022-01-04 18:17:08 +01:00
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
2018-09-28 17:54:21 +02:00
|
|
|
// GNU General Public License for more details.
|
|
|
|
|
//
|
|
|
|
|
// You should have received a copy of the GNU General Public License
|
2022-01-04 18:17:08 +01:00
|
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
2025-01-22 02:54:33 +01:00
|
|
|
//
|
|
|
|
|
// The origin of this software must not be misrepresented; you must not
|
|
|
|
|
// claim that you wrote the original software.
|
|
|
|
|
//
|
|
|
|
|
// Altered source versions must be plainly marked as such, and must not be
|
|
|
|
|
// misrepresented as being the original software.
|
|
|
|
|
//
|
|
|
|
|
// This notice may not be removed or altered from any source distribution.
|
2018-09-28 17:54:21 +02:00
|
|
|
|
2020-04-05 23:53:44 +02:00
|
|
|
#include "ConcreteNetwork.hh"
|
2020-04-05 20:35:51 +02:00
|
|
|
|
2020-04-05 23:53:44 +02:00
|
|
|
#include "PatternMatch.hh"
|
|
|
|
|
#include "Report.hh"
|
|
|
|
|
#include "Liberty.hh"
|
|
|
|
|
#include "PortDirection.hh"
|
|
|
|
|
#include "ConcreteLibrary.hh"
|
|
|
|
|
#include "Network.hh"
|
2018-09-28 17:54:21 +02:00
|
|
|
|
|
|
|
|
namespace sta {
|
|
|
|
|
|
2025-04-12 01:59:48 +02:00
|
|
|
using std::string;
|
|
|
|
|
|
2018-09-28 17:54:21 +02:00
|
|
|
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);
|
|
|
|
|
|
2023-01-19 19:23:45 +01:00
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2019-10-25 17:51:59 +02:00
|
|
|
NetworkReader *
|
2018-09-28 17:54:21 +02:00
|
|
|
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:
|
|
|
|
|
void findNext();
|
|
|
|
|
|
|
|
|
|
ConcreteInstanceNetMap::Iterator iter_;
|
|
|
|
|
ConcreteNet *next_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
ConcreteInstanceNetIterator::
|
|
|
|
|
ConcreteInstanceNetIterator(ConcreteInstanceNetMap *nets):
|
|
|
|
|
iter_(nets),
|
2019-03-13 01:25:53 +01:00
|
|
|
next_(nullptr)
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
|
|
|
|
findNext();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
ConcreteInstanceNetIterator::hasNext()
|
|
|
|
|
{
|
2019-03-13 01:25:53 +01:00
|
|
|
return next_ != nullptr;
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Skip nets that have been merged.
|
|
|
|
|
void
|
|
|
|
|
ConcreteInstanceNetIterator::findNext()
|
|
|
|
|
{
|
|
|
|
|
while (iter_.hasNext()) {
|
|
|
|
|
next_ = iter_.next();
|
2019-03-13 01:25:53 +01:00
|
|
|
if (next_->mergedInto() == nullptr)
|
2018-09-28 17:54:21 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2019-03-13 01:25:53 +01:00
|
|
|
next_ = nullptr;
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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:
|
|
|
|
|
void findNext();
|
|
|
|
|
|
2023-06-28 19:01:39 +02:00
|
|
|
const ConcretePinSeq &pins_;
|
2018-09-28 17:54:21 +02:00
|
|
|
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()
|
|
|
|
|
{
|
2019-03-13 01:25:53 +01:00
|
|
|
return next_ != nullptr;
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
2019-03-13 01:25:53 +01:00
|
|
|
next_ = nullptr;
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
class ConcreteNetPinIterator : public NetPinIterator
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
explicit ConcreteNetPinIterator(const ConcreteNet *net);
|
|
|
|
|
bool hasNext();
|
|
|
|
|
Pin *next();
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
ConcretePin *next_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
ConcreteNetPinIterator::ConcreteNetPinIterator(const ConcreteNet *net) :
|
|
|
|
|
next_(net->pins_)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
ConcreteNetPinIterator::hasNext()
|
|
|
|
|
{
|
2019-03-13 01:25:53 +01:00
|
|
|
return next_ != nullptr;
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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:
|
|
|
|
|
ConcreteTerm *next_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
ConcreteNetTermIterator::ConcreteNetTermIterator(const ConcreteNet *net) :
|
|
|
|
|
next_(net->terms_)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
ConcreteNetTermIterator::hasNext()
|
|
|
|
|
{
|
2019-03-13 01:25:53 +01:00
|
|
|
return next_ != nullptr;
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Term *
|
|
|
|
|
ConcreteNetTermIterator::next()
|
|
|
|
|
{
|
|
|
|
|
ConcreteTerm *next = next_;
|
|
|
|
|
next_ = next_->net_next_;
|
|
|
|
|
return reinterpret_cast<Term*>(next);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2023-01-19 19:23:45 +01:00
|
|
|
ObjectId ConcreteNetwork::object_id_ = 0;
|
|
|
|
|
|
2018-09-28 17:54:21 +02:00
|
|
|
ConcreteNetwork::ConcreteNetwork() :
|
|
|
|
|
NetworkReader(),
|
2019-03-13 01:25:53 +01:00
|
|
|
top_instance_(nullptr),
|
2023-01-19 19:23:45 +01:00
|
|
|
constant_nets_{NetSet(this), NetSet(this)},
|
2019-03-13 01:25:53 +01:00
|
|
|
link_func_(nullptr)
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ConcreteNetwork::~ConcreteNetwork()
|
|
|
|
|
{
|
|
|
|
|
clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ConcreteNetwork::clear()
|
|
|
|
|
{
|
|
|
|
|
deleteTopInstance();
|
|
|
|
|
deleteCellNetworkViews();
|
|
|
|
|
library_seq_.deleteContentsClear();
|
|
|
|
|
library_map_.clear();
|
|
|
|
|
Network::clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ConcreteNetwork::deleteTopInstance()
|
|
|
|
|
{
|
|
|
|
|
if (top_instance_) {
|
2019-05-20 01:06:06 +02:00
|
|
|
deleteInstance(top_instance_);
|
2019-03-13 01:25:53 +01:00
|
|
|
top_instance_ = nullptr;
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
{
|
2019-05-20 01:06:06 +02:00
|
|
|
return top_instance_;
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
class ConcreteLibraryIterator1 : public Iterator<Library*>
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
explicit ConcreteLibraryIterator1(const ConcreteLibrarySeq &lib_seq_);
|
|
|
|
|
virtual bool hasNext();
|
|
|
|
|
virtual Library *next();
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
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:
|
|
|
|
|
void findNext();
|
|
|
|
|
|
|
|
|
|
ConcreteLibrarySeq::ConstIterator iter_;
|
|
|
|
|
LibertyLibrary *next_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
ConcreteLibertyLibraryIterator::
|
|
|
|
|
ConcreteLibertyLibraryIterator(const ConcreteNetwork *network):
|
|
|
|
|
iter_(network->library_seq_),
|
2019-03-13 01:25:53 +01:00
|
|
|
next_(nullptr)
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
|
|
|
|
findNext();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ConcreteLibertyLibraryIterator::~ConcreteLibertyLibraryIterator()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
ConcreteLibertyLibraryIterator::hasNext()
|
|
|
|
|
{
|
2019-03-13 01:25:53 +01:00
|
|
|
return next_ != nullptr;
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LibertyLibrary *
|
|
|
|
|
ConcreteLibertyLibraryIterator::next()
|
|
|
|
|
{
|
|
|
|
|
LibertyLibrary *next = next_;
|
|
|
|
|
findNext();
|
|
|
|
|
return next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ConcreteLibertyLibraryIterator::findNext()
|
|
|
|
|
{
|
2019-03-13 01:25:53 +01:00
|
|
|
next_ = nullptr;
|
2018-09-28 17:54:21 +02:00
|
|
|
while (iter_.hasNext()) {
|
|
|
|
|
ConcreteLibrary *lib = iter_.next();
|
2019-06-28 22:38:56 +02:00
|
|
|
if (lib->isLiberty()) {
|
|
|
|
|
LibertyLibrary *liberty = static_cast<LibertyLibrary*>(lib);
|
|
|
|
|
if (liberty) {
|
|
|
|
|
next_ = liberty;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LibertyLibraryIterator *
|
|
|
|
|
ConcreteNetwork::libertyLibraryIterator() const
|
|
|
|
|
{
|
|
|
|
|
return new ConcreteLibertyLibraryIterator(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
Library *
|
2019-05-20 01:06:06 +02:00
|
|
|
ConcreteNetwork::makeLibrary(const char *name,
|
|
|
|
|
const char *filename)
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
2019-06-28 22:38:56 +02:00
|
|
|
ConcreteLibrary *library = new ConcreteLibrary(name, filename, false);
|
2018-09-28 17:54:21 +02:00
|
|
|
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
|
2021-08-13 17:37:42 +02:00
|
|
|
ConcreteNetwork::deleteLibrary(Library *library)
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
2021-08-13 17:37:42 +02:00
|
|
|
ConcreteLibrary *clib = reinterpret_cast<ConcreteLibrary*>(library);
|
|
|
|
|
library_map_.erase(clib->name());
|
|
|
|
|
library_seq_.eraseObject(clib);
|
|
|
|
|
delete clib;
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char *
|
|
|
|
|
ConcreteNetwork::name(const Library *library) const
|
|
|
|
|
{
|
|
|
|
|
const ConcreteLibrary *clib =
|
|
|
|
|
reinterpret_cast<const ConcreteLibrary*>(library);
|
|
|
|
|
return clib->name();
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-19 19:23:45 +01:00
|
|
|
ObjectId
|
|
|
|
|
ConcreteNetwork::id(const Library *library) const
|
|
|
|
|
{
|
|
|
|
|
const ConcreteLibrary *clib =
|
|
|
|
|
reinterpret_cast<const ConcreteLibrary*>(library);
|
|
|
|
|
return clib->id();
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-28 17:54:21 +02:00
|
|
|
LibertyLibrary *
|
|
|
|
|
ConcreteNetwork::findLiberty(const char *name)
|
|
|
|
|
{
|
|
|
|
|
ConcreteLibrary *lib = library_map_.findKey(name);
|
2019-11-05 18:14:35 +01:00
|
|
|
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;
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
2019-03-13 01:25:53 +01:00
|
|
|
return nullptr;
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
2023-01-19 19:23:45 +01:00
|
|
|
CellSeq
|
2018-09-28 17:54:21 +02:00
|
|
|
ConcreteNetwork::findCellsMatching(const Library *library,
|
2023-01-19 19:23:45 +01:00
|
|
|
const PatternMatch *pattern) const
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
|
|
|
|
const ConcreteLibrary *clib =
|
|
|
|
|
reinterpret_cast<const ConcreteLibrary*>(library);
|
2023-01-19 19:23:45 +01:00
|
|
|
return clib->findCellsMatching(pattern);
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-19 19:23:45 +01:00
|
|
|
ObjectId
|
|
|
|
|
ConcreteNetwork::id(const Cell *cell) const
|
|
|
|
|
{
|
|
|
|
|
const ConcreteCell *ccell = reinterpret_cast<const ConcreteCell*>(cell);
|
|
|
|
|
return ccell->id();
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-28 17:54:21 +02:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-11 17:49:12 +02:00
|
|
|
void
|
|
|
|
|
ConcreteNetwork::setAttribute(Cell *cell,
|
2024-03-13 01:00:47 +01:00
|
|
|
const string &key,
|
|
|
|
|
const string &value)
|
2022-07-11 17:49:12 +02:00
|
|
|
{
|
|
|
|
|
ConcreteCell *ccell = reinterpret_cast<ConcreteCell*>(cell);
|
|
|
|
|
ccell->setAttribute(key, value);
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-28 17:54:21 +02:00
|
|
|
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);
|
2019-06-16 07:20:54 +02:00
|
|
|
return ccell->libertyCell();
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
2019-06-24 17:35:04 +02:00
|
|
|
const LibertyCell *
|
|
|
|
|
ConcreteNetwork::libertyCell(const Cell *cell) const
|
|
|
|
|
{
|
|
|
|
|
const ConcreteCell *ccell = reinterpret_cast<const ConcreteCell*>(cell);
|
|
|
|
|
return ccell->libertyCell();
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-14 21:05:34 +02:00
|
|
|
Cell *
|
|
|
|
|
ConcreteNetwork::cell(LibertyCell *cell) const
|
|
|
|
|
{
|
|
|
|
|
return reinterpret_cast<Cell*>(cell);
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-24 17:35:04 +02:00
|
|
|
const Cell *
|
|
|
|
|
ConcreteNetwork::cell(const LibertyCell *cell) const
|
|
|
|
|
{
|
|
|
|
|
return reinterpret_cast<const Cell*>(cell);
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-28 17:54:21 +02:00
|
|
|
const char *
|
|
|
|
|
ConcreteNetwork::filename(const Cell *cell)
|
|
|
|
|
{
|
|
|
|
|
const ConcreteCell *ccell = reinterpret_cast<const ConcreteCell*>(cell);
|
|
|
|
|
return ccell->filename();
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-13 01:00:47 +01:00
|
|
|
string
|
2024-03-09 06:56:25 +01:00
|
|
|
ConcreteNetwork::getAttribute(const Cell *cell,
|
2024-03-13 01:00:47 +01:00
|
|
|
const string &key) const
|
2022-07-11 17:49:12 +02:00
|
|
|
{
|
|
|
|
|
const ConcreteCell *ccell = reinterpret_cast<const ConcreteCell*>(cell);
|
|
|
|
|
return ccell->getAttribute(key);
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-18 18:37:10 +02:00
|
|
|
const AttributeMap &
|
|
|
|
|
ConcreteNetwork::attributeMap(const Cell *cell) const
|
|
|
|
|
{
|
|
|
|
|
const ConcreteCell *ccell = reinterpret_cast<const ConcreteCell*>(cell);
|
|
|
|
|
return ccell->attributeMap();
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-28 17:54:21 +02:00
|
|
|
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));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
2021-08-13 00:50:25 +02:00
|
|
|
ConcreteNetwork::groupBusPorts(Cell *cell,
|
2021-08-13 02:46:02 +02:00
|
|
|
std::function<bool(const char*)> port_msb_first)
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
2019-06-28 20:51:43 +02:00
|
|
|
Library *lib = library(cell);
|
|
|
|
|
ConcreteLibrary *clib = reinterpret_cast<ConcreteLibrary*>(lib);
|
2018-09-28 17:54:21 +02:00
|
|
|
ConcreteCell *ccell = reinterpret_cast<ConcreteCell*>(cell);
|
2023-01-19 19:23:45 +01:00
|
|
|
ccell->groupBusPorts(clib->busBrktLeft(), clib->busBrktRight(),
|
|
|
|
|
port_msb_first);
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-19 19:23:45 +01:00
|
|
|
ObjectId
|
|
|
|
|
ConcreteNetwork::nextObjectId()
|
|
|
|
|
{
|
|
|
|
|
return object_id_++;
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-28 17:54:21 +02:00
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
class ConcreteCellPortIterator1 : public CellPortIterator
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
explicit ConcreteCellPortIterator1(const ConcreteCell *cell);
|
|
|
|
|
~ConcreteCellPortIterator1();
|
|
|
|
|
virtual bool hasNext() { return iter_->hasNext(); }
|
|
|
|
|
virtual Port *next();
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
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:
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-19 19:23:45 +01:00
|
|
|
ObjectId
|
|
|
|
|
ConcreteNetwork::id(const Port *port) const
|
|
|
|
|
{
|
|
|
|
|
const ConcretePort *cport = reinterpret_cast<const ConcretePort*>(port);
|
|
|
|
|
return cport->id();
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-28 17:54:21 +02:00
|
|
|
Cell *
|
|
|
|
|
ConcreteNetwork::cell(const Port *port) const
|
|
|
|
|
{
|
|
|
|
|
const ConcretePort *cport = reinterpret_cast<const ConcretePort*>(port);
|
|
|
|
|
return cport->cell();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LibertyPort *
|
2019-07-02 16:07:34 +02:00
|
|
|
ConcreteNetwork::libertyPort(const Port *port) const
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
2019-07-02 16:07:34 +02:00
|
|
|
const ConcretePort *cport = reinterpret_cast<const ConcretePort*>(port);
|
2019-06-16 07:20:54 +02:00
|
|
|
return cport->libertyPort();
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2023-11-25 22:13:59 +01:00
|
|
|
// This has to skip over missing bus bits in the members.
|
2018-09-28 17:54:21 +02:00
|
|
|
class ConcretePortMemberIterator1 : public PortMemberIterator
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
explicit ConcretePortMemberIterator1(const ConcretePort *port);
|
|
|
|
|
~ConcretePortMemberIterator1();
|
2023-11-25 22:13:59 +01:00
|
|
|
virtual bool hasNext();
|
2018-09-28 17:54:21 +02:00
|
|
|
virtual Port *next();
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
ConcretePortMemberIterator *iter_;
|
2023-11-25 22:13:59 +01:00
|
|
|
ConcretePort *next_;
|
2018-09-28 17:54:21 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
ConcretePortMemberIterator1::ConcretePortMemberIterator1(const ConcretePort *
|
|
|
|
|
port) :
|
2023-11-25 22:13:59 +01:00
|
|
|
iter_(port->memberIterator()),
|
|
|
|
|
next_(nullptr)
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ConcretePortMemberIterator1::~ConcretePortMemberIterator1()
|
|
|
|
|
{
|
|
|
|
|
delete iter_;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-25 22:13:59 +01:00
|
|
|
bool
|
|
|
|
|
ConcretePortMemberIterator1::hasNext()
|
|
|
|
|
{
|
|
|
|
|
while (next_ == nullptr
|
|
|
|
|
&& iter_->hasNext())
|
|
|
|
|
next_ = iter_->next();
|
|
|
|
|
return next_ != nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-28 17:54:21 +02:00
|
|
|
Port *
|
|
|
|
|
ConcretePortMemberIterator1::next()
|
|
|
|
|
{
|
2023-11-25 22:13:59 +01:00
|
|
|
ConcretePort *next = next_;
|
|
|
|
|
next_ = nullptr;
|
|
|
|
|
return reinterpret_cast<Port*>(next);
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-19 19:23:45 +01:00
|
|
|
ObjectId
|
|
|
|
|
ConcreteNetwork::id(const Instance *instance) const
|
|
|
|
|
{
|
|
|
|
|
const ConcreteInstance *inst =
|
|
|
|
|
reinterpret_cast<const ConcreteInstance*>(instance);
|
|
|
|
|
return inst->id();
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-13 01:00:47 +01:00
|
|
|
string
|
2024-03-09 06:56:25 +01:00
|
|
|
ConcreteNetwork::getAttribute(const Instance *inst,
|
2024-03-13 01:00:47 +01:00
|
|
|
const string &key) const
|
2022-07-11 17:49:12 +02:00
|
|
|
{
|
|
|
|
|
const ConcreteInstance *cinst = reinterpret_cast<const ConcreteInstance*>(inst);
|
|
|
|
|
return cinst->getAttribute(key);
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-18 18:37:10 +02:00
|
|
|
const AttributeMap &
|
|
|
|
|
ConcreteNetwork::attributeMap(const Instance *inst) const
|
|
|
|
|
{
|
|
|
|
|
const ConcreteInstance *cinst = reinterpret_cast<const ConcreteInstance*>(inst);
|
|
|
|
|
return cinst->attributeMap();
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-28 17:54:21 +02:00
|
|
|
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,
|
2023-01-19 19:23:45 +01:00
|
|
|
NetSeq &matches) const
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
|
|
|
|
const ConcreteInstance *inst =
|
|
|
|
|
reinterpret_cast<const ConcreteInstance*>(instance);
|
2023-01-19 19:23:45 +01:00
|
|
|
return inst->findNetsMatching(pattern, matches);
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2023-01-19 19:23:45 +01:00
|
|
|
ObjectId
|
|
|
|
|
ConcreteNetwork::id(const Pin *pin) const
|
|
|
|
|
{
|
|
|
|
|
const ConcretePin *cpin = reinterpret_cast<const ConcretePin*>(pin);
|
|
|
|
|
return cpin->id();
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-28 17:54:21 +02:00
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-11 16:28:42 +01:00
|
|
|
VertexId
|
2019-11-11 17:38:25 +01:00
|
|
|
ConcreteNetwork::vertexId(const Pin *pin) const
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
|
|
|
|
const ConcretePin *cpin = reinterpret_cast<const ConcretePin*>(pin);
|
2019-11-11 16:28:42 +01:00
|
|
|
return cpin->vertexId();
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2019-11-11 17:38:25 +01:00
|
|
|
ConcreteNetwork::setVertexId(Pin *pin,
|
|
|
|
|
VertexId id)
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
|
|
|
|
ConcretePin *cpin = reinterpret_cast<ConcretePin*>(pin);
|
2019-11-11 16:28:42 +01:00
|
|
|
cpin->setVertexId(id);
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2023-01-19 19:23:45 +01:00
|
|
|
ObjectId
|
|
|
|
|
ConcreteNetwork::id(const Term *term) const
|
|
|
|
|
{
|
|
|
|
|
const ConcreteTerm *cterm = reinterpret_cast<const ConcreteTerm*>(term);
|
|
|
|
|
return cterm->id();
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-28 17:54:21 +02:00
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-19 19:23:45 +01:00
|
|
|
ObjectId
|
|
|
|
|
ConcreteNetwork::id(const Net *net) const
|
|
|
|
|
{
|
|
|
|
|
const ConcreteNet *cnet = reinterpret_cast<const ConcreteNet*>(net);
|
|
|
|
|
return cnet->id();
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-28 17:54:21 +02:00
|
|
|
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
|
|
|
|
|
{
|
2019-03-13 01:25:53 +01:00
|
|
|
return constant_nets_[int(LogicValue::one)].hasKey(const_cast<Net*>(net));
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
ConcreteNetwork::isGround(const Net *net) const
|
|
|
|
|
{
|
2019-03-13 01:25:53 +01:00
|
|
|
return constant_nets_[int(LogicValue::zero)].hasKey(const_cast<Net*>(net));
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
2020-03-16 04:05:30 +01:00
|
|
|
clearNetDrvrPinMap();
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
2023-01-19 19:23:45 +01:00
|
|
|
ConcreteInstance *inst = new ConcreteInstance(name, cell, cparent);
|
2018-09-28 17:54:21 +02:00
|
|
|
if (parent)
|
|
|
|
|
cparent->addChild(inst);
|
|
|
|
|
return reinterpret_cast<Instance*>(inst);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2019-01-20 18:44:24 +01:00
|
|
|
ConcreteNetwork::makePins(Instance *inst)
|
|
|
|
|
{
|
|
|
|
|
CellPortBitIterator *port_iterator = portBitIterator(cell(inst));
|
|
|
|
|
while (port_iterator->hasNext()) {
|
|
|
|
|
Port *port = port_iterator->next();
|
2019-03-13 01:25:53 +01:00
|
|
|
makePin(inst, port, nullptr);
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
2019-01-20 18:44:24 +01:00
|
|
|
delete port_iterator;
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2019-04-11 05:36:48 +02:00
|
|
|
ConcreteNetwork::replaceCell(Instance *inst,
|
2019-06-14 21:05:34 +02:00
|
|
|
Cell *cell)
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
2019-06-14 21:05:34 +02:00
|
|
|
ConcreteCell *ccell = reinterpret_cast<ConcreteCell*>(cell);
|
2019-06-21 21:02:35 +02:00
|
|
|
int port_count = ccell->portBitCount();
|
|
|
|
|
ConcreteInstance *cinst = reinterpret_cast<ConcreteInstance*>(inst);
|
2023-06-28 19:01:39 +02:00
|
|
|
ConcretePinSeq &pins = cinst->pins_;
|
|
|
|
|
ConcretePinSeq rpins(port_count);
|
2019-07-07 18:58:47 +02:00
|
|
|
for (int i = 0; i < port_count; i++)
|
|
|
|
|
rpins[i] = nullptr;
|
2019-06-21 21:02:35 +02:00
|
|
|
for (int i = 0; i < port_count; i++) {
|
|
|
|
|
ConcretePin *cpin = pins[i];
|
2019-06-21 21:50:57 +02:00
|
|
|
if (cpin) {
|
|
|
|
|
ConcretePort *pin_cport = reinterpret_cast<ConcretePort*>(cpin->port());
|
|
|
|
|
ConcretePort *cport = ccell->findPort(pin_cport->name());
|
2022-01-15 20:51:05 +01:00
|
|
|
if (cport) {
|
|
|
|
|
rpins[cport->pinIndex()] = cpin;
|
|
|
|
|
cpin->port_ = cport;
|
2023-01-19 19:23:45 +01:00
|
|
|
cpin->id_ = ConcreteNetwork::nextObjectId();
|
2022-01-15 20:51:05 +01:00
|
|
|
}
|
2019-06-21 21:50:57 +02:00
|
|
|
}
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
2019-06-21 21:02:35 +02:00
|
|
|
cinst->pins_ = rpins;
|
2019-06-14 21:05:34 +02:00
|
|
|
cinst->setCell(ccell);
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-03 17:07:00 +02:00
|
|
|
Pin *
|
|
|
|
|
ConcreteNetwork::connect(Instance *inst,
|
|
|
|
|
LibertyPort *port,
|
|
|
|
|
Net *net)
|
|
|
|
|
{
|
|
|
|
|
return connect(inst, reinterpret_cast<Port*>(port), net);
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-11 17:49:12 +02:00
|
|
|
void
|
|
|
|
|
ConcreteNetwork::setAttribute(Instance *inst,
|
2024-03-13 01:00:47 +01:00
|
|
|
const string &key,
|
|
|
|
|
const string &value)
|
2022-07-11 17:49:12 +02:00
|
|
|
{
|
|
|
|
|
ConcreteInstance *cinst = reinterpret_cast<ConcreteInstance*>(inst);
|
|
|
|
|
cinst->setAttribute(key, value);
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-28 17:54:21 +02:00
|
|
|
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);
|
|
|
|
|
}
|
2019-05-20 01:06:06 +02:00
|
|
|
if (inst == top_instance_) {
|
2019-01-17 00:37:31 +01:00
|
|
|
// makeTerm
|
|
|
|
|
ConcreteTerm *cterm = new ConcreteTerm(cpin, cnet);
|
2023-06-28 19:01:39 +02:00
|
|
|
if (cnet)
|
|
|
|
|
cnet->addTerm(cterm);
|
2019-01-17 00:37:31 +01:00
|
|
|
cpin->term_ = cterm;
|
2019-03-13 01:25:53 +01:00
|
|
|
cpin->net_ = nullptr;
|
2019-01-17 00:37:31 +01:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
cpin->net_ = cnet;
|
2018-09-28 17:54:21 +02:00
|
|
|
connectNetPin(cnet, cpin);
|
2019-01-17 00:37:31 +01:00
|
|
|
}
|
2018-09-28 17:54:21 +02:00
|
|
|
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)) {
|
2019-03-13 01:25:53 +01:00
|
|
|
if (cnet->terms_ == nullptr) {
|
2018-09-28 17:54:21 +02:00
|
|
|
Net *net = reinterpret_cast<Net*>(cnet);
|
|
|
|
|
PinSet *drvrs = net_drvr_pin_map_.findKey(net);
|
|
|
|
|
if (drvrs)
|
|
|
|
|
drvrs->insert(pin);
|
|
|
|
|
}
|
|
|
|
|
else
|
2020-03-16 04:05:30 +01:00
|
|
|
clearNetDrvrPinMap();
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ConcreteNetwork::disconnectPin(Pin *pin)
|
|
|
|
|
{
|
|
|
|
|
ConcretePin *cpin = reinterpret_cast<ConcretePin*>(pin);
|
2019-05-20 01:06:06 +02:00
|
|
|
if (reinterpret_cast<Instance*>(cpin->instance()) == top_instance_) {
|
2018-09-28 17:54:21 +02:00
|
|
|
ConcreteTerm *cterm = cpin->term_;
|
2019-01-17 00:37:31 +01:00
|
|
|
if (cterm) {
|
|
|
|
|
ConcreteNet *cnet = cterm->net_;
|
|
|
|
|
if (cnet) {
|
|
|
|
|
cnet->deleteTerm(cterm);
|
2020-03-16 04:05:30 +01:00
|
|
|
clearNetDrvrPinMap();
|
2019-01-17 00:37:31 +01:00
|
|
|
}
|
2019-03-13 01:25:53 +01:00
|
|
|
cpin->term_ = nullptr;
|
2019-01-17 00:37:31 +01:00
|
|
|
delete cterm;
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
ConcreteNet *cnet = cpin->net();
|
|
|
|
|
if (cnet)
|
|
|
|
|
disconnectNetPin(cnet, cpin);
|
2019-03-13 01:25:53 +01:00
|
|
|
cpin->net_ = nullptr;
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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.
|
2019-03-13 01:25:53 +01:00
|
|
|
if (cnet->terms_ == nullptr) {
|
2018-09-28 17:54:21 +02:00
|
|
|
Net *net = reinterpret_cast<Net*>(cnet);
|
|
|
|
|
PinSet *drvrs = net_drvr_pin_map_.findKey(net);
|
|
|
|
|
if (drvrs)
|
2019-04-11 05:36:48 +02:00
|
|
|
drvrs->erase(pin);
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
else
|
2020-03-16 04:05:30 +01:00
|
|
|
clearNetDrvrPinMap();
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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.
|
2019-03-13 01:25:53 +01:00
|
|
|
pin->net_ = nullptr;
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
2019-04-11 05:36:48 +02:00
|
|
|
constant_nets_[int(LogicValue::zero)].erase(net);
|
|
|
|
|
constant_nets_[int(LogicValue::one)].erase(net);
|
2018-09-28 17:54:21 +02:00
|
|
|
PinSet *drvrs = net_drvr_pin_map_.findKey(net);
|
|
|
|
|
if (drvrs) {
|
|
|
|
|
delete drvrs;
|
2019-04-11 05:36:48 +02:00
|
|
|
net_drvr_pin_map_.erase(net);
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ConcreteInstance *cinst =
|
|
|
|
|
reinterpret_cast<ConcreteInstance*>(cnet->instance());
|
|
|
|
|
cinst->deleteNet(cnet);
|
|
|
|
|
delete cnet;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ConcreteNetwork::clearConstantNets()
|
|
|
|
|
{
|
2019-03-13 01:25:53 +01:00
|
|
|
constant_nets_[int(LogicValue::zero)].clear();
|
|
|
|
|
constant_nets_[int(LogicValue::one)].clear();
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ConcreteNetwork::addConstantNet(Net *net,
|
2019-03-13 01:25:53 +01:00
|
|
|
LogicValue value)
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
2022-01-15 20:51:05 +01:00
|
|
|
if (value == LogicValue::zero
|
|
|
|
|
|| value == LogicValue::one)
|
|
|
|
|
constant_nets_[int(value)].insert(net);
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ConstantPinIterator *
|
|
|
|
|
ConcreteNetwork::constantPinIterator()
|
|
|
|
|
{
|
2019-03-13 01:25:53 +01:00
|
|
|
return new NetworkConstantPinIterator(this,
|
|
|
|
|
constant_nets_[int(LogicValue::zero)],
|
|
|
|
|
constant_nets_[int(LogicValue::one)]);
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
// Optimized version of Network::visitConnectedPins.
|
|
|
|
|
void
|
|
|
|
|
ConcreteNetwork::visitConnectedPins(const Net *net,
|
|
|
|
|
PinVisitor &visitor,
|
2023-01-19 19:23:45 +01:00
|
|
|
NetSet &visited_nets) const
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2023-01-19 19:23:45 +01:00
|
|
|
ConcreteInstance::ConcreteInstance(const char *name,
|
|
|
|
|
ConcreteCell *cell,
|
|
|
|
|
ConcreteInstance *parent) :
|
2019-05-20 01:06:06 +02:00
|
|
|
name_(stringCopy(name)),
|
2023-01-19 19:23:45 +01:00
|
|
|
id_(ConcreteNetwork::nextObjectId()),
|
|
|
|
|
cell_(cell),
|
2018-09-28 17:54:21 +02:00
|
|
|
parent_(parent),
|
2019-03-13 01:25:53 +01:00
|
|
|
children_(nullptr),
|
|
|
|
|
nets_(nullptr)
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
2019-05-20 01:06:06 +02:00
|
|
|
initPins();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ConcreteInstance::initPins()
|
|
|
|
|
{
|
2023-06-28 19:01:39 +02:00
|
|
|
ConcreteCell *ccell = reinterpret_cast<ConcreteCell*>(cell_);
|
|
|
|
|
pins_.resize(ccell->portBitCount());
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ConcreteInstance::~ConcreteInstance()
|
|
|
|
|
{
|
|
|
|
|
stringDelete(name_);
|
|
|
|
|
delete children_;
|
|
|
|
|
delete nets_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Instance *
|
|
|
|
|
ConcreteInstance::findChild(const char *name) const
|
|
|
|
|
{
|
|
|
|
|
if (children_)
|
|
|
|
|
return reinterpret_cast<Instance*>(children_->findKey(name));
|
|
|
|
|
else
|
2019-03-13 01:25:53 +01:00
|
|
|
return nullptr;
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
2019-03-13 01:25:53 +01:00
|
|
|
return nullptr;
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ConcretePin *
|
|
|
|
|
ConcreteInstance::findPin(const Port *port) const
|
|
|
|
|
{
|
|
|
|
|
const ConcretePort *cport = reinterpret_cast<const ConcretePort*>(port);
|
2023-06-28 19:01:39 +02:00
|
|
|
size_t port_index = cport->pinIndex();
|
|
|
|
|
if (port_index < pins_.size())
|
|
|
|
|
return pins_[port_index];
|
|
|
|
|
else
|
|
|
|
|
return nullptr;
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ConcreteNet *
|
|
|
|
|
ConcreteInstance::findNet(const char *net_name) const
|
|
|
|
|
{
|
2019-03-13 01:25:53 +01:00
|
|
|
ConcreteNet *net = nullptr;
|
2018-09-28 17:54:21 +02:00
|
|
|
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,
|
2023-01-19 19:23:45 +01:00
|
|
|
NetSeq &matches) const
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
|
|
|
|
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))
|
2023-01-19 19:23:45 +01:00
|
|
|
matches.push_back(reinterpret_cast<Net*>(cnet));
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
ConcreteNet *cnet = findNet(pattern->pattern());
|
|
|
|
|
if (cnet)
|
2023-01-19 19:23:45 +01:00
|
|
|
matches.push_back(reinterpret_cast<Net*>(cnet));
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
InstanceNetIterator *
|
|
|
|
|
ConcreteInstance::netIterator() const
|
|
|
|
|
{
|
|
|
|
|
return reinterpret_cast<InstanceNetIterator*>
|
|
|
|
|
(new ConcreteInstanceNetIterator(nets_));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
InstanceChildIterator *
|
|
|
|
|
ConcreteInstance::childIterator() const
|
|
|
|
|
{
|
|
|
|
|
return new ConcreteInstanceChildIterator(children_);
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-11 17:49:12 +02:00
|
|
|
void
|
2024-03-13 01:00:47 +01:00
|
|
|
ConcreteInstance::setAttribute(const string &key,
|
|
|
|
|
const string &value)
|
2022-07-11 17:49:12 +02:00
|
|
|
{
|
2024-11-14 03:25:26 +01:00
|
|
|
attribute_map_[key] = value;
|
2022-07-11 17:49:12 +02:00
|
|
|
}
|
|
|
|
|
|
2024-03-13 01:00:47 +01:00
|
|
|
string
|
|
|
|
|
ConcreteInstance::getAttribute(const string &key) const
|
2022-07-11 17:49:12 +02:00
|
|
|
{
|
2024-11-14 03:25:26 +01:00
|
|
|
const auto &itr = attribute_map_.find(key);
|
|
|
|
|
if (itr != attribute_map_.end())
|
|
|
|
|
return itr->second;
|
2024-03-12 21:08:54 +01:00
|
|
|
return "";
|
2022-07-11 17:49:12 +02:00
|
|
|
}
|
|
|
|
|
|
2018-09-28 17:54:21 +02:00
|
|
|
void
|
|
|
|
|
ConcreteInstance::addChild(ConcreteInstance *child)
|
|
|
|
|
{
|
2019-03-13 01:25:53 +01:00
|
|
|
if (children_ == nullptr)
|
2018-09-28 17:54:21 +02:00
|
|
|
children_ = new ConcreteInstanceChildMap;
|
|
|
|
|
(*children_)[child->name()] = child;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ConcreteInstance::deleteChild(ConcreteInstance *child)
|
|
|
|
|
{
|
2019-04-11 05:36:48 +02:00
|
|
|
children_->erase(child->name());
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ConcreteInstance::addPin(ConcretePin *pin)
|
|
|
|
|
{
|
|
|
|
|
ConcretePort *cport = reinterpret_cast<ConcretePort *>(pin->port());
|
2023-06-28 19:01:39 +02:00
|
|
|
size_t pin_index = cport->pinIndex();
|
|
|
|
|
if (pin_index >= pins_.size())
|
|
|
|
|
pins_.resize(pin_index + 1);
|
|
|
|
|
pins_[pin_index] = pin;
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ConcreteInstance::deletePin(ConcretePin *pin)
|
|
|
|
|
{
|
|
|
|
|
ConcretePort *cport = reinterpret_cast<ConcretePort *>(pin->port());
|
2019-03-13 01:25:53 +01:00
|
|
|
pins_[cport->pinIndex()] = nullptr;
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ConcreteInstance::addNet(ConcreteNet *net)
|
|
|
|
|
{
|
2019-03-13 01:25:53 +01:00
|
|
|
if (nets_ == nullptr)
|
2018-09-28 17:54:21 +02:00
|
|
|
nets_ = new ConcreteInstanceNetMap;
|
|
|
|
|
(*nets_)[net->name()] = net;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ConcreteInstance::addNet(const char *name,
|
|
|
|
|
ConcreteNet *net)
|
|
|
|
|
{
|
2019-03-13 01:25:53 +01:00
|
|
|
if (nets_ == nullptr)
|
2018-09-28 17:54:21 +02:00
|
|
|
nets_ = new ConcreteInstanceNetMap;
|
|
|
|
|
(*nets_)[name] = net;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ConcreteInstance::deleteNet(ConcreteNet *net)
|
|
|
|
|
{
|
2019-04-11 05:36:48 +02:00
|
|
|
nets_->erase(net->name());
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2019-05-20 19:35:22 +02:00
|
|
|
ConcreteInstance::setCell(ConcreteCell *cell)
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
|
|
|
|
cell_ = cell;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
ConcretePin::ConcretePin(ConcreteInstance *instance,
|
|
|
|
|
ConcretePort *port,
|
|
|
|
|
ConcreteNet *net) :
|
|
|
|
|
instance_(instance),
|
|
|
|
|
port_(port),
|
|
|
|
|
net_(net),
|
2019-03-13 01:25:53 +01:00
|
|
|
term_(nullptr),
|
2023-01-19 19:23:45 +01:00
|
|
|
id_(ConcreteNetwork::nextObjectId()),
|
2019-03-13 01:25:53 +01:00
|
|
|
net_next_(nullptr),
|
|
|
|
|
net_prev_(nullptr),
|
2019-11-11 16:28:42 +01:00
|
|
|
vertex_id_(vertex_id_null)
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char *
|
|
|
|
|
ConcretePin::name() const
|
|
|
|
|
{
|
|
|
|
|
return port_->name();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2019-11-11 16:28:42 +01:00
|
|
|
ConcretePin::setVertexId(VertexId id)
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
2019-11-11 16:28:42 +01:00
|
|
|
vertex_id_ = id;
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
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),
|
2023-01-19 19:23:45 +01:00
|
|
|
id_(ConcreteNetwork::nextObjectId()),
|
2019-03-13 01:25:53 +01:00
|
|
|
net_next_(nullptr)
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
ConcreteNet::ConcreteNet(const char *name,
|
|
|
|
|
ConcreteInstance *instance) :
|
|
|
|
|
name_(stringCopy(name)),
|
2023-01-19 19:23:45 +01:00
|
|
|
id_(ConcreteNetwork::nextObjectId()),
|
2018-09-28 17:54:21 +02:00
|
|
|
instance_(instance),
|
2019-03-13 01:25:53 +01:00
|
|
|
pins_(nullptr),
|
|
|
|
|
terms_(nullptr),
|
|
|
|
|
merged_into_(nullptr)
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
2019-03-13 01:25:53 +01:00
|
|
|
pins_ = nullptr;
|
2018-09-28 17:54:21 +02:00
|
|
|
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;
|
|
|
|
|
}
|
2019-03-13 01:25:53 +01:00
|
|
|
terms_ = nullptr;
|
2018-09-28 17:54:21 +02:00
|
|
|
// 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_;
|
2019-03-13 01:25:53 +01:00
|
|
|
pin->net_prev_ = nullptr;
|
2018-09-28 17:54:21 +02:00
|
|
|
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)
|
|
|
|
|
{
|
2019-03-13 01:25:53 +01:00
|
|
|
ConcreteTerm *net_prev_term = nullptr;
|
2018-09-28 17:54:21 +02:00
|
|
|
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:
|
|
|
|
|
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();
|
2020-03-16 04:05:30 +01:00
|
|
|
clearNetDrvrPinMap();
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2019-05-20 01:06:06 +02:00
|
|
|
ConcreteNetwork::setTopInstance(Instance *top_inst)
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
|
|
|
|
if (top_instance_) {
|
2019-05-20 01:06:06 +02:00
|
|
|
deleteInstance(top_instance_);
|
2018-09-28 17:54:21 +02:00
|
|
|
clearConstantNets();
|
2020-03-16 04:05:30 +01:00
|
|
|
clearNetDrvrPinMap();
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
top_instance_ = top_inst;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2025-01-22 02:35:21 +01:00
|
|
|
ConcreteNetwork::setLinkFunc(LinkNetworkFunc link)
|
2018-09-28 17:54:21 +02:00
|
|
|
{
|
|
|
|
|
link_func_ = link;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
ConcreteNetwork::linkNetwork(const char *top_cell_name,
|
|
|
|
|
bool make_black_boxes,
|
|
|
|
|
Report *report)
|
|
|
|
|
{
|
|
|
|
|
if (link_func_) {
|
|
|
|
|
clearConstantNets();
|
|
|
|
|
deleteTopInstance();
|
2025-01-22 02:35:21 +01:00
|
|
|
top_instance_ = link_func_(top_cell_name, make_black_boxes);
|
2022-10-05 05:50:27 +02:00
|
|
|
if (top_instance_)
|
|
|
|
|
checkNetworkLibertyCorners();
|
2019-06-27 01:01:58 +02:00
|
|
|
return top_instance_ != nullptr;
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
else {
|
2024-01-08 03:23:53 +01:00
|
|
|
report->error(1000, "cell type %s can not be linked.", top_cell_name);
|
2018-09-28 17:54:21 +02:00
|
|
|
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.
|
2019-03-13 01:25:53 +01:00
|
|
|
Instance *top_instance = network->makeInstance(top_cell, "", nullptr);
|
2018-09-28 17:54:21 +02:00
|
|
|
ConcreteBindingTbl bindings(network);
|
2019-03-13 01:25:53 +01:00
|
|
|
makeClonePins(view, top_instance, view, &bindings, nullptr, nullptr, network);
|
2018-09-28 17:54:21 +02:00
|
|
|
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;
|
|
|
|
|
}
|
2019-03-13 01:25:53 +01:00
|
|
|
return nullptr;
|
2018-09-28 17:54:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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))
|
2019-03-13 01:25:53 +01:00
|
|
|
makeClonePins(proto, clone, nullptr, nullptr, parent, parent_bindings, network);
|
2018-09-28 17:54:21 +02:00
|
|
|
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);
|
2019-03-13 01:25:53 +01:00
|
|
|
Net *clone_net = nullptr;
|
2018-09-28 17:54:21 +02:00
|
|
|
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);
|
2019-03-13 01:25:53 +01:00
|
|
|
Net *clone_child_net = nullptr;
|
2018-09-28 17:54:21 +02:00
|
|
|
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);
|
2019-03-13 01:25:53 +01:00
|
|
|
if (net == nullptr) {
|
2018-09-28 17:54:21 +02:00
|
|
|
net = network_->makeNet(network_->name(proto_net), parent);
|
|
|
|
|
map_[proto_net] = net;
|
|
|
|
|
}
|
|
|
|
|
return net;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace
|