resizer support

This commit is contained in:
James Cherry 2019-05-27 22:46:24 -07:00
parent 8242035b22
commit 53df9472d7
15 changed files with 178 additions and 62 deletions

View File

@ -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

View File

@ -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 *,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -35,8 +35,6 @@ typedef Set<LibertyCellSeq*> 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;
}

View File

@ -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.

View File

@ -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<TableTemplateType>(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<LibertyPort*>(ports_[0]);
LibertyPort *port2 = static_cast<LibertyPort*>(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<LibertyPort*>(ports_[0]);
LibertyPort *port2 = static_cast<LibertyPort*>(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)
{

View File

@ -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);

View File

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

View File

@ -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())

View File

@ -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]
}

View File

@ -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
}
}

View File

@ -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]
}
}

View File

@ -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);