Qucs-GUI
0.0.19
|
00001 /*************************************************************************** 00002 verilogfile.cpp 00003 --------------- 00004 begin : Sat Mar 31 2007 00005 copyright : (C) 2007 by Stefan Jahn 00006 email : stefa@lkcc.org 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 "verilogfile.h" 00019 #include "qucs.h" 00020 #include "main.h" 00021 #include "schematic.h" 00022 #include "misc.h" 00023 00024 #include <QTextStream> 00025 #include <QRegExp> 00026 #include <QFileInfo> 00027 00028 00029 Verilog_File::Verilog_File() 00030 { 00031 Type = isDigitalComponent; 00032 Description = QObject::tr("Verilog file"); 00033 00034 Props.append(new Property("File", "sub.v", false, 00035 QObject::tr("Name of Verilog file"))); 00036 00037 Model = "Verilog"; 00038 Name = "X"; 00039 00040 // Do NOT call createSymbol() here. But create port to let it rotate. 00041 Ports.append(new Port(0, 0)); 00042 } 00043 00044 // ------------------------------------------------------- 00045 Component* Verilog_File::newOne() 00046 { 00047 Verilog_File *p = new Verilog_File(); 00048 p->Props.getFirst()->Value = Props.getFirst()->Value; 00049 p->recreate(0); 00050 return p; 00051 } 00052 00053 // ------------------------------------------------------- 00054 Element* Verilog_File::info(QString& Name, char* &BitmapFile, bool getNewOne) 00055 { 00056 Name = QObject::tr("Verilog file"); 00057 BitmapFile = (char *) "vhdlfile"; 00058 00059 if(getNewOne) { 00060 Verilog_File *p = new Verilog_File(); 00061 p->recreate(0); // createSymbol() is NOT called in constructor !!! 00062 return p; 00063 } 00064 return 0; 00065 } 00066 00067 // ------------------------------------------------------- 00068 QString Verilog_File::verilogCode(int) 00069 { 00070 QString s; 00071 QListIterator<Port *> iport(Ports); 00072 Port *pp = iport.next(); 00073 if(pp) { 00074 s = " " + ModuleName + " " + Name + " ("; 00075 00076 // output all node names 00077 if(pp) s += pp->Connection->Name; 00078 while(iport.hasNext()) 00079 { 00080 pp = iport.next(); 00081 s += ", "+pp->Connection->Name; // node names 00082 } 00083 00084 s += ");\n"; 00085 } 00086 return s; 00087 } 00088 00089 // ------------------------------------------------------- 00090 // Returns a comma separated list of the port names of the last 00091 // entity in this file. 00092 QString Verilog_File::loadFile() 00093 { 00094 QString s, File(Props.getFirst()->Value); 00095 QFileInfo Info(File); 00096 if(Info.isRelative()) 00097 File = QucsSettings.QucsWorkDir.filePath(File); 00098 00099 QFile f(File); 00100 if(!f.open(QIODevice::ReadOnly)) 00101 return QString(""); 00102 00103 QTextStream stream(&f); 00104 File = stream.readAll(); // QString is better for "find" function 00105 f.close(); 00106 00107 // parse ports, i.e. network connections 00108 Verilog_File_Info VInfo(File); 00109 ModuleName = VInfo.ModuleName; 00110 return VInfo.PortNames; 00111 } 00112 00113 // ------------------------------------------------------- 00114 void Verilog_File::createSymbol() 00115 { 00116 // use the screen-compatible metric 00117 QFontMetrics metrics(QucsSettings.font, 0); // get size of text 00118 int fHeight = metrics.lineSpacing(); 00119 00120 int No = 0; 00121 QString tmp, PortNames = loadFile(); 00122 if(!PortNames.isEmpty()) 00123 No = PortNames.count(',') + 1; 00124 00125 00126 #define HALFWIDTH 24 00127 int h = 30*((No-1)/2) + 15; 00128 Lines.append(new Line(-HALFWIDTH, -h, HALFWIDTH, -h,QPen(Qt::darkBlue,2))); 00129 Lines.append(new Line( HALFWIDTH, -h, HALFWIDTH, h,QPen(Qt::darkBlue,2))); 00130 Lines.append(new Line(-HALFWIDTH, h, HALFWIDTH, h,QPen(Qt::darkBlue,2))); 00131 Lines.append(new Line(-HALFWIDTH, -h,-HALFWIDTH, h,QPen(Qt::darkBlue,2))); 00132 00133 tmp = QObject::tr("verilog"); 00134 int w = metrics.width(tmp); 00135 Texts.append(new Text(w/-2, fHeight/-2, tmp)); 00136 00137 00138 int y = 15-h, i = 0; 00139 while(i<No) { 00140 Lines.append(new Line(-30, y,-HALFWIDTH, y,QPen(Qt::darkBlue,2))); 00141 Ports.append(new Port(-30, y)); 00142 tmp = PortNames.section(',', i, i); 00143 w = metrics.width(tmp); 00144 Texts.append(new Text(-26-w, y-fHeight-2, tmp)); 00145 i++; 00146 00147 if(i == No) break; 00148 Lines.append(new Line(HALFWIDTH, y, 30, y,QPen(Qt::darkBlue,2))); 00149 Ports.append(new Port( 30, y)); 00150 tmp = PortNames.section(',', i, i); 00151 Texts.append(new Text( 27, y-fHeight-2, tmp)); 00152 y += 60; 00153 i++; 00154 } 00155 00156 x1 = -30; y1 = -h-2; 00157 x2 = 30; y2 = h+2; 00158 tx = x1+4; 00159 ty = y2+4; 00160 } 00161 00162 // ------------------------------------------------------- 00163 QString Verilog_File::getSubcircuitFile() 00164 { 00165 // construct full filename 00166 QString FileName = Props.getFirst()->Value; 00167 return misc::properAbsFileName(FileName); 00168 } 00169 00170 // ------------------------------------------------------- 00171 bool Verilog_File::createSubNetlist(QTextStream *stream) 00172 { 00173 ErrText = ""; 00174 00175 // check filename 00176 QString FileName = Props.getFirst()->Value; 00177 if(FileName.isEmpty()) { 00178 ErrText += QObject::tr("ERROR: No file name in %1 component \"%2\"."). 00179 arg(Model).arg(Name); 00180 return false; 00181 } 00182 00183 // construct full filename 00184 FileName = getSubcircuitFile(); 00185 00186 // open file for reading 00187 QFile f(FileName); 00188 if(!f.open(QIODevice::ReadOnly)) { 00189 ErrText += QObject::tr("ERROR: Cannot open %1 file \"%2\"."). 00190 arg(Model).arg(FileName); 00191 return false; 00192 } 00193 00194 // write the whole Verilog file into the netlist output 00195 QByteArray FileContent = f.readAll(); 00196 f.close(); 00197 (*stream) << '\n'; 00198 //?stream->writeRawBytes(FileContent.data(), FileContent.size()); 00199 (*stream) << FileContent.data(); 00200 (*stream) << '\n'; 00201 return true; 00202 } 00203 00204 // ------------------------------------------------------- 00205 Verilog_File_Info::Verilog_File_Info() 00206 { 00207 ModuleName = ""; 00208 PortNames = ""; 00209 } 00210 00211 // ------------------------------------------------------- 00212 Verilog_File_Info::Verilog_File_Info(QString File, bool isfile) 00213 { 00214 if (isfile) { 00215 QFile f(File); 00216 if(!f.open(QIODevice::ReadOnly)) 00217 File = ""; 00218 else { 00219 QByteArray FileContent = f.readAll(); 00220 File = QString(FileContent); 00221 } 00222 f.close(); 00223 } 00224 00225 QString s; 00226 int i=0, j, k=0; 00227 while((i=File.indexOf("//", i)) >= 0) { // remove all Verilog comments 00228 j = File.indexOf('\n', i+2); // (This also finds "//" within a ... 00229 if(j < 0) // string, but as no strings are ... 00230 File = File.left(i); // allowed in module headers, it ... 00231 else // does not matter.) 00232 File.remove(i, j-i); 00233 } 00234 00235 i=0; 00236 while((i=File.indexOf("/*", i)) >= 0) { // remove all Verilog comments 00237 j = File.indexOf("*/", i+2); // (This also finds "/*" within a ... 00238 if(j < 0) // string, but as no strings are ... 00239 File = File.left(i); // allowed in module headers, it ... 00240 else // does not matter.) 00241 File.remove(i, j-i+2); 00242 } 00243 00244 QRegExp Expr,Expr1; 00245 Expr.setCaseSensitivity(Qt::CaseSensitive); 00246 Expr1.setCaseSensitivity(Qt::CaseSensitive); 00247 k--; 00248 Expr.setPattern("\\bmodule\\b"); // start of last module 00249 k = File.lastIndexOf(Expr, k); 00250 if(k < 0) 00251 return; 00252 00253 Expr.setPattern("\\bendmodule\\b"); // end of last module 00254 i = File.indexOf(Expr, k+7); 00255 if(i < 0) 00256 return; 00257 s = File.mid(k+7, i-k-7); // cut out module declaration 00258 00259 Expr.setPattern("\\b"); 00260 i = s.indexOf(Expr); 00261 if(i < 0) 00262 return; 00263 j = s.indexOf(Expr, i+1); 00264 if(j < 0) 00265 return; 00266 ModuleName = s.mid(i, j-i); // save module name 00267 00268 i = s.indexOf('(', j); 00269 if(i < 0) 00270 return; 00271 00272 j = s.indexOf(')', i); 00273 if(j < 0) 00274 return; 00275 s = s.mid(i+1, j-i-1); 00276 00277 // parse ports, i.e. network connections; and generics, i.e. parameters 00278 PortNames = parsePorts (s, 0); 00279 } 00280 00281 // ------------------------------------------------------- 00282 QString Verilog_File_Info::parsePorts(QString s, int i) 00283 { 00284 QRegExp Expr,Expr1; 00285 Expr.setCaseSensitivity(Qt::CaseSensitive); 00286 Expr1.setCaseSensitivity(Qt::CaseSensitive); 00287 00288 int j; 00289 i = 0; // remove all Verilog identifiers (e.g. "input") 00290 Expr.setPattern("(\\binput\\b|\\boutput\\b|\\binout\\b)"); 00291 Expr1.setPattern("(\\b)"); 00292 while((i=s.indexOf(Expr, i)) >= 0) { 00293 j = s.indexOf(Expr1, i+1); 00294 if(j < 0) 00295 s = s.left(i); 00296 else 00297 s.remove(i, j-i); 00298 } 00299 00300 s.remove(' '); 00301 s.remove('\n'); 00302 s.remove('\t'); 00303 return s; 00304 }