Squashed commit of the following:

commit 339ca3171ea95ba86c6234e7510578a9d863018d
Author: James Cherry <cherry@parallaxsw.com>
Date:   Wed Mar 22 21:20:52 2023 -0700

    ccs lib only use OutputWaveform for parsing

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit a1ba29146e3a15f1976bd30ade3f1f9929a67e05
Author: James Cherry <cherry@parallaxsw.com>
Date:   Wed Mar 22 20:28:31 2023 -0700

    ccs

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 44b19aeda1ab892192341544ea49ce466472a5af
Author: James Cherry <cherry@parallaxsw.com>
Date:   Wed Mar 22 19:33:24 2023 -0700

    ccs ref time tbl

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit a0ff298634117ddc0c7ef630f944a994ac7a29c2
Author: James Cherry <cherry@parallaxsw.com>
Date:   Wed Mar 22 19:15:56 2023 -0700

    ccs lib

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
James Cherry 2023-03-23 07:01:04 -07:00
parent 6c3ba16e07
commit eeb1575d46
5 changed files with 401 additions and 349 deletions

View File

@ -34,11 +34,11 @@ class Units;
class Report; class Report;
class Table; class Table;
class OutputWaveforms; class OutputWaveforms;
class OutputWaveform; class Table1;
typedef Vector<float> FloatSeq; typedef Vector<float> FloatSeq;
typedef Vector<FloatSeq*> FloatTable; typedef Vector<FloatSeq*> FloatTable;
typedef Vector<OutputWaveform*> OutputWaveformSeq; typedef Vector<Table1*> Table1Seq;
TableAxisVariable TableAxisVariable
stringTableAxisVariable(const char *variable); stringTableAxisVariable(const char *variable);
@ -275,16 +275,16 @@ public:
size_t axis_idx2, size_t axis_idx2,
size_t axis_idx3) const = 0; size_t axis_idx3) const = 0;
// Table interpolated lookup. // Table interpolated lookup.
virtual float findValue(float value1, virtual float findValue(float axis_value1,
float value2, float axis_value2,
float value3) const = 0; float axis_value3) const = 0;
// Table interpolated lookup with scale factor. // Table interpolated lookup with scale factor.
float findValue(const LibertyLibrary *library, float findValue(const LibertyLibrary *library,
const LibertyCell *cell, const LibertyCell *cell,
const Pvt *pvt, const Pvt *pvt,
float value1, float axis_value1,
float value2, float axis_value2,
float value3) const; float axis_value3) const;
virtual void reportValue(const char *result_name, virtual void reportValue(const char *result_name,
const LibertyLibrary *library, const LibertyLibrary *library,
const LibertyCell *cell, const LibertyCell *cell,
@ -306,12 +306,12 @@ class Table0 : public Table
public: public:
Table0(float value); Table0(float value);
virtual int order() const { return 0; } virtual int order() const { return 0; }
virtual float value(size_t index1, virtual float value(size_t axis_index1,
size_t index2, size_t axis_index2,
size_t index3) const; size_t axis_index3) const;
virtual float findValue(float value1, virtual float findValue(float axis_value1,
float value2, float axis_value2,
float value3) const; float axis_value3) const;
virtual void reportValue(const char *result_name, virtual void reportValue(const char *result_name,
const LibertyLibrary *library, const LibertyLibrary *library,
const LibertyCell *cell, const LibertyCell *cell,
@ -343,13 +343,17 @@ public:
Table1 &operator= (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 axis_index1,
size_t index2, size_t axis_index2,
size_t index3) const; size_t axis_index3) const;
float value(size_t index1) const; float value(size_t index1) const;
float findValue(float value1) const; float findValue(float axis_value1) const;
float findValue(float value1, void findValue(float axis_value1,
bool extrapolate) const; // Return values.
float &value,
bool &extrapolated) const;
float findValueClip(float axis_value1,
float clip_value) const;
virtual float findValue(float value1, virtual float findValue(float value1,
float value2, float value2,
float value3) const; float value3) const;
@ -385,14 +389,14 @@ public:
virtual int order() const { return 2; } virtual int order() const { return 2; }
TableAxisPtr axis1() const { return axis1_; } TableAxisPtr axis1() const { return axis1_; }
TableAxisPtr axis2() const { return axis2_; } TableAxisPtr axis2() const { return axis2_; }
virtual float value(size_t index1, virtual float value(size_t axis_index1,
size_t index2, size_t axis_index2,
size_t index3) const; size_t axis_index3) const;
float value(size_t index1, float value(size_t axis_index1,
size_t index2) const; size_t axis_index2) const;
virtual float findValue(float value1, virtual float findValue(float axis_value1,
float value2, float axis_value2,
float value3) const; float axis_value3) const;
FloatTable *values3() { return values_; } FloatTable *values3() { return values_; }
virtual void reportValue(const char *result_name, virtual void reportValue(const char *result_name,
const LibertyLibrary *library, const LibertyLibrary *library,
@ -428,12 +432,12 @@ public:
virtual ~Table3() {} virtual ~Table3() {}
virtual int order() const { return 3; } virtual int order() const { return 3; }
TableAxisPtr axis3() const { return axis3_; } TableAxisPtr axis3() const { return axis3_; }
virtual float value(size_t index1, virtual float value(size_t axis_index1,
size_t index2, size_t axis_index2,
size_t index3) const; size_t axis_index3) const;
virtual float findValue(float value1, virtual float findValue(float axis_value1,
float value2, float axis_value2,
float value3) const; float axis_value3) const;
virtual void reportValue(const char *result_name, virtual void reportValue(const char *result_name,
const LibertyLibrary *library, const LibertyLibrary *library,
const LibertyCell *cell, const LibertyCell *cell,
@ -495,60 +499,33 @@ private:
TableModel *capacitance_models_[2][RiseFall::index_count]; 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. // Two dimensional (slew/cap) table of one dimensional time/current tables.
class OutputWaveforms class OutputWaveforms
{ {
public: public:
OutputWaveforms(TableAxisPtr slew_axis, OutputWaveforms(TableAxisPtr slew_axis,
TableAxisPtr cap_axis, TableAxisPtr cap_axis,
Vector<OutputWaveform*> &waveforms); Table1Seq &current_waveforms,
Table1 *ref_times);
~OutputWaveforms(); ~OutputWaveforms();
OutputWaveform voltageWaveform(float in_slew, Table1 voltageWaveform(float in_slew,
float load_cap); float load_cap);
Table1 currentWaveform(float slew,
float cap);
float referenceTime(float slew);
static bool checkAxes(TableTemplate *tbl_template);
private: private:
Table1 *voltageWaveform(size_t wave_index,
float cap);
// Row. // Row.
TableAxisPtr slew_axis_; TableAxisPtr slew_axis_;
// Column. // Column.
TableAxisPtr cap_axis_; TableAxisPtr cap_axis_;
OutputWaveformSeq waveforms_; Table1Seq current_waveforms_;
Table1Seq voltage_waveforms_;
Table1 *ref_times_;
}; };
class DriverWaveform class DriverWaveform

View File

@ -2517,7 +2517,8 @@ LibertyReader::endOutputCurrentRiseFall(LibertyGroup *group)
slew_values); slew_values);
TableAxisPtr cap_axis = make_shared<TableAxis>(TableAxisVariable::total_output_net_capacitance, TableAxisPtr cap_axis = make_shared<TableAxis>(TableAxisVariable::total_output_net_capacitance,
cap_values); cap_values);
Vector<OutputWaveform*> 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_) { for (OutputWaveform *waveform : output_currents_) {
size_t slew_index, cap_index; size_t slew_index, cap_index;
bool slew_exists, cap_exists; bool slew_exists, cap_exists;
@ -2525,14 +2526,18 @@ LibertyReader::endOutputCurrentRiseFall(LibertyGroup *group)
cap_axis->findAxisIndex(waveform->cap(), cap_index, cap_exists); cap_axis->findAxisIndex(waveform->cap(), cap_index, cap_exists);
if (slew_exists && cap_exists) { if (slew_exists && cap_exists) {
size_t index = slew_index * cap_axis->size() + cap_index; 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 else
libWarn(913, group, "output current waveform %.2e %.2e not found.", libWarn(913, group, "output current waveform %.2e %.2e not found.",
waveform->slew(), waveform->slew(),
waveform->cap()); 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); timing_->setOutputWaveforms(rf_, output_current);
} }
@ -2543,7 +2548,7 @@ LibertyReader::beginVector(LibertyGroup *group)
beginTable(group, TableTemplateType::output_current, current_scale_); 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_ && !OutputWaveform::checkAxes(tbl_template_)) if (tbl_template_ && !OutputWaveforms::checkAxes(tbl_template_))
libWarn(118, group, "unsupported model axis."); libWarn(118, group, "unsupported model axis.");
} }
} }
@ -5754,4 +5759,22 @@ PortNameBitIterator::findRangeBusNameNext()
range_name_next_ = nullptr; 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 } // namespace

