/*************************************************************************** qucs2spice.cpp ---------------- begin : Mon Dec 1 2014 copyright : (C) 2014 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 "qucs2spice.h" #include "spicecompat.h" #include "components/equation.h" #include "misc.h" /*! \file qucs2spice.cpp \brief Implementation of qucs2spice namespace */ namespace qucs2spice { QString convert_rcl(const QString& line); QString convert_header(QString line); QString convert_diode(QString line,bool xyce=false); QString convert_jfet(QString line, bool xyce=false); QString convert_mosfet(QString line, bool xyce=false); QString convert_bjt(QString line); QString convert_cccs(const QString& line); QString convert_ccvs(const QString& line); QString convert_ccs(const QString& line, bool voltage); QString convert_vccs(const QString& line); QString convert_vcvs(const QString& line); QString convert_vcs(const QString& line, bool voltage); QString convert_dc_src(const QString& line); QString convert_edd(const QString& line, QStringList &EqnsAndVars); QString convert_subckt(QString line); QString convert_gyrator(QString line); void ExtractVarsAndValues(QString line,QStringList& VarsAndVals); void subsVoltages(QStringList &tokens, QStringList& nods); } /*! * \brief qucs2spice::convert_netlist Convert Qucs netlist to Spice netlist * \param[in] netlist Qucs netlist as single string * \param xyce True if xyce-compatible netlist is needed. * \return Spice netlist as a single string */ QString qucs2spice::convert_netlist(QString netlist, bool xyce) { QStringList net_lst=netlist.split("\n"); QRegularExpression res_pattern("^[ \t]*R:[A-Za-z]+.*"); QRegularExpression cap_pattern("^[ \t]*C:[A-Za-z]+.*"); QRegularExpression ind_pattern("^[ \t]*L:[A-Za-z]+.*"); QRegularExpression diode_pattern("^[ \t]*Diode:[A-Za-z]+.*"); QRegularExpression mosfet_pattern("^[ \t]*MOSFET:[A-Za-z]+.*"); QRegularExpression jfet_pattern("^[ \t]*JFET:[A-Za-z]+.*"); QRegularExpression bjt_pattern("^[ \t]*BJT:[A-Za-z]+.*"); QRegularExpression ccvs_pattern("^[ \t]*CCVS:[A-Za-z]+.*"); QRegularExpression cccs_pattern("^[ \t]*CCCS:[A-Za-z]+.*"); QRegularExpression vcvs_pattern("^[ \t]*VCVS:[A-Za-z]+.*"); QRegularExpression vccs_pattern("^[ \t]*VCCS:[A-Za-z]+.*"); QRegularExpression subckt_head_pattern("^[ \t]*\\.Def:[A-Za-z]+.*"); QRegularExpression ends_pattern("^[ \t]*\\.Def:End[ \t]*$"); QRegularExpression dc_pattern("^[ \t]*[VI]dc:[A-Za-z]+.*"); QRegularExpression edd_pattern("^[ \t]*EDD:[A-Za-z]+.*"); QRegularExpression eqn_pattern("^[ \t]*Eqn:[A-Za-z]+.*"); QRegularExpression subckt_pattern("^[ \t]*Sub:[A-Za-z]+.*"); QRegularExpression gyrator_pattern("^[ \t]*Gyrator:[A-Za-z]+.*"); QString s=""; QStringList EqnsAndVars; for (QString line : net_lst) { // Find equations if (eqn_pattern.match(line).hasMatch()) { line.remove(QRegularExpression("^[ \t]*Eqn:[A-Za-z]+\\w+\\s+")); ExtractVarsAndValues(line,EqnsAndVars); } } EqnsAndVars.removeAll("Export"); EqnsAndVars.removeAll("no"); EqnsAndVars.removeAll("yes"); for (QString& line : net_lst) { if (subckt_head_pattern.match(line).hasMatch()) { if (ends_pattern.match(line).hasMatch()) s += ".ENDS\n"; else s += convert_header(line); } if (res_pattern.match(line).hasMatch()) s += convert_rcl(line); if (cap_pattern.match(line).hasMatch()) s += convert_rcl(line); if (ind_pattern.match(line).hasMatch()) s += convert_rcl(line); if (diode_pattern.match(line).hasMatch()) s += convert_diode(line,xyce); if (mosfet_pattern.match(line).hasMatch()) s += convert_mosfet(line,xyce); if (jfet_pattern.match(line).hasMatch()) s += convert_jfet(line,xyce); if (bjt_pattern.match(line).hasMatch()) s += convert_bjt(line); if (vccs_pattern.match(line).hasMatch()) s += convert_vccs(line); if (vcvs_pattern.match(line).hasMatch()) s += convert_vcvs(line); if (cccs_pattern.match(line).hasMatch()) s+= convert_cccs(line); if (ccvs_pattern.match(line).hasMatch()) s+= convert_ccvs(line); if (dc_pattern.match(line).hasMatch()) s += convert_dc_src(line); if (edd_pattern.match(line).hasMatch()) s += convert_edd(line,EqnsAndVars); if (subckt_pattern.match(line).hasMatch()) s+= convert_subckt(line); if (gyrator_pattern.match(line).hasMatch()) s+= convert_gyrator(line); } //s.replace(" gnd "," 0 "); return s; } QString qucs2spice::convert_rcl(const QString& line) { QString s=""; QStringList lst = line.split(" ",qucs::SkipEmptyParts); QString s1 = lst.takeFirst(); s += s1.remove(':'); s += " " + lst.takeFirst(); s += " " + lst.takeFirst() + " "; s1 = lst.takeFirst().remove("\""); int idx = s1.indexOf('='); s += s1.right(s1.count()-idx-1); s += "\n"; return s; } QString qucs2spice::convert_header(QString line) { QString s = line; s.replace(".Def:",".SUBCKT "); QStringList lst = s.split(' ',qucs::SkipEmptyParts); lst.insert(2," gnd "); // ground s = lst.join(" "); s += "\n"; return s; } QString qucs2spice::convert_diode(QString line,bool xyce) { QString s=""; QStringList lst = line.split(" ",qucs::SkipEmptyParts); QString name = lst.takeFirst(); int idx = name.indexOf(':'); name = name.right(name.count()-idx-1); // name QString K = lst.takeFirst(); QString A = lst.takeFirst(); s += QString("D%1 %2 %3 DMOD_%4 \n").arg(name).arg(A).arg(K).arg(name); QString mod_params = lst.join(" "); mod_params.remove('\"'); if (xyce) s += QString(".MODEL DMOD_%1 D(LEVEL=2 %2) \n").arg(name).arg(mod_params); else s += QString(".MODEL DMOD_%1 D(%2) \n").arg(name).arg(mod_params); return s; } QString qucs2spice::convert_mosfet(QString line, bool xyce) { QString s=""; QStringList lst = line.split(" ",qucs::SkipEmptyParts); QString name = lst.takeFirst(); int idx = name.indexOf(':'); name = name.right(name.count()-idx-1); // name QString G = lst.takeFirst(); QString D = lst.takeFirst(); QString S = lst.takeFirst(); QString Sub = lst.takeFirst(); QString L = ""; QString W = ""; QString Typ = "NMOS"; QStringList par_lst; par_lst.clear(); for(int i=0;i