LibertyCell::higherDrive(), slowerDrive()

This commit is contained in:
James Cherry 2019-05-25 17:08:53 -07:00
parent cfaef559e6
commit 6a194ef6ee
11 changed files with 124 additions and 92 deletions

View File

@ -626,7 +626,7 @@ add_flex_bison_dependency(SdfLex SdfParser)
include(FindSWIG)
add_custom_command(OUTPUT ${STA_HOME}/app/StaApp_wrap.cc
COMMAND ${SWIG_EXECUTABLE} -tcl8 -c++ -namespace -prefix sta -o ${STA_HOME}/app/StaApp_wrap.cc ${STA_HOME}/app/StaApp.i
COMMAND ${SWIG_EXECUTABLE} -tcl8 -c++ -namespace -prefix sta -I${STA_HOME}/tcl -I${STA_HOME}/sdf -I${STA_HOME}/dcalc -I${STA_HOME}/parasitics -I${STA_HOME}/verilog -o ${STA_HOME}/app/StaApp_wrap.cc ${STA_HOME}/app/StaApp.i
COMMAND ${STA_HOME}/etc/SwigCleanup.tcl ${STA_HOME}/app/StaApp_wrap.cc
WORKING_DIRECTORY ${STA_HOME}
DEPENDS ${STA_SWIG_FILES}

View File

@ -16,10 +16,10 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
%include "../tcl/StaException.i"
%include "../tcl/StaTcl.i"
%include "../verilog/Verilog.i"
%include "../tcl/NetworkEdit.i"
%include "../sdf/Sdf.i"
%include "../dcalc/DelayCalc.i"
%include "../parasitics/Parasitics.i"
%include "StaException.i"
%include "StaTcl.i"
%include "Verilog.i"
%include "NetworkEdit.i"
%include "Sdf.i"
%include "DelayCalc.i"
%include "Parasitics.i"

View File

@ -15,6 +15,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#include "Machine.hh"
#include "UnorderedMap.hh"
#include "PortDirection.hh"
#include "Transition.hh"
#include "MinMax.hh"
@ -28,14 +29,16 @@
namespace sta {
typedef Map<unsigned,LibertyCellSeq*, std::less<unsigned> > LibertyCellHashMap;
typedef UnorderedMap<unsigned, LibertyCellSeq*> LibertyCellHashMap;
typedef Set<LibertyCellSeq*> LibertyCellSeqSet;
static LibertyCellEquivMap *
findEquivCells1(const LibertyLibrary *library);
static void
deleteEquivCellMap(LibertyCellEquivMap *equiv_map);
static void
sortCellEquivs(LibertyCellEquivMap *cell_equivs);
float
static float
cellDriveResistance(const LibertyCell *cell);
static unsigned
@ -55,15 +58,19 @@ static bool
equivCellSequentials(const LibertyCell *cell1,
const LibertyCell *cell2);
LibertyCellEquivMap *
makeEquivCellMap(const LibertyLibrary *library)
void
findEquivCells(const LibertyLibrary *library)
{
// Build a map from each cell in the library to a group (CellSeq) of
// cells with equivalent functionality.
LibertyCellEquivMap *cell_equivs = findEquivCells1(library);
// Sort by drive strength.
sortCellEquivs(cell_equivs);
return cell_equivs;
deleteEquivCellMap(cell_equivs);
}
void
// Delete the LibertyCellEquivMap returned by makeEquivCellMap.
static void
deleteEquivCellMap(LibertyCellEquivMap *equiv_map)
{
// Multiple cells can point to the same cell sequence, so collect
@ -147,14 +154,21 @@ sortCellEquivs(LibertyCellEquivMap *cell_equivs)
while (equivs_iter.hasNext()) {
LibertyCellSeq *equivs = equivs_iter.next();
sort(equivs, CellDriveResistanceLess());
LibertyCell *lower = nullptr;
LibertyCellSeq::Iterator cell_iter(equivs);
while (cell_iter.hasNext()) {
LibertyCell *cell = cell_iter.next();
if (lower) {
lower->setHigherDrive(cell);
cell->setLowerDrive(lower);
}
lower = cell;
}
}
}
// Use the worst "drive" for all the timing arcs in the cell.
// Note that this function can NOT be static for sun's compiler to
// be happy with using it in a sort predicate (presumably because the
// template functions are compiled outside the scope of this file).
float
static float
cellDriveResistance(const LibertyCell *cell)
{
float max_drive = 0.0;

View File

@ -22,14 +22,10 @@
namespace sta {
// Build a map from each cell in the library to a group (CellSeq) of
// cells with equivalent functionality, sorted by drive strength.
LibertyCellEquivMap *
makeEquivCellMap(const LibertyLibrary *library);
// Delete the LibertyCellEquivMap returned by makeEquivCellMap.
// Find equivalent cells, sort by drive strength and
// and set cell->higherDrive/lowerDrive.
void
deleteEquivCellMap(LibertyCellEquivMap *equiv_map);
findEquivCells(const LibertyLibrary *library);
// Predicate that is true when the ports, functions, sequentials and
// timing arcs match.

View File

@ -82,7 +82,6 @@ LibertyLibrary::LibertyLibrary(const char *name,
default_wire_load_mode_(WireloadMode::unknown),
default_wire_load_selection_(nullptr),
default_operating_conditions_(nullptr),
equiv_cell_map_(nullptr),
ocv_arc_depth_(0.0),
default_ocv_derate_(nullptr)
{
@ -123,8 +122,6 @@ LibertyLibrary::~LibertyLibrary()
operating_conditions_.deleteContents();
wireloads_.deleteContents();
wire_load_selections_.deleteContents();
if (equiv_cell_map_)
deleteEquivCellMap(equiv_cell_map_);
delete units_;
ocv_derate_map_.deleteContents();
@ -500,15 +497,6 @@ LibertyLibrary::setDefaultOutputPinRes(const TransRiseFall *tr,
default_output_pin_res_.setValue(tr, value);
}
LibertyCellSeq *
LibertyLibrary::findEquivCells(LibertyCell *cell)
{
if (equiv_cell_map_ == nullptr)
equiv_cell_map_ = makeEquivCellMap(this);
LibertyCellSeq *equivs = equiv_cell_map_->findKey(cell);
return equivs;
}
void
LibertyLibrary::addWireload(Wireload *wireload)
{
@ -748,6 +736,12 @@ LibertyLibrary::makeCornerMap(LibertyCell *cell1,
}
}
void
LibertyLibrary::finish()
{
findEquivCells(this);
}
////////////////////////////////////////////////////////////////
float
@ -849,7 +843,9 @@ LibertyCell::LibertyCell(LibertyLibrary *library,
ocv_derate_(nullptr),
is_disabled_constraint_(false),
leakage_power_(0.0),
leakage_power_exists_(false)
leakage_power_exists_(false),
higher_drive_(nullptr),
lower_drive_(nullptr)
{
}
@ -1388,6 +1384,20 @@ LibertyCell::setCornerCell(LibertyCell *corner_cell,
////////////////////////////////////////////////////////////////
void
LibertyCell::setHigherDrive(LibertyCell *cell)
{
higher_drive_ = cell;
}
void
LibertyCell::setLowerDrive(LibertyCell *cell)
{
lower_drive_ = cell;
}
////////////////////////////////////////////////////////////////
float
LibertyCell::ocvArcDepth() const
{

View File

@ -223,7 +223,6 @@ public:
float slewDerateFromLibrary() const;
void setSlewDerateFromLibrary(float derate);
LibertyCellSeq *findEquivCells(LibertyCell *cell);
Units *units() { return units_; }
const Units *units() const { return units_; }
@ -279,6 +278,7 @@ public:
bool link,
int ap_index,
Report *report);
void finish();
protected:
float degradeWireSlew(const LibertyCell *cell,
@ -322,7 +322,6 @@ protected:
WireloadSelectionMap wire_load_selections_;
OperatingConditionsMap operating_conditions_;
OperatingConditions *default_operating_conditions_;
LibertyCellEquivMap *equiv_cell_map_;
float ocv_arc_depth_;
OcvDerate *default_ocv_derate_;
OcvDerateMap ocv_derate_map_;
@ -391,9 +390,6 @@ public:
void setScaleFactors(ScaleFactors *scale_factors);
ModeDef *makeModeDef(const char *name);
ModeDef *findModeDef(const char *name);
// Add scaled cell after it is complete.
void addScaledCell(OperatingConditions *op_cond,
LibertyCell *scaled_cell);
float area() const { return area_; }
void setArea(float area);
@ -410,15 +406,6 @@ public:
bool isClockGateOther() const;
bool isClockGate() const;
void setClockGateType(ClockGateType type);
virtual unsigned addTimingArcSet(TimingArcSet *set);
void addTimingArcAttrs(TimingArcAttrs *attrs);
virtual void addInternalPower(InternalPower *power);
void addInternalPowerAttrs(InternalPowerAttrs *attrs);
virtual void addLeakagePower(LeakagePower *power);
// Call after cell is finished being constructed.
virtual void finish(bool infer_latches,
Report *report,
Debug *debug);
// Internal to LibertyCellTimingArcSetIterator.
TimingArcSetSeq *timingArcSets(const LibertyPort *from,
const LibertyPort *to) const;
@ -427,13 +414,44 @@ public:
TimingArcSet *findTimingArcSet(TimingArcSet *key) const;
TimingArcSet *findTimingArcSet(unsigned arc_set_index) const;
bool hasTimingArcs(LibertyPort *port) const;
InternalPowerSeq *internalPowers() { return &internal_powers_; }
LeakagePowerSeq *leakagePowers() { return &leakage_powers_; }
void leakagePower(// Return values.
float &leakage,
bool &exists) const;
bool leakagePowerEx() const { return leakage_power_exists_; }
bool hasSequentials() const;
// Find the sequential with the output connected to an (internal) port.
Sequential *outputPortSequential(LibertyPort *port);
// Find bus declaration local to this cell.
BusDcl *findBusDcl(const char *name) const;
// True when TimingArcSetBuilder::makeRegLatchArcs infers register
// timing arcs.
bool hasInferedRegTimingArcs() const { return has_infered_reg_timing_arcs_; }
TestCell *testCell() const { return test_cell_; }
bool isLatchData(LibertyPort *port);
void latchEnable(TimingArcSet *arc_set,
// Return values.
LibertyPort *&enable_port,
FuncExpr *&enable_func,
TransRiseFall *&enable_tr) const;
TransRiseFall *latchCheckEnableTrans(TimingArcSet *check_set);
bool isDisabledConstraint() const { return is_disabled_constraint_; }
LibertyCell *cornerCell(int ap_index);
// AOCV
float ocvArcDepth() const;
OcvDerate *ocvDerate() const;
OcvDerate *findOcvDerate(const char *derate_name);
// Next higher/lower drive equivalent cells.
LibertyCell *higherDrive() const { return higher_drive_; }
LibertyCell *lowerDrive() const { return lower_drive_; }
// Build helpers.
void makeSequential(int size,
bool is_register,
FuncExpr *clk,
@ -444,40 +462,31 @@ public:
LogicValue clr_preset_out_inv,
LibertyPort *output,
LibertyPort *output_inv);
// Find the sequential with the output connected to an (internal) port.
Sequential *outputPortSequential(LibertyPort *port);
// Find bus declaration local to this cell.
BusDcl *findBusDcl(const char *name) const;
void addBusDcl(BusDcl *bus_dcl);
// True when TimingArcSetBuilder::makeRegLatchArcs infers register
// timing arcs.
bool hasInferedRegTimingArcs() const { return has_infered_reg_timing_arcs_; }
void setHasInferedRegTimingArcs(bool infered);
TestCell *testCell() const { return test_cell_; }
// Add scaled cell after it is complete.
void addScaledCell(OperatingConditions *op_cond,
LibertyCell *scaled_cell);
virtual unsigned addTimingArcSet(TimingArcSet *set);
void addTimingArcAttrs(TimingArcAttrs *attrs);
virtual void addInternalPower(InternalPower *power);
void addInternalPowerAttrs(InternalPowerAttrs *attrs);
virtual void addLeakagePower(LeakagePower *power);
void setLeakagePower(float leakage);
void setOcvArcDepth(float depth);
void setOcvDerate(OcvDerate *derate);
void addOcvDerate(OcvDerate *derate);
void addPgPort(LibertyPgPort *pg_port);
void setTestCell(TestCell *test);
bool isLatchData(LibertyPort *port);
void latchEnable(TimingArcSet *arc_set,
// Return values.
LibertyPort *&enable_port,
FuncExpr *&enable_func,
TransRiseFall *&enable_tr) const;
TransRiseFall *latchCheckEnableTrans(TimingArcSet *check_set);
bool isDisabledConstraint() const { return is_disabled_constraint_; }
void setHasInferedRegTimingArcs(bool infered);
void setIsDisabledConstraint(bool is_disabled);
LibertyCell *cornerCell(int ap_index);
void setCornerCell(LibertyCell *corner_cell,
int ap_index);
void setLeakagePower(float leakage);
// AOCV
float ocvArcDepth() const;
void setOcvArcDepth(float depth);
OcvDerate *ocvDerate() const;
void setOcvDerate(OcvDerate *derate);
OcvDerate *findOcvDerate(const char *derate_name);
void addOcvDerate(OcvDerate *derate);
void addPgPort(LibertyPgPort *pg_port);
// Call after cell is finished being constructed.
virtual void finish(bool infer_latches,
Report *report,
Debug *debug);
void setHigherDrive(LibertyCell *cell);
void setLowerDrive(LibertyCell *cell);
protected:
virtual void addPort(ConcretePort *port);
@ -511,7 +520,6 @@ protected:
bool interface_timing_;
ClockGateType clock_gate_type_;
TimingArcSetSeq timing_arc_sets_;
// Used to find matching arc sets in equivalent cells.
TimingArcSetMap timing_arc_set_map_;
LibertyPortPairTimingArcMap port_timing_arc_set_map_;
LibertyPortTimingArcMap timing_arc_set_from_map_;
@ -542,6 +550,9 @@ protected:
float leakage_power_;
bool leakage_power_exists_;
LibertyPgPortMap pg_port_map_;
// Next higher/lower drive equivalent cells.
LibertyCell *higher_drive_;
LibertyCell *lower_drive_;
private:
DISALLOW_COPY_AND_ASSIGN(LibertyCell);

View File

@ -578,6 +578,7 @@ void
LibertyReader::endLibrary(LibertyGroup *group)
{
endLibraryAttrs(group);
library_->finish();
}
void

View File

@ -509,6 +509,10 @@ getProperty(const LibertyCell *cell,
return PropertyValue(cell->filename());
else if (stringEqual(property, "library"))
return PropertyValue(cell->libertyLibrary());
else if (stringEqual(property, "higher_drive"))
return PropertyValue(cell->higherDrive());
else if (stringEqual(property, "lower_drive"))
return PropertyValue(cell->lowerDrive());
else
throw PropertyUnknown("liberty cell", property);
}
@ -706,7 +710,7 @@ pinSlewProperty(const Pin *pin,
const MinMax *min_max,
Sta *sta)
{
auto graph = sta->graph();
auto graph = sta->ensureGraph();
Vertex *vertex, *bidirect_drvr_vertex;
graph->pinVertices(pin, vertex, bidirect_drvr_vertex);
Slew slew = min_max->initValue();

View File

@ -3214,7 +3214,7 @@ Sta::setArcDelay(Edge *edge,
TimingArc *arc,
const Corner *corner,
const MinMaxAll *min_max,
float delay)
ArcDelay delay)
{
MinMaxIterator mm_iter(min_max);
while (mm_iter.hasNext()) {

View File

@ -705,7 +705,7 @@ public:
TimingArc *arc,
const Corner *corner,
const MinMaxAll *min_max,
float delay);
ArcDelay delay);
// Set annotated slew on a vertex for delay calculation.
void setAnnotatedSlew(Vertex *vertex,
const Corner *corner,

View File

@ -2275,13 +2275,6 @@ cells_equiv_ports(LibertyCell *cell1,
return equivCellPorts(cell1, cell2);
}
LibertyCellSeq *
find_equiv_cells(LibertyCell *cell)
{
LibertyLibrary *library = cell->libertyLibrary();
return library->findEquivCells(cell);
}
void
set_cmd_namespace_cmd(const char *namespc)
{
@ -2652,6 +2645,7 @@ PropertyValue
pin_property(const Pin *pin,
const char *property)
{
cmdLinkedNetwork();
return getProperty(pin, property, Sta::sta());
}
@ -2659,6 +2653,7 @@ PropertyValue
instance_property(const Instance *inst,
const char *property)
{
cmdLinkedNetwork();
return getProperty(inst, property, Sta::sta());
}
@ -2666,6 +2661,7 @@ PropertyValue
net_property(const Net *net,
const char *property)
{
cmdLinkedNetwork();
return getProperty(net, property, Sta::sta());
}