Skip to content

Commit

Permalink
Add parser for printed scalars output
Browse files Browse the repository at this point in the history
In custom simulation one can print measurement or calculation results.
For example 'print a b c d > custom.prn'. The file looks like:
a = a_value
b = b_real,b_imag
etc...
The parser adds theses to the dataset as scalars.
  • Loading branch information
ivandi committed Jan 6, 2024
1 parent ef5cb8e commit 06d93d1
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 2 deletions.
51 changes: 51 additions & 0 deletions qucs/extsimkernels/abstractspicekernel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -820,6 +820,46 @@ void AbstractSpiceKernel::parseSTEPOutput(QString ngspice_file,
}
}

/*!
* \brief AbstractSpiceKernel::parsePrnOutput Parse scalar print output.
* \param[in] ngspice_file Spice output file name
* \param[out] sim_points 2D array in which simulation points should be extracted. All simulation
* points from all sweep variable steps are extracted in a single array
* \param[out] var_list This list is filled by simulation variables. There is a list of dependent
* and independent variables. An independent variable is the first in list.
*/
void AbstractSpiceKernel::parsePrnOutput(const QString &ngspice_file,
QList<QList<double> > &sim_points,
QStringList &var_list,
bool isComplex) {
QChar eq_sep = '=';
QChar reim_sep = ',';
QList <double> sim_point;

QFile ofile(ngspice_file);
if (ofile.open(QFile::ReadOnly)) {
var_list.clear();
sim_points.clear();
var_list.append(""); // dummy indep var
sim_point.append(0.0);
QTextStream data(&ofile);
while (!data.atEnd()) {
QString line = data.readLine();
if (line.contains(eq_sep)) {
QString var = line.section(eq_sep, 0, 0).trimmed();
QString val = line.section(eq_sep, 1, 1).trimmed();
double re = val.section(reim_sep, 0, 0).toDouble();
double im = val.section(reim_sep, 1, 1).toDouble();
var_list.append(var);
sim_point.append(re);
if ( isComplex )
sim_point.append(im);
}
}
sim_points.append(sim_point);
ofile.close();
}
}

void AbstractSpiceKernel::extractBinSamples(QDataStream &dbl, QList<QList<double> > &sim_points,
int NumPoints, int NumVars, bool isComplex)
Expand Down Expand Up @@ -1041,9 +1081,11 @@ int AbstractSpiceKernel::checkRawOutupt(QString ngspice_file, QStringList &value
QFile ofile(ngspice_file);
int plots_cnt = 0;
int zeroindex_cnt = 0;
int prnln_cnt = 0;
bool isXyce = false;
if (ofile.open(QFile::ReadOnly)) {
QTextStream ngsp_data(&ofile);
QRegularExpression prnln_rx("^\\D\\w*\\s=\\s-?\\d.\\d+[Ee][+-]\\d+");
QRegularExpression rx("^0\\s+[0-9].*"); // Zero index pattern
while (!ngsp_data.atEnd()) {
QString lin = ngsp_data.readLine();
Expand All @@ -1056,6 +1098,8 @@ int AbstractSpiceKernel::checkRawOutupt(QString ngspice_file, QStringList &value
zeroindex_cnt++;
values.append(QString::number(zeroindex_cnt));
}
if (prnln_rx.match(lin).hasMatch())
prnln_cnt++;
}
ofile.close();
}
Expand All @@ -1065,6 +1109,8 @@ int AbstractSpiceKernel::checkRawOutupt(QString ngspice_file, QStringList &value
if (zeroindex_cnt>1) filetype = xyceSTDswp;
else filetype = xyceSTD;
} else filetype = spiceRaw;
if ( (plots_cnt == 0) && (zeroindex_cnt == 0) && (prnln_cnt > 0) )
filetype = spicePrn;
return filetype;
}

Expand Down Expand Up @@ -1195,6 +1241,11 @@ void AbstractSpiceKernel::convertToQucsData(const QString &qucs_dataset)
hasParSweep = true;
swp_var = "Number";
parseXYCESTDOutput(full_outfile,sim_points,var_list,isComplex,hasSwp);
break;
case spicePrn:
isComplex = true;
parsePrnOutput(full_outfile, sim_points, var_list, isComplex);
break;
default: break;
}
}
Expand Down
6 changes: 5 additions & 1 deletion qucs/extsimkernels/abstractspicekernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class AbstractSpiceKernel : public QObject
{
Q_OBJECT
private:
enum outType {xyceSTD, spiceRaw, spiceRawSwp, xyceSTDswp, Unknown};
enum outType {xyceSTD, spiceRaw, spiceRawSwp, xyceSTDswp, spicePrn, Unknown};

void normalizeVarsNames(QStringList &var_list);
int checkRawOutupt(QString ngspice_file, QStringList &values);
Expand Down Expand Up @@ -101,6 +101,10 @@ class AbstractSpiceKernel : public QObject
void parseSTEPOutput(QString ngspice_file,
QList< QList<double> > &sim_points,
QStringList &var_list, bool &isComplex);
void parsePrnOutput(const QString &ngspice_file,
QList< QList<double> > &sim_points,
QStringList &var_list,
bool isComplex);
void parseXYCESTDOutput(QString std_file,
QList< QList<double> > &sim_points,
QStringList &var_list, bool &isComplex, bool &hasParSweep);
Expand Down
7 changes: 6 additions & 1 deletion qucs/extsimkernels/customsimdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ CustomSimDialog::CustomSimDialog(SpiceCustomSim *pc, Schematic *sch, QWidget *pa
QLabel* lblVars = new QLabel(tr("Variables to plot (semicolon separated)"));
edtVars = new QLineEdit(comp->Props.at(1)->Value);

QLabel* lblOut = new QLabel(tr("Extra outputs (semicolon separated; raw-SPICE or XYCE-STD format)"));
QLabel* lblOut = new QLabel(tr("Extra outputs (semicolon separated; raw-SPICE or XYCE-STD or scalars print format)"));
edtOutputs = new QLineEdit(comp->Props.at(2)->Value);

btnApply = new QPushButton(tr("Apply"));
Expand Down Expand Up @@ -195,10 +195,15 @@ void CustomSimDialog::slotFindOutputs()
} else {
QRegularExpression write_ex("^\\s*write\\s.*");
write_ex.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
QRegularExpression print_rx("^print\\s+[\\w\\s]+>.+");
print_rx.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
for (const QString& line : strings) {
if (write_ex.match(line).hasMatch()) {
outps.append(line.section(QRegularExpression("\\s"),1,1,QString::SectionSkipEmpty));
}
else if ( print_rx.match(line).hasMatch() ) {
outps.append(line.section('>', 1, 1, QString::SectionSkipEmpty).trimmed());
}
}
}

Expand Down

0 comments on commit 06d93d1

Please sign in to comment.