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-02-16 01:13:16 +01:00
|
|
|
#pragma once
|
2018-09-28 17:54:21 +02:00
|
|
|
|
2021-08-13 04:52:50 +02:00
|
|
|
#include <functional>
|
|
|
|
|
|
2020-04-05 23:53:44 +02:00
|
|
|
#include "Vector.hh"
|
|
|
|
|
#include "Map.hh"
|
|
|
|
|
#include "StringUtil.hh"
|
|
|
|
|
#include "NetworkClass.hh"
|
2018-09-28 17:54:21 +02:00
|
|
|
|
|
|
|
|
// The classes defined in this file are a contrete implementation of
|
|
|
|
|
// the library API. They can be used by a reader to construct classes
|
|
|
|
|
// that implement the library portion of the network API.
|
|
|
|
|
|
|
|
|
|
namespace sta {
|
|
|
|
|
|
|
|
|
|
class ConcreteLibrary;
|
|
|
|
|
class ConcreteCell;
|
|
|
|
|
class ConcretePort;
|
|
|
|
|
class ConcreteCellPortBitIterator;
|
|
|
|
|
class PatternMatch;
|
2019-06-16 07:20:54 +02:00
|
|
|
class LibertyCell;
|
|
|
|
|
class LibertyPort;
|
2018-09-28 17:54:21 +02:00
|
|
|
|
2025-04-12 01:59:48 +02:00
|
|
|
typedef Map<std::string, ConcreteCell*> ConcreteCellMap;
|
2018-09-28 17:54:21 +02:00
|
|
|
typedef Vector<ConcretePort*> ConcretePortSeq;
|
2025-04-12 01:59:48 +02:00
|
|
|
typedef Map<std::string, ConcretePort*> ConcretePortMap;
|
2018-09-28 17:54:21 +02:00
|
|
|
typedef ConcreteCellMap::ConstIterator ConcreteLibraryCellIterator;
|
|
|
|
|
typedef ConcretePortSeq::ConstIterator ConcreteCellPortIterator;
|
|
|
|
|
typedef ConcretePortSeq::ConstIterator ConcretePortMemberIterator;
|
|
|
|
|
|
|
|
|
|
class ConcreteLibrary
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
explicit ConcreteLibrary(const char *name,
|
2019-06-28 22:38:56 +02:00
|
|
|
const char *filename,
|
|
|
|
|
bool is_liberty);
|
2019-07-01 07:30:53 +02:00
|
|
|
virtual ~ConcreteLibrary();
|
2025-03-31 00:27:53 +02:00
|
|
|
const char *name() const { return name_.c_str(); }
|
2018-09-28 17:54:21 +02:00
|
|
|
void setName(const char *name);
|
2023-01-19 19:23:45 +01:00
|
|
|
ObjectId id() const { return id_; }
|
2019-06-28 22:38:56 +02:00
|
|
|
bool isLiberty() const { return is_liberty_; }
|
2025-03-31 00:27:53 +02:00
|
|
|
const char *filename() const { return filename_.c_str(); }
|
2018-09-28 17:54:21 +02:00
|
|
|
void addCell(ConcreteCell *cell);
|
2019-06-28 22:38:56 +02:00
|
|
|
ConcreteCell *makeCell(const char *name,
|
|
|
|
|
bool is_leaf,
|
|
|
|
|
const char *filename);
|
2018-09-28 17:54:21 +02:00
|
|
|
void deleteCell(ConcreteCell *cell);
|
|
|
|
|
ConcreteLibraryCellIterator *cellIterator() const;
|
2019-06-28 22:38:56 +02:00
|
|
|
ConcreteCell *findCell(const char *name) const;
|
2023-01-19 19:23:45 +01:00
|
|
|
CellSeq findCellsMatching(const PatternMatch *pattern) const;
|
2021-10-07 01:55:43 +02:00
|
|
|
char busBrktLeft() const { return bus_brkt_left_; }
|
|
|
|
|
char busBrktRight() const { return bus_brkt_right_; }
|
2019-01-17 00:37:31 +01:00
|
|
|
void setBusBrkts(char left,
|
|
|
|
|
char right);
|
2018-09-28 17:54:21 +02:00
|
|
|
|
|
|
|
|
protected:
|
2019-01-17 00:37:31 +01:00
|
|
|
void renameCell(ConcreteCell *cell,
|
|
|
|
|
const char *cell_name);
|
2018-09-28 17:54:21 +02:00
|
|
|
|
2025-04-12 01:59:48 +02:00
|
|
|
std::string name_;
|
2023-01-19 19:23:45 +01:00
|
|
|
ObjectId id_;
|
2025-04-12 01:59:48 +02:00
|
|
|
std::string filename_;
|
2019-06-28 22:38:56 +02:00
|
|
|
bool is_liberty_;
|
2018-09-28 17:54:21 +02:00
|
|
|
char bus_brkt_left_;
|
|
|
|
|
char bus_brkt_right_;
|
|
|
|
|
ConcreteCellMap cell_map_;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
friend class ConcreteCell;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class ConcreteCell
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
// Use ConcreteLibrary::deleteCell.
|
2019-07-01 07:30:53 +02:00
|
|
|
virtual ~ConcreteCell();
|
2025-03-31 00:27:53 +02:00
|
|
|
const char *name() const { return name_.c_str(); }
|
2023-01-19 19:23:45 +01:00
|
|
|
ObjectId id() const { return id_; }
|
2025-03-31 00:27:53 +02:00
|
|
|
const char *filename() const { return filename_.c_str(); }
|
2023-01-19 19:23:45 +01:00
|
|
|
ConcreteLibrary *library() const { return library_; }
|
2019-06-24 17:35:04 +02:00
|
|
|
LibertyCell *libertyCell() const { return liberty_cell_; }
|
2019-06-16 07:20:54 +02:00
|
|
|
void setLibertyCell(LibertyCell *cell);
|
2019-11-13 22:58:38 +01:00
|
|
|
void *extCell() const { return ext_cell_; }
|
|
|
|
|
void setExtCell(void *ext_cell);
|
2019-06-28 22:38:56 +02:00
|
|
|
int portBitCount() const { return port_bit_count_; }
|
|
|
|
|
ConcretePort *findPort(const char *name) const;
|
2023-01-19 19:23:45 +01:00
|
|
|
PortSeq findPortsMatching(const PatternMatch *pattern) const;
|
2019-06-28 22:38:56 +02:00
|
|
|
ConcreteCellPortIterator *portIterator() const;
|
|
|
|
|
ConcreteCellPortBitIterator *portBitIterator() const;
|
|
|
|
|
bool isLeaf() const { return is_leaf_; }
|
2018-09-28 17:54:21 +02:00
|
|
|
void setIsLeaf(bool is_leaf);
|
2025-04-12 01:59:48 +02:00
|
|
|
void setAttribute(const std::string &key,
|
|
|
|
|
const std::string &value);
|
|
|
|
|
std::string getAttribute(const std::string &key) const;
|
2025-05-18 18:37:10 +02:00
|
|
|
const AttributeMap &attributeMap() const { return attribute_map_; }
|
2018-09-28 17:54:21 +02:00
|
|
|
|
|
|
|
|
// Cell acts as port factory.
|
|
|
|
|
ConcretePort *makePort(const char *name);
|
|
|
|
|
// Bus port.
|
2019-01-17 00:37:31 +01:00
|
|
|
ConcretePort *makeBusPort(const char *name,
|
|
|
|
|
int from_index,
|
|
|
|
|
int to_index);
|
2018-09-28 17:54:21 +02:00
|
|
|
// Bundle port.
|
2019-01-17 00:37:31 +01:00
|
|
|
ConcretePort *makeBundlePort(const char *name,
|
|
|
|
|
ConcretePortSeq *members);
|
2018-09-28 17:54:21 +02:00
|
|
|
// Group previously defined bus bit ports together.
|
2019-06-28 20:51:43 +02:00
|
|
|
void groupBusPorts(const char bus_brkt_left,
|
2021-08-13 00:50:25 +02:00
|
|
|
const char bus_brkt_right,
|
2021-08-13 02:46:02 +02:00
|
|
|
std::function<bool(const char*)> port_msb_first);
|
2018-09-28 17:54:21 +02:00
|
|
|
size_t portCount() const;
|
|
|
|
|
void setName(const char *name);
|
2019-06-28 22:38:56 +02:00
|
|
|
void addPort(ConcretePort *port);
|
2018-09-28 17:54:21 +02:00
|
|
|
void addPortBit(ConcretePort *port);
|
|
|
|
|
|
|
|
|
|
protected:
|
2023-01-19 19:23:45 +01:00
|
|
|
ConcreteCell(const char *name,
|
|
|
|
|
const char *filename,
|
|
|
|
|
bool is_leaf,
|
|
|
|
|
ConcreteLibrary *library);
|
2019-01-17 00:37:31 +01:00
|
|
|
ConcretePort *makeBusPort(const char *name,
|
|
|
|
|
int from_index,
|
|
|
|
|
int to_index,
|
2018-09-28 17:54:21 +02:00
|
|
|
ConcretePortSeq *members);
|
2019-01-17 00:37:31 +01:00
|
|
|
void makeBusPortBits(ConcretePort *bus_port,
|
|
|
|
|
const char *name,
|
|
|
|
|
int from_index,
|
|
|
|
|
int to_index);
|
2018-09-28 17:54:21 +02:00
|
|
|
// Bus port bit (internal to makeBusPortBits).
|
2019-06-28 22:38:56 +02:00
|
|
|
ConcretePort *makePort(const char *bit_name,
|
|
|
|
|
int bit_index);
|
2019-01-17 00:37:31 +01:00
|
|
|
void makeBusPortBit(ConcretePort *bus_port,
|
|
|
|
|
const char *name,
|
|
|
|
|
int index);
|
2018-09-28 17:54:21 +02:00
|
|
|
|
2025-04-12 01:59:48 +02:00
|
|
|
std::string name_;
|
2023-01-19 19:23:45 +01:00
|
|
|
ObjectId id_;
|
2018-09-28 17:54:21 +02:00
|
|
|
// Filename is optional.
|
2025-04-12 01:59:48 +02:00
|
|
|
std::string filename_;
|
2023-01-19 19:23:45 +01:00
|
|
|
ConcreteLibrary *library_;
|
2019-06-16 07:20:54 +02:00
|
|
|
LibertyCell *liberty_cell_;
|
2019-11-13 22:58:38 +01:00
|
|
|
// External application cell.
|
|
|
|
|
void *ext_cell_;
|
2018-09-28 17:54:21 +02:00
|
|
|
// Non-bus and bus ports (but no expanded bus bit ports).
|
|
|
|
|
ConcretePortSeq ports_;
|
|
|
|
|
ConcretePortMap port_map_;
|
|
|
|
|
// Port bit count (expanded buses).
|
|
|
|
|
int port_bit_count_;
|
|
|
|
|
bool is_leaf_;
|
2022-07-11 17:49:12 +02:00
|
|
|
AttributeMap attribute_map_;
|
2018-09-28 17:54:21 +02:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
friend class ConcreteLibrary;
|
|
|
|
|
friend class ConcreteCellPortBitIterator;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class ConcretePort
|
|
|
|
|
{
|
|
|
|
|
public:
|
2019-07-01 07:30:53 +02:00
|
|
|
virtual ~ConcretePort();
|
2025-03-31 00:27:53 +02:00
|
|
|
const char *name() const { return name_.c_str(); }
|
2023-01-19 19:23:45 +01:00
|
|
|
ObjectId id() const { return id_; }
|
2019-06-28 22:38:56 +02:00
|
|
|
const char *busName() const;
|
|
|
|
|
Cell *cell() const;
|
|
|
|
|
ConcreteLibrary *library() const { return cell_->library(); }
|
|
|
|
|
PortDirection *direction() const { return direction_; }
|
2019-07-02 16:07:34 +02:00
|
|
|
LibertyPort *libertyPort() const { return liberty_port_; }
|
2019-06-16 07:20:54 +02:00
|
|
|
void setLibertyPort(LibertyPort *port);
|
2019-11-13 22:58:38 +01:00
|
|
|
// External application port.
|
|
|
|
|
void *extPort() const { return ext_port_; }
|
|
|
|
|
void setExtPort(void *port);
|
2019-06-28 22:38:56 +02:00
|
|
|
void setDirection(PortDirection *dir);
|
2018-09-28 17:54:21 +02:00
|
|
|
// Bundles are groups of related ports that do not use
|
|
|
|
|
// bus notation.
|
2019-06-28 22:38:56 +02:00
|
|
|
bool isBundle() const { return is_bundle_; }
|
2025-06-16 16:45:21 +02:00
|
|
|
ConcretePort *bundlePort() const { return bundle_port_; }
|
|
|
|
|
bool isBundleMember() const { return bundle_port_ != nullptr; }
|
|
|
|
|
void setBundlePort(ConcretePort *port);
|
2019-06-28 22:38:56 +02:00
|
|
|
bool isBus() const { return is_bus_; }
|
2018-09-28 17:54:21 +02:00
|
|
|
// Index of cell bit ports.
|
|
|
|
|
// Bus/bundle ports do not have an pin index.
|
2019-06-28 22:38:56 +02:00
|
|
|
int pinIndex() const { return pin_index_; }
|
2018-09-28 17:54:21 +02:00
|
|
|
void setPinIndex(int index);
|
|
|
|
|
// Size is the bus/bundle member count (1 for non-bus/bundle ports).
|
2019-06-28 22:38:56 +02:00
|
|
|
int size() const;
|
|
|
|
|
int fromIndex() const { return from_index_; }
|
|
|
|
|
int toIndex() const { return to_index_; }
|
2018-09-28 17:54:21 +02:00
|
|
|
// Bus member, bus[subscript].
|
2019-06-28 22:38:56 +02:00
|
|
|
ConcretePort *findBusBit(int index) const;
|
2018-09-28 17:54:21 +02:00
|
|
|
// Predicate to determine if subscript is within bus range.
|
|
|
|
|
// (toIndex > fromIndex) && fromIndex <= subscript <= toIndex
|
|
|
|
|
// || (fromIndex > toIndex) && fromIndex >= subscript >= toIndex
|
|
|
|
|
bool busIndexInRange(int index) const;
|
|
|
|
|
// A port has members if it is a bundle or bus.
|
|
|
|
|
bool hasMembers() const;
|
2019-06-28 22:38:56 +02:00
|
|
|
ConcretePort *findMember(int index) const;
|
|
|
|
|
ConcretePortMemberIterator *memberIterator() const;
|
2018-09-28 17:54:21 +02:00
|
|
|
void setBusBitIndex(int index);
|
|
|
|
|
|
|
|
|
|
// Bus bit port functions.
|
|
|
|
|
// Bus bit is one bit of a bus port.
|
2019-06-28 22:38:56 +02:00
|
|
|
bool isBusBit() const;
|
2018-09-28 17:54:21 +02:00
|
|
|
// Bit index within bus port.
|
|
|
|
|
// The bit index of A[3] is 3.
|
2019-06-28 22:38:56 +02:00
|
|
|
int busBitIndex() const { return to_index_; }
|
2018-09-28 17:54:21 +02:00
|
|
|
ConcretePortSeq *memberPorts() const { return member_ports_; }
|
|
|
|
|
void addPortBit(ConcretePort *port);
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
// Constructors for factory in cell class.
|
2023-01-19 19:23:45 +01:00
|
|
|
ConcretePort(const char *name,
|
|
|
|
|
bool is_bus,
|
2020-05-11 16:14:36 +02:00
|
|
|
int from_index,
|
2019-01-17 00:37:31 +01:00
|
|
|
int to_index,
|
|
|
|
|
bool is_bundle,
|
2023-01-19 19:23:45 +01:00
|
|
|
ConcretePortSeq *member_ports,
|
|
|
|
|
ConcreteCell *cell);
|
2018-09-28 17:54:21 +02:00
|
|
|
|
2025-04-12 01:59:48 +02:00
|
|
|
std::string name_;
|
2023-01-19 19:23:45 +01:00
|
|
|
ObjectId id_;
|
2018-09-28 17:54:21 +02:00
|
|
|
ConcreteCell *cell_;
|
|
|
|
|
PortDirection *direction_;
|
2019-06-16 07:20:54 +02:00
|
|
|
LibertyPort *liberty_port_;
|
2019-11-13 22:58:38 +01:00
|
|
|
// External application port.
|
|
|
|
|
void *ext_port_;
|
2018-09-28 17:54:21 +02:00
|
|
|
int pin_index_;
|
|
|
|
|
bool is_bundle_;
|
|
|
|
|
bool is_bus_;
|
|
|
|
|
int from_index_;
|
|
|
|
|
int to_index_;
|
|
|
|
|
// Expanded bus bit ports (ordered by from_index_ to to_index_)
|
|
|
|
|
// or bundle member ports.
|
|
|
|
|
ConcretePortSeq *member_ports_;
|
2025-06-16 16:45:21 +02:00
|
|
|
ConcretePort *bundle_port_;
|
2018-09-28 17:54:21 +02:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
friend class ConcreteCell;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class ConcreteCellPortBitIterator : public Iterator<ConcretePort*>
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
explicit ConcreteCellPortBitIterator(const ConcreteCell *cell);
|
|
|
|
|
virtual bool hasNext();
|
|
|
|
|
virtual ConcretePort *next();
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
void findNext();
|
|
|
|
|
|
|
|
|
|
ConcretePortSeq::ConstIterator port_iter_;
|
|
|
|
|
ConcretePortMemberIterator *member_iter_;
|
|
|
|
|
ConcretePort *next_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
} // Namespace
|