Skip to content

Commit

Permalink
Merge pull request #1201 from ThomasZecha/current
Browse files Browse the repository at this point in the history
Introduce optional netlisting to console
  • Loading branch information
ra3xdh authored Feb 4, 2025
2 parents 4637aa9 + e27883f commit 75040f3
Show file tree
Hide file tree
Showing 35 changed files with 873 additions and 586 deletions.
4 changes: 2 additions & 2 deletions qucs/components/component.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -828,7 +828,7 @@ QString Component::getVerilogACode() {
}
}

QString Component::getExpression(bool, bool) {
QString Component::getExpression(spicecompat::SpiceDialect) {
return QString();
}

Expand All @@ -840,7 +840,7 @@ QStringList Component::getExtraVariables() {
return QStringList();
}

QString Component::getProbeVariable(bool) {
QString Component::getProbeVariable(spicecompat::SpiceDialect) {
return QString();
}

Expand Down
4 changes: 2 additions & 2 deletions qucs/components/component.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ class Component : public Element {
QString getNetlist();
QString getSpiceNetlist(spicecompat::SpiceDialect dialect = spicecompat::SPICEDefault);
QString getVerilogACode();
virtual QString getExpression(bool isXyce = false, bool isCdl = false);
virtual QString getExpression(spicecompat::SpiceDialect dialect = spicecompat::SPICEDefault);
virtual QString getEquations(QString sim, QStringList &dep_vars);
virtual QStringList getExtraVariables();
virtual QString getProbeVariable(bool isXyce = false);
virtual QString getProbeVariable(spicecompat::SpiceDialect dialect = spicecompat::SPICEDefault);
virtual QString getSpiceModel();
virtual QString getSpiceLibrary() { return QString(); }
virtual QStringList getSpiceLibraryFiles() { return QStringList(); }
Expand Down
11 changes: 4 additions & 7 deletions qucs/components/equation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,14 +119,11 @@ QString Equation::getVAExpressions()
/*!
* \brief Equation::getExpression Extract equations that don't contain simulation variables
* (voltages/cureents) in .PARAM section of spice netlist
* \param isXyce True if Xyce is used.
* \param isCdl True if CDL is used.
* \param dialect Which spice-dialect is used.
* \return .PARAM section of spice netlist as a single string.
*/
QString Equation::getExpression(bool isXyce, bool isCdl /* = false */)
QString Equation::getExpression(spicecompat::SpiceDialect dialect /* = spicecompat::SPICEDefault */)
{
Q_UNUSED(isCdl);

if (isActive != COMP_IS_ACTIVE) return QString();

QStringList ng_vars,ngsims;
Expand All @@ -145,9 +142,9 @@ QString Equation::getExpression(bool isXyce, bool isCdl /* = false */)
QStringList tokens;
QString eqn = Props.at(i)->Value;
spicecompat::splitEqn(eqn,tokens);
spicecompat::convert_functions(tokens,isXyce);
spicecompat::convert_functions(tokens, dialect == spicecompat::SPICEXyce);
eqn = tokens.join("");
if (isXyce) {
if (dialect == spicecompat::SPICEXyce) {
eqn.replace("^","**");

if (!(fp_pattern.match(eqn).hasMatch()||
Expand Down
2 changes: 1 addition & 1 deletion qucs/components/equation.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class Equation : public Component {
~Equation();
Component* newOne();
static Element* info(QString&, char* &, bool getNewOne=false);
QString getExpression(bool isXyce, bool isCdl = false);
QString getExpression(spicecompat::SpiceDialect dialect = spicecompat::SPICEDefault);
QString getEquations(QString sim, QStringList &dep_vars);
QString getVAvariables();
QString getVAExpressions();
Expand Down
6 changes: 3 additions & 3 deletions qucs/components/iprobe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,13 @@ QString iProbe::spice_netlist(spicecompat::SpiceDialect dialect /* = spicecompat

/*!
* \brief iProbe::getProbeVariable Get current probe variable
* \param isXyce True if Xyce simulator
* \param dialect Spice dialect used
* \return Current probe variable in Ngspice or Xyce notation
*/
QString iProbe::getProbeVariable(bool isXyce)
QString iProbe::getProbeVariable(spicecompat::SpiceDialect dialect)
{
QString s;
if (isXyce) {
if (dialect == spicecompat::SPICEXyce) {
s = QStringLiteral("I(V%1)").arg(Name);
} else {
s = QStringLiteral("V%1#branch").arg(Name);
Expand Down
4 changes: 2 additions & 2 deletions qucs/components/iprobe.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ class iProbe : public Component {
~iProbe();
Component* newOne();
static Element* info(QString&, char* &, bool getNewOne=false);
QString getExpression(bool, bool) { return "";}
QString getProbeVariable(bool isXyce = false);
QString getExpression(spicecompat::SpiceDialect) { return "";}
QString getProbeVariable(spicecompat::SpiceDialect dialect = spicecompat::SPICEDefault);

protected:
QString spice_netlist(spicecompat::SpiceDialect dialect = spicecompat::SPICEDefault);
Expand Down
2 changes: 1 addition & 1 deletion qucs/components/vprobe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ Element* vProbe::info(QString& Name, char* &BitmapFile, bool getNewOne)
return 0;
}

QString vProbe::getProbeVariable(bool)
QString vProbe::getProbeVariable(spicecompat::SpiceDialect)
{
return Name;
}
Expand Down
2 changes: 1 addition & 1 deletion qucs/components/vprobe.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class vProbe : public Component {
~vProbe();
Component* newOne();
static Element* info(QString&, char* &, bool getNewOne=false);
QString getProbeVariable(bool isXyce = false);
QString getProbeVariable(spicecompat::SpiceDialect dialect = spicecompat::SPICEDefault);
protected:
QString spice_netlist(spicecompat::SpiceDialect dialect = spicecompat::SPICEDefault);
};
Expand Down
2 changes: 1 addition & 1 deletion qucs/extsimkernels/CdlNetlistWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ void CdlNetlistWriter::startNetlist()
{
if (pc->isEquation)
{
s = pc->getExpression(false, true);
s = pc->getExpression(spicecompat::CDL);
a_netlistStream << s;
}
}
Expand Down
44 changes: 29 additions & 15 deletions qucs/extsimkernels/externsimdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
#include "main.h"
#include "qucs.h"

ExternSimDialog::ExternSimDialog(Schematic *sch, bool netlist_mode) :
ExternSimDialog::ExternSimDialog(Schematic* sch, bool netlist2Console, bool netlist_mode) :
QDialog(sch),
a_schematic(sch),
a_buttonStopSim(new QPushButton(tr("Stop"),this)),
Expand All @@ -37,7 +37,8 @@ ExternSimDialog::ExternSimDialog(Schematic *sch, bool netlist_mode) :
a_ngspice(new Ngspice(sch,this)),
a_xyce(new Xyce(sch,this)),
a_wasSimulated(true),
a_hasError(false)
a_hasError(false),
a_netlist2Console(netlist2Console)
{
const QString workdir(QucsSettings.S4Qworkdir);

Expand Down Expand Up @@ -296,27 +297,40 @@ void ExternSimDialog::slotStop()
void ExternSimDialog::slotSaveNetlist()
{
QFileInfo inf(a_schematic->getDocName());
QString filename = QFileDialog::getSaveFileName(this,tr("Save netlist"),inf.path()+QDir::separator()+"netlist.cir",
"All files (*)");
if (filename.isEmpty()) return;
QString filename;

if (!a_netlist2Console)
{
filename = QFileDialog::getSaveFileName(
this,
tr("Save netlist"),
inf.path() + QDir::separator() + "netlist.cir",
"All files (*)");
if (filename.isEmpty())
{
return;
}
}

switch (QucsSettings.DefaultSimulator) {
switch (QucsSettings.DefaultSimulator)
{
case spicecompat::simNgspice:
case spicecompat::simSpiceOpus: {
a_ngspice->SaveNetlist(filename);
}
case spicecompat::simSpiceOpus:
a_ngspice->SaveNetlist(filename, a_netlist2Console);
break;
case spicecompat::simXyce: {
a_xyce->SaveNetlist(filename);
}
case spicecompat::simXyce:
a_xyce->SaveNetlist(filename, a_netlist2Console);
break;
default:
break;
}

if (!QFile::exists(filename)) {
QMessageBox::critical(0, QObject::tr("Save netlist"),
QObject::tr("Disk write error!"), QMessageBox::Ok);
if (!a_netlist2Console && !QFile::exists(filename))
{
QMessageBox::critical(
nullptr,
QObject::tr("Save netlist"),
QObject::tr("Disk write error!"), QMessageBox::Ok);
}
}

Expand Down
9 changes: 6 additions & 3 deletions qucs/extsimkernels/externsimdialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class ExternSimDialog : public QDialog
Q_OBJECT

private:
Schematic *a_schematic;
Schematic* a_schematic;

QPushButton *a_buttonStopSim;
QPushButton *a_buttonSaveNetlist;
Expand All @@ -46,10 +46,13 @@ class ExternSimDialog : public QDialog

bool a_wasSimulated;
bool a_hasError;
bool a_netlist2Console;

public:
explicit ExternSimDialog(Schematic *sch,
bool netlist_mode = false);
explicit ExternSimDialog(
Schematic* sch,
bool netlist2Console,
bool netlist_mode = false);
~ExternSimDialog();

bool wasSimulated() const { return a_wasSimulated; }
Expand Down
54 changes: 40 additions & 14 deletions qucs/extsimkernels/ngspice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@
#include "config.h"
#endif

#include <QScopedPointer>

#include <iostream>

/*!
\file ngspice.cpp
\brief Implementation of the Ngspice class
Expand All @@ -43,7 +47,7 @@
* \param schematic Schematic that need to be simulated with Ngspice.
* \param parent Parent object
*/
Ngspice::Ngspice(Schematic *schematic, QObject *parent) :
Ngspice::Ngspice(Schematic* schematic, QObject *parent) :
AbstractSpiceKernel(schematic, parent),
a_spinit_name()
{
Expand All @@ -67,8 +71,11 @@ Ngspice::Ngspice(Schematic *schematic, QObject *parent) :
* \param[out] vars The list of output variables and node names.
* \param[out] outputs The list of spice output raw text files.
*/
void Ngspice::createNetlist(QTextStream &stream, int ,
QStringList &simulations, QStringList &vars, QStringList &outputs)
void Ngspice::createNetlist(
QTextStream& stream,
QStringList& simulations,
QStringList& vars,
QStringList& outputs)
{
Q_UNUSED(simulations);

Expand Down Expand Up @@ -464,7 +471,7 @@ void Ngspice::slotSimulate()

QString netfile = "spice4qucs.cir";
QString tmp_path = QDir::toNativeSeparators(a_workdir+QDir::separator()+netfile);
SaveNetlist(tmp_path);
SaveNetlist(tmp_path, false);

removeAllSimulatorOutputs();

Expand Down Expand Up @@ -583,24 +590,43 @@ void Ngspice::slotProcessOutput()
* \brief Ngspice::SaveNetlist Create netlist and save it to file without execution
* of simulator.
* \param[in] filename Absolute path to netlist
* \param[in] netlist2Console Whether netlist to console instead to file
*/
void Ngspice::SaveNetlist(QString filename)
void Ngspice::SaveNetlist(QString filename, bool netlist2Console)
{
int num=0;
a_sims.clear();
a_vars.clear();

QFile spice_file(filename);
if (spice_file.open(QFile::WriteOnly)) {
QTextStream stream(&spice_file);
createNetlist(stream,num,a_sims,a_vars,a_output_files);
spice_file.close();
QScopedPointer<QString> netlistString;
QScopedPointer<QTextStream> netlistStream;
QScopedPointer<QFile> netlistFile;

if (netlist2Console)
{
netlistString.reset(new QString);
netlistStream.reset(new QTextStream(netlistString.get()));
}
else
{
QString msg=QStringLiteral("Tried to save netlist \nin %1\n(could not open for writing!)").arg(filename);
QString final_msg=QStringLiteral("%1\n This could be an error in the QSettings settings file\n(usually in ~/.config/qucs/qucs_s.conf)\nThe value for S4Q_workdir (default:/spice4qucs) needs to be writeable!\nFor a Simulation Simulation will raise error! (most likely S4Q_workdir does not exists)").arg(msg);
QMessageBox::critical(nullptr,tr("Problem with SaveNetlist"),final_msg,QMessageBox::Ok);
netlistFile.reset(new QFile(filename));
if (netlistFile->open(QFile::WriteOnly))
{
netlistStream.reset(new QTextStream(netlistFile.get()));
}
else
{
QString msg = QStringLiteral("Tried to save netlist \nin %1\n(could not open for writing!)").arg(filename);
QString final_msg = QStringLiteral("%1\n This could be an error in the QSettings settings file\n(usually in ~/.config/qucs/qucs_s.conf)\nThe value for S4Q_workdir (default:/spice4qucs) needs to be writeable!\nFor a Simulation Simulation will raise error! (most likely S4Q_workdir does not exists)").arg(msg);
QMessageBox::critical(nullptr,tr("Problem with SaveNetlist"), final_msg, QMessageBox::Ok);
return;
}
}

createNetlist(*netlistStream, a_sims, a_vars, a_output_files);

if (netlist2Console)
{
std::cout << netlistString->toUtf8().constData() << std::endl;
}
}

Expand Down
13 changes: 8 additions & 5 deletions qucs/extsimkernels/ngspice.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,22 +41,25 @@ class Ngspice : public AbstractSpiceKernel
QString a_spinit_name;

bool checkNodeNames(QStringList &incompat);
static QString collectSpiceinit(Schematic *sch);
static QString collectSpiceinit(Schematic* sch);
bool findMathFuncInc(QString &mathf_inc);
QString getParentSWPscript(Component *pc_swp, QString sim, bool before, bool &hasDblSWP);
QString getParentSWPCntVar(Component *pc_swp, QString sim);
void cleanSpiceinit();
void createSpiceinit(const QString &initial_spiceinit);

public:
explicit Ngspice(Schematic *schematic, QObject *parent = 0);
void SaveNetlist(QString filename);
explicit Ngspice(Schematic* schematic, QObject *parent = 0);
void SaveNetlist(QString filename, bool netlist2Console);
void setSimulatorCmd(QString cmd);
void setSimulatorParameters(QString parameters);

protected:
void createNetlist(QTextStream &stream, int NumPorts, QStringList &simulations,
QStringList &vars, QStringList &outputs);
void createNetlist(
QTextStream& stream,
QStringList& simulations,
QStringList& vars,
QStringList& outputs);

public slots:
void slotSimulate();
Expand Down
Loading

0 comments on commit 75040f3

Please sign in to comment.