liberty driver_waveform
Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
parent
55fc69577a
commit
6c3ba16e07
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
|
||||||
|
|
@ -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_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
352
messages.txt
352
messages.txt
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
79
tcl/StaTcl.i
79
tcl/StaTcl.i
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue