Skip to content

Commit

Permalink
fixed subcircuit simulation fails.
Browse files Browse the repository at this point in the history
  • Loading branch information
dsm committed Aug 1, 2024
1 parent bd13116 commit cad9744
Showing 1 changed file with 113 additions and 115 deletions.
228 changes: 113 additions & 115 deletions qucs/components/subcircuit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,51 +16,46 @@
***************************************************************************/

#include "subcircuit.h"
#include "schematic.h"
#include "extsimkernels/spicecompat.h"
#include "main.h"
#include "misc.h"
#include "extsimkernels/spicecompat.h"
#include "schematic.h"

#include <QTextStream>
#include <QFileInfo>
#include <QMutex>
#include <QTextStream>



Subcircuit::Subcircuit()
{
Type = isComponent; // both analog and digital
Subcircuit::Subcircuit() {
Type = isComponent; // both analog and digital
Description = QObject::tr("subcircuit");

Props.append(new Property("File", "", false,
QObject::tr("name of qucs schematic file")));
QObject::tr("name of qucs schematic file")));

Model = "Sub";
Name = "SUB";
Name = "SUB";
SpiceModel = "X";

// Do NOT call createSymbol() here. But create port to let it rotate.
Ports.append(new Port(0, 0, false));
}

// ---------------------------------------------------------------------
Component* Subcircuit::newOne()
{
Component *Subcircuit::newOne() {
Subcircuit *p = new Subcircuit();
p->Props.front()->Value = Props.front()->Value;
p->recreate(0);
return p;
}

// -------------------------------------------------------
Element* Subcircuit::info(QString& Name, char* &BitmapFile, bool getNewOne)
{
Element *Subcircuit::info(QString &Name, char *&BitmapFile, bool getNewOne) {
Name = QObject::tr("Subcircuit");
BitmapFile = (char *) "subcircuit";
BitmapFile = (char *)"subcircuit";

if(getNewOne) {
if (getNewOne) {
Subcircuit *p = new Subcircuit();
p->recreate(0); // createSymbol() is NOT called in constructor !!!
p->recreate(0); // createSymbol() is NOT called in constructor !!!
return p;
}
return 0;
Expand All @@ -69,75 +64,77 @@ Element* Subcircuit::info(QString& Name, char* &BitmapFile, bool getNewOne)
// ---------------------------------------------------------------------
// Makes the schematic symbol subcircuit with the correct number
// of ports.
void Subcircuit::createSymbol()
{
void Subcircuit::createSymbol() {
int No;
QString FileName(Props.front()->Value);
FileName = getSubcircuitFile();

tx = INT_MIN;
ty = INT_MIN;
if(loadSymbol(FileName) > 0) { // try to load subcircuit symbol
if(tx == INT_MIN) tx = x1+4;
if(ty == INT_MIN) ty = y2+4;
if (loadSymbol(FileName) > 0) { // try to load subcircuit symbol
if (tx == INT_MIN)
tx = x1 + 4;
if (ty == INT_MIN)
ty = y2 + 4;
// remove unused ports
QMutableListIterator<Port *> ip(Ports);
Port *pp;
while (ip.hasNext()) {
pp = ip.next();
if(!pp->avail) {
pp = ip.peekNext();
ip.remove();
if (!pp->avail) {
pp = ip.peekNext();
ip.remove();
}
}
}
else {
} else {
No = Schematic::testFile(FileName);
if(No < 0) No = 0;
if (No < 0)
No = 0;

Ports.clear();
remakeSymbol(No); // no symbol was found -> create standard symbol
remakeSymbol(No); // no symbol was found -> create standard symbol
}
}

// ---------------------------------------------------------------------
void Subcircuit::remakeSymbol(int No)
{
int h = 30*((No-1)/2) + 15;
Lines.append(new qucs::Line(-15, -h, 15, -h,QPen(Qt::darkBlue,2)));
Lines.append(new qucs::Line( 15, -h, 15, h,QPen(Qt::darkBlue,2)));
Lines.append(new qucs::Line(-15, h, 15, h,QPen(Qt::darkBlue,2)));
Lines.append(new qucs::Line(-15, -h,-15, h,QPen(Qt::darkBlue,2)));
Texts.append(new Text(-10, -6,"sub"));

int i=0, y = 15-h;
while(i<No) {
void Subcircuit::remakeSymbol(int No) {
int h = 30 * ((No - 1) / 2) + 15;
Lines.append(new qucs::Line(-15, -h, 15, -h, QPen(Qt::darkBlue, 2)));
Lines.append(new qucs::Line(15, -h, 15, h, QPen(Qt::darkBlue, 2)));
Lines.append(new qucs::Line(-15, h, 15, h, QPen(Qt::darkBlue, 2)));
Lines.append(new qucs::Line(-15, -h, -15, h, QPen(Qt::darkBlue, 2)));
Texts.append(new Text(-10, -6, "sub"));

int i = 0, y = 15 - h;
while (i < No) {
i++;
Lines.append(new qucs::Line(-30, y,-15, y,QPen(Qt::darkBlue,2)));
Ports.append(new Port(-30, y));
Texts.append(new Text(-25,y-14,QString::number(i)));
Lines.append(new qucs::Line(-30, y, -15, y, QPen(Qt::darkBlue, 2)));
Ports.append(new Port(-30, y));
Texts.append(new Text(-25, y - 14, QString::number(i)));

if(i == No) break;
if (i == No)
break;
i++;
Lines.append(new qucs::Line( 15, y, 30, y,QPen(Qt::darkBlue,2)));
Ports.append(new Port( 30, y));
Texts.append(new Text( 19,y-14,QString::number(i)));
Lines.append(new qucs::Line(15, y, 30, y, QPen(Qt::darkBlue, 2)));
Ports.append(new Port(30, y));
Texts.append(new Text(19, y - 14, QString::number(i)));
y += 60;
}

x1 = -30; y1 = -h-2;
x2 = 30; y2 = h+2;
tx = x1+4;
ty = y2+4;
x1 = -30;
y1 = -h - 2;
x2 = 30;
y2 = h + 2;
tx = x1 + 4;
ty = y2 + 4;
}

// ---------------------------------------------------------------------
// Loads the symbol for the subcircuit from the schematic file and
// returns the number of painting elements.
int Subcircuit::loadSymbol(const QString& DocName)
{
int Subcircuit::loadSymbol(const QString &DocName) {
QFile file(DocName);
if(!file.open(QIODevice::ReadOnly))
if (!file.open(QIODevice::ReadOnly))
return -1;

QString Line;
Expand All @@ -149,105 +146,108 @@ int Subcircuit::loadSymbol(const QString& DocName)
file.close();
QTextStream stream(&FileString, QIODevice::ReadOnly);


// read header **************************
do {
if(stream.atEnd()) return -2;
if (stream.atEnd())
return -2;
Line = stream.readLine();
Line = Line.trimmed();
} while(Line.isEmpty());
} while (Line.isEmpty());

if(Line.left(16) != "<Qucs Schematic ") // wrong file type ?
if (Line.left(16) != "<Qucs Schematic ") // wrong file type ?
return -3;

Line = Line.mid(16, Line.length()-17);
Line = Line.mid(16, Line.length() - 17);
VersionTriplet SymbolVersion = VersionTriplet(Line);
if (SymbolVersion > QucsVersion) {// wrong version number ?
if (!QucsSettings.IgnoreFutureVersion) {
return -4;
}
if (SymbolVersion > QucsVersion) { // wrong version number ?
if (!QucsSettings.IgnoreFutureVersion) {
return -4;
}
}

// read content *************************
while(!stream.atEnd()) {
while (!stream.atEnd()) {
Line = stream.readLine();
if(Line == "<Symbol>") break;
if (Line == "<Symbol>")
break;
}

x1 = y1 = INT_MAX;
x2 = y2 = INT_MIN;

int z=0, Result;
while(!stream.atEnd()) {
int z = 0, Result;
while (!stream.atEnd()) {
Line = stream.readLine();
if(Line == "</Symbol>") {
x1 -= 4; // enlarge component boundings a little
if (Line == "</Symbol>") {
x1 -= 4; // enlarge component boundings a little
x2 += 4;
y1 -= 4;
y2 += 4;
return z; // return number of ports
return z; // return number of ports
}

Line = Line.trimmed();
if(Line.at(0) != '<') return -5;
if(Line.at(Line.length()-1) != '>') return -6;
Line = Line.mid(1, Line.length()-2); // cut off start and end character
if (Line.at(0) != '<')
return -5;
if (Line.at(Line.length() - 1) != '>')
return -6;
Line = Line.mid(1, Line.length() - 2); // cut off start and end character
Result = analyseLine(Line, 1);
if(Result < 0) return -7; // line format error
if (Result < 0)
return -7; // line format error
z += Result;
}

return -8; // field not closed
return -8; // field not closed
}

// -------------------------------------------------------
QString Subcircuit::netlist()
{
QString s = Model+":"+Name;
QString Subcircuit::netlist() {
QString s = Model + ":" + Name;

// output all node names
for (Port *p1 : Ports)
s += " "+p1->Connection->Name; // node names
s += " " + p1->Connection->Name; // node names

// type for subcircuit
QString f = misc::properFileName(Props.first()->Value);
s += " Type=\""+misc::properName(f)+"\"";
QString f = misc::properFileName(Props.at(0)->Value);
s += " Type=\"" + misc::properName(f) + "\"";

// output all user defined properties
for(Property *pp : Props)
s += " "+pp->Name+"=\""+pp->Value+"\"";
for (qsizetype i = 1; i < Props.size(); i++)
s += " " + Props.at(i)->Name + "=\"" + Props.at(i)->Value + "\"";
return s + '\n';
}

QString Subcircuit::spice_netlist(bool)
{
QString s;
QString f = misc::properFileName(Props.first()->Value);
s += spicecompat::check_refdes(Name,SpiceModel);
for (Port *p1 : Ports) {
QString nam = p1->Connection->Name;
if (nam=="gnd") nam = "0";
s += " "+nam; // node names
}
s += " " + misc::properName(f);
for(Property *pp : Props) {
s += QString(" %1=%2").arg(pp->Name).arg(spicecompat::normalize_value(pp->Value));
}
s += "\n";
return s;
QString Subcircuit::spice_netlist(bool) {
QString s;
QString f = misc::properFileName(Props.at(0)->Value);
s += spicecompat::check_refdes(Name, SpiceModel);
for (Port *p1 : Ports) {
QString nam = p1->Connection->Name;
if (nam == "gnd")
nam = "0";
s += " " + nam; // node names
}
s += " " + misc::properName(f);
for (qsizetype i = 1; i < Props.size(); i++) {
s += QString(" %1=%2").arg(
Props.at(i)->Name, spicecompat::normalize_value(Props.at(i)->Value));
}
s += "\n";
return s;
}

// -------------------------------------------------------
QString Subcircuit::vhdlCode(int)
{
QString f = misc::properFileName(Props.first()->Value);
QString Subcircuit::vhdlCode(int) {
QString f = misc::properFileName(Props.at(0)->Value);
QString s = " " + Name + ": entity Sub_" + misc::properName(f);

// output all user defined properties
if (Props.at(1) != nullptr) {
s += " generic map (";
s += Props.at(1)->Value;
for(int i = 2; i < Props.size(); i++){
for (qsizetype i = 2; i < Props.size(); i++) {
s += ", " + Props.at(i)->Value;
}
s += ")";
Expand All @@ -257,49 +257,47 @@ QString Subcircuit::vhdlCode(int)
s += " port map (";
QListIterator<Port *> iport(Ports);
Port *pp = iport.next();
if(pp)
if (pp)
s += pp->Connection->Name;
while (iport.hasNext()) {
pp = iport.next();
s += ", "+pp->Connection->Name; // node names
s += ", " + pp->Connection->Name; // node names
}

s += ");\n";
return s;
}

// -------------------------------------------------------
QString Subcircuit::verilogCode(int)
{
QString f = misc::properFileName(Props.first()->Value);
QString Subcircuit::verilogCode(int) {
QString f = misc::properFileName(Props.at(0)->Value);
QString s = " Sub_" + misc::properName(f);

// output all user defined properties
if (Props.at(1) != nullptr) {
s += " #(";
s += misc::Verilog_Param(Props.at(1)->Value);
for(int i = 2; i < Props.size(); i++)
for (qsizetype i = 2; i < Props.size(); i++)
s += ", " + misc::Verilog_Param(Props.at(i)->Value);
s += ")";
}

// output all node names
s += " " + Name + " (";
s += " " + Name + " (";
QListIterator<Port *> iport(Ports);
Port *pp = iport.next();
if(pp)
if (pp)
s += pp->Connection->Name;
while (iport.hasNext()) {
pp = iport.next();
s += ", "+pp->Connection->Name; // node names
s += ", " + pp->Connection->Name; // node names
}

s += ");\n";
return s;
}

// -------------------------------------------------------
QString Subcircuit::getSubcircuitFile()
{
return misc::properAbsFileName(Props.front()->Value, containingSchematic);
QString Subcircuit::getSubcircuitFile() {
return misc::properAbsFileName(Props.at(0)->Value, containingSchematic);
}

0 comments on commit cad9744

Please sign in to comment.