Qucs-GUI  0.0.19
/home/travis/build/Qucs/qucs/qucs/qucs/components/verilogfile.cpp
Go to the documentation of this file.
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 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines