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:
parent
6c3ba16e07
commit
eeb1575d46
|
|
@ -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 ¤t_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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 ¤t_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);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
|
||||||
33
tcl/StaTcl.i
33
tcl/StaTcl.i
|
|
@ -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();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue