From eeb1575d465f1637ab58bfdfa8d053ad23510a13 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Thu, 23 Mar 2023 07:01:04 -0700 Subject: [PATCH] Squashed commit of the following: commit 339ca3171ea95ba86c6234e7510578a9d863018d Author: James Cherry Date: Wed Mar 22 21:20:52 2023 -0700 ccs lib only use OutputWaveform for parsing Signed-off-by: James Cherry commit a1ba29146e3a15f1976bd30ade3f1f9929a67e05 Author: James Cherry Date: Wed Mar 22 20:28:31 2023 -0700 ccs Signed-off-by: James Cherry commit 44b19aeda1ab892192341544ea49ce466472a5af Author: James Cherry Date: Wed Mar 22 19:33:24 2023 -0700 ccs ref time tbl Signed-off-by: James Cherry commit a0ff298634117ddc0c7ef630f944a994ac7a29c2 Author: James Cherry Date: Wed Mar 22 19:15:56 2023 -0700 ccs lib Signed-off-by: James Cherry Signed-off-by: James Cherry --- include/sta/TableModel.hh | 127 ++++----- liberty/LibertyReader.cc | 31 ++- liberty/LibertyReaderPvt.hh | 21 ++ liberty/TableModel.cc | 538 ++++++++++++++++++------------------ tcl/StaTcl.i | 33 ++- 5 files changed, 401 insertions(+), 349 deletions(-) diff --git a/include/sta/TableModel.hh b/include/sta/TableModel.hh index 2d08f089..39d1c320 100644 --- a/include/sta/TableModel.hh +++ b/include/sta/TableModel.hh @@ -34,11 +34,11 @@ class Units; class Report; class Table; class OutputWaveforms; -class OutputWaveform; +class Table1; typedef Vector FloatSeq; typedef Vector FloatTable; -typedef Vector OutputWaveformSeq; +typedef Vector Table1Seq; TableAxisVariable stringTableAxisVariable(const char *variable); @@ -275,16 +275,16 @@ public: size_t axis_idx2, size_t axis_idx3) const = 0; // Table interpolated lookup. - virtual float findValue(float value1, - float value2, - float value3) const = 0; + virtual float findValue(float axis_value1, + float axis_value2, + float axis_value3) const = 0; // Table interpolated lookup with scale factor. float findValue(const LibertyLibrary *library, const LibertyCell *cell, const Pvt *pvt, - float value1, - float value2, - float value3) const; + float axis_value1, + float axis_value2, + float axis_value3) const; virtual void reportValue(const char *result_name, const LibertyLibrary *library, const LibertyCell *cell, @@ -306,12 +306,12 @@ class Table0 : public Table public: Table0(float value); virtual int order() const { return 0; } - virtual float value(size_t index1, - size_t index2, - size_t index3) const; - virtual float findValue(float value1, - float value2, - float value3) const; + virtual float value(size_t axis_index1, + size_t axis_index2, + size_t axis_index3) const; + virtual float findValue(float axis_value1, + float axis_value2, + float axis_value3) const; virtual void reportValue(const char *result_name, const LibertyLibrary *library, const LibertyCell *cell, @@ -343,13 +343,17 @@ public: Table1 &operator= (Table1 &&table); virtual int order() const { return 1; } virtual TableAxisPtr axis1() const { return axis1_; } - virtual float value(size_t index1, - size_t index2, - size_t index3) const; + virtual float value(size_t axis_index1, + size_t axis_index2, + size_t axis_index3) const; float value(size_t index1) const; - float findValue(float value1) const; - float findValue(float value1, - bool extrapolate) const; + float findValue(float axis_value1) const; + void findValue(float axis_value1, + // Return values. + float &value, + bool &extrapolated) const; + float findValueClip(float axis_value1, + float clip_value) const; virtual float findValue(float value1, float value2, float value3) const; @@ -385,14 +389,14 @@ public: virtual int order() const { return 2; } TableAxisPtr axis1() const { return axis1_; } TableAxisPtr axis2() const { return axis2_; } - virtual float value(size_t index1, - size_t index2, - size_t index3) const; - float value(size_t index1, - size_t index2) const; - virtual float findValue(float value1, - float value2, - float value3) const; + virtual float value(size_t axis_index1, + size_t axis_index2, + size_t axis_index3) const; + float value(size_t axis_index1, + size_t axis_index2) const; + virtual float findValue(float axis_value1, + float axis_value2, + float axis_value3) const; FloatTable *values3() { return values_; } virtual void reportValue(const char *result_name, const LibertyLibrary *library, @@ -428,12 +432,12 @@ public: virtual ~Table3() {} virtual int order() const { return 3; } TableAxisPtr axis3() const { return axis3_; } - virtual float value(size_t index1, - size_t index2, - size_t index3) const; - virtual float findValue(float value1, - float value2, - float value3) const; + virtual float value(size_t axis_index1, + size_t axis_index2, + size_t axis_index3) const; + virtual float findValue(float axis_value1, + float axis_value2, + float axis_value3) const; virtual void reportValue(const char *result_name, const LibertyLibrary *library, const LibertyCell *cell, @@ -495,60 +499,33 @@ private: TableModel *capacitance_models_[2][RiseFall::index_count]; }; -class OutputWaveform -{ -public: - OutputWaveform(float axis_value1, - float axis_value2, - Table1 *currents, - float reference_time); - OutputWaveform(float slew, - float cap, - Table1 *currents, - Table1 *voltages, - 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 *voltages(); - float referenceTime() const { return reference_time_; } - 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: - float slew_; - float cap_; - Table1 *currents_; - Table1 *voltages_; - float reference_time_; -}; - // Two dimensional (slew/cap) table of one dimensional time/current tables. class OutputWaveforms { public: OutputWaveforms(TableAxisPtr slew_axis, TableAxisPtr cap_axis, - Vector &waveforms); + Table1Seq ¤t_waveforms, + Table1 *ref_times); ~OutputWaveforms(); - OutputWaveform voltageWaveform(float in_slew, - float load_cap); + Table1 voltageWaveform(float in_slew, + float load_cap); + Table1 currentWaveform(float slew, + float cap); + float referenceTime(float slew); + static bool checkAxes(TableTemplate *tbl_template); private: + Table1 *voltageWaveform(size_t wave_index, + float cap); + // Row. TableAxisPtr slew_axis_; // Column. TableAxisPtr cap_axis_; - OutputWaveformSeq waveforms_; + Table1Seq current_waveforms_; + Table1Seq voltage_waveforms_; + Table1 *ref_times_; }; class DriverWaveform diff --git a/liberty/LibertyReader.cc b/liberty/LibertyReader.cc index 3ce401f4..e47fc6e0 100644 --- a/liberty/LibertyReader.cc +++ b/liberty/LibertyReader.cc @@ -2517,7 +2517,8 @@ LibertyReader::endOutputCurrentRiseFall(LibertyGroup *group) slew_values); TableAxisPtr cap_axis = make_shared(TableAxisVariable::total_output_net_capacitance, cap_values); - Vector waveforms(slew_axis->size() * cap_axis->size()); + FloatSeq *ref_times = new FloatSeq(slew_values->size()); + Table1Seq current_waveforms(slew_axis->size() * cap_axis->size()); for (OutputWaveform *waveform : output_currents_) { size_t slew_index, cap_index; bool slew_exists, cap_exists; @@ -2525,14 +2526,18 @@ LibertyReader::endOutputCurrentRiseFall(LibertyGroup *group) cap_axis->findAxisIndex(waveform->cap(), cap_index, cap_exists); if (slew_exists && cap_exists) { size_t index = slew_index * cap_axis->size() + cap_index; - waveforms[index] = waveform; + current_waveforms[index] = waveform->currents(); + (*ref_times)[slew_index] = waveform->referenceTime(); } else libWarn(913, group, "output current waveform %.2e %.2e not found.", waveform->slew(), waveform->cap()); } - OutputWaveforms *output_current = new OutputWaveforms(slew_axis, cap_axis, waveforms); + Table1 *ref_time_tbl = new Table1(ref_times, slew_axis); + OutputWaveforms *output_current = new OutputWaveforms(slew_axis, cap_axis, + current_waveforms, + ref_time_tbl); timing_->setOutputWaveforms(rf_, output_current); } @@ -2543,7 +2548,7 @@ LibertyReader::beginVector(LibertyGroup *group) beginTable(group, TableTemplateType::output_current, current_scale_); scale_factor_type_ = ScaleFactorType::unknown; reference_time_exists_ = false; - if (tbl_template_ && !OutputWaveform::checkAxes(tbl_template_)) + if (tbl_template_ && !OutputWaveforms::checkAxes(tbl_template_)) libWarn(118, group, "unsupported model axis."); } } @@ -5754,4 +5759,22 @@ PortNameBitIterator::findRangeBusNameNext() range_name_next_ = nullptr; } +//////////////////////////////////////////////////////////////// + +OutputWaveform::OutputWaveform(float slew, + float cap, + Table1 *currents, + float reference_time) : + slew_(slew), + cap_(cap), + currents_(currents), + reference_time_(reference_time) +{ +} + +OutputWaveform::~OutputWaveform() +{ + delete currents_; +} + } // namespace diff --git a/liberty/LibertyReaderPvt.hh b/liberty/LibertyReaderPvt.hh index 03bd7326..15f3af0a 100644 --- a/liberty/LibertyReaderPvt.hh +++ b/liberty/LibertyReaderPvt.hh @@ -45,6 +45,7 @@ class LeakagePowerGroup; class PortNameBitIterator; class TimingArcBuilder; class LibertyAttr; +class OutputWaveform; typedef void (LibertyReader::*LibraryAttrVisitor)(LibertyAttr *attr); typedef void (LibertyReader::*LibraryGroupVisitor)(LibertyGroup *group); @@ -868,4 +869,24 @@ protected: unsigned size_; }; +class OutputWaveform +{ +public: + OutputWaveform(float axis_value1, + float axis_value2, + Table1 *currents, + float reference_time); + ~OutputWaveform(); + float slew() const { return slew_; } + float cap() const { return cap_; } + Table1 *currents() const { return currents_; } + float referenceTime() const { return reference_time_; } + +private: + float slew_; + float cap_; + Table1 *currents_; + float reference_time_; +}; + } // namespace diff --git a/liberty/TableModel.cc b/liberty/TableModel.cc index d703993f..48b988c2 100644 --- a/liberty/TableModel.cc +++ b/liberty/TableModel.cc @@ -657,22 +657,22 @@ TableModel::axis3() const } float -TableModel::value(size_t index1, - size_t index2, - size_t index3) const +TableModel::value(size_t axis_index1, + size_t axis_index2, + size_t axis_index3) const { - return table_->value(index1, index2, index3); + return table_->value(axis_index1, axis_index2, axis_index3); } float TableModel::findValue(const LibertyLibrary *library, const LibertyCell *cell, const Pvt *pvt, - float value1, - float value2, - float value3) const + float axis_value1, + float axis_value2, + float axis_value3) const { - return table_->findValue(value1, value2, value3) + return table_->findValue(axis_value1, axis_value2, axis_value3) * scaleFactor(library, cell, pvt); } @@ -847,53 +847,69 @@ Table1::operator=(Table1 &&table) } float -Table1::value(size_t index1, +Table1::value(size_t axis_index1, size_t, size_t) const { - return value(index1); + return value(axis_index1); } float -Table1::value(size_t index1) const +Table1::value(size_t axis_index1) const { - return (*values_)[index1]; + return (*values_)[axis_index1]; } float -Table1::findValue(float value1, +Table1::findValue(float axis_value1, float, float) const { - return findValue(value1); + return findValue(axis_value1); } float -Table1::findValue(float value1) const +Table1::findValue(float axis_value1) const { - return findValue(value1, true); + float value; + bool extrapolated; + findValue(axis_value1, value, extrapolated); + return value; } float -Table1::findValue(float value1, - bool extrapolate) const +Table1::findValueClip(float axis_value1, + float clip_value) const { - if (axis1_->size() == 1) - return value(value1); + float value; + bool extrapolated; + findValue(axis_value1, value, extrapolated); + if (extrapolated) + return clip_value; + else + return value; +} + +void +Table1::findValue(float axis_value1, + // Return values. + float &value, + bool &extrapolated) const +{ + if (axis1_->size() == 1) { + value = this->value(axis_value1); + extrapolated = false; + } else { - size_t index1 = axis1_->findAxisIndex(value1); - float x1 = value1; - float x1l = axis1_->axisValue(index1); - float x1u = axis1_->axisValue(index1 + 1); - float y1 = value(index1); - float y2 = value(index1 + 1); + size_t axis_index1 = axis1_->findAxisIndex(axis_value1); + float x1 = axis_value1; + float x1l = axis1_->axisValue(axis_index1); + float x1u = axis1_->axisValue(axis_index1 + 1); + float y1 = this->value(axis_index1); + float y2 = this->value(axis_index1 + 1); float dx1 = (x1 - x1l) / (x1u - x1l); - if (x1 <= x1l && !extrapolate) - return y1; - else if (x1 >= x1u && !extrapolate) - return y2; - else - return (1 - dx1) * y1 + dx1 * y2; + value = (1 - dx1) * y1 + dx1 * y2; + extrapolated = (x1 < x1l || x1 >= x1u); } } @@ -988,25 +1004,25 @@ Table2::~Table2() } float -Table2::value(size_t index1, - size_t index2, +Table2::value(size_t axis_index1, + size_t axis_index2, size_t) const { - return value(index1, index2); + return value(axis_index1, axis_index2); } float -Table2::value(size_t index1, - size_t index2) const +Table2::value(size_t axis_index1, + size_t axis_index2) const { - FloatSeq *row = (*values_)[index1]; - return (*row)[index2]; + FloatSeq *row = (*values_)[axis_index1]; + return (*row)[axis_index2]; } // Bilinear Interpolation. float -Table2::findValue(float value1, - float value2, +Table2::findValue(float axis_value1, + float axis_value2, float) const { size_t size1 = axis1_->size(); @@ -1015,13 +1031,13 @@ Table2::findValue(float value1, if (size2 == 1) return value(0, 0); else { - size_t index2 = axis2_->findAxisIndex(value2); - float x2 = value2; - float y00 = value(0, index2); - float x2l = axis2_->axisValue(index2); - float x2u = axis2_->axisValue(index2 + 1); + size_t axis_index2 = axis2_->findAxisIndex(axis_value2); + float x2 = axis_value2; + float y00 = value(0, axis_index2); + float x2l = axis2_->axisValue(axis_index2); + float x2u = axis2_->axisValue(axis_index2 + 1); float dx2 = (x2 - x2l) / (x2u - x2l); - float y01 = value(0, index2 + 1); + float y01 = value(0, axis_index2 + 1); float tbl_value = (1 - dx2) * y00 + dx2 * y01; @@ -1029,33 +1045,33 @@ Table2::findValue(float value1, } } else if (size2 == 1) { - size_t index1 = axis1_->findAxisIndex(value1); - float x1 = value1; - float y00 = value(index1, 0); - float x1l = axis1_->axisValue(index1); - float x1u = axis1_->axisValue(index1 + 1); + size_t axis_index1 = axis1_->findAxisIndex(axis_value1); + float x1 = axis_value1; + float y00 = value(axis_index1, 0); + float x1l = axis1_->axisValue(axis_index1); + float x1u = axis1_->axisValue(axis_index1 + 1); float dx1 = (x1 - x1l) / (x1u - x1l); - float y10 = value(index1 + 1, 0); + float y10 = value(axis_index1 + 1, 0); float tbl_value = (1 - dx1) * y00 + dx1 * y10; return tbl_value; } else { - size_t index1 = axis1_->findAxisIndex(value1); - size_t index2 = axis2_->findAxisIndex(value2); - float x1 = value1; - float x2 = value2; - float y00 = value(index1, index2); - float x1l = axis1_->axisValue(index1); - float x1u = axis1_->axisValue(index1 + 1); + size_t axis_index1 = axis1_->findAxisIndex(axis_value1); + size_t axis_index2 = axis2_->findAxisIndex(axis_value2); + float x1 = axis_value1; + float x2 = axis_value2; + float y00 = value(axis_index1, axis_index2); + float x1l = axis1_->axisValue(axis_index1); + float x1u = axis1_->axisValue(axis_index1 + 1); float dx1 = (x1 - x1l) / (x1u - x1l); - float y10 = value(index1 + 1, index2); - float y11 = value(index1 + 1, index2 + 1); - float x2l = axis2_->axisValue(index2); - float x2u = axis2_->axisValue(index2 + 1); + float y10 = value(axis_index1 + 1, axis_index2); + float y11 = value(axis_index1 + 1, axis_index2 + 1); + float x2l = axis2_->axisValue(axis_index2); + float x2u = axis2_->axisValue(axis_index2 + 1); float dx2 = (x2 - x2l) / (x2u - x2l); - float y01 = value(index1, index2 + 1); + float y01 = value(axis_index1, axis_index2 + 1); float tbl_value = (1 - dx1) * (1 - dx2) * y00 + dx1 * (1 - dx2) * y10 @@ -1173,30 +1189,30 @@ Table3::Table3(FloatTable *values, } float -Table3::value(size_t index1, - size_t index2, - size_t index3) const +Table3::value(size_t axis_index1, + size_t axis_index2, + size_t axis_index3) const { - size_t row = index1 * axis2_->size() + index2; - return values_->operator[](row)->operator[](index3); + size_t row = axis_index1 * axis2_->size() + axis_index2; + return values_->operator[](row)->operator[](axis_index3); } // Bilinear Interpolation. float -Table3::findValue(float value1, - float value2, - float value3) const +Table3::findValue(float axis_value1, + float axis_value2, + float axis_value3) const { - size_t index1 = axis1_->findAxisIndex(value1); - size_t index2 = axis2_->findAxisIndex(value2); - size_t index3 = axis3_->findAxisIndex(value3); - float x1 = value1; - float x2 = value2; - float x3 = value3; + size_t axis_index1 = axis1_->findAxisIndex(axis_value1); + size_t axis_index2 = axis2_->findAxisIndex(axis_value2); + size_t axis_index3 = axis3_->findAxisIndex(axis_value3); + float x1 = axis_value1; + float x2 = axis_value2; + float x3 = axis_value3; float dx1 = 0.0; float dx2 = 0.0; float dx3 = 0.0; - float y000 = value(index1, index2, index3); + float y000 = value(axis_index1, axis_index2, axis_index3); float y001 = 0.0; float y010 = 0.0; float y011 = 0.0; @@ -1206,31 +1222,31 @@ Table3::findValue(float value1, float y111 = 0.0; if (axis1_->size() != 1) { - float x1l = axis1_->axisValue(index1); - float x1u = axis1_->axisValue(index1 + 1); + float x1l = axis1_->axisValue(axis_index1); + float x1u = axis1_->axisValue(axis_index1 + 1); dx1 = (x1 - x1l) / (x1u - x1l); - y100 = value(index1 + 1, index2, index3); + y100 = value(axis_index1 + 1, axis_index2, axis_index3); if (axis3_->size() != 1) - y101 = value(index1 + 1, index2, index3 + 1); + y101 = value(axis_index1 + 1, axis_index2, axis_index3 + 1); if (axis2_->size() != 1) { - y110 = value(index1 + 1, index2 + 1, index3); + y110 = value(axis_index1 + 1, axis_index2 + 1, axis_index3); if (axis3_->size() != 1) - y111 = value(index1 + 1, index2 + 1, index3 + 1); + y111 = value(axis_index1 + 1, axis_index2 + 1, axis_index3 + 1); } } if (axis2_->size() != 1) { - float x2l = axis2_->axisValue(index2); - float x2u = axis2_->axisValue(index2 + 1); + float x2l = axis2_->axisValue(axis_index2); + float x2u = axis2_->axisValue(axis_index2 + 1); dx2 = (x2 - x2l) / (x2u - x2l); - y010 = value(index1, index2 + 1, index3); + y010 = value(axis_index1, axis_index2 + 1, axis_index3); if (axis3_->size() != 1) - y011 = value(index1, index2 + 1, index3 + 1); + y011 = value(axis_index1, axis_index2 + 1, axis_index3 + 1); } if (axis3_->size() != 1) { - float x3l = axis3_->axisValue(index3); - float x3u = axis3_->axisValue(index3 + 1); + float x3l = axis3_->axisValue(axis_index3); + float x3u = axis3_->axisValue(axis_index3 + 1); dx3 = (x3 - x3l) / (x3u - x3l); - y001 = value(index1, index2, index3 + 1); + y001 = value(axis_index1, axis_index2, axis_index3 + 1); } float tbl_value @@ -1294,15 +1310,15 @@ Table3::reportValue(const char *result_name, *result += unit3->asString(value3, digits); *result += '\n'; - size_t index1 = axis1_->findAxisIndex(value1); - size_t index2 = axis2_->findAxisIndex(value2); - size_t index3 = axis3_->findAxisIndex(value3); + size_t axis_index1 = axis1_->findAxisIndex(value1); + size_t axis_index2 = axis2_->findAxisIndex(value2); + size_t axis_index3 = axis3_->findAxisIndex(value3); *result += " | | "; - *result += unit3->asString(axis3_->axisValue(index3), digits); + *result += unit3->asString(axis3_->axisValue(axis_index3), digits); if (axis3_->size() != 1) { *result += " "; - *result += unit3->asString(axis3_->axisValue(index3 + 1), digits); + *result += unit3->asString(axis3_->axisValue(axis_index3 + 1), digits); } *result += '\n'; @@ -1310,13 +1326,13 @@ Table3::reportValue(const char *result_name, if (axis1_->size() != 1) { *result += " "; - *result += unit1->asString(axis1_->axisValue(index1+1), digits); + *result += unit1->asString(axis1_->axisValue(axis_index1+1), digits); *result += " v / "; - *result += table_unit->asString(value(index1+1,index2,index3), + *result += table_unit->asString(value(axis_index1+1,axis_index2,axis_index3), digits); if (axis3_->size() != 1) { *result += " "; - *result += table_unit->asString(value(index1+1,index2,index3+1), + *result += table_unit->asString(value(axis_index1+1,axis_index2,axis_index3+1), digits); } } @@ -1326,14 +1342,14 @@ Table3::reportValue(const char *result_name, } *result += '\n'; - *result += unit1->asString(axis1_->axisValue(index1), digits); + *result += unit1->asString(axis1_->axisValue(axis_index1), digits); *result += " "; - *result += unit2->asString(axis2_->axisValue(index2), digits); + *result += unit2->asString(axis2_->axisValue(axis_index2), digits); *result += " | "; - *result += table_unit->asString(value(index1, index2, index3), digits); + *result += table_unit->asString(value(axis_index1, axis_index2, axis_index3), digits); if (axis3_->size() != 1) { *result += " "; - *result += table_unit->asString(value(index1, index2, index3+1), + *result += table_unit->asString(value(axis_index1, axis_index2, axis_index3+1), digits); } *result += '\n'; @@ -1341,25 +1357,25 @@ Table3::reportValue(const char *result_name, *result += " |/ "; if (axis1_->size() != 1 && axis2_->size() != 1) { - *result += table_unit->asString(value(index1+1,index2+1,index3), + *result += table_unit->asString(value(axis_index1+1,axis_index2+1,axis_index3), digits); if (axis3_->size() != 1) { *result += " "; - *result +=table_unit->asString(value(index1+1,index2+1,index3+1), + *result +=table_unit->asString(value(axis_index1+1,axis_index2+1,axis_index3+1), digits); } } *result += '\n'; *result += " "; - *result += unit2->asString(axis2_->axisValue(index2 + 1), digits); + *result += unit2->asString(axis2_->axisValue(axis_index2 + 1), digits); *result += " | "; if (axis2_->size() != 1) { - *result += table_unit->asString(value(index1, index2+1, index3), + *result += table_unit->asString(value(axis_index1, axis_index2+1, axis_index3), digits); if (axis3_->size() != 1) { *result += " "; - *result +=table_unit->asString(value(index1, index2+1,index3+1), + *result +=table_unit->asString(value(axis_index1, axis_index2+1,axis_index3+1), digits); } } @@ -1388,24 +1404,24 @@ Table3::report(const Units *units, const Unit *unit1 = axis1_->unit(units); const Unit *unit2 = axis2_->unit(units); const Unit *unit3 = axis3_->unit(units); - for (size_t index1 = 0; index1 < axis1_->size(); index1++) { + for (size_t axis_index1 = 0; axis_index1 < axis1_->size(); axis_index1++) { report->reportLine("%s %s", tableVariableString(axis1_->variable()), - unit1->asString(axis1_->axisValue(index1), digits)); + unit1->asString(axis1_->axisValue(axis_index1), digits)); report->reportLine("%s", tableVariableString(axis3_->variable())); report->reportLine(" ------------------------------"); string line = " "; - for (size_t index3 = 0; index3 < axis3_->size(); index3++) { - line += unit3->asString(axis3_->axisValue(index3), digits); + for (size_t axis_index3 = 0; axis_index3 < axis3_->size(); axis_index3++) { + line += unit3->asString(axis3_->axisValue(axis_index3), digits); line += " "; } report->reportLineString(line); - for (size_t index2 = 0; index2 < axis2_->size(); index2++) { - line = unit2->asString(axis2_->axisValue(index2),digits); + for (size_t axis_index2 = 0; axis_index2 < axis2_->size(); axis_index2++) { + line = unit2->asString(axis2_->axisValue(axis_index2),digits); line += " |"; - for (size_t index3 = 0; index3 < axis3_->size(); index3++) { - line += table_unit->asString(value(index1, index2, index3), digits); + for (size_t axis_index3 = 0; axis_index3 < axis3_->size(); axis_index3++) { + line += table_unit->asString(value(axis_index1, axis_index2, axis_index3), digits); line += " "; } report->reportLineString(line); @@ -1564,67 +1580,29 @@ tableVariableUnit(TableAxisVariable variable, //////////////////////////////////////////////////////////////// -OutputWaveform::OutputWaveform(float slew, - float cap, - Table1 *currents, - float reference_time) : - slew_(slew), - cap_(cap), - currents_(currents), - voltages_(nullptr), - reference_time_(reference_time) + +//////////////////////////////////////////////////////////////// + +OutputWaveforms::OutputWaveforms(TableAxisPtr slew_axis, + TableAxisPtr cap_axis, + Table1Seq ¤t_waveforms, + Table1 *ref_times) : + slew_axis_(slew_axis), + cap_axis_(cap_axis), + current_waveforms_(current_waveforms), + ref_times_(ref_times) { } -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) +OutputWaveforms::~OutputWaveforms() { -} - -OutputWaveform::~OutputWaveform() -{ - 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_; + current_waveforms_.deleteContents(); + voltage_waveforms_.deleteContents(); + delete ref_times_; } bool -OutputWaveform::checkAxes(TableTemplate *tbl_template) +OutputWaveforms::checkAxes(TableTemplate *tbl_template) { TableAxisPtr axis1 = tbl_template->axis1(); TableAxisPtr axis2 = tbl_template->axis2(); @@ -1640,66 +1618,7 @@ OutputWaveform::checkAxes(TableTemplate *tbl_template) && axis3->variable() == TableAxisVariable::time); } -string -OutputWaveform::reportCurrentWaveform(const Units *units, - int digits) const -{ - TableAxisPtr time_axis = currents_->axis1(); - const Unit *time_unit = units->timeUnit(); - const Unit *current_unit = units->currentUnit(); - return reportWaveform(currents_, time_unit, current_unit, digits); -} - -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'; - - for (size_t i = 0; i < time_axis->size(); i++) { - float value = waveform->value(i); - result += waveform_unit->asString(value, digits); - result += " "; - } - return result; -} - -//////////////////////////////////////////////////////////////// - -OutputWaveforms::OutputWaveforms(TableAxisPtr slew_axis, - TableAxisPtr cap_axis, - OutputWaveformSeq &waveforms) : - slew_axis_(slew_axis), - cap_axis_(cap_axis), - waveforms_(waveforms) -{ -} - -OutputWaveforms::~OutputWaveforms() -{ - waveforms_.deleteContents(); -} - -OutputWaveform +Table1 OutputWaveforms::voltageWaveform(float slew, float cap) { @@ -1709,18 +1628,14 @@ OutputWaveforms::voltageWaveform(float slew, size_t wave_index01 = slew_index * cap_axis_->size() + (cap_index + 1); size_t wave_index10 = (slew_index + 1) * cap_axis_->size() + cap_index; size_t wave_index11 = (slew_index + 1) * cap_axis_->size() + (cap_index + 1); - 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(); + const Table1 *values00 = voltageWaveform(wave_index00, cap); + const Table1 *values01 = voltageWaveform(wave_index01, cap); + const Table1 *values10 = voltageWaveform(wave_index10, cap); + const Table1 *values11 = voltageWaveform(wave_index11, cap); + TableAxisPtr time_axis00 = values00->axis1(); + TableAxisPtr time_axis01 = values01->axis1(); + TableAxisPtr time_axis10 = values10->axis1(); + TableAxisPtr time_axis11 = values11->axis1(); // Find time axis min/max. size_t time_step_count = 20; @@ -1738,7 +1653,7 @@ OutputWaveforms::voltageWaveform(float slew, time_values); // Interpolate waveform samples at time steps. - float volt_max = voltages00->value(voltages00->values()->size() - 1); + float value = values00->value(values00->values()->size() - 1); size_t index1 = slew_index; size_t index2 = cap_index; float x1 = slew; @@ -1749,41 +1664,136 @@ OutputWaveforms::voltageWaveform(float slew, float x2l = cap_axis_->axisValue(index2); float x2u = cap_axis_->axisValue(index2 + 1); float dx2 = (x2 - x2l) / (x2u - x2l); - FloatSeq *voltages = new FloatSeq; + FloatSeq *values = 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); + float prev_value = 0.0; + constexpr float value_tol = .01; + float value_end = value * (1.0 - value_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 y00 = values00->findValue(time); + float y10 = values10->findValue(time); + float y11 = values11->findValue(time); + float y01 = values01->findValue(time); float voltage = (1 - dx1) * (1 - dx2) * y00 + dx1 * (1 - dx2) * y10 + dx1 * dx2 * y11 + (1 - dx1) * dx2 * y01; - if (voltage > volt_tol) + if (voltage > value_tol) waveform_started = true; if (waveform_started) { time_values->push_back(time); - voltages->push_back(voltage); + values->push_back(voltage); } - if (prev_volt > volt_end) + if (prev_value > value_end) break; - prev_volt = voltage; + prev_value = voltage; } + return Table1(values, time_axis); +} - // Interpolate reference time. - // (only depends on slew) - float ref_time - = (1 - dx1) * waveform00->referenceTime() - + dx1 * waveform10->referenceTime(); +Table1 * +OutputWaveforms::voltageWaveform(size_t wave_index, + float cap) +{ + Table1 *voltages = voltage_waveforms_[wave_index]; + if (voltages == nullptr) { + FloatSeq *voltages1 = new FloatSeq; + Table1 *currents = current_waveforms_[wave_index]; + voltages = new Table1(voltages1, currents->axis1()); + voltage_waveforms_[wave_index] = voltages; - Table1 *waveform = new Table1(voltages, time_axis); - return OutputWaveform(slew, cap, nullptr, waveform, ref_time); + // 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; + voltages1->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; + voltages1->push_back(voltage); + prev_time = time; + prev_current = current; + } + } + return voltages; +} + +Table1 +OutputWaveforms::currentWaveform(float slew, + float cap) +{ + size_t slew_index = slew_axis_->findAxisIndex(slew); + size_t cap_index = cap_axis_->findAxisIndex(cap); + size_t wave_index00 = slew_index * cap_axis_->size() + cap_index; + size_t wave_index01 = slew_index * cap_axis_->size() + (cap_index + 1); + size_t wave_index10 = (slew_index + 1) * cap_axis_->size() + cap_index; + size_t wave_index11 = (slew_index + 1) * cap_axis_->size() + (cap_index + 1); + const Table1 *values00 = current_waveforms_[wave_index00]; + const Table1 *values01 = current_waveforms_[wave_index01]; + const Table1 *values10 = current_waveforms_[wave_index10]; + const Table1 *values11 = current_waveforms_[wave_index11]; + TableAxisPtr time_axis00 = values00->axis1(); + TableAxisPtr time_axis01 = values01->axis1(); + TableAxisPtr time_axis10 = values10->axis1(); + TableAxisPtr time_axis11 = values11->axis1(); + + // Find time axis min/max. + size_t time_step_count = 20; + float time_min = time_axis00->min(); + time_min = min(time_min, time_axis01->min()); + time_min = min(time_min, time_axis10->min()); + time_min = min(time_min, time_axis11->min()); + float time_max = time_axis00->max(); + time_max = max(time_max, time_axis01->max()); + 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(time_axis00->variable(), + time_values); + + // Interpolate waveform samples at time steps. + size_t index1 = slew_index; + size_t index2 = cap_index; + float x1 = slew; + float x2 = cap; + float x1l = slew_axis_->axisValue(index1); + float x1u = slew_axis_->axisValue(index1 + 1); + float dx1 = (x1 - x1l) / (x1u - x1l); + float x2l = cap_axis_->axisValue(index2); + float x2u = cap_axis_->axisValue(index2 + 1); + float dx2 = (x2 - x2l) / (x2u - x2l); + FloatSeq *values = new FloatSeq; + for (size_t i = 0; i <= time_step_count; i++) { + float time = time_min + time_step * i; + float y00 = values00->findValueClip(time, 0.0); + float y10 = values10->findValueClip(time, 0.0); + float y11 = values11->findValueClip(time, 0.0); + float y01 = values01->findValueClip(time, 0.0); + float value + = (1 - dx1) * (1 - dx2) * y00 + + dx1 * (1 - dx2) * y10 + + dx1 * dx2 * y11 + + (1 - dx1) * dx2 * y01; + time_values->push_back(time); + values->push_back(value); + if (time > time_max) + break; + } + return Table1(values, time_axis); +} + +float +OutputWaveforms::referenceTime(float slew) +{ + return ref_times_->findValue(slew); } //////////////////////////////////////////////////////////////// diff --git a/tcl/StaTcl.i b/tcl/StaTcl.i index c74b3426..c6442943 100644 --- a/tcl/StaTcl.i +++ b/tcl/StaTcl.i @@ -3788,6 +3788,14 @@ format_voltage(const char *value, return Sta::sta()->units()->voltageUnit()->asString(value1, digits); } +const char * +format_current(const char *value, + int digits) +{ + float value1 = strtof(value, nullptr); + return Sta::sta()->units()->currentUnit()->asString(value1, digits); +} + const char * format_power(const char *value, int digits) @@ -5649,12 +5657,25 @@ voltage_waveform(float in_slew, { GateTableModel *gate_model = dynamic_cast(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; + OutputWaveforms *waveforms = gate_model->outputWaveforms(); + if (waveforms) { + Table1 waveform = waveforms->voltageWaveform(in_slew, load_cap); + return waveform; + } + } + return Table1(); +} + +Table1 +current_waveform(float in_slew, + float load_cap) +{ + GateTableModel *gate_model = dynamic_cast(self->model()); + if (gate_model) { + OutputWaveforms *waveforms = gate_model->outputWaveforms(); + if (waveforms) { + Table1 waveform = waveforms->currentWaveform(in_slew, load_cap); + return waveform; } } return Table1();