View File

@ -45,6 +45,7 @@ class LeakagePowerGroup;
class PortNameBitIterator; class PortNameBitIterator;
class TimingArcBuilder; class TimingArcBuilder;
class LibertyAttr; class LibertyAttr;
class OutputWaveform;
typedef void (LibertyReader::*LibraryAttrVisitor)(LibertyAttr *attr); typedef void (LibertyReader::*LibraryAttrVisitor)(LibertyAttr *attr);
typedef void (LibertyReader::*LibraryGroupVisitor)(LibertyGroup *group); typedef void (LibertyReader::*LibraryGroupVisitor)(LibertyGroup *group);
@ -868,4 +869,24 @@ protected:
unsigned size_; 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 } // namespace

View File

@ -657,22 +657,22 @@ TableModel::axis3() const
} }
float float
TableModel::value(size_t index1, TableModel::value(size_t axis_index1,
size_t index2, size_t axis_index2,
size_t index3) const size_t axis_index3) const
{ {
return table_->value(index1, index2, index3); return table_->value(axis_index1, axis_index2, axis_index3);
} }
float float
TableModel::findValue(const LibertyLibrary *library, TableModel::findValue(const LibertyLibrary *library,
const LibertyCell *cell, const LibertyCell *cell,
const Pvt *pvt, const Pvt *pvt,
float value1, float axis_value1,
float value2, float axis_value2,
float value3) const float axis_value3) const
{ {
return table_->findValue(value1, value2, value3) return table_->findValue(axis_value1, axis_value2, axis_value3)
* scaleFactor(library, cell, pvt); * scaleFactor(library, cell, pvt);
} }
@ -847,53 +847,69 @@ Table1::operator=(Table1 &&table)
} }
float float
Table1::value(size_t index1, Table1::value(size_t axis_index1,
size_t, size_t,
size_t) const size_t) const
{ {
return value(index1); return value(axis_index1);
} }
float float
Table1::value(size_t index1) const Table1::value(size_t axis_index1) const
{ {
return (*values_)[index1]; return (*values_)[axis_index1];
} }
float float
Table1::findValue(float value1, Table1::findValue(float axis_value1,
float, float,
float) const float) const
{ {
return findValue(value1); return findValue(axis_value1);
} }
float 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 float
Table1::findValue(float value1, Table1::findValueClip(float axis_value1,
bool extrapolate) const float clip_value) const
{ {
if (axis1_->size() == 1) float value;
return value(value1); bool extrapolated;
else { findValue(axis_value1, value, extrapolated);
size_t index1 = axis1_->findAxisIndex(value1); if (extrapolated)
float x1 = value1; return clip_value;
float x1l = axis1_->axisValue(index1);
float x1u = axis1_->axisValue(index1 + 1);
float y1 = value(index1);
float y2 = value(index1 + 1);
float dx1 = (x1 - x1l) / (x1u - x1l);
if (x1 <= x1l && !extrapolate)
return y1;
else if (x1 >= x1u && !extrapolate)
return y2;
else else
return (1 - dx1) * y1 + dx1 * y2; 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 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);
value = (1 - dx1) * y1 + dx1 * y2;
extrapolated = (x1 < x1l || x1 >= x1u);
} }
} }
@ -988,25 +1004,25 @@ Table2::~Table2()
} }
float float
Table2::value(size_t index1, Table2::value(size_t axis_index1,
size_t index2, size_t axis_index2,
size_t) const size_t) const
{ {
return value(index1, index2); return value(axis_index1, axis_index2);
} }
float float
Table2::value(size_t index1, Table2::value(size_t axis_index1,
size_t index2) const size_t axis_index2) const
{ {
FloatSeq *row = (*values_)[index1]; FloatSeq *row = (*values_)[axis_index1];
return (*row)[index2]; return (*row)[axis_index2];
} }
// Bilinear Interpolation. // Bilinear Interpolation.
float float
Table2::findValue(float value1, Table2::findValue(float axis_value1,
float value2, float axis_value2,
float) const float) const
{ {
size_t size1 = axis1_->size(); size_t size1 = axis1_->size();
@ -1015,13 +1031,13 @@ Table2::findValue(float value1,
if (size2 == 1) if (size2 == 1)
return value(0, 0); return value(0, 0);
else { else {
size_t index2 = axis2_->findAxisIndex(value2); size_t axis_index2 = axis2_->findAxisIndex(axis_value2);
float x2 = value2; float x2 = axis_value2;
float y00 = value(0, index2); float y00 = value(0, axis_index2);
float x2l = axis2_->axisValue(index2); float x2l = axis2_->axisValue(axis_index2);
float x2u = axis2_->axisValue(index2 + 1); float x2u = axis2_->axisValue(axis_index2 + 1);
float dx2 = (x2 - x2l) / (x2u - x2l); float dx2 = (x2 - x2l) / (x2u - x2l);
float y01 = value(0, index2 + 1); float y01 = value(0, axis_index2 + 1);
float tbl_value float tbl_value
= (1 - dx2) * y00 = (1 - dx2) * y00
+ dx2 * y01; + dx2 * y01;
@ -1029,33 +1045,33 @@ Table2::findValue(float value1,
} }
} }
else if (size2 == 1) { else if (size2 == 1) {
size_t index1 = axis1_->findAxisIndex(value1); size_t axis_index1 = axis1_->findAxisIndex(axis_value1);
float x1 = value1; float x1 = axis_value1;
float y00 = value(index1, 0); float y00 = value(axis_index1, 0);
float x1l = axis1_->axisValue(index1); float x1l = axis1_->axisValue(axis_index1);
float x1u = axis1_->axisValue(index1 + 1); float x1u = axis1_->axisValue(axis_index1 + 1);
float dx1 = (x1 - x1l) / (x1u - x1l); float dx1 = (x1 - x1l) / (x1u - x1l);
float y10 = value(index1 + 1, 0); float y10 = value(axis_index1 + 1, 0);
float tbl_value float tbl_value
= (1 - dx1) * y00 = (1 - dx1) * y00
+ dx1 * y10; + dx1 * y10;
return tbl_value; return tbl_value;
} }
else { else {
size_t index1 = axis1_->findAxisIndex(value1); size_t axis_index1 = axis1_->findAxisIndex(axis_value1);
size_t index2 = axis2_->findAxisIndex(value2); size_t axis_index2 = axis2_->findAxisIndex(axis_value2);
float x1 = value1; float x1 = axis_value1;
float x2 = value2; float x2 = axis_value2;
float y00 = value(index1, index2); float y00 = value(axis_index1, axis_index2);
float x1l = axis1_->axisValue(index1); float x1l = axis1_->axisValue(axis_index1);
float x1u = axis1_->axisValue(index1 + 1); float x1u = axis1_->axisValue(axis_index1 + 1);
float dx1 = (x1 - x1l) / (x1u - x1l); float dx1 = (x1 - x1l) / (x1u - x1l);
float y10 = value(index1 + 1, index2); float y10 = value(axis_index1 + 1, axis_index2);
float y11 = value(index1 + 1, index2 + 1); float y11 = value(axis_index1 + 1, axis_index2 + 1);
float x2l = axis2_->axisValue(index2); float x2l = axis2_->axisValue(axis_index2);
float x2u = axis2_->axisValue(index2 + 1); float x2u = axis2_->axisValue(axis_index2 + 1);
float dx2 = (x2 - x2l) / (x2u - x2l); float dx2 = (x2 - x2l) / (x2u - x2l);
float y01 = value(index1, index2 + 1); float y01 = value(axis_index1, axis_index2 + 1);
float tbl_value float tbl_value
= (1 - dx1) * (1 - dx2) * y00 = (1 - dx1) * (1 - dx2) * y00
+ dx1 * (1 - dx2) * y10 + dx1 * (1 - dx2) * y10
@ -1173,30 +1189,30 @@ Table3::Table3(FloatTable *values,
} }
float float
Table3::value(size_t index1, Table3::value(size_t axis_index1,
size_t index2, size_t axis_index2,
size_t index3) const size_t axis_index3) const
{ {
size_t row = index1 * axis2_->size() + index2; size_t row = axis_index1 * axis2_->size() + axis_index2;
return values_->operator[](row)->operator[](index3); return values_->operator[](row)->operator[](axis_index3);
} }
// Bilinear Interpolation. // Bilinear Interpolation.
float float
Table3::findValue(float value1, Table3::findValue(float axis_value1,
float value2, float axis_value2,
float value3) const float axis_value3) const
{ {
size_t index1 = axis1_->findAxisIndex(value1); size_t axis_index1 = axis1_->findAxisIndex(axis_value1);
size_t index2 = axis2_->findAxisIndex(value2); size_t axis_index2 = axis2_->findAxisIndex(axis_value2);
size_t index3 = axis3_->findAxisIndex(value3); size_t axis_index3 = axis3_->findAxisIndex(axis_value3);
float x1 = value1; float x1 = axis_value1;
float x2 = value2; float x2 = axis_value2;
float x3 = value3; float x3 = axis_value3;
float dx1 = 0.0; float dx1 = 0.0;
float dx2 = 0.0; float dx2 = 0.0;
float dx3 = 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 y001 = 0.0;
float y010 = 0.0; float y010 = 0.0;
float y011 = 0.0; float y011 = 0.0;
@ -1206,31 +1222,31 @@ Table3::findValue(float value1,
float y111 = 0.0; float y111 = 0.0;
if (axis1_->size() != 1) { if (axis1_->size() != 1) {
float x1l = axis1_->axisValue(index1); float x1l = axis1_->axisValue(axis_index1);
float x1u = axis1_->axisValue(index1 + 1); float x1u = axis1_->axisValue(axis_index1 + 1);
dx1 = (x1 - x1l) / (x1u - x1l); dx1 = (x1 - x1l) / (x1u - x1l);
y100 = value(index1 + 1, index2, index3); y100 = value(axis_index1 + 1, axis_index2, axis_index3);
if (axis3_->size() != 1) 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) { 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) 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) { if (axis2_->size() != 1) {
float x2l = axis2_->axisValue(index2); float x2l = axis2_->axisValue(axis_index2);
float x2u = axis2_->axisValue(index2 + 1); float x2u = axis2_->axisValue(axis_index2 + 1);
dx2 = (x2 - x2l) / (x2u - x2l); dx2 = (x2 - x2l) / (x2u - x2l);
y010 = value(index1, index2 + 1, index3); y010 = value(axis_index1, axis_index2 + 1, axis_index3);
if (axis3_->size() != 1) 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) { if (axis3_->size() != 1) {
float x3l = axis3_->axisValue(index3); float x3l = axis3_->axisValue(axis_index3);
float x3u = axis3_->axisValue(index3 + 1); float x3u = axis3_->axisValue(axis_index3 + 1);
dx3 = (x3 - x3l) / (x3u - x3l); dx3 = (x3 - x3l) / (x3u - x3l);
y001 = value(index1, index2, index3 + 1); y001 = value(axis_index1, axis_index2, axis_index3 + 1);
} }
float tbl_value float tbl_value
@ -1294,15 +1310,15 @@ Table3::reportValue(const char *result_name,
*result += unit3->asString(value3, digits); *result += unit3->asString(value3, digits);
*result += '\n'; *result += '\n';
size_t index1 = axis1_->findAxisIndex(value1); size_t axis_index1 = axis1_->findAxisIndex(value1);
size_t index2 = axis2_->findAxisIndex(value2); size_t axis_index2 = axis2_->findAxisIndex(value2);
size_t index3 = axis3_->findAxisIndex(value3); size_t axis_index3 = axis3_->findAxisIndex(value3);
*result += " | | "; *result += " | | ";
*result += unit3->asString(axis3_->axisValue(index3), digits); *result += unit3->asString(axis3_->axisValue(axis_index3), digits);
if (axis3_->size() != 1) { if (axis3_->size() != 1) {
*result += " "; *result += " ";
*result += unit3->asString(axis3_->axisValue(index3 + 1), digits); *result += unit3->asString(axis3_->axisValue(axis_index3 + 1), digits);
} }
*result += '\n'; *result += '\n';
@ -1310,13 +1326,13 @@ Table3::reportValue(const char *result_name,
if (axis1_->size() != 1) { if (axis1_->size() != 1) {
*result += " "; *result += " ";
*result += unit1->asString(axis1_->axisValue(index1+1), digits); *result += unit1->asString(axis1_->axisValue(axis_index1+1), digits);
*result += " v / "; *result += " v / ";
*result += table_unit->asString(value(index1+1,index2,index3), *result += table_unit->asString(value(axis_index1+1,axis_index2,axis_index3),
digits); digits);
if (axis3_->size() != 1) { if (axis3_->size() != 1) {
*result += " "; *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); digits);
} }
} }
@ -1326,14 +1342,14 @@ Table3::reportValue(const char *result_name,
} }
*result += '\n'; *result += '\n';
*result += unit1->asString(axis1_->axisValue(index1), digits); *result += unit1->asString(axis1_->axisValue(axis_index1), digits);
*result += " "; *result += " ";
*result += unit2->asString(axis2_->axisValue(index2), digits); *result += unit2->asString(axis2_->axisValue(axis_index2), digits);
*result += " | "; *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) { if (axis3_->size() != 1) {
*result += " "; *result += " ";
*result += table_unit->asString(value(index1, index2, index3+1), *result += table_unit->asString(value(axis_index1, axis_index2, axis_index3+1),
digits); digits);
} }
*result += '\n'; *result += '\n';
@ -1341,25 +1357,25 @@ Table3::reportValue(const char *result_name,
*result += " |/ "; *result += " |/ ";
if (axis1_->size() != 1 if (axis1_->size() != 1
&& axis2_->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); digits);
if (axis3_->size() != 1) { if (axis3_->size() != 1) {
*result += " "; *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); digits);
} }
} }
*result += '\n'; *result += '\n';
*result += " "; *result += " ";
*result += unit2->asString(axis2_->axisValue(index2 + 1), digits); *result += unit2->asString(axis2_->axisValue(axis_index2 + 1), digits);
*result += " | "; *result += " | ";
if (axis2_->size() != 1) { 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); digits);
if (axis3_->size() != 1) { if (axis3_->size() != 1) {
*result += " "; *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); digits);
} }
} }
@ -1388,24 +1404,24 @@ Table3::report(const Units *units,
const Unit *unit1 = axis1_->unit(units); const Unit *unit1 = axis1_->unit(units);
const Unit *unit2 = axis2_->unit(units); const Unit *unit2 = axis2_->unit(units);
const Unit *unit3 = axis3_->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()), 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("%s", tableVariableString(axis3_->variable()));
report->reportLine(" ------------------------------"); report->reportLine(" ------------------------------");
string line = " "; string line = " ";
for (size_t index3 = 0; index3 < axis3_->size(); index3++) { for (size_t axis_index3 = 0; axis_index3 < axis3_->size(); axis_index3++) {
line += unit3->asString(axis3_->axisValue(index3), digits); line += unit3->asString(axis3_->axisValue(axis_index3), digits);
line += " "; line += " ";
} }
report->reportLineString(line); report->reportLineString(line);
for (size_t index2 = 0; index2 < axis2_->size(); index2++) { for (size_t axis_index2 = 0; axis_index2 < axis2_->size(); axis_index2++) {
line = unit2->asString(axis2_->axisValue(index2),digits); line = unit2->asString(axis2_->axisValue(axis_index2),digits);
line += " |"; line += " |";
for (size_t index3 = 0; index3 < axis3_->size(); index3++) { for (size_t axis_index3 = 0; axis_index3 < axis3_->size(); axis_index3++) {
line += table_unit->asString(value(index1, index2, index3), digits); line += table_unit->asString(value(axis_index1, axis_index2, axis_index3), digits);
line += " "; line += " ";
} }
report->reportLineString(line); report->reportLineString(line);
@ -1564,67 +1580,29 @@ tableVariableUnit(TableAxisVariable variable,
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
OutputWaveform::OutputWaveform(float slew,
float cap, ////////////////////////////////////////////////////////////////
Table1 *currents,
float reference_time) : OutputWaveforms::OutputWaveforms(TableAxisPtr slew_axis,
slew_(slew), TableAxisPtr cap_axis,
cap_(cap), Table1Seq &current_waveforms,
currents_(currents), Table1 *ref_times) :
voltages_(nullptr), slew_axis_(slew_axis),
reference_time_(reference_time) cap_axis_(cap_axis),
current_waveforms_(current_waveforms),
ref_times_(ref_times)
{ {
} }
OutputWaveform::OutputWaveform(float slew, OutputWaveforms::~OutputWaveforms()
float cap,
Table1 *currents,
Table1 *voltages,
float reference_time) :
slew_(slew),
cap_(cap),
currents_(currents),
voltages_(voltages),
reference_time_(reference_time)
{ {
} current_waveforms_.deleteContents();
voltage_waveforms_.deleteContents();
OutputWaveform::~OutputWaveform() delete ref_times_;
{
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
OutputWaveform::checkAxes(TableTemplate *tbl_template) OutputWaveforms::checkAxes(TableTemplate *tbl_template)
{ {
TableAxisPtr axis1 = tbl_template->axis1(); TableAxisPtr axis1 = tbl_template->axis1();
TableAxisPtr axis2 = tbl_template->axis2(); TableAxisPtr axis2 = tbl_template->axis2();
@ -1640,66 +1618,7 @@ OutputWaveform::checkAxes(TableTemplate *tbl_template)
&& axis3->variable() == TableAxisVariable::time); && axis3->variable() == TableAxisVariable::time);
} }
string Table1
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
OutputWaveforms::voltageWaveform(float slew, OutputWaveforms::voltageWaveform(float slew,
float cap) 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_index01 = slew_index * cap_axis_->size() + (cap_index + 1);
size_t wave_index10 = (slew_index + 1) * cap_axis_->size() + cap_index; 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); size_t wave_index11 = (slew_index + 1) * cap_axis_->size() + (cap_index + 1);
OutputWaveform *waveform00 = waveforms_[wave_index00]; const Table1 *values00 = voltageWaveform(wave_index00, cap);
OutputWaveform *waveform01 = waveforms_[wave_index01]; const Table1 *values01 = voltageWaveform(wave_index01, cap);
OutputWaveform *waveform10 = waveforms_[wave_index10]; const Table1 *values10 = voltageWaveform(wave_index10, cap);
OutputWaveform *waveform11 = waveforms_[wave_index11]; const Table1 *values11 = voltageWaveform(wave_index11, cap);
const Table1 *voltages00 = waveform00->voltages(); TableAxisPtr time_axis00 = values00->axis1();
const Table1 *voltages01 = waveform01->voltages(); TableAxisPtr time_axis01 = values01->axis1();
const Table1 *voltages10 = waveform10->voltages(); TableAxisPtr time_axis10 = values10->axis1();
const Table1 *voltages11 = waveform11->voltages(); TableAxisPtr time_axis11 = values11->axis1();
TableAxisPtr time_axis00 = voltages00->axis1();
TableAxisPtr time_axis01 = voltages01->axis1();
TableAxisPtr time_axis10 = voltages10->axis1();
TableAxisPtr time_axis11 = voltages11->axis1();
// Find time axis min/max. // Find time axis min/max.
size_t time_step_count = 20; size_t time_step_count = 20;
@ -1738,7 +1653,7 @@ OutputWaveforms::voltageWaveform(float slew,
time_values); time_values);
// Interpolate waveform samples at time steps. // 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 index1 = slew_index;
size_t index2 = cap_index; size_t index2 = cap_index;
float x1 = slew; float x1 = slew;
@ -1749,41 +1664,136 @@ OutputWaveforms::voltageWaveform(float slew,
float x2l = cap_axis_->axisValue(index2); float x2l = cap_axis_->axisValue(index2);
float x2u = cap_axis_->axisValue(index2 + 1); float x2u = cap_axis_->axisValue(index2 + 1);
float dx2 = (x2 - x2l) / (x2u - x2l); float dx2 = (x2 - x2l) / (x2u - x2l);
FloatSeq *voltages = new FloatSeq; FloatSeq *values = new FloatSeq;
bool waveform_started = false; bool waveform_started = false;
float prev_volt = 0.0; float prev_value = 0.0;
constexpr float volt_tol = .01; constexpr float value_tol = .01;
float volt_end = volt_max * (1.0 - volt_tol); float value_end = value * (1.0 - value_tol);
for (size_t i = 0; i <= time_step_count; i++) { for (size_t i = 0; i <= time_step_count; i++) {
float time = time_min + time_step * i; float time = time_min + time_step * i;
float y00 = voltages00->findValue(time, true); float y00 = values00->findValue(time);
float y10 = voltages10->findValue(time, true); float y10 = values10->findValue(time);
float y11 = voltages11->findValue(time, true); float y11 = values11->findValue(time);
float y01 = voltages01->findValue(time, true); float y01 = values01->findValue(time);
float voltage float voltage
= (1 - dx1) * (1 - dx2) * y00 = (1 - dx1) * (1 - dx2) * y00
+ dx1 * (1 - dx2) * y10 + dx1 * (1 - dx2) * y10
+ dx1 * dx2 * y11 + dx1 * dx2 * y11
+ (1 - dx1) * dx2 * y01; + (1 - dx1) * dx2 * y01;
if (voltage > volt_tol) if (voltage > value_tol)
waveform_started = true; waveform_started = true;
if (waveform_started) { if (waveform_started) {
time_values->push_back(time); time_values->push_back(time);
voltages->push_back(voltage); values->push_back(voltage);
} }
if (prev_volt > volt_end) if (prev_value > value_end)
break; break;
prev_volt = voltage; prev_value = voltage;
}
return Table1(values, time_axis);
} }
// Interpolate reference time. Table1 *
// (only depends on slew) OutputWaveforms::voltageWaveform(size_t wave_index,
float ref_time float cap)
= (1 - dx1) * waveform00->referenceTime() {
+ dx1 * waveform10->referenceTime(); 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); // i = C dv/dt
return OutputWaveform(slew, cap, nullptr, waveform, ref_time); // 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<TableAxis>(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);
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////

View File

@ -3788,6 +3788,14 @@ format_voltage(const char *value,
return Sta::sta()->units()->voltageUnit()->asString(value1, digits); 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 * const char *
format_power(const char *value, format_power(const char *value,
int digits) int digits)
@ -5649,12 +5657,25 @@ voltage_waveform(float in_slew,
{ {
GateTableModel *gate_model = dynamic_cast<GateTableModel*>(self->model()); GateTableModel *gate_model = dynamic_cast<GateTableModel*>(self->model());
if (gate_model) { if (gate_model) {
OutputWaveforms *output_waveforms = gate_model->outputWaveforms(); OutputWaveforms *waveforms = gate_model->outputWaveforms();
if (output_waveforms) { if (waveforms) {
OutputWaveform voltage_waveform = Table1 waveform = waveforms->voltageWaveform(in_slew, load_cap);
output_waveforms->voltageWaveform(in_slew, load_cap); return waveform;
Table1 voltages(std::move(*voltage_waveform.voltages())); }
return voltages; }
return Table1();
}
Table1
current_waveform(float in_slew,
float load_cap)
{
GateTableModel *gate_model = dynamic_cast<GateTableModel*>(self->model());
if (gate_model) {
OutputWaveforms *waveforms = gate_model->outputWaveforms();
if (waveforms) {
Table1 waveform = waveforms->currentWaveform(in_slew, load_cap);
return waveform;
} }
} }
return Table1(); return Table1();