Skip to content

Commit

Permalink
Merge pull request #1194 from ra3xdh/fix_1138
Browse files Browse the repository at this point in the history
Fix plotting XSPICE digital nodes
  • Loading branch information
ra3xdh authored Jan 7, 2025
2 parents 11d0c1a + f876e6f commit b955037
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 9 deletions.
56 changes: 49 additions & 7 deletions qucs/extsimkernels/abstractspicekernel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,9 @@ void AbstractSpiceKernel::slotSimulate()
* and independent variables. An independent variable is the first in list.
* \param isComplex Type of variables. True if complex. False if real.
*/
void AbstractSpiceKernel::parseNgSpiceSimOutput(QString ngspice_file,QList< QList<double> > &sim_points,QStringList &var_list, bool &isComplex)
void AbstractSpiceKernel::parseNgSpiceSimOutput(QString ngspice_file, QList< QList<double> > &sim_points,
QStringList &var_list, bool &isComplex,
QStringList &digital_vars, QList<int> &dig_vars_dims)
{
isComplex = false;
bool isBinary = false;
Expand Down Expand Up @@ -384,6 +386,11 @@ void AbstractSpiceKernel::parseNgSpiceSimOutput(QString ngspice_file,QList< QLis
lin = ngsp_data.readLine();
QString dep_var = lin.section(sep,1,1,QString::SectionSkipEmpty);
var_list.append(dep_var);
if (lin.contains("dims=")) {
digital_vars.append(dep_var); // XSPICE digital node
QString tail = lin.section("dims=",1,1,QString::SectionSkipEmpty);
dig_vars_dims.append(tail.toInt());
}
}
continue;
}
Expand Down Expand Up @@ -1163,12 +1170,13 @@ void AbstractSpiceKernel::convertToQucsData(const QString &qucs_dataset)

for (const QString& ngspice_output_filename : a_output_files) { // For every simulation convert results to Qucs dataset
QList< QList<double> > sim_points;
QStringList var_list;
QStringList var_list, digital_vars;
QString swp_var,swp_var2;
QStringList swp_var_val,swp_var2_val;
bool isComplex = false;
bool hasParSweep = false;
bool hasDblParSweep = false;
QList<int> dig_vars_dims;

QString dataset_prefix;
bool isCustomPrefix = false;
Expand Down Expand Up @@ -1252,7 +1260,7 @@ void AbstractSpiceKernel::convertToQucsData(const QString &qucs_dataset)
parseSTEPOutput(full_outfile,sim_points,var_list,isComplex);
break;
case spiceRaw:
parseNgSpiceSimOutput(full_outfile,sim_points,var_list,isComplex);
parseNgSpiceSimOutput(full_outfile, sim_points, var_list, isComplex, digital_vars, dig_vars_dims);
break;
case xyceSTD:
parseXYCESTDOutput(full_outfile,sim_points,var_list,isComplex,hasSwp);
Expand All @@ -1271,6 +1279,8 @@ void AbstractSpiceKernel::convertToQucsData(const QString &qucs_dataset)
}
if (var_list.isEmpty()) continue; // nothing to convert
normalizeVarsNames(var_list, dataset_prefix, isCustomPrefix);
digital_vars.prepend(var_list.first());
normalizeVarsNames(digital_vars, dataset_prefix, isCustomPrefix);

QString indep = var_list.first();
//QList<double> sim_point;
Expand Down Expand Up @@ -1313,10 +1323,37 @@ void AbstractSpiceKernel::convertToQucsData(const QString &qucs_dataset)
ds_stream<<"</indep>\n";
}

int dig_var_idx = 0;
for(int i=1;i<var_list.count();i++) { // output dep var
if (indep.isEmpty()) ds_stream<<QStringLiteral("<indep %1 %2>\n").arg(var_list.at(i)).arg(sim_points.count());
else ds_stream<<QStringLiteral("<dep %1 %2>\n").arg(var_list.at(i)).arg(indep);
bool is_digital_var = false;
bool digital_indep = false;
if (indep.isEmpty()) {
ds_stream<<QStringLiteral("<indep %1 %2>\n").arg(var_list.at(i)).arg(sim_points.count());
} else {
QString var = var_list.at(i);
is_digital_var = digital_vars.contains(var);
if (is_digital_var && !var.endsWith("_steps")) { // XSPICE digital node
// requires another X-variable; not time
QString var2 = var + "_steps";
var2.remove("v(");
var2.remove("i(");
var2.remove(")");
if (hasParSweep) {
var2 += " " + swp_var;
if (hasDblParSweep) var += " " + swp_var2;
}
ds_stream<<QStringLiteral("<dep %1 %2>\n").arg(var).arg(var2);
} else if (is_digital_var && var.endsWith("_steps") && // indep XSPICE digital var
!var.contains("(") && !var.contains(")")) {
digital_indep = true;
ds_stream<<QStringLiteral("<indep %1 %2>\n").arg(var).arg(dig_vars_dims.at(dig_var_idx));
} else {
ds_stream<<QStringLiteral("<dep %1 %2>\n").arg(var_list.at(i)).arg(indep);
}
}
int count = 0;
for (auto& sim_point : sim_points) {
if (is_digital_var && count > dig_vars_dims.at(dig_var_idx)) break;
if (isComplex) {
double re=sim_point.at(2*(i-1)+1);
double im = sim_point.at(2*i);
Expand All @@ -1329,9 +1366,14 @@ void AbstractSpiceKernel::convertToQucsData(const QString &qucs_dataset)
} else {
ds_stream<<QString::number(sim_point.at(i),'e',12)<<"\n";
}
count++;
}
if (indep.isEmpty() || digital_indep) {
ds_stream<<"</indep>\n";
} else {
ds_stream<<"</dep>\n";
}
if (indep.isEmpty()) ds_stream<<"</indep>\n";
else ds_stream<<"</dep>\n";
if (is_digital_var) dig_var_idx++;
}
}

Expand Down
5 changes: 3 additions & 2 deletions qucs/extsimkernels/abstractspicekernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,9 @@ class AbstractSpiceKernel : public QObject
virtual void createSubNetlsit(QTextStream& stream, bool lib = false);

void parseNgSpiceSimOutput(QString ngspice_file,
QList< QList<double> > &sim_points,
QStringList &var_list, bool &isComplex);
QList< QList<double> > &sim_points,
QStringList &var_list, bool &isComplex,
QStringList &digital_vars, QList<int> &dig_vars_dims);
void parseHBOutput(QString ngspice_file, QList< QList<double> > &sim_points,
QStringList &var_list, bool &hasParSweep);
void parseFourierOutput(QString ngspice_file, QList< QList<double> > &sim_points,
Expand Down

0 comments on commit b955037

Please sign in to comment.