check liberty corners
Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
parent
9d6bad01cc
commit
4f80bd6f8a
|
|
@ -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_; }
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
Loading…
Reference in New Issue