liberty driver_waveform

Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
James Cherry 2023-03-22 09:57:54 -07:00
parent 55fc69577a
commit 6c3ba16e07
11 changed files with 849 additions and 379 deletions

View File

@ -48,4 +48,15 @@ set_delay_calc_incremental_tolerance(float tol)
sta::Sta::sta()->setIncrementalDelayTolerance(tol); sta::Sta::sta()->setIncrementalDelayTolerance(tol);
} }
TmpString *
report_delay_calc_cmd(Edge *edge,
TimingArc *arc,
const Corner *corner,
const MinMax *min_max,
int digits)
{
cmdLinkedNetwork();
return Sta::sta()->reportDelayCalc(edge, arc, corner, min_max, digits);
}
%} // inline %} // inline

View File

@ -49,6 +49,7 @@ class StaState;
class Corner; class Corner;
class Corners; class Corners;
class DcalcAnalysisPt; class DcalcAnalysisPt;
class DriverWaveform;
typedef Map<const char*, TableTemplate*, CharPtrLess> TableTemplateMap; typedef Map<const char*, TableTemplate*, CharPtrLess> TableTemplateMap;
typedef Vector<TableTemplate*> TableTemplateSeq; typedef Vector<TableTemplate*> TableTemplateSeq;
@ -77,6 +78,7 @@ typedef Map<const char *, OcvDerate*, CharPtrLess> OcvDerateMap;
typedef Vector<InternalPowerAttrs*> InternalPowerAttrsSeq; typedef Vector<InternalPowerAttrs*> InternalPowerAttrsSeq;
typedef Map<const char *, float, CharPtrLess> SupplyVoltageMap; typedef Map<const char *, float, CharPtrLess> SupplyVoltageMap;
typedef Map<const char *, LibertyPgPort*, CharPtrLess> LibertyPgPortMap; typedef Map<const char *, LibertyPgPort*, CharPtrLess> LibertyPgPortMap;
typedef Map<const char *, DriverWaveform*, CharPtrLess> DriverWaveformMap;
enum class ClockGateType { none, latch_posedge, latch_negedge, other }; enum class ClockGateType { none, latch_posedge, latch_negedge, other };
@ -315,6 +317,10 @@ public:
Corners *corners, Corners *corners,
Report *report); Report *report);
DriverWaveform *findDriverWaveform(const char *name);
DriverWaveform *driverWaveformDefault() { return driver_waveform_default_; }
void addDriverWaveform(DriverWaveform *driver_waveform);
protected: protected:
float degradeWireSlew(const LibertyCell *cell, float degradeWireSlew(const LibertyCell *cell,
const Pvt *pvt, const Pvt *pvt,
@ -363,6 +369,9 @@ protected:
OcvDerateMap ocv_derate_map_; OcvDerateMap ocv_derate_map_;
SupplyVoltageMap supply_voltage_map_; SupplyVoltageMap supply_voltage_map_;
LibertyCellSeq *buffers_; LibertyCellSeq *buffers_;
DriverWaveformMap driver_waveform_map_;
// Unnamed driver waveform.
DriverWaveform *driver_waveform_default_;
static constexpr float input_threshold_default_ = .5; static constexpr float input_threshold_default_ = .5;
static constexpr float output_threshold_default_ = .5; static constexpr float output_threshold_default_ = .5;
@ -780,6 +789,9 @@ public:
void setRelatedPowerPin(const char *related_power_pin); void setRelatedPowerPin(const char *related_power_pin);
ReceiverModelPtr receiverModel() const { return receiver_model_; } ReceiverModelPtr receiverModel() const { return receiver_model_; }
void setReceiverModel(ReceiverModelPtr receiver_model); void setReceiverModel(ReceiverModelPtr receiver_model);
DriverWaveform *driverWaveform(const RiseFall *rf) const;
void setDriverWaveform(DriverWaveform *driver_waveform,
const RiseFall *rf);
static bool equiv(const LibertyPort *port1, static bool equiv(const LibertyPort *port1,
const LibertyPort *port2); const LibertyPort *port2);
@ -820,6 +832,7 @@ protected:
const char *related_power_pin_; const char *related_power_pin_;
Vector<LibertyPort*> corner_ports_; Vector<LibertyPort*> corner_ports_;
ReceiverModelPtr receiver_model_; ReceiverModelPtr receiver_model_;
DriverWaveform *driver_waveform_[RiseFall::index_count];
unsigned int min_pulse_width_exists_:RiseFall::index_count; unsigned int min_pulse_width_exists_:RiseFall::index_count;
bool min_period_exists_:1; bool min_period_exists_:1;

View File

@ -33,12 +33,12 @@ class Unit;
class Units; class Units;
class Report; class Report;
class Table; class Table;
class OutputCurrent; class OutputWaveforms;
class OutputCurrentWaveform; class OutputWaveform;
typedef Vector<float> FloatSeq; typedef Vector<float> FloatSeq;
typedef Vector<FloatSeq*> FloatTable; typedef Vector<FloatSeq*> FloatTable;
typedef Vector<OutputCurrentWaveform*> OutputCurrentWaveformSeq; typedef Vector<OutputWaveform*> OutputWaveformSeq;
TableAxisVariable TableAxisVariable
stringTableAxisVariable(const char *variable); stringTableAxisVariable(const char *variable);
@ -56,7 +56,7 @@ public:
TableModel *slew_model, TableModel *slew_model,
TableModel *slew_sigma_models[EarlyLate::index_count], TableModel *slew_sigma_models[EarlyLate::index_count],
ReceiverModelPtr receiver_model, ReceiverModelPtr receiver_model,
OutputCurrent *output_current); OutputWaveforms *output_waveforms);
virtual ~GateTableModel(); virtual ~GateTableModel();
virtual void gateDelay(const LibertyCell *cell, virtual void gateDelay(const LibertyCell *cell,
const Pvt *pvt, const Pvt *pvt,
@ -80,6 +80,8 @@ public:
const TableModel *delayModel() const { return delay_model_; } const TableModel *delayModel() const { return delay_model_; }
const TableModel *slewModel() const { return slew_model_; } const TableModel *slewModel() const { return slew_model_; }
ReceiverModelPtr receiverModel() const { return receiver_model_; }
OutputWaveforms *outputWaveforms() const { return output_waveforms_; }
// Check the axes before making the model. // Check the axes before making the model.
// Return true if the model axes are supported. // Return true if the model axes are supported.
static bool checkAxes(const TablePtr table); static bool checkAxes(const TablePtr table);
@ -127,7 +129,7 @@ protected:
TableModel *slew_model_; TableModel *slew_model_;
TableModel *slew_sigma_models_[EarlyLate::index_count]; TableModel *slew_sigma_models_[EarlyLate::index_count];
ReceiverModelPtr receiver_model_; ReceiverModelPtr receiver_model_;
OutputCurrent *output_current_; OutputWaveforms *output_waveforms_;
}; };
class CheckTableModel : public CheckTimingModel class CheckTableModel : public CheckTimingModel
@ -333,15 +335,21 @@ private:
class Table1 : public Table class Table1 : public Table
{ {
public: public:
Table1();
Table1(FloatSeq *values, Table1(FloatSeq *values,
TableAxisPtr axis1); TableAxisPtr axis1);
virtual ~Table1(); virtual ~Table1();
Table1(Table1 &&table);
Table1 &operator= (Table1 &&table);
virtual int order() const { return 1; } virtual int order() const { return 1; }
virtual TableAxisPtr axis1() const { return axis1_; } virtual TableAxisPtr axis1() const { return axis1_; }
virtual float value(size_t index1, virtual float value(size_t index1,
size_t index2, size_t index2,
size_t index3) const; size_t index3) const;
float value(size_t index1) const; float value(size_t index1) const;
float findValue(float value1) const;
float findValue(float value1,
bool extrapolate) const;
virtual float findValue(float value1, virtual float findValue(float value1,
float value2, float value2,
float value3) const; float value3) const;
@ -358,6 +366,7 @@ public:
string *result) const; string *result) const;
virtual void report(const Units *units, virtual void report(const Units *units,
Report *report) const; Report *report) const;
FloatSeq *values() const { return values_; }
using Table::findValue; using Table::findValue;
private: private:
@ -462,6 +471,8 @@ public:
size_t &index, size_t &index,
bool &exists) const; bool &exists) const;
FloatSeq *values() const { return values_; } FloatSeq *values() const { return values_; }
float min() const { return (*values_)[0]; }
float max() const { return (*values_)[values_->size() - 1]; }
private: private:
TableAxisVariable variable_; TableAxisVariable variable_;
@ -484,63 +495,74 @@ private:
TableModel *capacitance_models_[2][RiseFall::index_count]; TableModel *capacitance_models_[2][RiseFall::index_count];
}; };
class OutputCurrentWaveform class OutputWaveform
{ {
public: public:
OutputCurrentWaveform(float axis_value1, OutputWaveform(float axis_value1,
float axis_value2, float axis_value2,
TableAxisPtr axis, Table1 *currents,
Table1 *currents, float reference_time);
float reference_time); OutputWaveform(float slew,
~OutputCurrentWaveform(); float cap,
float axisValue1() const { return axis_value1_; } Table1 *currents,
float axisValue2() const { return axis_value2_; } Table1 *voltages,
TableAxisPtr axis() const { return axis_; } float reference_time);
~OutputWaveform();
float slew() const { return slew_; }
float cap() const { return cap_; }
TableAxisPtr timeAxis() const { return currents_->axis1(); }
Table1 *currents() const { return currents_; } Table1 *currents() const { return currents_; }
Table1 *voltages();
float referenceTime() const { return reference_time_; } float referenceTime() const { return reference_time_; }
void reportWaveform(const Units *units,
int digits,
string *result);
static bool checkAxes(TableTemplate *tbl_template); static bool checkAxes(TableTemplate *tbl_template);
string reportCurrentWaveform(const Units *units,
int digits) const;
string reportVoltageWaveform(const Units *units,
int digits) const;
string reportWaveform(const Table1 *waveform,
const Unit *time_unit,
const Unit *waveform_unit,
int digits) const;
private: private:
float axis_value1_; float slew_;
float axis_value2_; float cap_;
TableAxisPtr axis_;
Table1 *currents_; Table1 *currents_;
Table1 *voltages_;
float reference_time_; float reference_time_;
}; };
// Two dimensional table of one dimensional time/current tables. // Two dimensional (slew/cap) table of one dimensional time/current tables.
class OutputCurrent class OutputWaveforms
{ {
public: public:
OutputCurrent(TableAxisPtr axis1, OutputWaveforms(TableAxisPtr slew_axis,
TableAxisPtr axis2, TableAxisPtr cap_axis,
Vector<OutputCurrentWaveform*> &waveforms); Vector<OutputWaveform*> &waveforms);
~OutputCurrent(); ~OutputWaveforms();
void reportWaveform(const LibertyCell *cell, OutputWaveform voltageWaveform(float in_slew,
const Pvt *pvt, float load_cap);
float in_slew,
float load_cap,
int digits,
string *result) const;
private: private:
void findAxisValues(float in_slew,
float load_cap,
// Return values.
float &axis_value1,
float &axis_value2) const;
float axisValue(TableAxisPtr axis,
float in_slew,
float load_cap) const;
// Row. // Row.
TableAxisPtr axis1_; TableAxisPtr slew_axis_;
// Column. // Column.
TableAxisPtr axis2_; TableAxisPtr cap_axis_;
OutputCurrentWaveformSeq waveforms_; OutputWaveformSeq waveforms_;
};
class DriverWaveform
{
public:
DriverWaveform(const char *name,
TablePtr waveforms);
~DriverWaveform();
const char *name() const { return name_; }
Table1 waveform(float slew);
private:
const char *name_;
TablePtr waveforms_;
}; };
} // namespace } // namespace

