Files
OpenSTA/network/ConcreteLibrary.cc
T

618 lines
14 KiB
C++
Raw Normal View History

2018-09-28 08:54:21 -07:00
// OpenSTA, Static Timing Analyzer
2026-03-10 13:21:17 -07:00
// Copyright (c) 2026, Parallax Software, Inc.
2018-09-28 08:54:21 -07: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 10:17:08 -07:00
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2018-09-28 08:54:21 -07:00
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
2022-01-04 10:17:08 -07:00
// along with this program. If not, see <https://www.gnu.org/licenses/>.
2025-01-21 18:54:33 -07: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 08:54:21 -07:00
2020-04-05 14:53:44 -07:00
#include "ConcreteLibrary.hh"
2020-04-05 11:35:51 -07:00
2026-03-02 12:13:13 -08:00
#include <cmath>
2023-06-15 08:59:56 -07:00
#include <cstdlib>
2023-11-25 13:13:59 -08:00
#include <limits>
2020-04-05 11:35:51 -07:00
2026-04-15 09:38:10 -07:00
#include "ConcreteNetwork.hh"
2026-01-03 16:59:35 -08:00
#include "ContainerHelpers.hh"
2026-04-15 09:38:10 -07:00
#include "ParseBus.hh"
2020-04-05 14:53:44 -07:00
#include "PatternMatch.hh"
#include "PortDirection.hh"
2018-09-28 08:54:21 -07:00
namespace sta {
2019-08-13 21:34:35 -07:00
static constexpr char escape_ = '\\';
2026-04-02 19:22:08 -07:00
ConcreteLibrary::ConcreteLibrary(std::string_view name,
std::string_view filename,
2026-01-03 16:59:35 -08:00
bool is_liberty) :
2026-04-02 19:22:08 -07:00
name_(name),
filename_(filename),
2026-06-26 21:11:13 -07:00
id_(ConcreteNetwork::nextObjectId()),
2026-04-15 09:38:10 -07:00
is_liberty_(is_liberty)
2018-09-28 08:54:21 -07:00
{
}
ConcreteLibrary::~ConcreteLibrary()
{
2026-01-03 16:59:35 -08:00
deleteContents(cell_map_);
2018-09-28 08:54:21 -07:00
}
ConcreteCell *
2026-03-28 19:13:35 -07:00
ConcreteLibrary::makeCell(std::string_view name,
2026-01-03 16:59:35 -08:00
bool is_leaf,
2026-03-28 19:13:35 -07:00
std::string_view filename)
2018-09-28 08:54:21 -07:00
{
2023-01-19 11:23:45 -07:00
ConcreteCell *cell = new ConcreteCell(name, filename, is_leaf, this);
2018-09-28 08:54:21 -07:00
addCell(cell);
return cell;
}
void
ConcreteLibrary::addCell(ConcreteCell *cell)
{
cell_map_[cell->name()] = cell;
}
void
2026-03-28 19:13:35 -07:00
ConcreteLibrary::removeCell(ConcreteCell *cell)
2018-09-28 08:54:21 -07:00
{
cell_map_.erase(cell->name());
2018-09-28 08:54:21 -07:00
}
void
ConcreteLibrary::deleteCell(ConcreteCell *cell)
{
cell_map_.erase(cell->name());
2018-09-28 08:54:21 -07:00
delete cell;
}
ConcreteLibraryCellIterator *
ConcreteLibrary::cellIterator() const
{
return new ConcreteLibraryCellIterator(cell_map_);
}
ConcreteCell *
2026-03-28 19:13:35 -07:00
ConcreteLibrary::findCell(std::string_view name) const
2018-09-28 08:54:21 -07:00
{
2026-03-28 19:13:35 -07:00
return findStringKey(cell_map_, name);
2018-09-28 08:54:21 -07:00
}
2023-01-19 11:23:45 -07:00
CellSeq
ConcreteLibrary::findCellsMatching(const PatternMatch *pattern) const
2018-09-28 08:54:21 -07:00
{
2023-01-19 11:23:45 -07:00
CellSeq matches;
2026-01-03 16:59:35 -08:00
for (auto [name, cell] : cell_map_) {
if (pattern->match(name))
2023-01-19 11:23:45 -07:00
matches.push_back(reinterpret_cast<Cell*>(cell));
2018-09-28 08:54:21 -07:00
}
2023-01-19 11:23:45 -07:00
return matches;
2018-09-28 08:54:21 -07:00
}
void
2019-01-16 15:37:31 -08:00
ConcreteLibrary::setBusBrkts(char left,
2026-01-03 16:59:35 -08:00
char right)
2018-09-28 08:54:21 -07:00
{
bus_brkt_left_ = left;
bus_brkt_right_ = right;
}
////////////////////////////////////////////////////////////////
2026-03-28 19:13:35 -07:00
ConcreteCell::ConcreteCell(std::string_view name,
std::string_view filename,
2026-01-03 16:59:35 -08:00
bool is_leaf,
2023-01-19 11:23:45 -07:00
ConcreteLibrary *library) :
2025-03-30 15:27:53 -07:00
name_(name),
2023-01-19 11:23:45 -07:00
id_(ConcreteNetwork::nextObjectId()),
2026-03-28 19:13:35 -07:00
filename_(filename),
2023-01-19 11:23:45 -07:00
library_(library),
2018-09-28 08:54:21 -07:00
is_leaf_(is_leaf)
{
}
ConcreteCell::~ConcreteCell()
{
2026-01-03 16:59:35 -08:00
deleteContents(ports_);
2018-09-28 08:54:21 -07:00
}
void
2026-03-28 19:13:35 -07:00
ConcreteCell::setName(std::string_view name)
2018-09-28 08:54:21 -07:00
{
2026-03-28 19:13:35 -07:00
library_->removeCell(this);
2025-03-30 15:27:53 -07:00
name_ = name;
2026-03-28 19:13:35 -07:00
library_->addCell(this);
2018-09-28 08:54:21 -07:00
}
void
ConcreteCell::setLibertyCell(LibertyCell *cell)
{
liberty_cell_ = cell;
}
2019-11-13 14:58:38 -07:00
void
ConcreteCell::setExtCell(void *ext_cell)
{
ext_cell_ = ext_cell;
}
2018-09-28 08:54:21 -07:00
ConcretePort *
2026-03-28 19:13:35 -07:00
ConcreteCell::makePort(std::string_view name)
2018-09-28 08:54:21 -07:00
{
2026-03-28 19:13:35 -07:00
ConcretePort *port = new ConcretePort(name, false, -1, -1,
false, nullptr, this);
2018-09-28 08:54:21 -07:00
addPort(port);
return port;
}
ConcretePort *
2026-03-28 19:13:35 -07:00
ConcreteCell::makeBundlePort(std::string_view name,
2026-01-03 16:59:35 -08:00
ConcretePortSeq *members)
2018-09-28 08:54:21 -07:00
{
2026-03-28 19:13:35 -07:00
ConcretePort *port = new ConcretePort(name, false, -1, -1, true,
members, this);
2018-09-28 08:54:21 -07:00
addPort(port);
for (ConcretePort *member : *members)
member->setBundlePort(port);
2018-09-28 08:54:21 -07:00
return port;
}
ConcretePort *
2026-03-28 19:13:35 -07:00
ConcreteCell::makeBusPort(std::string_view name,
2026-01-03 16:59:35 -08:00
int from_index,
int to_index)
2018-09-28 08:54:21 -07:00
{
2023-01-19 11:23:45 -07:00
ConcretePort *port = new ConcretePort(name, true, from_index, to_index,
2026-01-03 16:59:35 -08:00
false, new ConcretePortSeq, this);
2018-09-28 08:54:21 -07:00
addPort(port);
2026-03-28 19:13:35 -07:00
makeBusPortBits(port, port->name(), from_index, to_index);
2018-09-28 08:54:21 -07:00
return port;
}
ConcretePort *
2026-03-28 19:13:35 -07:00
ConcreteCell::makeBusPort(std::string_view name,
2026-01-03 16:59:35 -08:00
int from_index,
int to_index,
ConcretePortSeq *members)
2018-09-28 08:54:21 -07:00
{
2023-01-19 11:23:45 -07:00
ConcretePort *port = new ConcretePort(name, true, from_index, to_index,
2026-01-03 16:59:35 -08:00
false, members, this);
2018-09-28 08:54:21 -07:00
addPort(port);
return port;
}
void
2019-01-16 15:37:31 -08:00
ConcreteCell::makeBusPortBits(ConcretePort *bus_port,
2026-03-28 19:13:35 -07:00
std::string_view bus_name,
2026-01-03 16:59:35 -08:00
int from_index,
int to_index)
2018-09-28 08:54:21 -07:00
{
if (from_index < to_index) {
for (int index = from_index; index <= to_index; index++)
2026-03-28 19:13:35 -07:00
makeBusPortBit(bus_port, bus_name, index);
2018-09-28 08:54:21 -07:00
}
else {
for (int index = from_index; index >= to_index; index--)
2026-03-28 19:13:35 -07:00
makeBusPortBit(bus_port, bus_name, index);
2018-09-28 08:54:21 -07:00
}
}
void
2019-01-16 15:37:31 -08:00
ConcreteCell::makeBusPortBit(ConcretePort *bus_port,
2026-03-28 19:13:35 -07:00
std::string_view bus_name,
2026-01-03 16:59:35 -08:00
int bit_index)
2018-09-28 08:54:21 -07:00
{
2026-03-28 19:13:35 -07:00
std::string bit_name;
bit_name.append(bus_name);
bit_name += library_->busBrktLeft();
bit_name += std::to_string(bit_index);
bit_name += library_->busBrktRight();
ConcretePort *port = makePort(bit_name, bit_index);
2018-09-28 08:54:21 -07:00
bus_port->addPortBit(port);
addPortBit(port);
}
ConcretePort *
2026-04-15 09:38:10 -07:00
ConcreteCell::makePort(std::string_view bit_name,
2026-01-03 16:59:35 -08:00
int bit_index)
2018-09-28 08:54:21 -07:00
{
2026-03-28 19:13:35 -07:00
ConcretePort *port = new ConcretePort(bit_name, false,
bit_index, bit_index, false,
nullptr, this);
2018-09-28 08:54:21 -07:00
addPortBit(port);
return port;
}
void
ConcreteCell::addPortBit(ConcretePort *port)
{
port_map_[port->name()] = port;
port->setPinIndex(port_bit_count_++);
}
void
ConcreteCell::addPort(ConcretePort *port)
{
port_map_[port->name()] = port;
ports_.push_back(port);
if (!port->hasMembers())
port->setPinIndex(port_bit_count_++);
}
void
ConcreteCell::setIsLeaf(bool is_leaf)
{
is_leaf_ = is_leaf;
}
2022-07-11 08:49:12 -07:00
void
2026-03-28 19:13:35 -07:00
ConcreteCell::setAttribute(std::string_view key,
std::string_view value)
2022-07-11 08:49:12 -07:00
{
2026-03-28 19:13:35 -07:00
attribute_map_[std::string(key)] = value;
2022-07-11 08:49:12 -07:00
}
2026-03-02 12:13:13 -08:00
std::string
2026-03-28 19:13:35 -07:00
ConcreteCell::getAttribute(std::string_view key) const
2022-07-11 08:49:12 -07:00
{
2024-11-13 18:25:26 -08:00
const auto &itr = attribute_map_.find(key);
if (itr != attribute_map_.end())
return itr->second;
2024-03-12 20:08:54 +00:00
return "";
2022-07-11 08:49:12 -07:00
}
2018-09-28 08:54:21 -07:00
ConcretePort *
2026-03-28 19:13:35 -07:00
ConcreteCell::findPort(std::string_view name) const
2018-09-28 08:54:21 -07:00
{
2026-03-28 19:13:35 -07:00
return findStringKey(port_map_, name);
2018-09-28 08:54:21 -07:00
}
size_t
ConcreteCell::portCount() const
{
return ports_.size();
}
ConcreteCellPortIterator *
ConcreteCell::portIterator() const
{
return new ConcreteCellPortIterator(ports_);
}
ConcreteCellPortBitIterator *
ConcreteCell::portBitIterator() const
{
return new ConcreteCellPortBitIterator(this);
}
////////////////////////////////////////////////////////////////
2023-11-25 13:13:59 -08:00
// Helper class for ConcreteCell::groupBusPorts.
2018-09-28 08:54:21 -07:00
class BusPort
{
public:
2023-11-25 13:13:59 -08:00
BusPort();
void addBusBit(ConcretePort *port,
int index);
2018-09-28 08:54:21 -07:00
int from() const { return from_; }
int to() const { return to_; }
2023-11-25 13:13:59 -08:00
ConcretePortSeq &members() { return members_; }
2024-06-27 13:57:58 -07:00
const ConcretePortSeq &members() const { return members_; }
2023-11-25 13:13:59 -08:00
void setDirection(PortDirection *direction);
2024-06-27 13:57:58 -07:00
PortDirection *direction() const { return direction_; }
2018-09-28 08:54:21 -07:00
private:
int from_;
int to_;
PortDirection *direction_;
2023-11-25 13:13:59 -08:00
ConcretePortSeq members_;
2018-09-28 08:54:21 -07:00
};
2023-11-25 13:13:59 -08:00
BusPort::BusPort() :
from_(std::numeric_limits<int>::max()),
to_(std::numeric_limits<int>::min())
2018-09-28 08:54:21 -07:00
{
}
2019-12-09 16:57:18 -07:00
void
2023-11-25 13:13:59 -08:00
BusPort::setDirection(PortDirection *direction)
2019-12-09 16:57:18 -07:00
{
2023-11-25 13:13:59 -08:00
direction_ = direction;
2019-12-09 16:57:18 -07:00
}
2018-09-28 08:54:21 -07:00
void
2023-11-25 13:13:59 -08:00
BusPort::addBusBit(ConcretePort *port,
int index)
2018-09-28 08:54:21 -07:00
{
2026-03-02 12:13:13 -08:00
from_ = std::min(from_, index);
to_ = std::max(to_, index);
2023-11-25 13:13:59 -08:00
members_.push_back(port);
2018-09-28 08:54:21 -07:00
}
void
2026-04-13 14:58:16 -07:00
ConcreteCell::groupBusPorts(char bus_brkt_left,
char bus_brkt_right,
2026-04-15 09:38:10 -07:00
const std::function<bool(std::string_view)> &port_msb_first)
2018-09-28 08:54:21 -07:00
{
2019-06-28 11:51:43 -07:00
const char bus_brkts_left[2]{bus_brkt_left, '\0'};
const char bus_brkts_right[2]{bus_brkt_right, '\0'};
2026-03-02 12:13:13 -08:00
std::map<std::string, BusPort> bus_map;
2018-09-28 08:54:21 -07:00
// Find ungrouped bus ports.
// Remove bus bit ports from the ports_ vector during the scan by
// keeping an index to the next insertion index and skipping over
// the ones we want to remove.
2019-12-09 16:57:18 -07:00
ConcretePortSeq ports = ports_;
ports_.clear();
for (ConcretePort *port : ports) {
2023-03-26 06:34:36 -07:00
bool is_bus;
2026-03-02 12:13:13 -08:00
std::string bus_name;
2018-09-28 08:54:21 -07:00
int index;
2026-03-28 19:13:35 -07:00
parseBusName(port->name(), bus_brkts_left, bus_brkts_right, escape_,
2026-01-03 16:59:35 -08:00
is_bus, bus_name, index);
2023-03-26 06:34:36 -07:00
if (is_bus) {
2018-09-28 08:54:21 -07:00
if (!port->isBusBit()) {
2023-11-25 13:13:59 -08:00
BusPort &bus_port = bus_map[bus_name];
2026-01-03 16:59:35 -08:00
bus_port.addBusBit(port, index);
2023-11-25 13:13:59 -08:00
port->setBusBitIndex(index);
bus_port.setDirection(port->direction());
2018-09-28 08:54:21 -07:00
}
}
else
2019-12-09 16:57:18 -07:00
ports_.push_back(port);
2018-09-28 08:54:21 -07:00
}
// Make the bus ports.
2024-06-27 13:57:58 -07:00
for (const auto& [bus_name, bus_port] : bus_map) {
2023-11-25 13:13:59 -08:00
int from = bus_port.from();
int to = bus_port.to();
size_t size = to - from + 1;
2026-03-28 19:13:35 -07:00
bool msb_first = port_msb_first(bus_name);
2023-11-25 13:13:59 -08:00
ConcretePortSeq *members = new ConcretePortSeq(size);
// Index the bus bit ports.
for (ConcretePort *bus_bit : bus_port.members()) {
int bit_index = bus_bit->busBitIndex();
int member_index = msb_first ? to - bit_index : bit_index - from;
(*members)[member_index] = bus_bit;
2018-09-28 08:54:21 -07:00
}
2023-11-25 13:13:59 -08:00
if (msb_first)
2026-03-02 12:13:13 -08:00
std::swap(from, to);
2026-03-28 19:13:35 -07:00
ConcretePort *port = makeBusPort(bus_name, from, to, members);
2023-11-25 13:13:59 -08:00
port->setDirection(bus_port.direction());
2018-09-28 08:54:21 -07:00
}
}
////////////////////////////////////////////////////////////////
2026-03-28 19:13:35 -07:00
ConcretePort::ConcretePort(std::string_view name,
2026-01-03 16:59:35 -08:00
bool is_bus,
int from_index,
int to_index,
bool is_bundle,
ConcretePortSeq *member_ports,
2023-01-19 11:23:45 -07:00
ConcreteCell *cell) :
2025-03-30 15:27:53 -07:00
name_(name),
2023-01-19 11:23:45 -07:00
id_(ConcreteNetwork::nextObjectId()),
2018-09-28 08:54:21 -07:00
cell_(cell),
direction_(PortDirection::unknown()),
is_bundle_(is_bundle),
is_bus_(is_bus),
from_index_(from_index),
to_index_(to_index),
2026-04-15 09:38:10 -07:00
member_ports_(member_ports)
2018-09-28 08:54:21 -07:00
{
}
ConcretePort::~ConcretePort()
{
// The member ports of a bus are owned by the bus port.
// The member ports of a bundle are NOT owned by the bus port.
if (is_bus_)
2026-01-03 16:59:35 -08:00
deleteContents(member_ports_);
2018-09-28 08:54:21 -07:00
delete member_ports_;
}
Cell *
ConcretePort::cell() const
{
return reinterpret_cast<Cell*>(cell_);
}
void
ConcretePort::setLibertyPort(LibertyPort *port)
{
liberty_port_ = port;
}
void
ConcretePort::setBundlePort(ConcretePort *port)
{
bundle_port_ = port;
}
2019-11-13 14:58:38 -07:00
void
ConcretePort::setExtPort(void *port)
{
ext_port_ = port;
}
2026-03-28 19:13:35 -07:00
std::string
2018-09-28 08:54:21 -07:00
ConcretePort::busName() const
{
if (is_bus_) {
ConcreteLibrary *lib = cell_->library();
2026-03-28 19:13:35 -07:00
return sta::format("{}{}{}:{}{}",
name(),
lib->busBrktLeft(),
from_index_,
to_index_,
lib->busBrktRight());
2018-09-28 08:54:21 -07:00
}
else
2025-03-30 15:27:53 -07:00
return name();
2018-09-28 08:54:21 -07:00
}
ConcretePort *
ConcretePort::findMember(int index) const
{
return (*member_ports_)[index];
}
bool
ConcretePort::isBusBit() const
{
return from_index_ != -1
&& from_index_ == to_index_;
}
void
ConcretePort::setBusBitIndex(int index)
{
from_index_ = to_index_ = index;
}
int
ConcretePort::size() const
{
if (is_bus_)
2026-03-02 12:13:13 -08:00
return std::abs(to_index_ - from_index_) + 1;
2018-09-28 08:54:21 -07:00
else if (is_bundle_)
return static_cast<int>(member_ports_->size());
else
return 1;
}
void
ConcretePort::setPinIndex(int index)
{
pin_index_ = index;
}
void
ConcretePort::setDirection(PortDirection *dir)
{
direction_ = dir;
if (hasMembers()) {
ConcretePortMemberIterator *member_iter = memberIterator();
while (member_iter->hasNext()) {
ConcretePort *port_bit = member_iter->next();
2023-11-25 13:13:59 -08:00
if (port_bit)
port_bit->setDirection(dir);
2018-09-28 08:54:21 -07:00
}
delete member_iter;
}
}
void
ConcretePort::addPortBit(ConcretePort *port)
{
member_ports_->push_back(port);
}
ConcretePort *
ConcretePort::findBusBit(int index) const
{
if (from_index_ < to_index_
&& index <= to_index_
&& index >= from_index_)
return (*member_ports_)[index - from_index_];
else if (from_index_ >= to_index_
2026-01-03 16:59:35 -08:00
&& index >= to_index_
&& index <= from_index_)
2018-09-28 08:54:21 -07:00
return (*member_ports_)[from_index_ - index];
else
2019-03-12 17:25:53 -07:00
return nullptr;
2018-09-28 08:54:21 -07:00
}
bool
ConcretePort::busIndexInRange(int index) const
{
return (from_index_ <= to_index_
2026-01-03 16:59:35 -08:00
&& index <= to_index_
&& index >= from_index_)
2018-09-28 08:54:21 -07:00
|| (from_index_ > to_index_
2026-01-03 16:59:35 -08:00
&& index >= to_index_
&& index <= from_index_);
2018-09-28 08:54:21 -07:00
}
bool
ConcretePort::hasMembers() const
{
return is_bus_ || is_bundle_;
}
ConcretePortMemberIterator *
ConcretePort::memberIterator() const
{
return new ConcretePortMemberIterator(member_ports_);
}
////////////////////////////////////////////////////////////////
2026-01-03 16:59:35 -08:00
ConcreteCellPortBitIterator::ConcreteCellPortBitIterator(const ConcreteCell* cell) :
ports_(cell->ports_),
2026-04-15 09:38:10 -07:00
port_iter_(ports_.begin())
2018-09-28 08:54:21 -07:00
{
findNext();
}
bool
ConcreteCellPortBitIterator::hasNext()
{
2019-03-12 17:25:53 -07:00
return next_ != nullptr;
2018-09-28 08:54:21 -07:00
}
ConcretePort *
ConcreteCellPortBitIterator::next()
{
ConcretePort *next = next_;
findNext();
return next;
}
void
ConcreteCellPortBitIterator::findNext()
{
if (member_iter_) {
2019-03-03 17:50:56 -08:00
if (member_iter_->hasNext()) {
2018-09-28 08:54:21 -07:00
next_ = member_iter_->next();
2019-03-03 17:50:56 -08:00
return;
}
2018-09-28 08:54:21 -07:00
else {
delete member_iter_;
2019-03-12 17:25:53 -07:00
member_iter_ = nullptr;
2018-09-28 08:54:21 -07:00
}
}
2026-01-03 16:59:35 -08:00
while (port_iter_ != ports_.end()) {
ConcretePort *next = *port_iter_++;
2019-03-03 17:50:56 -08:00
if (next->isBus()) {
member_iter_ = next->memberIterator();
next_ = member_iter_->next();
return;
2018-09-28 08:54:21 -07:00
}
2019-03-03 17:50:56 -08:00
else if (!next->isBundle()) {
next_ = next;
return;
}
2019-03-12 17:25:53 -07:00
next_ = nullptr;
2018-09-28 08:54:21 -07:00
}
2019-03-12 17:25:53 -07:00
next_ = nullptr;
2018-09-28 08:54:21 -07:00
}
2026-04-13 14:58:16 -07:00
} // namespace sta