My Project  0.0.16
QUCS Mapping
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
verilogfile.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  verilogfile.cpp
3  ---------------
4  begin : Sat Mar 31 2007
5  copyright : (C) 2007 by Stefan Jahn
6  email : stefa@lkcc.org
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "verilogfile.h"
19 #include "qucs.h"
20 #include "main.h"
21 #include "schematic.h"
22 
23 #include <qregexp.h>
24 #include <qdir.h>
25 #include <qfileinfo.h>
26 
27 
29 {
31  Description = QObject::tr("Verilog file");
32 
33  Props.append(new Property("File", "sub.v", false,
34  QObject::tr("Name of Verilog file")));
35 
36  Model = "Verilog";
37  Name = "X";
38 
39  // Do NOT call createSymbol() here. But create port to let it rotate.
40  Ports.append(new Port(0, 0));
41 }
42 
43 // -------------------------------------------------------
45 {
46  Verilog_File *p = new Verilog_File();
47  p->Props.getFirst()->Value = Props.getFirst()->Value;
48  p->recreate(0);
49  return p;
50 }
51 
52 // -------------------------------------------------------
53 Element* Verilog_File::info(QString& Name, char* &BitmapFile, bool getNewOne)
54 {
55  Name = QObject::tr("Verilog file");
56  BitmapFile = (char *) "vhdlfile";
57 
58  if(getNewOne) {
59  Verilog_File *p = new Verilog_File();
60  p->recreate(0); // createSymbol() is NOT called in constructor !!!
61  return p;
62  }
63  return 0;
64 }
65 
66 // -------------------------------------------------------
68 {
69  QString s;
70  Port *pp = Ports.first();
71  if(pp) {
72  s = " " + ModuleName + " " + Name + " (";
73 
74  // output all node names
75  if(pp) s += pp->Connection->Name;
76  for(pp = Ports.next(); pp != 0; pp = Ports.next())
77  s += ", "+pp->Connection->Name; // node names
78 
79  s += ");\n";
80  }
81  return s;
82 }
83 
84 // -------------------------------------------------------
85 // Returns a comma separated list of the port names of the last
86 // entity in this file.
88 {
89  QString s, File(Props.getFirst()->Value);
90  QFileInfo Info(File);
91  if(Info.isRelative())
92  File = QucsWorkDir.filePath(File);
93 
94  QFile f(File);
95  if(!f.open(IO_ReadOnly))
96  return QString("");
97 
98  QTextStream stream(&f);
99  File = stream.read(); // QString is better for "find" function
100  f.close();
101 
102  // parse ports, i.e. network connections
103  Verilog_File_Info VInfo(File);
104  ModuleName = VInfo.ModuleName;
105  return VInfo.PortNames;
106 }
107 
108 // -------------------------------------------------------
110 {
111  QFontMetrics metrics(QucsSettings.font); // get size of text
112  int fHeight = metrics.lineSpacing();
113 
114  int No = 0;
115  QString tmp, PortNames = loadFile();
116  if(!PortNames.isEmpty())
117  No = PortNames.contains(',') + 1;
118 
119 
120  #define HALFWIDTH 24
121  int h = 30*((No-1)/2) + 15;
122  Lines.append(new Line(-HALFWIDTH, -h, HALFWIDTH, -h,QPen(QPen::darkBlue,2)));
123  Lines.append(new Line( HALFWIDTH, -h, HALFWIDTH, h,QPen(QPen::darkBlue,2)));
124  Lines.append(new Line(-HALFWIDTH, h, HALFWIDTH, h,QPen(QPen::darkBlue,2)));
125  Lines.append(new Line(-HALFWIDTH, -h,-HALFWIDTH, h,QPen(QPen::darkBlue,2)));
126 
127  tmp = QObject::tr("verilog");
128  int w = metrics.width(tmp);
129  Texts.append(new Text(w/-2, fHeight/-2, tmp));
130 
131 
132  int y = 15-h, i = 0;
133  while(i<No) {
134  Lines.append(new Line(-30, y,-HALFWIDTH, y,QPen(QPen::darkBlue,2)));
135  Ports.append(new Port(-30, y));
136  tmp = PortNames.section(',', i, i);
137  w = metrics.width(tmp);
138  Texts.append(new Text(-26-w, y-fHeight-2, tmp));
139  i++;
140 
141  if(i == No) break;
142  Lines.append(new Line(HALFWIDTH, y, 30, y,QPen(QPen::darkBlue,2)));
143  Ports.append(new Port( 30, y));
144  tmp = PortNames.section(',', i, i);
145  Texts.append(new Text( 27, y-fHeight-2, tmp));
146  y += 60;
147  i++;
148  }
149 
150  x1 = -30; y1 = -h-2;
151  x2 = 30; y2 = h+2;
152  tx = x1+4;
153  ty = y2+4;
154 }
155 
156 // -------------------------------------------------------
158 {
159  // construct full filename
160  QString FileName = Props.getFirst()->Value;
161  return properAbsFileName(FileName);
162 }
163 
164 // -------------------------------------------------------
165 bool Verilog_File::createSubNetlist(QTextStream *stream)
166 {
167  ErrText = "";
168 
169  // check filename
170  QString FileName = Props.getFirst()->Value;
171  if(FileName.isEmpty()) {
172  ErrText += QObject::tr("ERROR: No file name in %1 component \"%2\".").
173  arg(Model).arg(Name);
174  return false;
175  }
176 
177  // construct full filename
178  FileName = getSubcircuitFile();
179 
180  // open file for reading
181  QFile f(FileName);
182  if(!f.open(IO_ReadOnly)) {
183  ErrText += QObject::tr("ERROR: Cannot open %1 file \"%2\".").
184  arg(Model).arg(FileName);
185  return false;
186  }
187 
188  // write the whole Verilog file into the netlist output
189  QByteArray FileContent = f.readAll();
190  f.close();
191  (*stream) << '\n';
192  stream->writeRawBytes(FileContent.data(), FileContent.size());
193  (*stream) << '\n';
194  return true;
195 }
196 
197 // -------------------------------------------------------
199 {
200  ModuleName = "";
201  PortNames = "";
202 }
203 
204 // -------------------------------------------------------
206 {
207  if (isfile) {
208  QFile f(File);
209  if(!f.open(IO_ReadOnly))
210  File = "";
211  else {
212  QByteArray FileContent = f.readAll();
213  File = QString(FileContent);
214  }
215  f.close();
216  }
217 
218  QString s;
219  int i=0, j, k=0;
220  while((i=File.find("//", i)) >= 0) { // remove all Verilog comments
221  j = File.find('\n', i+2); // (This also finds "//" within a ...
222  if(j < 0) // string, but as no strings are ...
223  File = File.left(i); // allowed in module headers, it ...
224  else // does not matter.)
225  File.remove(i, j-i);
226  }
227 
228  i=0;
229  while((i=File.find("/*", i)) >= 0) { // remove all Verilog comments
230  j = File.find("*/", i+2); // (This also finds "/*" within a ...
231  if(j < 0) // string, but as no strings are ...
232  File = File.left(i); // allowed in module headers, it ...
233  else // does not matter.)
234  File.remove(i, j-i+2);
235  }
236 
237  QRegExp Expr,Expr1;
238  Expr.setCaseSensitive(true);
239  Expr1.setCaseSensitive(true);
240  k--;
241  Expr.setPattern("\\bmodule\\b"); // start of last module
242  k = File.findRev(Expr, k);
243  if(k < 0)
244  return;
245 
246  Expr.setPattern("\\bendmodule\\b"); // end of last module
247  i = File.find(Expr, k+7);
248  if(i < 0)
249  return;
250  s = File.mid(k+7, i-k-7); // cut out module declaration
251 
252  Expr.setPattern("\\b");
253  i = s.find(Expr);
254  if(i < 0)
255  return;
256  j = s.find(Expr, i+1);
257  if(j < 0)
258  return;
259  ModuleName = s.mid(i, j-i); // save module name
260 
261  i = s.find('(', j);
262  if(i < 0)
263  return;
264 
265  j = s.find(')', i);
266  if(j < 0)
267  return;
268  s = s.mid(i+1, j-i-1);
269 
270  // parse ports, i.e. network connections; and generics, i.e. parameters
271  PortNames = parsePorts (s, 0);
272 }
273 
274 // -------------------------------------------------------
275 QString Verilog_File_Info::parsePorts(QString s, int i)
276 {
277  QRegExp Expr,Expr1;
278  Expr.setCaseSensitive(true);
279  Expr1.setCaseSensitive(true);
280 
281  int j;
282  i = 0; // remove all Verilog identifiers (e.g. "input")
283  Expr.setPattern("(\\binput\\b|\\boutput\\b|\\binout\\b)");
284  Expr1.setPattern("(\\b)");
285  while((i=s.find(Expr, i)) >= 0) {
286  j = s.find(Expr1, i+1);
287  if(j < 0)
288  s = s.left(i);
289  else
290  s.remove(i, j-i);
291  }
292 
293  s.remove(' ');
294  s.remove('\n');
295  s.remove('\t');
296  return s;
297 }