Qucs-GUI
0.0.19
|
00001 /*************************************************************************** 00002 libcomp.cpp 00003 ------------- 00004 begin : Fri Jun 10 2005 00005 copyright : (C) 2005 by Michael Margraf 00006 email : michael.margraf@alumni.tu-berlin.de 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * * 00011 * This program is free software; you can redistribute it and/or modify * 00012 * it under the terms of the GNU General Public License as published by * 00013 * the Free Software Foundation; either version 2 of the License, or * 00014 * (at your option) any later version. * 00015 * * 00016 ***************************************************************************/ 00017 00018 #include "libcomp.h" 00019 #include "qucs.h" 00020 #include "main.h" 00021 #include "schematic.h" 00022 #include "misc.h" 00023 00024 #include <limits.h> 00025 00026 #include <QTextStream> 00027 #include <QDir> 00028 #include <QRegExp> 00029 #include <QDebug> 00030 00031 LibComp::LibComp() 00032 { 00033 Type = isComponent; // both analog and digital 00034 Description = QObject::tr("Component taken from Qucs library"); 00035 00036 Ports.append(new Port(0, 0)); // dummy port because of being device 00037 00038 Model = "Lib"; 00039 Name = "X"; 00040 00041 Props.append(new Property("Lib", "", true, 00042 QObject::tr("name of qucs library file"))); 00043 Props.append(new Property("Comp", "", true, 00044 QObject::tr("name of component in library"))); 00045 } 00046 00047 // --------------------------------------------------------------------- 00048 Component* LibComp::newOne() 00049 { 00050 LibComp *p = new LibComp(); 00051 p->Props.first()->Value = Props.first()->Value; 00052 p->Props.next()->Value = Props.next()->Value; 00053 p->recreate(0); 00054 return p; 00055 } 00056 00057 // --------------------------------------------------------------------- 00058 // Makes the schematic symbol subcircuit with the correct number 00059 // of ports. 00060 void LibComp::createSymbol() 00061 { 00062 tx = INT_MIN; 00063 ty = INT_MIN; 00064 if(loadSymbol() > 0) { 00065 if(tx == INT_MIN) tx = x1+4; 00066 if(ty == INT_MIN) ty = y2+4; 00067 } 00068 else { 00069 // only paint a rectangle 00070 Lines.append(new Line(-15, -15, 15, -15, QPen(Qt::darkBlue,2))); 00071 Lines.append(new Line( 15, -15, 15, 15, QPen(Qt::darkBlue,2))); 00072 Lines.append(new Line(-15, 15, 15, 15, QPen(Qt::darkBlue,2))); 00073 Lines.append(new Line(-15, -15,-15, 15, QPen(Qt::darkBlue,2))); 00074 00075 x1 = -18; y1 = -18; 00076 x2 = 18; y2 = 18; 00077 00078 tx = x1+4; 00079 ty = y2+4; 00080 } 00081 } 00082 00083 // --------------------------------------------------------------------- 00084 // Loads the section with name "Name" from library file into "Section". 00085 int LibComp::loadSection(const QString& Name, QString& Section, 00086 QStringList *Includes) 00087 { 00088 QDir Directory(QucsSettings.LibDir); 00089 QFile file(Directory.absFilePath(Props.first()->Value + ".lib")); 00090 if(!file.open(QIODevice::ReadOnly)) 00091 return -1; 00092 00093 QTextStream ReadWhole(&file); 00094 Section = ReadWhole.read(); 00095 file.close(); 00096 00097 00098 if(Section.left(14) != "<Qucs Library ") // wrong file type ? 00099 return -2; 00100 00101 int Start, End = Section.indexOf(' ', 14); 00102 if(End < 15) return -3; 00103 QString Line = Section.mid(14, End-14); 00104 if(!misc::checkVersion(Line)) // wrong version number ? 00105 return -3; 00106 00107 if(Name == "Symbol") { 00108 Start = Section.indexOf("\n<", 14); // if library has default symbol, take it 00109 if(Start > 0) 00110 if(Section.mid(Start+2, 14) == "DefaultSymbol>") { 00111 Start += 16; 00112 End = Section.indexOf("\n</DefaultSymbol>", Start); 00113 if(End < 0) return -9; 00114 Section = Section.mid(Start, End-Start); 00115 return 0; 00116 } 00117 } 00118 00119 // search component 00120 Line = "\n<Component " + Props.next()->Value + ">"; 00121 Start = Section.indexOf(Line); 00122 if(Start < 0) return -4; // component not found 00123 Start = Section.indexOf('\n', Start); 00124 if(Start < 0) return -5; // file corrupt 00125 Start++; 00126 End = Section.indexOf("\n</Component>", Start); 00127 if(End < 0) return -6; // file corrupt 00128 Section = Section.mid(Start, End-Start+1); 00129 00130 // search model includes 00131 if(Includes) { 00132 int StartI, EndI; 00133 StartI = Section.indexOf("<"+Name+"Includes"); 00134 if(StartI >= 0) { // includes found 00135 StartI = Section.indexOf('"', StartI); 00136 if(StartI < 0) return -10; // file corrupt 00137 EndI = Section.indexOf('>', StartI); 00138 if(EndI < 0) return -11; // file corrupt 00139 StartI++; EndI--; 00140 QString inc = Section.mid(StartI, EndI-StartI); 00141 QStringList f = QStringList::split(QRegExp("\"\\s+\""), inc); 00142 for(QStringList::Iterator it = f.begin(); it != f.end(); ++it ) { 00143 Includes->append(*it); 00144 } 00145 } 00146 } 00147 00148 // search model 00149 Start = Section.indexOf("<"+Name+">"); 00150 if(Start < 0) return -7; // symbol not found 00151 Start = Section.indexOf('\n', Start); 00152 if(Start < 0) return -8; // file corrupt 00153 while(Section.at(++Start) == ' ') ; 00154 End = Section.indexOf("</"+Name+">", Start); 00155 if(End < 0) return -9; // file corrupt 00156 00157 // snip actual model 00158 Section = Section.mid(Start, End-Start); 00159 return 0; 00160 } 00161 00162 // --------------------------------------------------------------------- 00163 // Loads the symbol for the subcircuit from the schematic file and 00164 // returns the number of painting elements. 00165 int LibComp::loadSymbol() 00166 { 00167 int z, Result; 00168 QString FileString, Line; 00169 z = loadSection("Symbol", FileString); 00170 if(z < 0) { 00171 if(z != -7) return z; 00172 00173 // If library component not defined as subcircuit, then load 00174 // new component and transfer data to this component. 00175 z = loadSection("Model", Line); 00176 if(z < 0) return z; 00177 00178 Component *pc = getComponentFromName(Line); 00179 if(pc == 0) return -20; 00180 00181 copyComponent(pc); 00182 00183 pc->Props.setAutoDelete(false); 00184 delete pc; 00185 00186 return 1; 00187 } 00188 00189 00190 z = 0; 00191 x1 = y1 = INT_MAX; 00192 x2 = y2 = INT_MIN; 00193 00194 QTextStream stream(&FileString, QIODevice::ReadOnly); 00195 while(!stream.atEnd()) { 00196 Line = stream.readLine(); 00197 Line = Line.trimmed(); 00198 if(Line.isEmpty()) continue; 00199 if(Line.at(0) != '<') return -11; 00200 if(Line.at(Line.length()-1) != '>') return -12; 00201 Line = Line.mid(1, Line.length()-2); // cut off start and end character 00202 Result = analyseLine(Line, 2); 00203 if(Result < 0) return -13; // line format error 00204 z += Result; 00205 } 00206 00207 x1 -= 4; x2 += 4; // enlarge component boundings a little 00208 y1 -= 4; y2 += 4; 00209 return z; // return number of ports 00210 } 00211 00212 // ------------------------------------------------------- 00213 QString LibComp::getSubcircuitFile() 00214 { 00215 QDir Directory(QucsSettings.LibDir); 00216 QString FileName = Directory.absFilePath(Props.first()->Value); 00217 return misc::properAbsFileName(FileName); 00218 } 00219 00220 // ------------------------------------------------------- 00221 bool LibComp::createSubNetlist(QTextStream *stream, QStringList &FileList, 00222 int type) 00223 { 00224 int r = -1; 00225 QString FileString; 00226 QStringList Includes; 00227 if(type&1) { 00228 r = loadSection("Model", FileString, &Includes); 00229 } else if(type&2) { 00230 r = loadSection("VHDLModel", FileString, &Includes); 00231 } else if(type&4) { 00232 r = loadSection("VerilogModel", FileString, &Includes); 00233 } 00234 if(r < 0) return false; 00235 00236 // also include files 00237 int error = 0; 00238 for(QStringList::Iterator it = Includes.begin(); 00239 it != Includes.end(); ++it ) { 00240 QString s = getSubcircuitFile()+"/"+*it; 00241 if(FileList.findIndex(s) >= 0) continue; 00242 FileList.append(s); 00243 00244 // load file and stuff into stream 00245 QFile file(s); 00246 if(!file.open(QIODevice::ReadOnly)) { 00247 error++; 00248 } else { 00249 QByteArray FileContent = file.readAll(); 00250 file.close(); 00251 //?stream->writeRawBytes(FileContent.data(), FileContent.size()); 00252 (*stream) << FileContent.data(); 00253 qDebug() << "hi from libcomp"; 00254 } 00255 } 00256 00257 (*stream) << "\n" << FileString << "\n"; 00258 return error > 0 ? false : true; 00259 } 00260 00261 // ------------------------------------------------------- 00262 QString LibComp::createType() 00263 { 00264 QString Type = misc::properFileName(Props.first()->Value); 00265 return misc::properName(Type + "_" + Props.next()->Value); 00266 } 00267 00268 // ------------------------------------------------------- 00269 QString LibComp::netlist() 00270 { 00271 QString s = "Sub:"+Name; // output as subcircuit 00272 00273 // output all node names 00274 foreach(Port *p1, Ports) 00275 s += " "+p1->Connection->Name; // node names 00276 00277 // output property 00278 s += " Type=\""+createType()+"\""; // type for subcircuit 00279 00280 // output user defined parameters 00281 for(Property *pp = Props.at(2); pp != 0; pp = Props.next()) 00282 s += " "+pp->Name+"=\""+pp->Value+"\""; 00283 00284 return s + '\n'; 00285 } 00286 00287 // ------------------------------------------------------- 00288 QString LibComp::verilogCode(int) 00289 { 00290 QString s = " Sub_" + createType() + " " + Name + " ("; 00291 00292 // output all node names 00293 QListIterator<Port *> iport(Ports); 00294 Port *pp = iport.next(); 00295 if(pp) s += pp->Connection->Name; 00296 while (iport.hasNext()) { 00297 pp = iport.next(); 00298 s += ", "+pp->Connection->Name; // node names 00299 } 00300 00301 s += ");\n"; 00302 return s; 00303 } 00304 00305 // ------------------------------------------------------- 00306 QString LibComp::vhdlCode(int) 00307 { 00308 QString s = " " + Name + ": entity Sub_" + createType() + " port map ("; 00309 00310 // output all node names 00311 QListIterator<Port *> iport(Ports); 00312 Port *pp = iport.next(); 00313 if(pp) s += pp->Connection->Name; 00314 while (iport.hasNext()) { 00315 pp = iport.next(); 00316 s += ", "+pp->Connection->Name; // node names 00317 } 00318 00319 s += ");\n"; 00320 return s; 00321 }