mirror of
https://github.com/ra3xdh/qucs_s
synced 2025-03-28 21:13:26 +00:00
All XSPICE-CM-related routines moved to XSPICE_CMbuilder class
This commit is contained in:
parent
31012e138d
commit
af2d8070a6
@ -17,6 +17,7 @@ spicecompat.h
|
||||
customsimdialog.h
|
||||
simsettingsdialog.h
|
||||
verilogawriter.h
|
||||
xspice_cmbuilder.h
|
||||
)
|
||||
|
||||
SET(EXTSIMKERNELS_SRCS
|
||||
@ -29,6 +30,7 @@ spicecompat.cpp
|
||||
customsimdialog.cpp
|
||||
simsettingsdialog.cpp
|
||||
verilogawriter.cpp
|
||||
xspice_cmbuilder.cpp
|
||||
)
|
||||
|
||||
SET(EXTSIMKERNELS_MOC_HDRS
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "xspice_cmbuilder.h"
|
||||
#include "components/iprobe.h"
|
||||
#include "components/vprobe.h"
|
||||
#include "components/equation.h"
|
||||
@ -39,8 +40,6 @@ Ngspice::Ngspice(Schematic *sch_, QObject *parent) :
|
||||
{
|
||||
simulator_cmd = QucsSettings.NgspiceExecutable;
|
||||
simulator_parameters = "";
|
||||
cmsubdir = "qucs_cmlib/";
|
||||
cmdir = QDir::convertSeparators(workdir+cmsubdir);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -351,12 +350,15 @@ void Ngspice::slotSimulate()
|
||||
|
||||
QString tmp_path = QDir::convertSeparators(workdir+"/spice4qucs.cir");
|
||||
SaveNetlist(tmp_path);
|
||||
createSpiceinit();
|
||||
if (needCompile()) {
|
||||
cleanCModelTree();
|
||||
createCModelTree();
|
||||
compileCMlib();
|
||||
|
||||
XSPICE_CMbuilder *CMbuilder = new XSPICE_CMbuilder(Sch);
|
||||
CMbuilder->createSpiceinit();
|
||||
if (CMbuilder->needCompile()) {
|
||||
CMbuilder->cleanCModelTree();
|
||||
CMbuilder->createCModelTree();
|
||||
CMbuilder->compileCMlib(output);
|
||||
}
|
||||
delete CMbuilder;
|
||||
|
||||
//startNgSpice(tmp_path);
|
||||
SimProcess->setWorkingDirectory(workdir);
|
||||
@ -415,152 +417,3 @@ void Ngspice::setSimulatorCmd(QString cmd)
|
||||
simulator_cmd = cmd;
|
||||
}
|
||||
|
||||
void Ngspice::createSpiceinit()
|
||||
{
|
||||
QString spinit_name=QDir::convertSeparators(workdir+"/.spiceinit");
|
||||
QFileInfo inf(spinit_name);
|
||||
if (inf.exists()) QFile::remove(spinit_name);
|
||||
|
||||
QFile spinit(spinit_name);
|
||||
if (spinit.open(QIODevice::WriteOnly)) {
|
||||
QTextStream stream(&spinit);
|
||||
for(Component *pc = Sch->DocComps.first(); pc != 0; pc = Sch->DocComps.next()) {
|
||||
if (pc->Model=="XSP_CMlib") {
|
||||
stream<<((XSP_CMlib *)pc)->getSpiceInit();
|
||||
}
|
||||
}
|
||||
if (needCompile()) stream<<"codemodel "+cmdir+"qucs_xspice.cm";
|
||||
spinit.close();
|
||||
}
|
||||
}
|
||||
|
||||
bool Ngspice::needCompile()
|
||||
{
|
||||
for(Component *pc = Sch->DocComps.first(); pc != 0; pc = Sch->DocComps.next()) {
|
||||
if (pc->Model=="XSP_CMod") return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Ngspice::cleanCModelTree Removes qucs_cmlib/ and all its contents.
|
||||
* Then creates an empty qucs_cmdir/
|
||||
*/
|
||||
void Ngspice::cleanCModelTree()
|
||||
{
|
||||
removeDir(cmdir);
|
||||
QDir wd(workdir);
|
||||
wd.mkdir(cmsubdir);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Ngspice::createCModelTree Obtain all cfunc.mod and ifspec.ifs files paths and
|
||||
* copy it into woriking directory of dynamic XSPICE CodeModels builder
|
||||
*/
|
||||
void Ngspice::createCModelTree()
|
||||
{
|
||||
QDir dir_cm(cmdir);
|
||||
QString lst_entries; // For modpath.lst
|
||||
QStringList objects; // Object files that need to be compiled
|
||||
|
||||
for(Component *pc = Sch->DocComps.first(); pc != 0; pc = Sch->DocComps.next()) {
|
||||
if (pc->Model=="XSP_CMod") {
|
||||
// Copy every cfunc.mod and ifspe.ifs pair into
|
||||
// unique subdirectory in qucs_cmlib/
|
||||
QString destdir = QDir::convertSeparators(pc->Name);
|
||||
dir_cm.mkdir(destdir);
|
||||
lst_entries += destdir + "\n";
|
||||
// Add cfunc.mod file
|
||||
QString file = pc->Props.at(0)->Value;
|
||||
QString destfile = normalizeModelName(file,destdir);
|
||||
QFile::copy(file,destfile);
|
||||
destfile.chop(4); // Add cfunc.o to objects
|
||||
destfile+=".o";
|
||||
objects.append(destfile);
|
||||
// Add ifspec.ifs file
|
||||
file = pc->Props.at(1)->Value;
|
||||
destfile = normalizeModelName(file,destdir);
|
||||
QFile::copy(file,destfile);
|
||||
destfile.chop(4); // Add ifspec.o to objects
|
||||
destfile+=".o";
|
||||
objects.append(destfile); // Add ifspec.o to objects
|
||||
}
|
||||
}
|
||||
|
||||
// Form modpath.lst. List all subdirectories entries in it
|
||||
QFile modpath_lst(cmdir+"/modpath.lst");
|
||||
if (modpath_lst.open(QIODevice::WriteOnly)) {
|
||||
QTextStream stream(&modpath_lst);
|
||||
stream<<lst_entries;
|
||||
modpath_lst.close();
|
||||
}
|
||||
|
||||
// Create empty udnpath.lst
|
||||
QFile udnpath_lst(cmdir+"/udnpath.lst");
|
||||
if (udnpath_lst.open(QIODevice::WriteOnly))
|
||||
udnpath_lst.close();
|
||||
|
||||
// Form proper Makefile
|
||||
QFile mkfile(cmdir+"/Makefile");
|
||||
if (mkfile.open(QIODevice::WriteOnly)) {
|
||||
QTextStream stream(&mkfile);
|
||||
QString rules_file = QucsSettings.BinDir+"../share/qucs/xspice_cmlib/cmlib.linux.rules.mk";
|
||||
stream<<"TARGET=qucs_xspice.cm\n";
|
||||
stream<<QString("OBJECTS=dlmain.o %1\n\n").arg(objects.join(" "));
|
||||
stream<<"include "+rules_file +"\n";
|
||||
mkfile.close();
|
||||
}
|
||||
|
||||
// Extract dlmain.c from the Ngspice installation
|
||||
QFileInfo inf(QucsSettings.NgspiceExecutable);
|
||||
QFile::copy(inf.path()+"/../share/ngspice/dlmain.c",cmdir+"/dlmain.c");
|
||||
}
|
||||
|
||||
QString Ngspice::normalizeModelName(QString &file, QString &destdir)
|
||||
{
|
||||
QFileInfo inf(file);
|
||||
QString filenam = inf.fileName();
|
||||
if (filenam.endsWith(".mod"))
|
||||
return QDir::convertSeparators(cmdir+'/'+destdir+"/cfunc.mod");
|
||||
if (filenam.endsWith(".ifs"))
|
||||
return QDir::convertSeparators(cmdir+'/'+destdir+"/ifspec.ifs");
|
||||
return QDir::convertSeparators(cmdir+'/'+destdir+'/'+filenam);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Ngspice::compileCMlib Compile all models and obtain qucs_xspice.cm
|
||||
*/
|
||||
void Ngspice::compileCMlib()
|
||||
{
|
||||
QProcess *make = new QProcess();
|
||||
make->setReadChannelMode(QProcess::MergedChannels);
|
||||
make->setWorkingDirectory(cmdir);
|
||||
make->start("make"); // For Unix
|
||||
make->waitForFinished();
|
||||
output += make->readAll();
|
||||
delete make;
|
||||
}
|
||||
|
||||
bool Ngspice::removeDir(const QString &dirName)
|
||||
{
|
||||
bool result = true;
|
||||
QDir dir(dirName);
|
||||
|
||||
if (dir.exists(dirName)) {
|
||||
Q_FOREACH(QFileInfo info, dir.entryInfoList(QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst)) {
|
||||
if (info.isDir()) {
|
||||
result = removeDir(info.absoluteFilePath());
|
||||
}
|
||||
else {
|
||||
result = QFile::remove(info.absoluteFilePath());
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
result = dir.rmdir(dirName);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -35,13 +35,8 @@ class Ngspice : public AbstractSpiceKernel
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
QString cmdir,cmsubdir;
|
||||
|
||||
QString getParentSWPscript(Component *pc_swp, QString sim, bool before, bool &hasDblSWP);
|
||||
void createSpiceinit();
|
||||
bool needCompile();
|
||||
QString normalizeModelName(QString &file,QString &destdir);
|
||||
bool removeDir(const QString &dirName);
|
||||
|
||||
public:
|
||||
explicit Ngspice(Schematic *sch_, QObject *parent = 0);
|
||||
@ -52,10 +47,6 @@ protected:
|
||||
void createNetlist(QTextStream &stream, int NumPorts, QStringList &simulations,
|
||||
QStringList &vars, QStringList &outputs);
|
||||
|
||||
void cleanCModelTree();
|
||||
void createCModelTree();
|
||||
void compileCMlib();
|
||||
|
||||
public slots:
|
||||
void slotSimulate();
|
||||
|
||||
|
185
qucs/extsimkernels/xspice_cmbuilder.cpp
Normal file
185
qucs/extsimkernels/xspice_cmbuilder.cpp
Normal file
@ -0,0 +1,185 @@
|
||||
/***************************************************************************
|
||||
xspice_cmbuilder.cpp
|
||||
----------------
|
||||
begin : Sun Jan 31 2015
|
||||
copyright : (C) 2015 by Vadim Kuznetsov
|
||||
email : ra3xdh@gmail.com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "xspice_cmbuilder.h"
|
||||
#include "spicecomponents/xsp_cmlib.h"
|
||||
#include "main.h"
|
||||
|
||||
XSPICE_CMbuilder::XSPICE_CMbuilder(Schematic *sch_)
|
||||
{
|
||||
workdir = QucsSettings.S4Qworkdir;
|
||||
Sch = sch_;
|
||||
cmsubdir = "qucs_cmlib/";
|
||||
cmdir = QDir::convertSeparators(workdir+cmsubdir);
|
||||
spinit_name=QDir::convertSeparators(workdir+"/.spiceinit");
|
||||
}
|
||||
|
||||
XSPICE_CMbuilder::~XSPICE_CMbuilder()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void XSPICE_CMbuilder::createSpiceinit()
|
||||
{
|
||||
|
||||
QFileInfo inf(spinit_name);
|
||||
if (inf.exists()) QFile::remove(spinit_name);
|
||||
|
||||
QFile spinit(spinit_name);
|
||||
if (spinit.open(QIODevice::WriteOnly)) {
|
||||
QTextStream stream(&spinit);
|
||||
for(Component *pc = Sch->DocComps.first(); pc != 0; pc = Sch->DocComps.next()) {
|
||||
if (pc->Model=="XSP_CMlib") {
|
||||
stream<<((XSP_CMlib *)pc)->getSpiceInit();
|
||||
}
|
||||
}
|
||||
if (needCompile()) stream<<"codemodel "+cmdir+"qucs_xspice.cm";
|
||||
spinit.close();
|
||||
}
|
||||
}
|
||||
|
||||
bool XSPICE_CMbuilder::needCompile()
|
||||
{
|
||||
for(Component *pc = Sch->DocComps.first(); pc != 0; pc = Sch->DocComps.next()) {
|
||||
if (pc->Model=="XSP_CMod") return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Ngspice::cleanCModelTree Removes qucs_cmlib/ and all its contents.
|
||||
* Then creates an empty qucs_cmdir/
|
||||
*/
|
||||
void XSPICE_CMbuilder::cleanCModelTree()
|
||||
{
|
||||
removeDir(cmdir);
|
||||
QDir wd(workdir);
|
||||
wd.mkdir(cmsubdir);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Ngspice::createCModelTree Obtain all cfunc.mod and ifspec.ifs files paths and
|
||||
* copy it into woriking directory of dynamic XSPICE CodeModels builder
|
||||
*/
|
||||
void XSPICE_CMbuilder::createCModelTree()
|
||||
{
|
||||
QDir dir_cm(cmdir);
|
||||
QString lst_entries; // For modpath.lst
|
||||
QStringList objects; // Object files that need to be compiled
|
||||
|
||||
for(Component *pc = Sch->DocComps.first(); pc != 0; pc = Sch->DocComps.next()) {
|
||||
if (pc->Model=="XSP_CMod") {
|
||||
// Copy every cfunc.mod and ifspe.ifs pair into
|
||||
// unique subdirectory in qucs_cmlib/
|
||||
QString destdir = QDir::convertSeparators(pc->Name);
|
||||
dir_cm.mkdir(destdir);
|
||||
lst_entries += destdir + "\n";
|
||||
// Add cfunc.mod file
|
||||
QString file = pc->Props.at(0)->Value;
|
||||
QString destfile = normalizeModelName(file,destdir);
|
||||
QFile::copy(file,destfile);
|
||||
destfile.chop(4); // Add cfunc.o to objects
|
||||
destfile+=".o";
|
||||
objects.append(destfile);
|
||||
// Add ifspec.ifs file
|
||||
file = pc->Props.at(1)->Value;
|
||||
destfile = normalizeModelName(file,destdir);
|
||||
QFile::copy(file,destfile);
|
||||
destfile.chop(4); // Add ifspec.o to objects
|
||||
destfile+=".o";
|
||||
objects.append(destfile); // Add ifspec.o to objects
|
||||
}
|
||||
}
|
||||
|
||||
// Form modpath.lst. List all subdirectories entries in it
|
||||
QFile modpath_lst(cmdir+"/modpath.lst");
|
||||
if (modpath_lst.open(QIODevice::WriteOnly)) {
|
||||
QTextStream stream(&modpath_lst);
|
||||
stream<<lst_entries;
|
||||
modpath_lst.close();
|
||||
}
|
||||
|
||||
// Create empty udnpath.lst
|
||||
QFile udnpath_lst(cmdir+"/udnpath.lst");
|
||||
if (udnpath_lst.open(QIODevice::WriteOnly))
|
||||
udnpath_lst.close();
|
||||
|
||||
// Form proper Makefile
|
||||
QFile mkfile(cmdir+"/Makefile");
|
||||
if (mkfile.open(QIODevice::WriteOnly)) {
|
||||
QTextStream stream(&mkfile);
|
||||
QString rules_file = QucsSettings.BinDir+"../share/qucs/xspice_cmlib/cmlib.linux.rules.mk";
|
||||
stream<<"TARGET=qucs_xspice.cm\n";
|
||||
stream<<QString("OBJECTS=dlmain.o %1\n\n").arg(objects.join(" "));
|
||||
stream<<"include "+rules_file +"\n";
|
||||
mkfile.close();
|
||||
}
|
||||
|
||||
// Extract dlmain.c from the Ngspice installation
|
||||
QFileInfo inf(QucsSettings.NgspiceExecutable);
|
||||
QFile::copy(inf.path()+"/../share/ngspice/dlmain.c",cmdir+"/dlmain.c");
|
||||
}
|
||||
|
||||
QString XSPICE_CMbuilder::normalizeModelName(QString &file, QString &destdir)
|
||||
{
|
||||
QFileInfo inf(file);
|
||||
QString filenam = inf.fileName();
|
||||
if (filenam.endsWith(".mod"))
|
||||
return QDir::convertSeparators(cmdir+'/'+destdir+"/cfunc.mod");
|
||||
if (filenam.endsWith(".ifs"))
|
||||
return QDir::convertSeparators(cmdir+'/'+destdir+"/ifspec.ifs");
|
||||
return QDir::convertSeparators(cmdir+'/'+destdir+'/'+filenam);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Ngspice::compileCMlib Compile all models and obtain qucs_xspice.cm
|
||||
*/
|
||||
void XSPICE_CMbuilder::compileCMlib(QString &output)
|
||||
{
|
||||
QProcess *make = new QProcess();
|
||||
make->setReadChannelMode(QProcess::MergedChannels);
|
||||
make->setWorkingDirectory(cmdir);
|
||||
make->start("make"); // For Unix
|
||||
make->waitForFinished();
|
||||
output += make->readAll();
|
||||
delete make;
|
||||
}
|
||||
|
||||
bool XSPICE_CMbuilder::removeDir(const QString &dirName)
|
||||
{
|
||||
bool result = true;
|
||||
QDir dir(dirName);
|
||||
|
||||
if (dir.exists(dirName)) {
|
||||
Q_FOREACH(QFileInfo info, dir.entryInfoList(QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst)) {
|
||||
if (info.isDir()) {
|
||||
result = removeDir(info.absoluteFilePath());
|
||||
}
|
||||
else {
|
||||
result = QFile::remove(info.absoluteFilePath());
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
result = dir.rmdir(dirName);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
48
qucs/extsimkernels/xspice_cmbuilder.h
Normal file
48
qucs/extsimkernels/xspice_cmbuilder.h
Normal file
@ -0,0 +1,48 @@
|
||||
/***************************************************************************
|
||||
xspice_cmbuilder.h
|
||||
----------------
|
||||
begin : Sun Jan 31 2015
|
||||
copyright : (C) 2015 by Vadim Kuznetsov
|
||||
email : ra3xdh@gmail.com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef XSPICE_CMBUILDER_H
|
||||
#define XSPICE_CMBUILDER_H
|
||||
|
||||
#include <QtCore>
|
||||
#include "schematic.h"
|
||||
|
||||
class XSPICE_CMbuilder
|
||||
{
|
||||
private:
|
||||
QString cmdir,cmsubdir;
|
||||
QString workdir,spinit_name;
|
||||
|
||||
Schematic *Sch;
|
||||
|
||||
public:
|
||||
XSPICE_CMbuilder(Schematic *sch_);
|
||||
~XSPICE_CMbuilder();
|
||||
|
||||
void createSpiceinit();
|
||||
bool needCompile();
|
||||
void cleanCModelTree();
|
||||
void createCModelTree();
|
||||
void compileCMlib(QString &ouptut);
|
||||
|
||||
private:
|
||||
QString normalizeModelName(QString &file,QString &destdir);
|
||||
bool removeDir(const QString &dirName);
|
||||
};
|
||||
|
||||
#endif // XSPICE_CMBUILDER_H
|
Loading…
x
Reference in New Issue
Block a user