Merge remote-tracking branch 'parallax/master'
Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
This commit is contained in:
commit
5ee1a31514
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 *
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
Loading…
Reference in New Issue