check liberty corners

Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
James Cherry 2022-10-04 20:50:27 -07:00
parent 9d6bad01cc
commit 4f80bd6f8a
6 changed files with 141 additions and 31 deletions

View File

@ -47,8 +47,9 @@ class InternalPowerAttrs;
class LibertyPgPort;
class StaState;
class Corner;
class Corners;
class DcalcAnalysisPt;
typedef Set<Library*> LibrarySet;
typedef Map<const char*, TableTemplate*, CharPtrLess> TableTemplateMap;
typedef Vector<TableTemplate*> TableTemplateSeq;
typedef Map<const char*, BusDcl *, CharPtrLess> BusDclMap;
@ -295,6 +296,10 @@ public:
bool link,
int ap_index,
Report *report);
static void
checkCorners(LibertyCell *cell,
Corners *corners,
Report *report);
protected:
float degradeWireSlew(const LibertyCell *cell,
@ -446,8 +451,8 @@ public:
bool isDisabledConstraint() const { return is_disabled_constraint_; }
LibertyCell *cornerCell(const Corner *corner,
const MinMax *min_max);
const LibertyCell *cornerCell(const Corner *corner,
const MinMax *min_max) const;
LibertyCell *cornerCell(const DcalcAnalysisPt *dcalc_ap);
LibertyCell *cornerCell(int ap_index);
// AOCV
float ocvArcDepth() const;
@ -493,6 +498,9 @@ public:
void bufferPorts(// Return values.
LibertyPort *&input,
LibertyPort *&output) const;
// Check all liberty cells to make sure they exist
// for all the defined corners.
static void checkLibertyCorners();
protected:
void addPort(ConcretePort *port);
@ -519,6 +527,8 @@ protected:
const LibertyPort *output) const;
bool hasInverterFunc(const LibertyPort *input,
const LibertyPort *output) const;
bool checkCornerCell(const Corner *corner,
const MinMax *min_max) const;
LibertyLibrary *liberty_library_;
float area_;
@ -720,6 +730,10 @@ public:
const MinMax *min_max);
const LibertyPort *cornerPort(const Corner *corner,
const MinMax *min_max) const;
LibertyPort *cornerPort(const DcalcAnalysisPt *dcalc_ap);
const LibertyPort *cornerPort(const DcalcAnalysisPt *dcalc_ap) const;
LibertyPort *cornerPort(int ap_index);
const LibertyPort *cornerPort(int ap_index) const;
void setCornerPort(LibertyPort *corner_port,
int ap_index);
const char *relatedGroundPin() const { return related_ground_pin_; }

View File

@ -127,6 +127,11 @@ public:
// This corresponds to a link_path of '*'.
LibertyLibrary *defaultLibertyLibrary() const;
void setDefaultLibertyLibrary(LibertyLibrary *library);
// Check liberty cells used by the network to make sure they exist
// for all the defined corners.
void checkNetworkLibertyCorners();
// Check liberty cells to make sure they exist for all the defined corners.
void checkLibertyCorners();
////////////////////////////////////////////////////////////////
// Cell functions.
@ -514,7 +519,6 @@ public:
virtual void mergeInto(Net *net,
Net *into_net) = 0;
virtual Net *mergedInto(Net *net) = 0;
};
// Network API to support the Parallax readers.

View File

@ -37,11 +37,10 @@
#include "Network.hh"
#include "PortDirection.hh"
#include "Corner.hh"
#include "DcalcAnalysisPt.hh"
namespace sta {
typedef Set<TimingModel*> TimingModelSet;
typedef Set<FuncExpr*> FuncExprSet;
typedef Set<LatchEnable*> LatchEnableSet;
void
@ -783,6 +782,23 @@ LibertyLibrary::makeCornerMap(LibertyCell *cell1,
}
}
void
LibertyLibrary::checkCorners(LibertyCell *cell,
Corners *corners,
Report *report)
{
for (const Corner *corner : *corners) {
for (auto min_max : MinMax::range()) {
if (!cell->checkCornerCell(corner, min_max))
report->error(705, "Liberty cell %s/%s for corner %s/%s not found",
cell->libertyLibrary()->name(),
cell->name(),
corner->name(),
min_max->asString());
}
}
}
////////////////////////////////////////////////////////////////
float
@ -1502,25 +1518,34 @@ LibertyCell *
LibertyCell::cornerCell(const Corner *corner,
const MinMax *min_max)
{
if (corner_cells_.empty())
return this;
else {
int ap_index = corner->libertyIndex(min_max);
return corner_cells_[ap_index];
}
return cornerCell(corner->libertyIndex(min_max));
}
const LibertyCell *
LibertyCell::cornerCell(const Corner *corner,
const MinMax *min_max) const
LibertyCell *
LibertyCell::cornerCell(const DcalcAnalysisPt *dcalc_ap)
{
return cornerCell(dcalc_ap->libertyIndex());
}
LibertyCell *
LibertyCell::cornerCell(int ap_index)
{
if (corner_cells_.empty())
return this;
else {
int ap_index = corner->libertyIndex(min_max);
else if (ap_index < static_cast<int>(corner_cells_.size()))
return corner_cells_[ap_index];
}
else
return nullptr;
}
bool
LibertyCell::checkCornerCell(const Corner *corner,
const MinMax *min_max) const
{
int lib_index = corner->libertyIndex(min_max);
return corner_cells_.empty()
|| (lib_index <= static_cast<int>(corner_cells_.size())
&& corner_cells_[lib_index]);
}
void
@ -2344,24 +2369,48 @@ LibertyPort *
LibertyPort::cornerPort(const Corner *corner,
const MinMax *min_max)
{
if (corner_ports_.empty())
return this;
else {
int ap_index = corner->libertyIndex(min_max);
return corner_ports_[ap_index];
}
return cornerPort(corner->libertyIndex(min_max));
}
const LibertyPort *
LibertyPort::cornerPort(const Corner *corner,
const MinMax *min_max) const
{
return cornerPort(corner->libertyIndex(min_max));
}
LibertyPort *
LibertyPort::cornerPort(const DcalcAnalysisPt *dcalc_ap)
{
return cornerPort(dcalc_ap->libertyIndex());
}
const LibertyPort *
LibertyPort::cornerPort(const DcalcAnalysisPt *dcalc_ap) const
{
return cornerPort(dcalc_ap->libertyIndex());
}
LibertyPort *
LibertyPort::cornerPort(int ap_index)
{
if (corner_ports_.empty())
return this;
else {
int ap_index = corner->libertyIndex(min_max);
else if (ap_index < static_cast<int>(corner_ports_.size()))
return corner_ports_[ap_index];
}
else
return nullptr;
}
const LibertyPort *
LibertyPort::cornerPort(int ap_index) const
{
if (corner_ports_.empty())
return this;
else if (ap_index < static_cast<int>(corner_ports_.size()))
return corner_ports_[ap_index];
else
return nullptr;
}
void

