diff --git a/CMakeLists.txt b/CMakeLists.txt
index 28f362ee..9cd2f3b3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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}
diff --git a/app/StaApp.i b/app/StaApp.i
index 68f32cd7..f38c4697 100644
--- a/app/StaApp.i
+++ b/app/StaApp.i
@@ -16,10 +16,10 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-%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"
diff --git a/liberty/EquivCells.cc b/liberty/EquivCells.cc
index e11caffa..b7cfc107 100644
--- a/liberty/EquivCells.cc
+++ b/liberty/EquivCells.cc
@@ -15,6 +15,7 @@
// along with this program. If not, see .
#include "Machine.hh"
+#include "UnorderedMap.hh"
#include "PortDirection.hh"
#include "Transition.hh"
#include "MinMax.hh"
@@ -28,14 +29,16 @@
namespace sta {
-typedef Map > LibertyCellHashMap;
+typedef UnorderedMap LibertyCellHashMap;
typedef Set 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;
diff --git a/liberty/EquivCells.hh b/liberty/EquivCells.hh
index 63aa5ea9..2b831052 100644
--- a/liberty/EquivCells.hh
+++ b/liberty/EquivCells.hh
@@ -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.
diff --git a/liberty/Liberty.cc b/liberty/Liberty.cc
index 5a267ba8..8f474a72 100644
--- a/liberty/Liberty.cc
+++ b/liberty/Liberty.cc
@@ -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
{
diff --git a/liberty/Liberty.hh b/liberty/Liberty.hh
index fb603ecc..a0620e49 100644
--- a/liberty/Liberty.hh
+++ b/liberty/Liberty.hh
@@ -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);
diff --git a/liberty/LibertyReader.cc b/liberty/LibertyReader.cc
index 67550600..90a90f1f 100644
--- a/liberty/LibertyReader.cc
+++ b/liberty/LibertyReader.cc
@@ -578,6 +578,7 @@ void
LibertyReader::endLibrary(LibertyGroup *group)
{
endLibraryAttrs(group);
+ library_->finish();
}
void
diff --git a/search/Property.cc b/search/Property.cc
index dee21fb7..14ca66ee 100644
--- a/search/Property.cc
+++ b/search/Property.cc
@@ -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();
diff --git a/search/Sta.cc b/search/Sta.cc
index 381b92ad..017e6af9 100644
--- a/search/Sta.cc
+++ b/search/Sta.cc
@@ -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()) {
diff --git a/search/Sta.hh b/search/Sta.hh
index 95df50be..d5093cc2 100644
--- a/search/Sta.hh
+++ b/search/Sta.hh
@@ -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,
diff --git a/tcl/StaTcl.i b/tcl/StaTcl.i
index 42ad15f7..3737886e 100644
--- a/tcl/StaTcl.i
+++ b/tcl/StaTcl.i
@@ -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());
}