View File

@ -82,7 +82,8 @@ LibertyLibrary::LibertyLibrary(const char *name,
default_operating_conditions_(nullptr), default_operating_conditions_(nullptr),
ocv_arc_depth_(0.0), ocv_arc_depth_(0.0),
default_ocv_derate_(nullptr), default_ocv_derate_(nullptr),
buffers_(nullptr) buffers_(nullptr),
driver_waveform_default_(nullptr)
{ {
// Scalar templates are builtin. // Scalar templates are builtin.
for (int i = 0; i != table_template_type_count; i++) { for (int i = 0; i != table_template_type_count; i++) {
@ -860,6 +861,23 @@ LibertyLibrary::supplyExists(const char *supply_name) const
return supply_voltage_map_.hasKey(supply_name); return supply_voltage_map_.hasKey(supply_name);
} }
DriverWaveform *
LibertyLibrary::findDriverWaveform(const char *name)
{
return driver_waveform_map_[name];
}
void
LibertyLibrary::addDriverWaveform(DriverWaveform *driver_waveform)
{
if (driver_waveform->name())
driver_waveform_map_[driver_waveform->name()] = driver_waveform;
else {
delete driver_waveform_default_;
driver_waveform_default_ = driver_waveform;
}
}
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
LibertyCellIterator::LibertyCellIterator(const LibertyLibrary *library) : LibertyCellIterator::LibertyCellIterator(const LibertyLibrary *library) :
@ -1920,6 +1938,7 @@ LibertyPort::LibertyPort(LibertyCell *cell,
related_ground_pin_(nullptr), related_ground_pin_(nullptr),
related_power_pin_(nullptr), related_power_pin_(nullptr),
receiver_model_(nullptr), receiver_model_(nullptr),
driver_waveform_{nullptr, nullptr},
min_pulse_width_exists_(false), min_pulse_width_exists_(false),
min_period_exists_(false), min_period_exists_(false),
is_clk_(false), is_clk_(false),
@ -2519,6 +2538,19 @@ portLibertyToSta(const char *port_name)
return sta_name; return sta_name;
} }
DriverWaveform *
LibertyPort::driverWaveform(const RiseFall *rf) const
{
return driver_waveform_[rf->index()];
}
void
LibertyPort::setDriverWaveform(DriverWaveform *driver_waveform,
const RiseFall *rf)
{
driver_waveform_[rf->index()] = driver_waveform;
}
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
LibertyPortSeq LibertyPortSeq

View File

@ -501,10 +501,14 @@ LibertyReader::defineVisitors()
defineGroupVisitor("output_current_fall", defineGroupVisitor("output_current_fall",
&LibertyReader::beginOutputCurrentFall, &LibertyReader::beginOutputCurrentFall,
&LibertyReader::endOutputCurrentRiseFall); &LibertyReader::endOutputCurrentRiseFall);
defineGroupVisitor("vector", defineGroupVisitor("vector", &LibertyReader::beginVector, &LibertyReader::endVector);
&LibertyReader::beginVector,
&LibertyReader::endVector);
defineAttrVisitor("reference_time", &LibertyReader::visitReferenceTime); defineAttrVisitor("reference_time", &LibertyReader::visitReferenceTime);
defineGroupVisitor("normalized_driver_waveform",
&LibertyReader::beginNormalizedDriverWaveform,
&LibertyReader::endNormalizedDriverWaveform);
defineAttrVisitor("driver_waveform_name", &LibertyReader::visitDriverWaveformName);
defineAttrVisitor("driver_waveform_rise", &LibertyReader::visitDriverWaveformRise);
defineAttrVisitor("driver_waveform_fall", &LibertyReader::visitDriverWaveformFall);
} }
void void
@ -2283,7 +2287,7 @@ TimingGroup::makeTableModels(LibertyReader *reader)
transition, transition,
slew_sigma_[rf_index], slew_sigma_[rf_index],
receiver_model_, receiver_model_,
output_current_[rf_index])); output_waveforms_[rf_index]));
TimingType timing_type = attrs_->timingType(); TimingType timing_type = attrs_->timingType();
if (timing_type == TimingType::clear if (timing_type == TimingType::clear
|| timing_type == TimingType::combinational || timing_type == TimingType::combinational
@ -2480,8 +2484,10 @@ void
LibertyReader::beginOutputCurrent(RiseFall *rf, LibertyReader::beginOutputCurrent(RiseFall *rf,
LibertyGroup *group) LibertyGroup *group)
{ {
if (timing_) if (timing_) {
rf_ = rf; rf_ = rf;
output_currents_.clear();
}
else else
libWarn(907, group, "output_current_%s group not in timing group.", libWarn(907, group, "output_current_%s group not in timing group.",
rf->name()); rf->name());
@ -2490,54 +2496,54 @@ LibertyReader::beginOutputCurrent(RiseFall *rf,
void void
LibertyReader::endOutputCurrentRiseFall(LibertyGroup *group) LibertyReader::endOutputCurrentRiseFall(LibertyGroup *group)
{ {
Set<float> axis_set1, axis_set2; Set<float> slew_set, cap_set;
FloatSeq *axis_values1 = new FloatSeq; FloatSeq *slew_values = new FloatSeq;
FloatSeq *axis_values2 = new FloatSeq; FloatSeq *cap_values = new FloatSeq;
for (OutputCurrentWaveform *waveform : output_current_waveforms_) { for (OutputWaveform *waveform : output_currents_) {
float axis_value1 = waveform->axisValue1(); float slew = waveform->slew();
if (!axis_set1.hasKey(axis_value1)) { if (!slew_set.hasKey(slew)) {
axis_set1.insert(axis_value1); slew_set.insert(slew);
axis_values1->push_back(axis_value1); slew_values->push_back(slew);
} }
float axis_value2 = waveform->axisValue2(); float cap = waveform->cap();
if (!axis_set2.hasKey(axis_value2)) { if (!cap_set.hasKey(cap)) {
axis_set2.insert(axis_value2); cap_set.insert(cap);
axis_values2->push_back(axis_value2); cap_values->push_back(cap);
} }
} }
sort(axis_values1, std::less<float>()); sort(slew_values, std::less<float>());
sort(axis_values2, std::less<float>()); sort(cap_values, std::less<float>());
TableAxisPtr axis1 = std::make_shared<TableAxis>(axis_[0]->variable(), TableAxisPtr slew_axis = make_shared<TableAxis>(TableAxisVariable::input_net_transition,
axis_values1); slew_values);
TableAxisPtr axis2 = std::make_shared<TableAxis>(axis_[1]->variable(), TableAxisPtr cap_axis = make_shared<TableAxis>(TableAxisVariable::total_output_net_capacitance,
axis_values2); cap_values);
Vector<OutputCurrentWaveform*> waveforms(axis1->size() * axis2->size()); Vector<OutputWaveform*> waveforms(slew_axis->size() * cap_axis->size());
for (OutputCurrentWaveform *waveform : output_current_waveforms_) { for (OutputWaveform *waveform : output_currents_) {
size_t index1, index2; size_t slew_index, cap_index;
bool exists1, exists2; bool slew_exists, cap_exists;
axis1->findAxisIndex(waveform->axisValue1(), index1, exists1); slew_axis->findAxisIndex(waveform->slew(), slew_index, slew_exists);
axis2->findAxisIndex(waveform->axisValue2(), index2, exists2); cap_axis->findAxisIndex(waveform->cap(), cap_index, cap_exists);
if (exists1 && exists2) { if (slew_exists && cap_exists) {
size_t index = index1 * axis2->size() + index2; size_t index = slew_index * cap_axis->size() + cap_index;
waveforms[index] = waveform; waveforms[index] = waveform;
} }
else else
libWarn(913, group, "output current waveform %.2e %.2e not found.", libWarn(913, group, "output current waveform %.2e %.2e not found.",
waveform->axisValue1(), waveform->slew(),
waveform->axisValue2()); waveform->cap());
} }
OutputCurrent *output_current = new OutputCurrent(axis1, axis2, waveforms); OutputWaveforms *output_current = new OutputWaveforms(slew_axis, cap_axis, waveforms);
timing_->setOutputCurrent(rf_, output_current); timing_->setOutputWaveforms(rf_, output_current);
} }
void void
LibertyReader::beginVector(LibertyGroup *group) LibertyReader::beginVector(LibertyGroup *group)
{ {
if (timing_) { if (timing_) {
beginTable(group, TableTemplateType::output_current, 1.0); beginTable(group, TableTemplateType::output_current, current_scale_);
scale_factor_type_ = ScaleFactorType::unknown; scale_factor_type_ = ScaleFactorType::unknown;
reference_time_exists_ = false; reference_time_exists_ = false;
if (tbl_template_ && !OutputCurrentWaveform::checkAxes(tbl_template_)) if (tbl_template_ && !OutputWaveform::checkAxes(tbl_template_))
libWarn(118, group, "unsupported model axis."); libWarn(118, group, "unsupported model axis.");
} }
} }
@ -2546,32 +2552,41 @@ void
LibertyReader::visitReferenceTime(LibertyAttr *attr) LibertyReader::visitReferenceTime(LibertyAttr *attr)
{ {
getAttrFloat(attr, reference_time_, reference_time_exists_); getAttrFloat(attr, reference_time_, reference_time_exists_);
if (reference_time_exists_)
reference_time_ *= time_scale_;
} }
void void
LibertyReader::endVector(LibertyGroup *group) LibertyReader::endVector(LibertyGroup *group)
{ {
if (timing_ && tbl_template_) { if (timing_ && tbl_template_) {
FloatSeq *axis_values1 = axis_values_[0]; FloatSeq *slew_values = axis_values_[0];
FloatSeq *axis_values2 = axis_values_[1]; FloatSeq *cap_values = axis_values_[1];
if (axis_values1->size() == 1 && axis_values2->size() == 1) { // Canonicalize axis order.
if (tbl_template_->axis1()->variable() == TableAxisVariable::input_net_transition) {
slew_values = axis_values_[0];
cap_values = axis_values_[1];
}
else {
slew_values = axis_values_[1];
cap_values = axis_values_[0];
}
if (slew_values->size() == 1 && cap_values->size() == 1) {
// Convert 1x1xN Table3 to Table1. // Convert 1x1xN Table3 to Table1.
float axis_value1 = (*axis_values1)[0]; float slew = (*slew_values)[0];
float axis_value2 = (*axis_values2)[0]; float cap = (*cap_values)[0];
Table3 *table3 = dynamic_cast<Table3*>(table_.get()); Table3 *table3 = dynamic_cast<Table3*>(table_.get());
FloatTable *values3 = table3->values3(); FloatTable *values3 = table3->values3();
// Steal the values. // Steal the values.
FloatSeq *values = (*values3)[0]; FloatSeq *values = (*values3)[0];
(*values3)[0] = nullptr; (*values3)[0] = nullptr;
Table1 *table1 = new Table1(values, axis_[2]); Table1 *table1 = new Table1(values, axis_[2]);
OutputCurrentWaveform *waveform = new OutputCurrentWaveform(axis_value1, OutputWaveform *waveform = new OutputWaveform(slew, cap, table1, reference_time_);
axis_value2, output_currents_.push_back(waveform);
axis_[2], table1,
reference_time_);
output_current_waveforms_.push_back(waveform);
} }
else else
libWarn(912, group->line(), "vector index_1 and index_2 must have one value."); libWarn(912,group->line(), "vector index_1 and index_2 must have exactly one value.");
if (!reference_time_exists_) if (!reference_time_exists_)
libWarn(908, group->line(), "vector reference_time not found."); libWarn(908, group->line(), "vector reference_time not found.");
reference_time_exists_ = false; reference_time_exists_ = false;
@ -2580,6 +2595,68 @@ LibertyReader::endVector(LibertyGroup *group)
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
void
LibertyReader::beginNormalizedDriverWaveform(LibertyGroup *group)
{
beginTable(group, TableTemplateType::delay, time_scale_);
driver_waveform_name_ = nullptr;
}
void
LibertyReader::visitDriverWaveformName(LibertyAttr *attr)
{
driver_waveform_name_ = stringCopy(getAttrString(attr));
}
void
LibertyReader::endNormalizedDriverWaveform(LibertyGroup *group)
{
if (table_) {
if (table_->axis1()->variable() == TableAxisVariable::input_net_transition) {
if (table_->axis2()->variable() == TableAxisVariable::normalized_voltage) {
// Null driver_waveform_name_ means it is the default unnamed waveform.
DriverWaveform *driver_waveform = new DriverWaveform(driver_waveform_name_,
table_);
library_->addDriverWaveform(driver_waveform);
}
else
libWarn(914, group, "normalized_driver_waveform variable_2 must be normalized_voltage");
}
else
libWarn(915, group, "normalized_driver_waveform variable_1 must be input_net_transition");
}
endTableModel();
}
void
LibertyReader::visitDriverWaveformRise(LibertyAttr *attr)
{
visitDriverWaveformRiseFall(attr, RiseFall::rise());
}
void
LibertyReader::visitDriverWaveformFall(LibertyAttr *attr)
{
visitDriverWaveformRiseFall(attr, RiseFall::fall());
}
void
LibertyReader::visitDriverWaveformRiseFall(LibertyAttr *attr,
const RiseFall *rf)
{
if (ports_) {
const char *driver_waveform_name = getAttrString(attr);
DriverWaveform *driver_waveform = library_->findDriverWaveform(driver_waveform_name);
if (driver_waveform) {
for (LibertyPort *port : *ports_)
port->setDriverWaveform(driver_waveform, rf);
}
}
}
///////////////////////////////////////////////////////////////
void void
LibertyReader::makeInternalPowers(LibertyPort *port, LibertyReader::makeInternalPowers(LibertyPort *port,
InternalPowerGroup *power_group) InternalPowerGroup *power_group)
@ -5365,7 +5442,7 @@ TimingGroup::TimingGroup(int line) :
intrinsic_exists_[rf_index] = false; intrinsic_exists_[rf_index] = false;
resistance_[rf_index] = 0.0F; resistance_[rf_index] = 0.0F;
resistance_exists_[rf_index] = false; resistance_exists_[rf_index] = false;
output_current_[rf_index] = nullptr; output_waveforms_[rf_index] = nullptr;
for (auto el_index : EarlyLate::rangeIndex()) { for (auto el_index : EarlyLate::rangeIndex()) {
delay_sigma_[rf_index][el_index] = nullptr; delay_sigma_[rf_index][el_index] = nullptr;
@ -5496,17 +5573,17 @@ TimingGroup::setReceiverModel(ReceiverModelPtr receiver_model)
receiver_model_ = receiver_model; receiver_model_ = receiver_model;
} }
OutputCurrent * OutputWaveforms *
TimingGroup::outputCurrent(RiseFall *rf) TimingGroup::outputWaveforms(RiseFall *rf)
{ {
return output_current_[rf->index()]; return output_waveforms_[rf->index()];
} }
void void
TimingGroup::setOutputCurrent(RiseFall *rf, TimingGroup::setOutputWaveforms(RiseFall *rf,
OutputCurrent *output_current) OutputWaveforms *output_waveforms)
{ {
output_current_[rf->index()] = output_current; output_waveforms_[rf->index()] = output_waveforms;
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////

View File

@ -57,7 +57,7 @@ typedef Vector<TimingGroup*> TimingGroupSeq;
typedef Vector<InternalPowerGroup*> InternalPowerGroupSeq; typedef Vector<InternalPowerGroup*> InternalPowerGroupSeq;
typedef Vector<LeakagePowerGroup*> LeakagePowerGroupSeq; typedef Vector<LeakagePowerGroup*> LeakagePowerGroupSeq;
typedef void (LibertyPort::*LibertyPortBoolSetter)(bool value); typedef void (LibertyPort::*LibertyPortBoolSetter)(bool value);
typedef Vector<OutputCurrentWaveform*> OutputCurrentWaveformSeq; typedef Vector<OutputWaveform*> OutputWaveformSeq;
class LibertyReader : public LibertyGroupVisitor class LibertyReader : public LibertyGroupVisitor
{ {
@ -443,6 +443,15 @@ public:
void endVector(LibertyGroup *group); void endVector(LibertyGroup *group);
void visitReferenceTime(LibertyAttr *attr); void visitReferenceTime(LibertyAttr *attr);
void beginNormalizedDriverWaveform(LibertyGroup *group);
void endNormalizedDriverWaveform(LibertyGroup *group);
void visitDriverWaveformName(LibertyAttr *attr);
void visitDriverWaveformRise(LibertyAttr *attr);
void visitDriverWaveformFall(LibertyAttr *attr);
void visitDriverWaveformRiseFall(LibertyAttr *attr,
const RiseFall *rf);
// Visitors for derived classes to overload. // Visitors for derived classes to overload.
virtual void beginGroup1(LibertyGroup *) {} virtual void beginGroup1(LibertyGroup *) {}
virtual void beginGroup2(LibertyGroup *) {} virtual void beginGroup2(LibertyGroup *) {}
@ -617,10 +626,11 @@ protected:
bool have_resistance_unit_; bool have_resistance_unit_;
const char *default_operating_condition_; const char *default_operating_condition_;
ReceiverModelPtr receiver_model_; ReceiverModelPtr receiver_model_;
OutputCurrentWaveformSeq output_current_waveforms_; OutputWaveformSeq output_currents_;
OutputCurrent *output_current_; OutputWaveforms *output_waveforms_;
float reference_time_; float reference_time_;
bool reference_time_exists_; bool reference_time_exists_;
const char *driver_waveform_name_;
static constexpr char escape_ = '\\'; static constexpr char escape_ = '\\';
@ -783,9 +793,9 @@ public:
EarlyLate *early_late, EarlyLate *early_late,
TableModel *model); TableModel *model);
void setReceiverModel(ReceiverModelPtr receiver_model); void setReceiverModel(ReceiverModelPtr receiver_model);
OutputCurrent *outputCurrent(RiseFall *rf); OutputWaveforms *outputWaveforms(RiseFall *rf);
void setOutputCurrent(RiseFall *rf, void setOutputWaveforms(RiseFall *rf,
OutputCurrent *output_current); OutputWaveforms *output_current);
protected: protected:
void makeLinearModels(LibertyLibrary *library); void makeLinearModels(LibertyLibrary *library);
@ -803,7 +813,7 @@ protected:
TableModel *transition_[RiseFall::index_count]; TableModel *transition_[RiseFall::index_count];
TableModel *delay_sigma_[RiseFall::index_count][EarlyLate::index_count]; TableModel *delay_sigma_[RiseFall::index_count][EarlyLate::index_count];
TableModel *slew_sigma_[RiseFall::index_count][EarlyLate::index_count]; TableModel *slew_sigma_[RiseFall::index_count][EarlyLate::index_count];
OutputCurrent *output_current_[RiseFall::index_count]; OutputWaveforms *output_waveforms_[RiseFall::index_count];
ReceiverModelPtr receiver_model_; ReceiverModelPtr receiver_model_;
}; };

View File

@ -26,6 +26,10 @@
namespace sta { namespace sta {
using std::string; using std::string;
using std::min;
using std::max;
using std::abs;
using std::make_shared;
static void static void
deleteSigmaModels(TableModel *models[EarlyLate::index_count]); deleteSigmaModels(TableModel *models[EarlyLate::index_count]);
@ -43,15 +47,19 @@ GateTableModel::GateTableModel(TableModel *delay_model,
TableModel *slew_model, TableModel *slew_model,
TableModel *slew_sigma_models[EarlyLate::index_count], TableModel *slew_sigma_models[EarlyLate::index_count],
ReceiverModelPtr receiver_model, ReceiverModelPtr receiver_model,
OutputCurrent *output_current) : OutputWaveforms *output_waveforms) :
delay_model_(delay_model), delay_model_(delay_model),
slew_model_(slew_model), slew_model_(slew_model),
receiver_model_(receiver_model), receiver_model_(receiver_model),
output_current_(output_current) output_waveforms_(output_waveforms)
{ {
for (auto el_index : EarlyLate::rangeIndex()) { for (auto el_index : EarlyLate::rangeIndex()) {
slew_sigma_models_[el_index] = slew_sigma_models ? slew_sigma_models[el_index] : nullptr; slew_sigma_models_[el_index] = slew_sigma_models
delay_sigma_models_[el_index] = delay_sigma_models ? delay_sigma_models[el_index] : nullptr; ? slew_sigma_models[el_index]
: nullptr;
delay_sigma_models_[el_index] = delay_sigma_models
? delay_sigma_models[el_index]
: nullptr;
} }
} }
@ -59,7 +67,7 @@ GateTableModel::~GateTableModel()
{ {
delete delay_model_; delete delay_model_;
delete slew_model_; delete slew_model_;
delete output_current_; delete output_waveforms_;
deleteSigmaModels(slew_sigma_models_); deleteSigmaModels(slew_sigma_models_);
deleteSigmaModels(delay_sigma_models_); deleteSigmaModels(delay_sigma_models_);
} }
@ -165,8 +173,6 @@ GateTableModel::reportGateDelay(const LibertyCell *cell,
load_cap, related_out_cap); load_cap, related_out_cap);
if (drvr_slew < 0.0) if (drvr_slew < 0.0)
*result += "Negative slew clipped to 0.0\n"; *result += "Negative slew clipped to 0.0\n";
if (output_current_)
output_current_->reportWaveform(cell, pvt, in_slew, load_cap, digits, result);
} }
void void
@ -801,6 +807,13 @@ Table0::report(const Units *units,
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
Table1::Table1() :
Table(),
values_(nullptr),
axis1_(nullptr)
{
}
Table1::Table1(FloatSeq *values, Table1::Table1(FloatSeq *values,
TableAxisPtr axis1) : TableAxisPtr axis1) :
Table(), Table(),
@ -809,11 +822,30 @@ Table1::Table1(FloatSeq *values,
{ {
} }
Table1::Table1(Table1 &&table) :
Table(),
values_(table.values_),
axis1_(table.axis1_)
{
table.values_ = nullptr;
table.axis1_ = nullptr;
}
Table1::~Table1() Table1::~Table1()
{ {
delete values_; delete values_;
} }
Table1 &
Table1::operator=(Table1 &&table)
{
values_ = table.values_;
axis1_ = table.axis1_;
table.values_ = nullptr;
table.axis1_ = nullptr;
return *this;
}
float float
Table1::value(size_t index1, Table1::value(size_t index1,
size_t, size_t,
@ -832,6 +864,19 @@ float
Table1::findValue(float value1, Table1::findValue(float value1,
float, float,
float) const float) const
{
return findValue(value1);
}
float
Table1::findValue(float value1) const
{
return findValue(value1, true);
}
float
Table1::findValue(float value1,
bool extrapolate) const
{ {
if (axis1_->size() == 1) if (axis1_->size() == 1)
return value(value1); return value(value1);
@ -843,7 +888,12 @@ Table1::findValue(float value1,
float y1 = value(index1); float y1 = value(index1);
float y2 = value(index1 + 1); float y2 = value(index1 + 1);
float dx1 = (x1 - x1l) / (x1u - x1l); float dx1 = (x1 - x1l) / (x1u - x1l);
return (1 - dx1) * y1 + dx1 * y2; if (x1 <= x1l && !extrapolate)
return y1;
else if (x1 >= x1u && !extrapolate)
return y2;
else
return (1 - dx1) * y1 + dx1 * y2;
} }
} }
@ -1514,26 +1564,67 @@ tableVariableUnit(TableAxisVariable variable,
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
OutputCurrentWaveform::OutputCurrentWaveform(float axis_value1, OutputWaveform::OutputWaveform(float slew,
float axis_value2, float cap,
TableAxisPtr axis, Table1 *currents,
Table1 *currents, float reference_time) :
float reference_time) : slew_(slew),
axis_value1_(axis_value1), cap_(cap),
axis_value2_(axis_value2),
axis_(axis),
currents_(currents), currents_(currents),
voltages_(nullptr),
reference_time_(reference_time) reference_time_(reference_time)
{ {
} }
OutputCurrentWaveform::~OutputCurrentWaveform() OutputWaveform::OutputWaveform(float slew,
float cap,
Table1 *currents,
Table1 *voltages,
float reference_time) :
slew_(slew),
cap_(cap),
currents_(currents),
voltages_(voltages),
reference_time_(reference_time)
{
}
OutputWaveform::~OutputWaveform()
{ {
delete currents_; delete currents_;
delete voltages_;
}
Table1 *
OutputWaveform::voltages()
{
if (voltages_ == nullptr) {
FloatSeq *voltages = new FloatSeq;
voltages_ = new Table1(voltages, currents_->axis1());
// i = C dv/dt
// Integrate current waveform to find voltage waveform.
TableAxisPtr time_axis = currents_->axis1();
float prev_time = time_axis->axisValue(0);
float prev_current = currents_->value(0);
float voltage = 0.0;
voltages->push_back(voltage);
bool invert = currents_->value(time_axis->size() - 1) < 0.0;
for (size_t i = 1; i < time_axis->size(); i++) {
float time = time_axis->axisValue(i);
float current = currents_->value(i);
float dv = (current + prev_current) / 2.0 * (time - prev_time) / cap_;
voltage += invert ? -dv : dv;
voltages->push_back(voltage);
prev_time = time;
prev_current = current;
}
}
return voltages_;
} }
bool bool
OutputCurrentWaveform::checkAxes(TableTemplate *tbl_template) OutputWaveform::checkAxes(TableTemplate *tbl_template)
{ {
TableAxisPtr axis1 = tbl_template->axis1(); TableAxisPtr axis1 = tbl_template->axis1();
TableAxisPtr axis2 = tbl_template->axis2(); TableAxisPtr axis2 = tbl_template->axis2();
@ -1549,83 +1640,181 @@ OutputCurrentWaveform::checkAxes(TableTemplate *tbl_template)
&& axis3->variable() == TableAxisVariable::time); && axis3->variable() == TableAxisVariable::time);
} }
void string
OutputCurrentWaveform::reportWaveform(const Units *units, OutputWaveform::reportCurrentWaveform(const Units *units,
int digits, int digits) const
string *result)
{ {
TableAxisPtr time_axis = currents_->axis1();
const Unit *time_unit = units->timeUnit(); const Unit *time_unit = units->timeUnit();
const Unit *current_unit = units->currentUnit(); const Unit *current_unit = units->currentUnit();
for (size_t i = 0; i < axis_->values()->size(); i++) { return reportWaveform(currents_, time_unit, current_unit, digits);
*result += time_unit->asString(axis_->axisValue(i), digits); }
*result += " ";
string
OutputWaveform::reportVoltageWaveform(const Units *units,
int digits) const
{
TableAxisPtr time_axis = voltages_->axis1();
const Unit *time_unit = units->timeUnit();
const Unit *voltage_unit = units->voltageUnit();
return reportWaveform(voltages_, time_unit, voltage_unit, digits);
}
string
OutputWaveform::reportWaveform(const Table1 *waveform,
const Unit *time_unit,
const Unit *waveform_unit,
int digits) const
{
string result;
TableAxisPtr time_axis = waveform->axis1();
for (size_t i = 0; i < time_axis->values()->size(); i++) {
float time = time_axis->axisValue(i);
result += time_unit->asString(time, digits);
result += " ";
} }
*result += '\n'; result += '\n';
for (size_t i = 0; i < currents_->axis1()->size(); i++) {
*result += current_unit->asString(currents_->value(i), digits); for (size_t i = 0; i < time_axis->size(); i++) {
*result += " "; float value = waveform->value(i);
result += waveform_unit->asString(value, digits);
result += " ";
} }
*result += '\n'; return result;
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
OutputCurrent::OutputCurrent(TableAxisPtr axis1, OutputWaveforms::OutputWaveforms(TableAxisPtr slew_axis,
TableAxisPtr axis2, TableAxisPtr cap_axis,
OutputCurrentWaveformSeq &waveforms) : OutputWaveformSeq &waveforms) :
axis1_(axis1), slew_axis_(slew_axis),
axis2_(axis2), cap_axis_(cap_axis),
waveforms_(waveforms) waveforms_(waveforms)
{ {
} }
OutputCurrent::~OutputCurrent() OutputWaveforms::~OutputWaveforms()
{ {
waveforms_.deleteContents(); waveforms_.deleteContents();
} }
void OutputWaveform
OutputCurrent::reportWaveform(const LibertyCell *cell, OutputWaveforms::voltageWaveform(float slew,
const Pvt *, float cap)
float in_slew,
float load_cap,
int digits,
string *result) const
{ {
float axis_value1, axis_value2; size_t slew_index = slew_axis_->findAxisIndex(slew);
findAxisValues(in_slew, load_cap, size_t cap_index = cap_axis_->findAxisIndex(cap);
axis_value1, axis_value2); size_t wave_index00 = slew_index * cap_axis_->size() + cap_index;
size_t index1 = axis1_->findAxisIndex(axis_value1); size_t wave_index01 = slew_index * cap_axis_->size() + (cap_index + 1);
size_t index2 = axis2_->findAxisIndex(axis_value2); size_t wave_index10 = (slew_index + 1) * cap_axis_->size() + cap_index;
size_t index = index1 * axis2_->size() + index2; size_t wave_index11 = (slew_index + 1) * cap_axis_->size() + (cap_index + 1);
waveforms_[index]->reportWaveform(cell->libertyLibrary()->units(), digits, result); OutputWaveform *waveform00 = waveforms_[wave_index00];
} OutputWaveform *waveform01 = waveforms_[wave_index01];
OutputWaveform *waveform10 = waveforms_[wave_index10];
OutputWaveform *waveform11 = waveforms_[wave_index11];
const Table1 *voltages00 = waveform00->voltages();
const Table1 *voltages01 = waveform01->voltages();
const Table1 *voltages10 = waveform10->voltages();
const Table1 *voltages11 = waveform11->voltages();
TableAxisPtr time_axis00 = voltages00->axis1();
TableAxisPtr time_axis01 = voltages01->axis1();
TableAxisPtr time_axis10 = voltages10->axis1();
TableAxisPtr time_axis11 = voltages11->axis1();
void // Find time axis min/max.
OutputCurrent::findAxisValues(float in_slew, size_t time_step_count = 20;
float load_cap, float time_min = time_axis00->min();
// Return values. time_min = min(time_min, time_axis01->min());
float &axis_value1, time_min = min(time_min, time_axis10->min());
float &axis_value2) const time_min = min(time_min, time_axis11->min());
{ float time_max = time_axis00->max();
axis_value1 = axisValue(axis1_, in_slew, load_cap); time_max = max(time_max, time_axis01->max());
axis_value2 = axisValue(axis2_, in_slew, load_cap); time_max = max(time_max, time_axis10->max());
} time_max = max(time_max, time_axis11->max());
float time_step = (time_max - time_min) / time_step_count;
FloatSeq *time_values = new FloatSeq;
TableAxisPtr time_axis = make_shared<TableAxis>(time_axis00->variable(),
time_values);
float // Interpolate waveform samples at time steps.
OutputCurrent::axisValue(TableAxisPtr axis, float volt_max = voltages00->value(voltages00->values()->size() - 1);
float in_slew, size_t index1 = slew_index;
float load_cap) const size_t index2 = cap_index;
{ float x1 = slew;
TableAxisVariable var = axis->variable(); float x2 = cap;
if (var == TableAxisVariable::input_net_transition) float x1l = slew_axis_->axisValue(index1);
return in_slew; float x1u = slew_axis_->axisValue(index1 + 1);
else if (var == TableAxisVariable::total_output_net_capacitance) float dx1 = (x1 - x1l) / (x1u - x1l);
return load_cap; float x2l = cap_axis_->axisValue(index2);
else { float x2u = cap_axis_->axisValue(index2 + 1);
criticalError(240, "unsupported table axes"); float dx2 = (x2 - x2l) / (x2u - x2l);
return 0.0; FloatSeq *voltages = new FloatSeq;
bool waveform_started = false;
float prev_volt = 0.0;
constexpr float volt_tol = .01;
float volt_end = volt_max * (1.0 - volt_tol);
for (size_t i = 0; i <= time_step_count; i++) {
float time = time_min + time_step * i;
float y00 = voltages00->findValue(time, true);
float y10 = voltages10->findValue(time, true);
float y11 = voltages11->findValue(time, true);
float y01 = voltages01->findValue(time, true);
float voltage
= (1 - dx1) * (1 - dx2) * y00
+ dx1 * (1 - dx2) * y10
+ dx1 * dx2 * y11
+ (1 - dx1) * dx2 * y01;
if (voltage > volt_tol)
waveform_started = true;
if (waveform_started) {
time_values->push_back(time);
voltages->push_back(voltage);
}
if (prev_volt > volt_end)
break;
prev_volt = voltage;
} }
// Interpolate reference time.
// (only depends on slew)
float ref_time
= (1 - dx1) * waveform00->referenceTime()
+ dx1 * waveform10->referenceTime();
Table1 *waveform = new Table1(voltages, time_axis);
return OutputWaveform(slew, cap, nullptr, waveform, ref_time);
}
////////////////////////////////////////////////////////////////
DriverWaveform::DriverWaveform(const char *name,
TablePtr waveforms) :
name_(name),
waveforms_(waveforms)
{
}
DriverWaveform::~DriverWaveform()
{
stringDelete(name_);
}
Table1
DriverWaveform::waveform(float slew)
{
TableAxisPtr volt_axis = waveforms_->axis2();
FloatSeq *time_values = new FloatSeq;
FloatSeq *volt_values = new FloatSeq;
for (float volt : *volt_axis->values()) {
float time = waveforms_->findValue(slew, volt, 0.0);
time_values->push_back(time);
volt_values->push_back(volt);
}
TableAxisPtr time_axis = make_shared<TableAxis>(TableAxisVariable::time,
time_values);
Table1 waveform(volt_values, time_axis);
return waveform;
} }
} // namespace } // namespace

View File

@ -1,173 +1,173 @@
0001 DmpCeff.cc:1597 cell %s delay model not supported on SPF parasitics by DMP delay calculator 0001 DmpCeff.cc:1597 cell %s delay model not supported on SPF parasitics by DMP delay calculator
0002 Liberty.cc:749 cell %s/%s port %s not found in cell %s/%s. 0002 Liberty.cc:750 cell %s/%s port %s not found in cell %s/%s.
0003 Liberty.cc:775 cell %s/%s %s -> %s timing group %s not found in cell %s/%s. 0003 Liberty.cc:776 cell %s/%s %s -> %s timing group %s not found in cell %s/%s.
0004 Liberty.cc:1710 cell %s/%s %s -> %s latch enable %s_edge is inconsistent with %s -> %s setup_%s check. 0004 Liberty.cc:1728 cell %s/%s %s -> %s latch enable %s_edge is inconsistent with %s -> %s setup_%s check.
0005 Liberty.cc:1724 cell %s/%s %s -> %s latch enable %s_edge is inconsistent with latch group enable function positive sense. 0005 Liberty.cc:1742 cell %s/%s %s -> %s latch enable %s_edge is inconsistent with latch group enable function positive sense.
0006 Liberty.cc:1732 cell %s/%s %s -> %s latch enable %s_edge is inconsistent with latch group enable function negative sense. 0006 Liberty.cc:1750 cell %s/%s %s -> %s latch enable %s_edge is inconsistent with latch group enable function negative sense.
0007 LibertyExpr.cc:82 %s references unknown port %s. 0007 LibertyExpr.cc:82 %s references unknown port %s.
0008 ConcreteNetwork.cc:1924 cell type %s can not be linked. 0008 ConcreteNetwork.cc:1917 cell type %s can not be linked.
0009 CycleAccting.cc:87 No common period was found between clocks %s and %s. 0009 CycleAccting.cc:87 No common period was found between clocks %s and %s.
0010 Genclks.cc:274 no master clock found for generated clock %s. 0010 Genclks.cc:274 no master clock found for generated clock %s.
0013 Genclks.cc:938 generated clock %s source pin %s missing paths from master clock %s. 0013 Genclks.cc:938 generated clock %s source pin %s missing paths from master clock %s.
0015 Sim.cc:865 propagated logic value %c differs from constraint value of %c on pin %s. 0015 Sim.cc:865 propagated logic value %c differs from constraint value of %c on pin %s.
0016 LibertyReader.cc:1045 default_max_fanout is 0.0. 0016 LibertyReader.cc:1049 default_max_fanout is 0.0.
0017 Sta.cc:2093 '%s' is not a valid endpoint. 0017 Sta.cc:2093 '%s' is not a valid endpoint.
0018 Sta.cc:2017 '%s' is not a valid start point. 0018 Sta.cc:2017 '%s' is not a valid start point.
0021 SpefParse.yy:805 %d is not positive. 0021 SpefParse.yy:805 %d is not positive.
0022 SpefParse.yy:814 %.4f is not positive. 0022 SpefParse.yy:814 %.4f is not positive.
0023 SpefParse.yy:820 %.4f is not positive. 0023 SpefParse.yy:820 %.4f is not positive.
0024 WritePathSpice.cc:425 pg_pin %s/%s voltage %s not found, 0024 WritePathSpice.cc:458 pg_pin %s/%s voltage %s not found,
0025 WritePathSpice.cc:432 Liberty pg_port %s/%s missing voltage_name attribute, 0025 WritePathSpice.cc:465 Liberty pg_port %s/%s missing voltage_name attribute,
0026 WritePathSpice.cc:960 %s pg_port %s not found, 0026 WritePathSpice.cc:1037 %s pg_port %s not found,
0027 WritePathSpice.cc:1015 no register/latch found for path from %s to %s, 0027 WritePathSpice.cc:1092 no register/latch found for path from %s to %s,
0028 WritePathSpice.cc:1382 The following subkcts are missing from %s 0028 WritePathSpice.cc:1464 The subkct file %s is missing definitions for %s
0029 WritePathSpice.cc:1440 subckt %s port %s has no corresponding liberty port, pg_port and is not power or ground. 0029 WritePathSpice.cc:1562 subckt %s port %s has no corresponding liberty port, pg_port and is not power or ground.
0030 LibertyReader.cc:624 library missing name. 0030 LibertyReader.cc:628 library missing name.
0031 LibertyReader.cc:656 default_wire_load %s not found. 0031 LibertyReader.cc:660 default_wire_load %s not found.
0032 LibertyReader.cc:667 default_wire_selection %s not found. 0032 LibertyReader.cc:671 default_wire_selection %s not found.
0033 LibertyReader.cc:689 input_threshold_pct_%s not found. 0033 LibertyReader.cc:693 input_threshold_pct_%s not found.
0034 LibertyReader.cc:693 output_threshold_pct_%s not found. 0034 LibertyReader.cc:697 output_threshold_pct_%s not found.
0035 LibertyReader.cc:697 slew_lower_threshold_pct_%s not found. 0035 LibertyReader.cc:701 slew_lower_threshold_pct_%s not found.
0036 LibertyReader.cc:701 slew_upper_threshold_pct_%s not found. 0036 LibertyReader.cc:705 slew_upper_threshold_pct_%s not found.
0037 LibertyReader.cc:706 Library %s is missing one or more thresholds. 0037 LibertyReader.cc:710 Library %s is missing one or more thresholds.
0038 LibertyReader.cc:796 unknown unit multiplier %s. 0038 LibertyReader.cc:800 unknown unit multiplier %s.
0039 LibertyReader.cc:815 unknown unit scale %c. 0039 LibertyReader.cc:819 unknown unit scale %c.
0040 LibertyReader.cc:818 unknown unit suffix %s. 0040 LibertyReader.cc:822 unknown unit suffix %s.
0041 LibertyReader.cc:844 capacitive_load_units are not ff or pf. 0041 LibertyReader.cc:848 capacitive_load_units are not ff or pf.
0042 LibertyReader.cc:847 capacitive_load_units are not a string. 0042 LibertyReader.cc:851 capacitive_load_units are not a string.
0043 LibertyReader.cc:850 capacitive_load_units missing suffix. 0043 LibertyReader.cc:854 capacitive_load_units missing suffix.
0044 LibertyReader.cc:853 capacitive_load_units scale is not a float. 0044 LibertyReader.cc:857 capacitive_load_units scale is not a float.
0045 LibertyReader.cc:856 capacitive_load_units missing scale and suffix. 0045 LibertyReader.cc:860 capacitive_load_units missing scale and suffix.
0046 LibertyReader.cc:859 capacitive_load_unit missing values suffix. 0046 LibertyReader.cc:863 capacitive_load_unit missing values suffix.
0047 LibertyReader.cc:877 delay_model %s not supported. 0047 LibertyReader.cc:881 delay_model %s not supported.
0048 LibertyReader.cc:881 delay_model %s not supported. 0048 LibertyReader.cc:885 delay_model %s not supported.
0049 LibertyReader.cc:885 delay_model %s not supported. 0049 LibertyReader.cc:889 delay_model %s not supported.
0050 LibertyReader.cc:890 delay_model %s not supported. 0050 LibertyReader.cc:894 delay_model %s not supported.
. .
0051 LibertyReader.cc:893 unknown delay_model %s 0051 LibertyReader.cc:897 unknown delay_model %s
. .
0052 LibertyReader.cc:912 unknown bus_naming_style format. 0052 LibertyReader.cc:916 unknown bus_naming_style format.
0053 LibertyReader.cc:590 library %s already exists. 0053 LibertyReader.cc:594 library %s already exists.
0054 LibertyReader.cc:933 voltage_map voltage is not a float. 0054 LibertyReader.cc:937 voltage_map voltage is not a float.
0055 LibertyReader.cc:936 voltage_map missing voltage. 0055 LibertyReader.cc:940 voltage_map missing voltage.
0056 LibertyReader.cc:939 voltage_map supply name is not a string. 0056 LibertyReader.cc:943 voltage_map supply name is not a string.
0057 LibertyReader.cc:942 voltage_map missing supply name and voltage. 0057 LibertyReader.cc:946 voltage_map missing supply name and voltage.
0058 LibertyReader.cc:945 voltage_map missing values suffix. 0058 LibertyReader.cc:949 voltage_map missing values suffix.
0059 LibertyReader.cc:1163 default_wire_load_mode %s not found. 0059 LibertyReader.cc:1167 default_wire_load_mode %s not found.
0060 LibertyReader.cc:679 default_operating_condition %s not found. 0060 LibertyReader.cc:683 default_operating_condition %s not found.
0061 LibertyReader.cc:1334 table template missing name. 0061 LibertyReader.cc:1338 table template missing name.
0062 LibertyReader.cc:1379 missing variable_%d attribute. 0062 LibertyReader.cc:1383 missing variable_%d attribute.
0063 LibertyReader.cc:1422 axis type %s not supported. 0063 LibertyReader.cc:1426 axis type %s not supported.
0064 LibertyReader.cc:1482 bus type %s missing bit_from. 0064 LibertyReader.cc:1486 bus type %s missing bit_from.
0065 LibertyReader.cc:1484 bus type %s missing bit_to. 0065 LibertyReader.cc:1488 bus type %s missing bit_to.
0066 LibertyReader.cc:1488 type missing name. 0066 LibertyReader.cc:1492 type missing name.
0067 LibertyReader.cc:1515 scaling_factors do not have a name. 0067 LibertyReader.cc:1519 scaling_factors do not have a name.
0068 LibertyReader.cc:1683 operating_conditions missing name. 0068 LibertyReader.cc:1687 operating_conditions missing name.
0069 LibertyReader.cc:1753 wire_load missing name. 0069 LibertyReader.cc:1757 wire_load missing name.
0070 LibertyReader.cc:1796 fanout_length is missing length and fanout. 0070 LibertyReader.cc:1800 fanout_length is missing length and fanout.
0071 LibertyReader.cc:1811 wire_load_selection missing name. 0071 LibertyReader.cc:1815 wire_load_selection missing name.
0072 LibertyReader.cc:1842 wireload %s not found. 0072 LibertyReader.cc:1846 wireload %s not found.
0074 LibertyReader.cc:1849 wire_load_from_area min not a float. 0074 LibertyReader.cc:1853 wire_load_from_area min not a float.
0075 LibertyReader.cc:1852 wire_load_from_area max not a float. 0075 LibertyReader.cc:1856 wire_load_from_area max not a float.
0076 LibertyReader.cc:1855 wire_load_from_area missing parameters. 0076 LibertyReader.cc:1859 wire_load_from_area missing parameters.
0077 LibertyReader.cc:1858 wire_load_from_area missing parameters. 0077 LibertyReader.cc:1862 wire_load_from_area missing parameters.
0078 LibertyReader.cc:1875 cell missing name. 0078 LibertyReader.cc:1879 cell missing name.
0079 LibertyReader.cc:1898 cell %s ocv_derate_group %s not found. 0079 LibertyReader.cc:1902 cell %s ocv_derate_group %s not found.
0080 LibertyReader.cc:1934 port %s function size does not match port size. 0080 LibertyReader.cc:1938 port %s function size does not match port size.
0081 LibertyReader.cc:2002 %s %s bus width mismatch. 0081 LibertyReader.cc:2006 %s %s bus width mismatch.
0082 LibertyReader.cc:2013 %s %s bus width mismatch. 0082 LibertyReader.cc:2017 %s %s bus width mismatch.
0083 LibertyReader.cc:2023 clear 0083 LibertyReader.cc:2027 clear
0084 LibertyReader.cc:2033 preset 0084 LibertyReader.cc:2037 preset
0085 LibertyReader.cc:2069 latch enable function is non-unate for port %s. 0085 LibertyReader.cc:2073 latch enable function is non-unate for port %s.
0086 LibertyReader.cc:2074 latch enable function is unknown for port %s. 0086 LibertyReader.cc:2078 latch enable function is unknown for port %s.
0087 LibertyReader.cc:2150 operating conditions %s not found. 0087 LibertyReader.cc:2154 operating conditions %s not found.
0088 LibertyReader.cc:2153 scaled_cell missing operating condition. 0088 LibertyReader.cc:2157 scaled_cell missing operating condition.
0089 LibertyReader.cc:2156 scaled_cell cell %s has not been defined. 0089 LibertyReader.cc:2160 scaled_cell cell %s has not been defined.
0090 LibertyReader.cc:2159 scaled_cell missing name. 0090 LibertyReader.cc:2163 scaled_cell missing name.
0091 LibertyReader.cc:2185 scaled_cell %s, %s port functions do not match cell port functions. 0091 LibertyReader.cc:2189 scaled_cell %s, %s port functions do not match cell port functions.
0092 LibertyReader.cc:2190 scaled_cell ports do not match cell ports. 0092 LibertyReader.cc:2194 scaled_cell ports do not match cell ports.
0093 LibertyReader.cc:2192 scaled_cell %s, %s timing does not match cell timing. 0093 LibertyReader.cc:2196 scaled_cell %s, %s timing does not match cell timing.
0094 LibertyReader.cc:2211 combinational timing to an input port. 0094 LibertyReader.cc:2215 combinational timing to an input port.
0095 LibertyReader.cc:2302 missing %s_transition. 0095 LibertyReader.cc:2306 missing %s_transition.
0096 LibertyReader.cc:2304 missing cell_%s. 0096 LibertyReader.cc:2308 missing cell_%s.
0099 LibertyReader.cc:2821 scaling_factors %s not found. 0099 LibertyReader.cc:2900 scaling_factors %s not found.
0100 LibertyReader.cc:2864 pin name is not a string. 0100 LibertyReader.cc:2943 pin name is not a string.
0101 LibertyReader.cc:2883 pin name is not a string. 0101 LibertyReader.cc:2962 pin name is not a string.
0102 LibertyReader.cc:2899 pin name is not a string. 0102 LibertyReader.cc:2978 pin name is not a string.
0103 LibertyReader.cc:2977 bus %s bus_type not found. 0103 LibertyReader.cc:3056 bus %s bus_type not found.
0104 LibertyReader.cc:3033 bus_type %s not found. 0104 LibertyReader.cc:3112 bus_type %s not found.
0105 LibertyReader.cc:3036 bus_type is not a string. 0105 LibertyReader.cc:3115 bus_type is not a string.
0106 LibertyReader.cc:3054 bundle %s member not found. 0106 LibertyReader.cc:3133 bundle %s member not found.
0107 LibertyReader.cc:3081 member is not a string. 0107 LibertyReader.cc:3160 member is not a string.
0108 LibertyReader.cc:3088 members attribute is missing values. 0108 LibertyReader.cc:3167 members attribute is missing values.
0109 LibertyReader.cc:3139 unknown port direction. 0109 LibertyReader.cc:3218 unknown port direction.
0110 LibertyReader.cc:3507 pulse_latch unknown pulse type. 0110 LibertyReader.cc:3586 pulse_latch unknown pulse type.
0111 LibertyReader.cc:3885 unknown timing_type %s. 0111 LibertyReader.cc:3964 unknown timing_type %s.
0112 LibertyReader.cc:3905 unknown timing_sense %s. 0112 LibertyReader.cc:3984 unknown timing_sense %s.
0113 LibertyReader.cc:3945 mode value is not a string. 0113 LibertyReader.cc:4024 mode value is not a string.
0114 LibertyReader.cc:3948 missing mode value. 0114 LibertyReader.cc:4027 missing mode value.
0115 LibertyReader.cc:3951 mode name is not a string. 0115 LibertyReader.cc:4030 mode name is not a string.
0116 LibertyReader.cc:3954 mode missing values. 0116 LibertyReader.cc:4033 mode missing values.
0117 LibertyReader.cc:3957 mode missing mode name and value. 0117 LibertyReader.cc:4036 mode missing mode name and value.
0118 LibertyReader.cc:2541 unsupported model axis. 0118 LibertyReader.cc:2547 unsupported model axis.
0119 LibertyReader.cc:4060 unsupported model axis. 0119 LibertyReader.cc:4139 unsupported model axis.
0120 LibertyReader.cc:4089 unsupported model axis. 0120 LibertyReader.cc:4168 unsupported model axis.
0121 LibertyReader.cc:4124 unsupported model axis. 0121 LibertyReader.cc:4203 unsupported model axis.
0122 LibertyReader.cc:4179 table template %s not found. 0122 LibertyReader.cc:4258 table template %s not found.
0123 LibertyReader.cc:4258 %s is missing values. 0123 LibertyReader.cc:4337 %s is missing values.
0124 LibertyReader.cc:4283 %s is not a list of floats. 0124 LibertyReader.cc:4362 %s is not a list of floats.
0125 LibertyReader.cc:4285 table row has %u columns but axis has %d. 0125 LibertyReader.cc:4364 table row has %u columns but axis has %d.
0126 LibertyReader.cc:4295 table has %u rows but axis has %d. 0126 LibertyReader.cc:4374 table has %u rows but axis has %d.
0127 LibertyReader.cc:4348 lut output is not a string. 0127 LibertyReader.cc:4427 lut output is not a string.
0128 LibertyReader.cc:4390 mode definition missing name. 0128 LibertyReader.cc:4469 mode definition missing name.
0129 LibertyReader.cc:4407 mode value missing name. 0129 LibertyReader.cc:4486 mode value missing name.
0130 LibertyReader.cc:4421 when attribute inside table model. 0130 LibertyReader.cc:4500 when attribute inside table model.
0131 LibertyReader.cc:4470 %s attribute is not a string. 0131 LibertyReader.cc:4549 %s attribute is not a string.
0132 LibertyReader.cc:4473 %s is not a simple attribute. 0132 LibertyReader.cc:4552 %s is not a simple attribute.
0133 LibertyReader.cc:4496 %s is not a simple attribute. 0133 LibertyReader.cc:4575 %s is not a simple attribute.
0134 LibertyReader.cc:4509 %s is not a simple attribute. 0134 LibertyReader.cc:4588 %s is not a simple attribute.
0135 LibertyReader.cc:4533 %s value %s is not a float. 0135 LibertyReader.cc:4612 %s value %s is not a float.
0136 LibertyReader.cc:4562 %s missing values. 0136 LibertyReader.cc:4641 %s missing values.
0137 LibertyReader.cc:4566 %s missing values. 0137 LibertyReader.cc:4645 %s missing values.
0138 LibertyReader.cc:4569 %s is not a complex attribute. 0138 LibertyReader.cc:4648 %s is not a complex attribute.
0139 LibertyReader.cc:4595 %s is not a float. 0139 LibertyReader.cc:4674 %s is not a float.
0140 LibertyReader.cc:4618 %s is missing values. 0140 LibertyReader.cc:4697 %s is missing values.
0141 LibertyReader.cc:4621 %s has more than one string. 0141 LibertyReader.cc:4700 %s has more than one string.
0142 LibertyReader.cc:4630 %s is missing values. 0142 LibertyReader.cc:4709 %s is missing values.
0143 LibertyReader.cc:4655 %s attribute is not boolean. 0143 LibertyReader.cc:4734 %s attribute is not boolean.
0144 LibertyReader.cc:4658 %s attribute is not boolean. 0144 LibertyReader.cc:4737 %s attribute is not boolean.
0145 LibertyReader.cc:4661 %s is not a simple attribute. 0145 LibertyReader.cc:4740 %s is not a simple attribute.
0146 LibertyReader.cc:4677 attribute %s value %s not recognized. 0146 LibertyReader.cc:4756 attribute %s value %s not recognized.
0147 LibertyReader.cc:4707 unknown early/late value. 0147 LibertyReader.cc:4786 unknown early/late value.
0148 LibertyReader.cc:4933 OCV derate group named %s not found. 0148 LibertyReader.cc:5012 OCV derate group named %s not found.
0149 LibertyReader.cc:4949 ocv_derate missing name. 0149 LibertyReader.cc:5028 ocv_derate missing name.
0150 LibertyReader.cc:5002 unknown rise/fall. 0150 LibertyReader.cc:5081 unknown rise/fall.
0151 LibertyReader.cc:5022 unknown derate type. 0151 LibertyReader.cc:5101 unknown derate type.
0152 LibertyReader.cc:5054 unsupported model axis. 0152 LibertyReader.cc:5133 unsupported model axis.
0153 LibertyReader.cc:5086 unsupported model axis. 0153 LibertyReader.cc:5165 unsupported model axis.
0154 LibertyReader.cc:5118 unsupported model axis. 0154 LibertyReader.cc:5197 unsupported model axis.
0155 LibertyReader.cc:5189 unknown pg_type. 0155 LibertyReader.cc:5268 unknown pg_type.
0156 LibertyReader.cc:5584 port %s subscript out of range. 0156 LibertyReader.cc:5663 port %s subscript out of range.
0157 LibertyReader.cc:5588 port range %s of non-bus port %s. 0157 LibertyReader.cc:5667 port range %s of non-bus port %s.
0158 LibertyReader.cc:5602 port %s not found. 0158 LibertyReader.cc:5681 port %s not found.
0159 LibertyReader.cc:5672 port %s not found. 0159 LibertyReader.cc:5751 port %s not found.
0160 LibertyReader.cc:1030 default_max_transition is 0.0. 0160 LibertyReader.cc:1034 default_max_transition is 0.0.
0161 LibertyReader.cc:3395 max_transition is 0.0. 0161 LibertyReader.cc:3474 max_transition is 0.0.
0162 LibertyReader.cc:4493 %s attribute is not an integer. 0162 LibertyReader.cc:4572 %s attribute is not an integer.
0163 LibertyReader.cc:1135 default_fanout_load is 0.0. 0163 LibertyReader.cc:1139 default_fanout_load is 0.0.
0164 LibertyReader.cc:2324 timing group from output port. 0164 LibertyReader.cc:2328 timing group from output port.
0165 LibertyReader.cc:2334 timing group from output port. 0165 LibertyReader.cc:2338 timing group from output port.
0166 LibertyReader.cc:2344 timing group from output port. 0166 LibertyReader.cc:2348 timing group from output port.
0167 LibertyReader.cc:2362 timing group from output port. 0167 LibertyReader.cc:2366 timing group from output port.
0168 LibertyReader.cc:2377 timing group from output port. 0168 LibertyReader.cc:2381 timing group from output port.
0169 LibertyReader.cc:4365 cell %s test_cell redefinition. 0169 LibertyReader.cc:4444 cell %s test_cell redefinition.
0170 LibertyReader.cc:3804 timing group missing related_pin/related_bus_pin. 0170 LibertyReader.cc:3883 timing group missing related_pin/related_bus_pin.
0179 SpefReader.cc:733 %s. 0179 SpefReader.cc:734 %s.
0190 VerilogReader.cc:1756 %s is not a verilog module. 0190 VerilogReader.cc:1756 %s is not a verilog module.
0191 VerilogReader.cc:1761 %s is not a verilog module. 0191 VerilogReader.cc:1761 %s is not a verilog module.
0201 StaTcl.i:117 no network has been linked. 0201 StaTcl.i:118 no network has been linked.
0202 StaTcl.i:131 network does not support edits. 0202 StaTcl.i:132 network does not support edits.
0204 StaTcl.i:4021 POCV support requires compilation with SSTA=1. 0204 StaTcl.i:4072 POCV support requires compilation with SSTA=1.
0206 LibertyExpr.cc:175 %s %s. 0206 LibertyExpr.cc:175 %s %s.
0207 GraphDelayCalc1.cc:738 port not found in cell 0207 GraphDelayCalc1.cc:738 port not found in cell
0208 Graph.cc:793 arc_delay_annotated array bounds exceeded 0208 Graph.cc:793 arc_delay_annotated array bounds exceeded
@ -184,20 +184,20 @@
0252 PathEnumed.cc:135 enumerated path required time 0252 PathEnumed.cc:135 enumerated path required time
0253 PathGroup.cc:399 unknown path end type 0253 PathGroup.cc:399 unknown path end type
0254 PathVertexRep.cc:145 tag group missing tag 0254 PathVertexRep.cc:145 tag group missing tag
0255 ReportPath.cc:289 unsupported path type 0255 ReportPath.cc:287 unsupported path type
0256 ReportPath.cc:310 unsupported path type 0256 ReportPath.cc:308 unsupported path type
0257 ReportPath.cc:349 unsupported path type 0257 ReportPath.cc:347 unsupported path type
0259 ReportPath.cc:2378 unsupported path type 0259 ReportPath.cc:2376 unsupported path type
0260 Search.cc:2628 max tag group index exceeded 0260 Search.cc:2628 max tag group index exceeded
0261 Search.cc:2860 max tag index exceeded 0261 Search.cc:2860 max tag index exceeded
0262 Search.cc:3551 unexpected filter path 0262 Search.cc:3551 unexpected filter path
0263 Search.cc:3719 tns incr existing vertex 0263 Search.cc:3719 tns incr existing vertex
0264 Sta.cc:4174 corresponding timing arc set not found in equiv cells 0264 Sta.cc:4180 corresponding timing arc set not found in equiv cells
0265 TagGroup.cc:297 tag group missing tag 0265 TagGroup.cc:297 tag group missing tag
0266 Sta.cc:2090 '%s' is not a valid endpoint. 0266 Sta.cc:2090 '%s' is not a valid endpoint.
0267 Sta.cc:2014 '%s' is not a valid start point. 0267 Sta.cc:2014 '%s' is not a valid start point.
0272 StaTcl.i:4007 unknown common clk pessimism mode. 0272 StaTcl.i:4058 unknown common clk pessimism mode.
0273 StaTcl.i:4963 unknown clock sense 0273 StaTcl.i:5003 unknown clock sense
0299 Power.tcl:241 activity cannot be set on clock ports. 0299 Power.tcl:241 activity cannot be set on clock ports.
0300 CmdUtil.tcl:44 no commands match '$pattern'. 0300 CmdUtil.tcl:44 no commands match '$pattern'.
0301 Power.tcl:218 activity should be 0.0 to 1.0 or 2.0 0301 Power.tcl:218 activity should be 0.0 to 1.0 or 2.0
@ -461,8 +461,8 @@
0604 Sdc.tcl:281 unknown $unit prefix '$prefix'. 0604 Sdc.tcl:281 unknown $unit prefix '$prefix'.
0605 Sdc.tcl:3547 wire load model '$model_name' not found. 0605 Sdc.tcl:3547 wire load model '$model_name' not found.
0606 Property.tcl:77 get_property unsupported object type $object_type. 0606 Property.tcl:77 get_property unsupported object type $object_type.
0607 StaTcl.i:4257 unknown report path field %s 0607 StaTcl.i:4308 unknown report path field %s
0608 StaTcl.i:4269 unknown report path field %s 0608 StaTcl.i:4320 unknown report path field %s
0609 Search.tcl:421 -all_violators is deprecated. Use -violators 0609 Search.tcl:421 -all_violators is deprecated. Use -violators
0610 Search.tcl:501 -max_transition deprecated. Use -max_slew. 0610 Search.tcl:501 -max_transition deprecated. Use -max_slew.
0611 Search.tcl:506 -min_transition deprecated. Use -min_slew. 0611 Search.tcl:506 -min_transition deprecated. Use -min_slew.
@ -480,7 +480,7 @@
0702 LibertyWriter.cc:436 3 axis table models not supported. 0702 LibertyWriter.cc:436 3 axis table models not supported.
0703 LibertyWriter.cc:576 %s/%s/%s timing arc type %s not supported. 0703 LibertyWriter.cc:576 %s/%s/%s timing arc type %s not supported.
0704 LibertyWriter.cc:289 %s/%s bundled ports not supported. 0704 LibertyWriter.cc:289 %s/%s bundled ports not supported.
0705 Liberty.cc:794 Liberty cell %s/%s for corner %s/%s not found. 0705 Liberty.cc:795 Liberty cell %s/%s for corner %s/%s not found.
0706 Parasitics.tcl:70 read_spef -increment is deprecated. 0706 Parasitics.tcl:70 read_spef -increment is deprecated.
0710 LumpedCapDelayCalc.cc:169 gate delay input variable is NaN 0710 LumpedCapDelayCalc.cc:169 gate delay input variable is NaN
0800 VcdReader.cc:109 unhandled vcd command. 0800 VcdReader.cc:109 unhandled vcd command.
@ -491,13 +491,15 @@
0806 ReadVcdActivities.cc:247 clock %s vcd period %s differs from SDC clock period %s 0806 ReadVcdActivities.cc:247 clock %s vcd period %s differs from SDC clock period %s
0807 Sdc.tcl:394 only one of -cells, -data_pins, -clock_pins, -async_pins, -output_pins are suppported. 0807 Sdc.tcl:394 only one of -cells, -data_pins, -clock_pins, -async_pins, -output_pins are suppported.
0810 MakeTimingModel.cc:189 clock %s pin %s is inside model block. 0810 MakeTimingModel.cc:189 clock %s pin %s is inside model block.
0900 LibertyReader.cc:2761 level_shifter_type must be HL, LH, or HL_LH 0900 LibertyReader.cc:2840 level_shifter_type must be HL, LH, or HL_LH
0901 LibertyReader.cc:2797 switch_cell_type must be coarse_grain or fine_grain 0901 LibertyReader.cc:2876 switch_cell_type must be coarse_grain or fine_grain
0902 LibertyReader.cc:2460 unsupported model axis. 0902 LibertyReader.cc:2464 unsupported model axis.
0903 LibertyReader.cc:4140 %s group not in timing group. 0903 LibertyReader.cc:4219 %s group not in timing group.
0904 LibertyReader.cc:2443 receiver_capacitance group not in timing or pin group. 0904 LibertyReader.cc:2447 receiver_capacitance group not in timing or pin group.
0906 LibertyReader.cc:4033 unsupported model axis. 0906 LibertyReader.cc:4112 unsupported model axis.
0907 LibertyReader.cc:2486 output_current_%s group not in timing group. 0907 LibertyReader.cc:2492 output_current_%s group not in timing group.
0908 LibertyReader.cc:2575 vector reference_time not found. 0908 LibertyReader.cc:2591 vector reference_time not found.
0912 LibertyReader.cc:2573 vector index_1 and index_2 must have one value. 0912 LibertyReader.cc:2589 vector index_1 and index_2 must have exactly one value.
0913 LibertyReader.cc:2525 output current waveform %.2e %.2e not found. 0913 LibertyReader.cc:2531 output current waveform %.2e %.2e not found.
0914 LibertyReader.cc:2624 normalized_driver_waveform variable_2 must be normalized_voltage
0915 LibertyReader.cc:2627 normalized_driver_waveform variable_1 must be input_net_transition

View File

@ -81,7 +81,7 @@ private:
void writeHeader(); void writeHeader();
void writeStageInstances(); void writeStageInstances();
void writeInputSource(); void writeInputSource();
void writeStepVoltSource(const Pin *pin, void writeRampVoltSource(const Pin *pin,
const RiseFall *rf, const RiseFall *rf,
float slew, float slew,
float time, float time,
@ -137,6 +137,11 @@ private:
void writeWaveformEdge(const RiseFall *rf, void writeWaveformEdge(const RiseFall *rf,
float time, float time,
float slew); float slew);
void writeWaveformVoltSource(const Pin *pin,
DriverWaveform *drvr_waveform,
const RiseFall *rf,
float slew,
int &volt_index);
void writeClkedStepSource(const Pin *pin, void writeClkedStepSource(const Pin *pin,
const RiseFall *rf, const RiseFall *rf,
const Clock *clk, const Clock *clk,
@ -164,6 +169,7 @@ private:
int &volt_index); int &volt_index);
float slewAxisMinValue(TimingArc *arc); float slewAxisMinValue(TimingArc *arc);
float pgPortVoltage(LibertyPgPort *pg_port); float pgPortVoltage(LibertyPgPort *pg_port);
void writePrintStmt();
// Stage "accessors". // Stage "accessors".
// //
@ -323,6 +329,7 @@ WritePathSpice::writeSpice()
// Find subckt port names as a side-effect of writeSubckts. // Find subckt port names as a side-effect of writeSubckts.
writeSubckts(); writeSubckts();
writeHeader(); writeHeader();
writePrintStmt();
writeStageInstances(); writeStageInstances();
writeMeasureStmts(); writeMeasureStmts();
writeInputSource(); writeInputSource();
@ -369,6 +376,18 @@ WritePathSpice::writeHeader()
float time_step = max_time / 1e+3; float time_step = max_time / 1e+3;
streamPrint(spice_stream_, ".tran %.3g %.3g\n\n", streamPrint(spice_stream_, ".tran %.3g %.3g\n\n",
time_step, max_time); time_step, max_time);
streamPrint(spice_stream_, ".options nomod\n");
}
void
WritePathSpice::writePrintStmt()
{
streamPrint(spice_stream_, ".print tran");
for (Stage stage = stageFirst(); stage <= stageLast(); stage++) {
streamPrint(spice_stream_, " v(%s)", stageDrvrPinName(stage));
streamPrint(spice_stream_, " v(%s)", stageLoadPinName(stage));
}
streamPrint(spice_stream_, "\n\n");
} }
float float
@ -477,11 +496,55 @@ WritePathSpice::writeInputWaveform()
float time0 = slew0; float time0 = slew0;
int volt_index = 1; int volt_index = 1;
const Pin *drvr_pin = stageDrvrPin(input_stage); const Pin *drvr_pin = stageDrvrPin(input_stage);
writeStepVoltSource(drvr_pin, rf, slew0, time0, volt_index); const Pin *load_pin = stageLoadPin(input_stage);
const LibertyPort *load_port = network_->libertyPort(load_pin);
DriverWaveform *drvr_waveform = nullptr;
if (load_port)
drvr_waveform = load_port->driverWaveform(rf);
if (drvr_waveform)
writeWaveformVoltSource(drvr_pin, drvr_waveform,
rf, slew0, volt_index);
else
writeRampVoltSource(drvr_pin, rf, slew0, time0, volt_index);
} }
void void
WritePathSpice::writeStepVoltSource(const Pin *pin, WritePathSpice::writeWaveformVoltSource(const Pin *pin,
DriverWaveform *drvr_waveform,
const RiseFall *rf,
float slew,
int &volt_index)
{
float volt0, volt1, volt_factor;
if (rf == RiseFall::rise()) {
volt0 = gnd_voltage_;
volt1 = power_voltage_;
volt_factor = power_voltage_;
}
else {
volt0 = power_voltage_;
volt1 = gnd_voltage_;
volt_factor = -power_voltage_;
}
streamPrint(spice_stream_, "v%d %s 0 pwl(\n",
volt_index,
network_->pathName(pin));
streamPrint(spice_stream_, "+%.3e %.3e\n", 0.0, volt0);
Table1 waveform = drvr_waveform->waveform(slew);
TableAxisPtr time_axis = waveform.axis1();
for (size_t time_index = 0; time_index < time_axis->size(); time_index++) {
float time = time_axis->axisValue(time_index);
float wave_volt = waveform.value(time_index);
float volt = volt0 + wave_volt * volt_factor;
streamPrint(spice_stream_, "+%.3e %.3e\n", time, volt);
}
streamPrint(spice_stream_, "+%.3e %.3e\n", maxTime(), volt1);
streamPrint(spice_stream_, "+)\n");
volt_index++;
}
void
WritePathSpice::writeRampVoltSource(const Pin *pin,
const RiseFall *rf, const RiseFall *rf,
float slew, float slew,
float time, float time,
@ -942,7 +1005,7 @@ WritePathSpice::writeClkedStepSource(const Pin *pin,
Vertex *vertex = graph_->pinLoadVertex(pin); Vertex *vertex = graph_->pinLoadVertex(pin);
float slew = findSlew(vertex, rf, nullptr, dcalc_ap_index); float slew = findSlew(vertex, rf, nullptr, dcalc_ap_index);
float time = clkWaveformTImeOffset(clk) + clk->period() / 2.0; float time = clkWaveformTImeOffset(clk) + clk->period() / 2.0;
writeStepVoltSource(pin, rf, slew, time, volt_index); writeRampVoltSource(pin, rf, slew, time, volt_index);
} }
void void

View File

@ -49,6 +49,7 @@
#include "Transition.hh" #include "Transition.hh"
#include "TimingRole.hh" #include "TimingRole.hh"
#include "TimingArc.hh" #include "TimingArc.hh"
#include "TableModel.hh"
#include "Liberty.hh" #include "Liberty.hh"
#include "LibertyWriter.hh" #include "LibertyWriter.hh"
#include "EquivCells.hh" #include "EquivCells.hh"
@ -567,13 +568,13 @@ using namespace sta;
%typemap(in) RiseFall* { %typemap(in) RiseFall* {
int length; int length;
const char *arg = Tcl_GetStringFromObj($input, &length); const char *arg = Tcl_GetStringFromObj($input, &length);
RiseFall *tr = RiseFall::find(arg); RiseFall *rf = RiseFall::find(arg);
if (tr == nullptr) { if (rf == nullptr) {
Tcl_SetResult(interp,const_cast<char*>("Error: unknown transition name."), Tcl_SetResult(interp,const_cast<char*>("Error: unknown rise/fall edge."),
TCL_STATIC); TCL_STATIC);
return TCL_ERROR; return TCL_ERROR;
} }
$1 = tr; $1 = rf;
} }
%typemap(out) RiseFall* { %typemap(out) RiseFall* {
@ -875,6 +876,44 @@ using namespace sta;
$1 = ints; $1 = ints;
} }
%typemap(out) Table1 {
Table1 &table = $1;
Tcl_Obj *list3 = Tcl_NewListObj(0, nullptr);
Tcl_Obj *list1 = Tcl_NewListObj(0, nullptr);
for (float f : *table.axis1()->values()) {
Tcl_Obj *obj = Tcl_NewDoubleObj(f);
Tcl_ListObjAppendElement(interp, list1, obj);
}
Tcl_Obj *list2 = Tcl_NewListObj(0, nullptr);
for (float f : *table.values()) {
Tcl_Obj *obj = Tcl_NewDoubleObj(f);
Tcl_ListObjAppendElement(interp, list2, obj);
}
Tcl_ListObjAppendElement(interp, list3, list1);
Tcl_ListObjAppendElement(interp, list3, list2);
Tcl_SetObjResult(interp, list3);
}
%typemap(out) Table1* {
Table1 *table = $1;
Tcl_Obj *list3 = Tcl_NewListObj(0, nullptr);
if (table) {
Tcl_Obj *list1 = Tcl_NewListObj(0, nullptr);
for (float f : *table->axis1()->values()) {
Tcl_Obj *obj = Tcl_NewDoubleObj(f);
Tcl_ListObjAppendElement(interp, list1, obj);
}
Tcl_Obj *list2 = Tcl_NewListObj(0, nullptr);
for (float f : *table->values()) {
Tcl_Obj *obj = Tcl_NewDoubleObj(f);
Tcl_ListObjAppendElement(interp, list2, obj);
}
Tcl_ListObjAppendElement(interp, list3, list1);
Tcl_ListObjAppendElement(interp, list3, list2);
}
Tcl_SetObjResult(interp, list3);
}
%typemap(in) MinMax* { %typemap(in) MinMax* {
int length; int length;
char *arg = Tcl_GetStringFromObj($input, &length); char *arg = Tcl_GetStringFromObj($input, &length);
@ -4586,17 +4625,6 @@ find_clk_min_period(const Clock *clk,
return sta->findClkMinPeriod(clk, ignore_port_paths); return sta->findClkMinPeriod(clk, ignore_port_paths);
} }
TmpString *
report_delay_calc_cmd(Edge *edge,
TimingArc *arc,
const Corner *corner,
const MinMax *min_max,
int digits)
{
cmdLinkedNetwork();
return Sta::sta()->reportDelayCalc(edge, arc, corner, min_max, digits);
}
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
PinSeq PinSeq
@ -5601,6 +5629,9 @@ full_name()
to); to);
} }
TimingArcSeq &
timing_arcs() { return self->arcs(); }
} // TimingArcSet methods } // TimingArcSet methods
%extend TimingArc { %extend TimingArc {
@ -5611,6 +5642,24 @@ const char *from_edge_name() { return self->fromEdge()->asRiseFall()->name(); }
Transition *to_edge() { return self->toEdge(); } Transition *to_edge() { return self->toEdge(); }
const char *to_edge_name() { return self->toEdge()->asRiseFall()->name(); } const char *to_edge_name() { return self->toEdge()->asRiseFall()->name(); }
TimingRole *role() { return self->role(); } TimingRole *role() { return self->role(); }
Table1
voltage_waveform(float in_slew,
float load_cap)
{
GateTableModel *gate_model = dynamic_cast<GateTableModel*>(self->model());
if (gate_model) {
OutputWaveforms *output_waveforms = gate_model->outputWaveforms();
if (output_waveforms) {
OutputWaveform voltage_waveform =
output_waveforms->voltageWaveform(in_slew, load_cap);
Table1 voltages(std::move(*voltage_waveform.voltages()));
return voltages;
}
}
return Table1();
}
} // TimingArc methods } // TimingArc methods
%extend Instance { %extend Instance {

View File

@ -56,11 +56,13 @@ RiseFall::opposite() const
} }
RiseFall * RiseFall *
RiseFall::find(const char *tr_str) RiseFall::find(const char *rf_str)
{ {
if (stringEq(tr_str, rise_.name())) if (stringEq(rf_str, rise_.name())
|| stringEq(rf_str, rise_.shortName()))
return &rise_; return &rise_;
else if (stringEq(tr_str, fall_.name())) else if (stringEq(rf_str, fall_.name())
|| stringEq(rf_str, fall_.shortName()))
return &fall_; return &fall_;
else else
return nullptr; return nullptr;