From 53df9472d76e26cef42fd0b02ba235d943f2b5da Mon Sep 17 00:00:00 2001 From: James Cherry Date: Mon, 27 May 2019 22:46:24 -0700 Subject: [PATCH] resizer support --- CMakeLists.txt | 33 ++++++++++---- dcalc/GraphDelayCalc.cc | 7 +++ dcalc/GraphDelayCalc.hh | 5 +- dcalc/GraphDelayCalc1.cc | 18 ++++++++ dcalc/GraphDelayCalc1.hh | 2 + liberty/EquivCells.cc | 15 ++---- liberty/EquivCells.hh | 5 +- liberty/Liberty.cc | 98 +++++++++++++++++++++++++++++----------- liberty/Liberty.hh | 21 ++++++--- liberty/LibertyReader.cc | 1 - search/Power.cc | 2 +- tcl/Cmds.tcl | 8 ++++ tcl/NetworkEdit.tcl | 4 +- tcl/Sta.tcl | 6 +-- tcl/StaTcl.i | 15 +++++- 15 files changed, 178 insertions(+), 62 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9cd2f3b3..82af4b28 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,9 +56,6 @@ message(STATUS "Install prefix: ${CMAKE_INSTALL_PREFIX}") set(STA_SOURCE app/StaMain.cc - app/StaApp_wrap.cc - app/TclInitVar.cc - app/StaApp_wrap.cc dcalc/ArcDelayCalc.cc dcalc/ArnoldiDelayCalc.cc @@ -213,6 +210,11 @@ set(STA_SOURCE verilog/VerilogParse.cc ) +set(STA_CMD_SOURCE + app/TclInitVar.cc + app/StaApp_wrap.cc +) + set(STA_HEADERS app/StaMain.hh @@ -648,7 +650,6 @@ add_custom_command(OUTPUT ${STA_HOME}/app/TclInitVar.cc set(STA_INCLUDE_DIRS app dcalc - dcalc/verilog graph liberty network @@ -663,13 +664,29 @@ set(STA_INCLUDE_DIRS ) ########################################################### -# Library +# Library without TCL commands. +# This is used to build applications that define +# their own SWIG and TCL commands. ########################################################### # compatibility with configure set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${STA_HOME}/app) -add_library(OpenSTA ${STA_SOURCE}) +add_library(OpenSTAnoCmds ${STA_SOURCE}) + +target_include_directories(OpenSTAnoCmds PUBLIC ${STA_INCLUDE_DIRS}) + +target_compile_features(OpenSTAnoCmds + PUBLIC cxx_auto_type + ) + +target_compile_options(OpenSTAnoCmds PUBLIC ${STA_COMPILE_OPTIONS}) + +########################################################### +# Library +########################################################### + +add_library(OpenSTA ${STA_SOURCE} ${STA_CMD_SOURCE}) target_include_directories(OpenSTA PUBLIC ${STA_INCLUDE_DIRS}) @@ -677,6 +694,8 @@ target_compile_features(OpenSTA PUBLIC cxx_auto_type ) +target_compile_options(OpenSTA PUBLIC ${STA_COMPILE_OPTIONS}) + ########################################################### # Executable ########################################################### @@ -704,9 +723,7 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") target_link_libraries(sta -pthread) endif() -target_compile_options(OpenSTA PUBLIC ${STA_COMPILE_OPTIONS}) target_compile_options(sta PUBLIC ${STA_COMPILE_OPTIONS}) -message(STATUS "Compiler options: ${STA_COMPILE_OPTIONS}") ################################################################ # Install diff --git a/dcalc/GraphDelayCalc.cc b/dcalc/GraphDelayCalc.cc index 2cf7e962..ab11ea0a 100644 --- a/dcalc/GraphDelayCalc.cc +++ b/dcalc/GraphDelayCalc.cc @@ -87,6 +87,13 @@ GraphDelayCalc::loadCap(const Pin *, return 0.0F; } +float +GraphDelayCalc::loadCap(const Pin *, + const DcalcAnalysisPt *) const +{ + return 0.0F; +} + void GraphDelayCalc::netCaps(const Pin *, const TransRiseFall *, diff --git a/dcalc/GraphDelayCalc.hh b/dcalc/GraphDelayCalc.hh index a53f6da4..103a93b0 100644 --- a/dcalc/GraphDelayCalc.hh +++ b/dcalc/GraphDelayCalc.hh @@ -79,10 +79,13 @@ public: // Return values. float &pin_cap, float &wire_cap) const; - // Load pin_cap + wire_cap. + // Load pin_cap + wire_cap including parasitic. virtual float loadCap(const Pin *drvr_pin, const TransRiseFall *to_tr, const DcalcAnalysisPt *dcalc_ap) const; + // Load pin_cap + wire_cap including parasitic min/max for rise/fall. + virtual float loadCap(const Pin *drvr_pin, + const DcalcAnalysisPt *dcalc_ap) const; // Load pin_cap + wire_cap. virtual float loadCap(const Pin *drvr_pin, Parasitic *drvr_parasitic, diff --git a/dcalc/GraphDelayCalc1.cc b/dcalc/GraphDelayCalc1.cc index 902108dd..ba5155ec 100644 --- a/dcalc/GraphDelayCalc1.cc +++ b/dcalc/GraphDelayCalc1.cc @@ -1039,6 +1039,24 @@ GraphDelayCalc1::findDriverEdgeDelays(LibertyCell *drvr_cell, return delay_changed; } +float +GraphDelayCalc1::loadCap(const Pin *drvr_pin, + const DcalcAnalysisPt *dcalc_ap) const +{ + const MinMax *min_max = dcalc_ap->constraintMinMax(); + float load_cap = 0.0; + TransRiseFallIterator drvr_tr_iter; + while (drvr_tr_iter.hasNext()) { + TransRiseFall *drvr_tr = drvr_tr_iter.next(); + Parasitic *drvr_parasitic = arc_delay_calc_->findParasitic(drvr_pin, drvr_tr, + dcalc_ap); + float cap = loadCap(drvr_pin, nullptr, drvr_parasitic, drvr_tr, dcalc_ap); + if (min_max->compare(cap, load_cap)) + load_cap = cap; + } + return load_cap; +} + float GraphDelayCalc1::loadCap(const Pin *drvr_pin, const TransRiseFall *drvr_tr, diff --git a/dcalc/GraphDelayCalc1.hh b/dcalc/GraphDelayCalc1.hh index 3417b834..e081637f 100644 --- a/dcalc/GraphDelayCalc1.hh +++ b/dcalc/GraphDelayCalc1.hh @@ -55,6 +55,8 @@ public: virtual float loadCap(const Pin *drvr_pin, const TransRiseFall *drvr_tr, const DcalcAnalysisPt *dcalc_ap) const; + virtual float loadCap(const Pin *drvr_pin, + const DcalcAnalysisPt *dcalc_ap) const; virtual void loadCap(const Pin *drvr_pin, Parasitic *drvr_parasitic, const TransRiseFall *tr, diff --git a/liberty/EquivCells.cc b/liberty/EquivCells.cc index b7cfc107..47b4617b 100644 --- a/liberty/EquivCells.cc +++ b/liberty/EquivCells.cc @@ -35,8 +35,6 @@ typedef Set LibertyCellSeqSet; static LibertyCellEquivMap * findEquivCells1(const LibertyLibrary *library); static void -deleteEquivCellMap(LibertyCellEquivMap *equiv_map); -static void sortCellEquivs(LibertyCellEquivMap *cell_equivs); static float cellDriveResistance(const LibertyCell *cell); @@ -58,7 +56,7 @@ static bool equivCellSequentials(const LibertyCell *cell1, const LibertyCell *cell2); -void +LibertyCellEquivMap * findEquivCells(const LibertyLibrary *library) { // Build a map from each cell in the library to a group (CellSeq) of @@ -66,11 +64,11 @@ findEquivCells(const LibertyLibrary *library) LibertyCellEquivMap *cell_equivs = findEquivCells1(library); // Sort by drive strength. sortCellEquivs(cell_equivs); - deleteEquivCellMap(cell_equivs); + return cell_equivs; } // Delete the LibertyCellEquivMap returned by makeEquivCellMap. -static void +void deleteEquivCellMap(LibertyCellEquivMap *equiv_map) { // Multiple cells can point to the same cell sequence, so collect @@ -129,12 +127,7 @@ findEquivCells1(const LibertyLibrary *library) } } - LibertyCellHashMap::Iterator hash_iter(cell_hash); - while (hash_iter.hasNext()) { - LibertyCellSeq *cells = hash_iter.next(); - delete cells; - } - + cell_hash.deleteContents(); return cell_equivs; } diff --git a/liberty/EquivCells.hh b/liberty/EquivCells.hh index 2b831052..896fa68c 100644 --- a/liberty/EquivCells.hh +++ b/liberty/EquivCells.hh @@ -24,8 +24,11 @@ namespace sta { // Find equivalent cells, sort by drive strength and // and set cell->higherDrive/lowerDrive. -void +LibertyCellEquivMap * findEquivCells(const LibertyLibrary *library); +// Delete findEquivCells return value. +void +deleteEquivCellMap(LibertyCellEquivMap *equiv_map); // Predicate that is true when the ports, functions, sequentials and // timing arcs match. diff --git a/liberty/Liberty.cc b/liberty/Liberty.cc index 5e276c5c..d324ed45 100644 --- a/liberty/Liberty.cc +++ b/liberty/Liberty.cc @@ -83,12 +83,15 @@ LibertyLibrary::LibertyLibrary(const char *name, default_wire_load_selection_(nullptr), default_operating_conditions_(nullptr), ocv_arc_depth_(0.0), - default_ocv_derate_(nullptr) + default_ocv_derate_(nullptr), + equiv_cell_map_(nullptr), + buffers_(nullptr) { // Scalar templates are builtin. for (int i = 0; i != int(TableTemplateType::count); i++) { TableTemplateType type = static_cast(i); - TableTemplate *scalar_template = new TableTemplate("scalar", nullptr, nullptr, nullptr); + TableTemplate *scalar_template = new TableTemplate("scalar", nullptr, + nullptr, nullptr); addTableTemplate(scalar_template, type); } @@ -129,6 +132,8 @@ LibertyLibrary::~LibertyLibrary() const char *supply_name = name_volt.first; stringDelete(supply_name); } + deleteEquivCellMap(equiv_cell_map_); + delete buffers_; } LibertyCell * @@ -149,6 +154,22 @@ LibertyLibrary::findLibertyCellsMatching(PatternMatch *pattern, } } +LibertyCellSeq * +LibertyLibrary::buffers() +{ + if (buffers_ == nullptr) { + buffers_ = new LibertyCellSeq; + LibertyCellIterator cell_iter(this); + while (cell_iter.hasNext()) { + LibertyCell *cell = cell_iter.next(); + if (!cell->dontUse() + && cell->isBuffer()) + buffers_->push_back(cell); + } + } + return buffers_; +} + void LibertyLibrary::setDelayModelType(DelayModelType type) { @@ -737,9 +758,17 @@ LibertyLibrary::makeCornerMap(LibertyCell *cell1, } void -LibertyLibrary::finish() +LibertyLibrary::ensureEquivCells() { - findEquivCells(this); + if (equiv_cell_map_ == nullptr) + equiv_cell_map_ = sta::findEquivCells(this); +} + +LibertyCellSeq * +LibertyLibrary::findEquivCells(LibertyCell *cell) +{ + ensureEquivCells(); + return equiv_cell_map_->findKey(cell); } //////////////////////////////////////////////////////////////// @@ -1022,33 +1051,16 @@ LibertyCell::setClockGateType(ClockGateType type) bool LibertyCell::isBuffer() const -{ - LibertyPort *input, *output; - return isBuffer(input, output); -} - -bool -LibertyCell::isBuffer(// Return values. - LibertyPort *&input, - LibertyPort *&output) const { if (ports_.size() == 2) { LibertyPort *port1 = static_cast(ports_[0]); LibertyPort *port2 = static_cast(ports_[1]); - if (port1->direction()->isInput() - && port2->direction()->isOutput() - && hasBufferFunc(port1, port2)) { - input = port1; - output = port2; - return true; - } - else if (port2->direction()->isInput() - && port1->direction()->isOutput() - && hasBufferFunc(port2, port1)) { - input = port2; - output = port1; - return true; - } + return (port1->direction()->isInput() + && port2->direction()->isOutput() + && hasBufferFunc(port1, port2)) + || (port2->direction()->isInput() + && port1->direction()->isOutput() + && hasBufferFunc(port2, port1)); } return false; } @@ -1063,6 +1075,24 @@ LibertyCell::hasBufferFunc(const LibertyPort *input, && func->port() == input; } +void +LibertyCell::bufferPorts(// Return values. + LibertyPort *&input, + LibertyPort *&output) +{ + LibertyPort *port1 = static_cast(ports_[0]); + LibertyPort *port2 = static_cast(ports_[1]); + if (port1->direction()->isInput() + && port2->direction()->isOutput()) { + input = port1; + output = port2; + } + else { + input = port2; + output = port1; + } +} + unsigned LibertyCell::addTimingArcSet(TimingArcSet *arc_set) { @@ -1427,6 +1457,20 @@ LibertyCell::setCornerCell(LibertyCell *corner_cell, //////////////////////////////////////////////////////////////// +LibertyCell * +LibertyCell::higherDrive() const +{ + liberty_library_->ensureEquivCells(); + return higher_drive_; +} + +LibertyCell * +LibertyCell::lowerDrive() const +{ + liberty_library_->ensureEquivCells(); + return lower_drive_; +} + void LibertyCell::setHigherDrive(LibertyCell *cell) { diff --git a/liberty/Liberty.hh b/liberty/Liberty.hh index 30e294f8..c0070056 100644 --- a/liberty/Liberty.hh +++ b/liberty/Liberty.hh @@ -118,6 +118,10 @@ public: LibertyCell *findLibertyCell(const char *name) const; void findLibertyCellsMatching(PatternMatch *pattern, LibertyCellSeq *cells); + LibertyCellSeq *findEquivCells(LibertyCell *cell); + // Liberty cells that are buffers. + LibertyCellSeq *buffers(); + DelayModelType delayModelType() const { return delay_model_type_; } void setDelayModelType(DelayModelType type); void addBusDcl(BusDcl *bus_dcl); @@ -262,6 +266,7 @@ public: // Make scaled cell. Call LibertyCell::addScaledCell after it is complete. LibertyCell *makeScaledCell(const char *name, const char *filename); + static void makeCornerMap(LibertyLibrary *lib, int ap_index, @@ -278,7 +283,6 @@ public: bool link, int ap_index, Report *report); - void finish(); protected: float degradeWireSlew(const LibertyCell *cell, @@ -286,6 +290,7 @@ protected: const TableModel *model, float in_slew, float wire_delay) const; + void ensureEquivCells(); Units *units_; DelayModelType delay_model_type_; @@ -326,6 +331,8 @@ protected: OcvDerate *default_ocv_derate_; OcvDerateMap ocv_derate_map_; SupplyVoltageMap supply_voltage_map_; + LibertyCellEquivMap *equiv_cell_map_; + LibertyCellSeq *buffers_; // Set if any library has rise/fall capacitances. static bool found_rise_fall_caps_; @@ -337,6 +344,7 @@ protected: private: DISALLOW_COPY_AND_ASSIGN(LibertyLibrary); + friend class LibertyCell; friend class LibertyCellIterator; friend class TableTemplateIterator; friend class OperatingConditionsIterator; @@ -448,8 +456,8 @@ public: OcvDerate *findOcvDerate(const char *derate_name); // Next higher/lower drive equivalent cells. - LibertyCell *higherDrive() const { return higher_drive_; } - LibertyCell *lowerDrive() const { return lower_drive_; } + LibertyCell *higherDrive() const; + LibertyCell *lowerDrive() const; // Build helpers. void makeSequential(int size, @@ -488,9 +496,10 @@ public: void setHigherDrive(LibertyCell *cell); void setLowerDrive(LibertyCell *cell); bool isBuffer() const; - bool isBuffer(// Return values. - LibertyPort *&input, - LibertyPort *&output) const; + // Only valid when isBuffer() returns true. + void bufferPorts(// Return values. + LibertyPort *&input, + LibertyPort *&output); protected: virtual void addPort(ConcretePort *port); diff --git a/liberty/LibertyReader.cc b/liberty/LibertyReader.cc index 90a90f1f..67550600 100644 --- a/liberty/LibertyReader.cc +++ b/liberty/LibertyReader.cc @@ -578,7 +578,6 @@ void LibertyReader::endLibrary(LibertyGroup *group) { endLibraryAttrs(group); - library_->finish(); } void diff --git a/search/Power.cc b/search/Power.cc index 44ca0cc9..2e4e3e97 100644 --- a/search/Power.cc +++ b/search/Power.cc @@ -500,7 +500,7 @@ Power::power(const Instance *inst, const Pin *to_pin = pin_iter->next(); const LibertyPort *to_port = network_->libertyPort(to_pin); float load_cap = to_port->direction()->isAnyOutput() - ? graph_delay_calc_->loadCap(to_pin, TransRiseFall::rise(), dcalc_ap) + ? graph_delay_calc_->loadCap(to_pin, dcalc_ap) : 0.0; PwrActivity activity = findClkedActivity(to_pin, inst_clk); if (to_port->direction()->isAnyOutput()) diff --git a/tcl/Cmds.tcl b/tcl/Cmds.tcl index 06c5ed6f..2948b6b1 100644 --- a/tcl/Cmds.tcl +++ b/tcl/Cmds.tcl @@ -1907,6 +1907,14 @@ proc get_full_name { object } { return [get_object_property $object "full_name"] } +proc sort_by_name { objects } { + return [lsort -command name_cmp $objects] +} + +proc name_cmp { obj1 obj2 } { + return [string compare [get_name $obj1] [get_name $obj2]] +} + proc sort_by_full_name { objects } { return [lsort -command full_name_cmp $objects] } diff --git a/tcl/NetworkEdit.tcl b/tcl/NetworkEdit.tcl index 8174560e..bd5a6fff 100644 --- a/tcl/NetworkEdit.tcl +++ b/tcl/NetworkEdit.tcl @@ -225,8 +225,8 @@ proc replace_cell { instances lib_cell } { set insts [get_instances_error "instances" $instances] foreach inst $insts { set inst_cell [$inst liberty_cell] - if { $inst_cell != "NULL" \ - && ![cells_equiv_ports $inst_cell $cell] } { + if { $inst_cell == "NULL" \ + || ![equiv_cell_ports $inst_cell $cell] } { return 0 } } diff --git a/tcl/Sta.tcl b/tcl/Sta.tcl index 96048354..993f5f22 100644 --- a/tcl/Sta.tcl +++ b/tcl/Sta.tcl @@ -956,7 +956,7 @@ proc_redirect report_clock_properties { define_sta_cmd_args "report_object_full_names" {[-verbose] objects} proc report_object_full_names { args } { - parse_key_args "report_object_names" args keys {} flags {-verbose} + parse_key_args "report_object_full_names" args keys {} flags {-verbose} set objects [lindex $args 0] if { [info exists flags(-verbose)] } { @@ -986,7 +986,7 @@ proc report_object_names { args } { if { [info exists flags(-verbose)] } { puts -nonewline "{" set first 1 - foreach obj [sort_by_full_name $objects] { + foreach obj [sort_by_name $objects] { if { !$first } { puts -nonewline ", " } @@ -995,7 +995,7 @@ proc report_object_names { args } { } puts "}" } else { - foreach obj [sort_by_full_name $objects] { + foreach obj [sort_by_name $objects] { puts [get_name $obj] } } diff --git a/tcl/StaTcl.i b/tcl/StaTcl.i index 5122d53c..c2c8cf37 100644 --- a/tcl/StaTcl.i +++ b/tcl/StaTcl.i @@ -2273,8 +2273,21 @@ find_cells_matching(const char *pattern, return cells; } +LibertyCellSeq * +find_library_buffers(LibertyLibrary *library) +{ + return library->buffers(); +} + +LibertyCellSeq * +equiv_cells(LibertyCell *cell) +{ + LibertyLibrary *library = cell->libertyLibrary(); + return library->findEquivCells(cell); +} + bool -cells_equiv_ports(LibertyCell *cell1, +equiv_cell_ports(LibertyCell *cell1, LibertyCell *cell2) { return equivCellPorts(cell1, cell2);