View File

@ -1849,6 +1849,8 @@ ConcreteNetwork::linkNetwork(const char *top_cell_name,
clearConstantNets();
deleteTopInstance();
top_instance_ = link_func_(top_cell_name, make_black_boxes, report, this);
if (top_instance_)
checkNetworkLibertyCorners();
return top_instance_ != nullptr;
}
else {

View File

@ -21,6 +21,7 @@
#include "PatternMatch.hh"
#include "Liberty.hh"
#include "PortDirection.hh"
#include "Corner.hh"
namespace sta {
@ -94,6 +95,47 @@ Network::setDefaultLibertyLibrary(LibertyLibrary *library)
default_liberty_ = library;
}
void
Network::checkLibertyCorners()
{
if (corners_->count() > 1) {
LibertyLibraryIterator *lib_iter = libertyLibraryIterator();
LibertyCellSet cells;
while (lib_iter->hasNext()) {
LibertyLibrary *lib = lib_iter->next();
LibertyCellIterator cell_iter(lib);
while (cell_iter.hasNext()) {
LibertyCell *cell = cell_iter.next();
LibertyCell *link_cell = findLibertyCell(cell->name());
cells.insert(link_cell);
}
}
delete lib_iter;
for (LibertyCell *cell : cells)
LibertyLibrary::checkCorners(cell, corners_, report_);
}
}
void
Network::checkNetworkLibertyCorners()
{
if (corners_->count() > 1) {
LibertyCellSet network_cells;
LeafInstanceIterator *leaf_iter = network_->leafInstanceIterator();
while (leaf_iter->hasNext()) {
const Instance *inst = leaf_iter->next();
LibertyCell *cell = libertyCell(inst);
if (cell)
network_cells.insert(cell);
}
delete leaf_iter;
for (LibertyCell *cell : network_cells)
LibertyLibrary::checkCorners(cell, corners_, report_);
}
}
// Only used by Sta::setMinLibrary so linear search is acceptable.
LibertyLibrary *
Network::findLibertyFilename(const char *filename)

View File

@ -784,9 +784,8 @@ Power::findOutputInternalPower(const Pin *to_pin,
cell->name());
const DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(MinMax::max());
const Pvt *pvt = dcalc_ap->operatingConditions();
const MinMax *min_max = MinMax::max();
LibertyCell *corner_cell = cell->cornerCell(corner, min_max);
const LibertyPort *to_corner_port = to_port->cornerPort(corner, min_max);
LibertyCell *corner_cell = cell->cornerCell(dcalc_ap);
const LibertyPort *to_corner_port = to_port->cornerPort(dcalc_ap);
debugPrint(debug_, "power", 2, " cap = %s",
units_->capacitanceUnit()->asString(load_cap));
FuncExpr *func = to_port->function();
@ -999,7 +998,7 @@ Power::findSwitchingPower(LibertyCell *cell,
{
MinMax *mm = MinMax::max();
const DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(mm);
LibertyCell *corner_cell = cell->cornerCell(corner, MinMax::max());
LibertyCell *corner_cell = cell->cornerCell(dcalc_ap);
float volt = portVoltage(corner_cell, to_port, dcalc_ap);
float switching = .5 * load_cap * volt * volt * activity.activity();
debugPrint(debug_, "power", 2, "switching %s/%s activity = %.2e volt = %.2f %.3e",