Merge remote-tracking branch 'parallax/master'

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
This commit is contained in:
Matt Liberty 2025-06-24 14:57:14 +00:00
commit 5ee1a31514
11 changed files with 136 additions and 116 deletions

View File

@ -157,7 +157,7 @@ git clone https://github.com/parallaxsw/OpenSTA.git
cd OpenSTA
mkdir build
cd build
cmake -DCUDD_DIR=<CUDD_INSTALL_DIR> ,.
cmake -DCUDD_DIR=<CUDD_INSTALL_DIR> ..
make
```
The default build type is release to compile optimized code.

View File

@ -67,10 +67,10 @@ bool
equivCellPorts(const LibertyCell *cell1,
const LibertyCell *cell2);
// Predicate that is true when the ports and their functions match.
// Predicate that is true cell functions match.
bool
equivCellPortsAndFuncs(const LibertyCell *cell1,
const LibertyCell *cell2);
equivCellFuncs(const LibertyCell *cell1,
const LibertyCell *cell2);
// Predicate that is true when the timing arc sets match.
bool

View File

@ -46,17 +46,16 @@ template<class TYPE>
class PropertyRegistry
{
public:
void defineProperty(const std::string property,
std::function<PropertyValue (TYPE object,
Sta *sta)> handler);
typedef std::function<PropertyValue (TYPE object, Sta *sta)> PropertyHandler;
void defineProperty(const std::string &property,
PropertyHandler handler);
PropertyValue getProperty(TYPE object,
const std::string property,
const std::string &property,
const char *type_name,
Sta *sta);
private:
std::map<const std::string, std::function<PropertyValue (TYPE object,
Sta *sta)>> registry_;
std::map<std::string, PropertyHandler> registry_;
};
class Properties
@ -99,33 +98,24 @@ public:
// [] (const Instance *, Sta *) -> PropertyValue {
// return PropertyValue("bar");
// });
void defineProperty(std::string property,
std::function<PropertyValue (const Library *lib,
Sta *sta)> handler);
void defineProperty(std::string property,
std::function<PropertyValue (const LibertyLibrary *lib,
Sta *sta)> handler);
void defineProperty(std::string property,
std::function<PropertyValue (const Cell *cell,
Sta *sta)> handler);
void defineProperty(std::string property,
std::function<PropertyValue (const LibertyCell *cell,
Sta *sta)> handler);
void defineProperty(std::string property,
std::function<PropertyValue (const Port *Port,
Sta *sta)> handler);
void defineProperty(std::string property,
std::function<PropertyValue (const LibertyPort *port,
Sta *sta)> handler);
void defineProperty(std::string property,
std::function<PropertyValue (const Instance *inst,
Sta *sta)> handler);
void defineProperty(std::string property,
std::function<PropertyValue (const Pin *pin,
Sta *sta)> handler);
void defineProperty(std::string property,
std::function<PropertyValue (const Net *net,
Sta *sta)> handler);
void defineProperty(std::string &property,
PropertyRegistry<const Library *>::PropertyHandler handler);
void defineProperty(std::string &property,
PropertyRegistry<const LibertyLibrary *>::PropertyHandler handler);
void defineProperty(std::string &property,
PropertyRegistry<const Cell *>::PropertyHandler handler);
void defineProperty(std::string &property,
PropertyRegistry<const LibertyCell *>::PropertyHandler handler);
void defineProperty(std::string &property,
PropertyRegistry<const Port *>::PropertyHandler handler);
void defineProperty(std::string &property,
PropertyRegistry<const LibertyPort *>::PropertyHandler handler);
void defineProperty(std::string &property,
PropertyRegistry<const Instance *>::PropertyHandler handler);
void defineProperty(std::string &property,
PropertyRegistry<const Pin *>::PropertyHandler handler);
void defineProperty(std::string &property,
PropertyRegistry<const Net *>::PropertyHandler handler);
protected:
PropertyValue portSlew(const Port *port,

View File

@ -71,6 +71,8 @@ static unsigned
hashCellPgPorts(const LibertyCell *cell);
static unsigned
hashPgPort(const LibertyPgPort *port);
static bool
cellHasFuncs(const LibertyCell *cell);
static bool
equivCellPgPorts(const LibertyCell *cell1,
@ -329,35 +331,44 @@ bool
equivCells(const LibertyCell *cell1,
const LibertyCell *cell2)
{
return equivCellPortsAndFuncs(cell1, cell2)
return equivCellPorts(cell1, cell2)
&& equivCellFuncs(cell1, cell2)
&& equivCellPgPorts(cell1, cell2)
&& equivCellSequentials(cell1, cell2)
&& equivCellStatetables(cell1, cell2)
&& equivCellTimingArcSets(cell1, cell2);
// Reqwuire timing arc equivalence if there are no functions.
&& (cellHasFuncs(cell1)
|| equivCellTimingArcSets(cell1, cell2));
}
static bool
cellHasFuncs(const LibertyCell *cell)
{
LibertyCellPortIterator port_iter(cell);
while (port_iter.hasNext()) {
LibertyPort *port = port_iter.next();
if (port->function())
return true;
}
return false;
}
bool
equivCellPortsAndFuncs(const LibertyCell *cell1,
const LibertyCell *cell2)
equivCellFuncs(const LibertyCell *cell1,
const LibertyCell *cell2)
{
if (cell1->portCount() != cell2->portCount())
return false;
else {
LibertyCellPortIterator port_iter1(cell1);
while (port_iter1.hasNext()) {
LibertyPort *port1 = port_iter1.next();
const char *name = port1->name();
LibertyPort *port2 = cell2->findLibertyPort(name);
if (!(port2
&& LibertyPort::equiv(port1, port2)
&& FuncExpr::equiv(port1->function(), port2->function())
&& FuncExpr::equiv(port1->tristateEnable(),
port2->tristateEnable()))){
return false;
}
}
return true;
LibertyCellPortIterator port_iter1(cell1);
while (port_iter1.hasNext()) {
LibertyPort *port1 = port_iter1.next();
const char *name = port1->name();
LibertyPort *port2 = cell2->findLibertyPort(name);
if (!(port2
&& FuncExpr::equiv(port1->function(), port2->function())
&& FuncExpr::equiv(port1->tristateEnable(),
port2->tristateEnable())))
return false;
}
return true;
}
bool

View File

@ -254,8 +254,12 @@ FuncExpr::bitSubExpr(int bit_offset)
return makePort(port);
}
else {
LibertyPort *port = port_->findLibertyMember(bit_offset);
return makePort(port);
if (bit_offset < port_->size()) {
LibertyPort *port = port_->findLibertyMember(bit_offset);
return makePort(port);
}
else
return nullptr;
}
}
else

View File

@ -130,15 +130,13 @@ LibertyLibrary::~LibertyLibrary()
wireloads_.deleteContents();
wire_load_selections_.deleteContents();
delete units_;
// Also deletes default_ocv_derate_
ocv_derate_map_.deleteContents();
delete buffers_;
delete inverters_;
driver_waveform_map_.deleteContents();
delete driver_waveform_default_;
delete default_ocv_derate_;
default_ocv_derate_ = nullptr;
}
LibertyCell *

View File

@ -2305,8 +2305,13 @@ void
LibertyReader::checkScaledCell(LibertyGroup *group)
{
if (equivCellPorts(cell_, scaled_cell_owner_)) {
if (!equivCellPortsAndFuncs(cell_, scaled_cell_owner_))
libWarn(1206, group, "scaled_cell %s, %s port functions do not match cell port functions.",
if (!equivCellPorts(cell_, scaled_cell_owner_))
libWarn(1206, group, "scaled_cell %s, %s ports do not match cell ports",
cell_->name(),
op_cond_->name());
if (!equivCellFuncs(cell_, scaled_cell_owner_))
libWarn(1206, group,
"scaled_cell %s, %s port functions do not match cell port functions.",
cell_->name(),
op_cond_->name());
}
@ -4920,7 +4925,7 @@ LibertyReader::visitWhen(LibertyAttr *attr)
false, "when", attr);
}
}
if (timing_) {
if (timing_ && !in_ccsn_) {
const char *func = getAttrString(attr);
if (func) {
TimingArcAttrs *attrs = timing_->attrs().get();

View File

@ -109,7 +109,8 @@ GenclkInfo::setFoundLatchFdbkEdges(bool found)
Genclks::Genclks(StaState *sta) :
StaState(sta),
found_insertion_delays_(false)
found_insertion_delays_(false),
vertex_src_paths_map_(graph_)
{
}
@ -124,6 +125,7 @@ Genclks::clear()
{
found_insertion_delays_ = false;
genclk_info_map_.deleteContentsClear();
vertex_src_paths_map_.clear();
clearSrcPaths();
}
@ -846,21 +848,27 @@ Genclks::findSrcArrivals(Clock *gclk,
insert_iter.visit(levelize_->maxLevel(), &arrival_visitor);
}
// Copy existing generated clock source paths from vertex to tag_bldr.
// Copy generated clock source paths to tag_bldr.
void
Genclks::copyGenClkSrcPaths(Vertex *vertex,
TagGroupBldr *tag_bldr)
{
Path *paths = graph_->paths(vertex);
if (paths) {
TagGroup *tag_group = search_->tagGroup(vertex);
if (tag_group) {
for (auto const [tag, path_index] : *tag_group->pathIndexMap()) {
if (tag->isGenClkSrcPath()) {
Path &path = paths[path_index];
tag_bldr->insertPath(path);
}
auto itr = vertex_src_paths_map_.find(vertex);
if (itr != vertex_src_paths_map_.end()) {
std::vector<const Path*> &src_paths = itr->second;
for (const Path *path : src_paths) {
Path src_path = *path;
Path *prev_path = src_path.prevPath();
if (prev_path) {
Path *prev_vpath = Path::vertexPath(prev_path, this);
src_path.setPrevPath(prev_vpath);
}
debugPrint(debug_, "genclk", 3, "vertex %s insert genclk %s src path %s %ss",
src_path.vertex(this)->to_string(this).c_str(),
src_path.tag(this)->genClkSrcPathClk(this)->name(),
src_path.tag(this)->pathAnalysisPt(this)->pathMinMax()->to_string().c_str(),
src_path.tag(this)->to_string(true, false, this).c_str());
tag_bldr->insertPath(src_path);
}
}
}
@ -941,10 +949,20 @@ Genclks::recordSrcPaths(Clock *gclk)
}
}
}
if (!found_src_paths
// Don't warn if the master clock is ideal.
&& gclk->masterClk()
&& gclk->masterClk()->isPropagated())
if (found_src_paths) {
for (const Path &path : src_paths) {
if (!path.isNull()) {
const Path *p = &path;
while (p) {
vertex_src_paths_map_[p->vertex(this)].push_back(p);
p = p->prevPath();
}
}
}
}
// Don't warn if the master clock is ideal.
else if (gclk->masterClk()
&& gclk->masterClk()->isPropagated())
report_->warn(1062, "generated clock %s source pin %s missing paths from master clock %s.",
gclk->name(),
network_->pathName(gclk_pin),

View File

@ -27,7 +27,7 @@
#include "Map.hh"
#include "Transition.hh"
#include "NetworkClass.hh"
#include "GraphClass.hh"
#include "Graph.hh"
#include "SdcClass.hh"
#include "SearchClass.hh"
#include "StaState.hh"
@ -51,6 +51,7 @@ public:
typedef Map<Clock*, GenclkInfo*> GenclkInfoMap;
typedef Map<ClockPinPair, std::vector<Path>, ClockPinPairLess> GenclkSrcPathMap;
typedef std::map<Vertex*, std::vector<const Path*>, VertexIdLess> VertexGenclkSrcPathsMap;
class Genclks : public StaState
{
@ -133,6 +134,7 @@ private:
bool found_insertion_delays_;
GenclkSrcPathMap genclk_src_paths_;
GenclkInfoMap genclk_info_map_;
VertexGenclkSrcPathsMap vertex_src_paths_map_;
};
} // namespace

View File

@ -1308,73 +1308,64 @@ Properties::capacitancePropertyValue(float cap)
////////////////////////////////////////////////////////////////
void
Properties::defineProperty(std::string property,
std::function<PropertyValue (const Library *lib,
Sta *sta)> handler)
Properties::defineProperty(std::string &property,
PropertyRegistry<const Library *>::PropertyHandler handler)
{
registry_library_.defineProperty(property, handler);
}
void
Properties::defineProperty(std::string property,
std::function<PropertyValue (const LibertyLibrary *lib,
Sta *sta)> handler)
Properties::defineProperty(std::string &property,
PropertyRegistry<const LibertyLibrary *>::PropertyHandler handler)
{
registry_liberty_library_.defineProperty(property, handler);
}
void
Properties::defineProperty(std::string property,
std::function<PropertyValue (const Cell *cell,
Sta *sta)> handler)
Properties::defineProperty(std::string &property,
PropertyRegistry<const Cell *>::PropertyHandler handler)
{
registry_cell_.defineProperty(property, handler);
}
void
Properties::defineProperty(std::string property,
std::function<PropertyValue (const LibertyCell *cell,
Sta *sta)> handler)
Properties::defineProperty(std::string &property,
PropertyRegistry<const LibertyCell *>::PropertyHandler handler)
{
registry_liberty_cell_.defineProperty(property, handler);
}
void
Properties::defineProperty(std::string property,
std::function<PropertyValue (const Port *Port,
Sta *sta)> handler)
Properties::defineProperty(std::string &property,
PropertyRegistry<const Port *>::PropertyHandler handler)
{
registry_port_.defineProperty(property, handler);
}
void
Properties::defineProperty(std::string property,
std::function<PropertyValue (const LibertyPort *port,
Sta *sta)> handler)
Properties::defineProperty(std::string &property,
PropertyRegistry<const LibertyPort *>::PropertyHandler handler)
{
registry_liberty_port_.defineProperty(property, handler);
}
void
Properties::defineProperty(std::string property,
std::function<PropertyValue (const Instance *inst,
Sta *sta)> handler)
Properties::defineProperty(std::string &property,
PropertyRegistry<const Instance *>::PropertyHandler handler)
{
registry_instance_.defineProperty(property, handler);
}
void
Properties::defineProperty(std::string property,
std::function<PropertyValue (const Pin *pin,
Sta *sta)> handler)
Properties::defineProperty(std::string &property,
PropertyRegistry<const Pin *>::PropertyHandler handler)
{
registry_pin_.defineProperty(property, handler);
}
void
Properties::defineProperty(std::string property,
std::function<PropertyValue (const Net *net,
Sta *sta)> handler)
Properties::defineProperty(std::string &property,
PropertyRegistry<const Net *>::PropertyHandler handler)
{
registry_net_.defineProperty(property, handler);
}
@ -1384,7 +1375,7 @@ Properties::defineProperty(std::string property,
template<class TYPE>
PropertyValue
PropertyRegistry<TYPE>::getProperty(TYPE object,
const std::string property,
const std::string &property,
const char *type_name,
Sta *sta)
@ -1398,9 +1389,8 @@ PropertyRegistry<TYPE>::getProperty(TYPE object,
template<class TYPE>
void
PropertyRegistry<TYPE>::defineProperty(const std::string property,
std::function<PropertyValue (TYPE object,
Sta *sta)> handler)
PropertyRegistry<TYPE>::defineProperty(const std::string &property,
PropertyHandler handler)
{
registry_[property] = handler;
}

View File

@ -1276,8 +1276,7 @@ Search::arrivalsChanged(Vertex *vertex,
|| path1->tag(this) != path2->tag(this)
|| !delayEqual(path1->arrival(), path2->arrival())
|| path1->prevEdge(this) != path2->prevEdge(this)
|| path1->prevArc(this) != path2->prevArc(this)
|| path1->prevPath() != path2->prevPath())
|| path1->prevArc(this) != path2->prevArc(this))
return true;
}
return false;
@ -1409,6 +1408,7 @@ ArrivalVisitor::seedInputDelayArrival(const Pin *pin,
{
TagGroupBldr tag_bldr(true, this);
tag_bldr.init(vertex);
search_->genclks()->copyGenClkSrcPaths(vertex, &tag_bldr);
search_->seedInputDelayArrival(pin, vertex, input_delay,
!network_->isTopLevelPort(pin), &tag_bldr);
search_->setVertexArrivals(vertex, &tag_bldr);
@ -1480,6 +1480,7 @@ Search::seedArrival(Vertex *vertex)
else if (isInputArrivalSrchStart(vertex)) {
TagGroupBldr tag_bldr(true, this);
tag_bldr.init(vertex);
genclks_->copyGenClkSrcPaths(vertex, &tag_bldr);
seedInputArrival(pin, vertex, &tag_bldr);
setVertexArrivals(vertex, &tag_bldr);
if (!tag_bldr.empty())
@ -1496,6 +1497,7 @@ Search::seedArrival(Vertex *vertex)
network_->pathName(pin));
TagGroupBldr tag_bldr(true, this);
tag_bldr.init(vertex);
genclks_->copyGenClkSrcPaths(vertex, &tag_bldr);
if (makeUnclkedPaths(vertex, is_reg_clk, false, &tag_bldr))
// Only search downstream if there are no false paths from here.
arrival_iter_->enqueueAdjacentVertices(vertex, search_adj_);
@ -1737,6 +1739,7 @@ Search::seedInputArrival(const Pin *pin,
// There can be multiple arrivals for a pin with wrt different clocks.
TagGroupBldr tag_bldr(true, this);
tag_bldr.init(vertex);
genclks_->copyGenClkSrcPaths(vertex, &tag_bldr);
InputDelaySet *input_delays = sdc_->inputDelaysLeafPin(pin);
if (input_delays) {
for (InputDelay *input_delay : *input_delays) {
@ -3221,7 +3224,6 @@ Search::findRequireds(Level level)
seedInvalidRequireds();
int required_count = required_iter_->visitParallel(level, &req_visitor);
deleteTagsPrev();
genclks_->updateSrcPathPrevs();
requireds_exist_ = true;
debugPrint(debug_, "search", 1, "found %d requireds", required_count);
stats.report("Find requireds");