Qucs-GUI  0.0.18
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
vhdlfile.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  vhdlfile.cpp
3  --------------
4  begin : Sat Apr 15 2006
5  copyright : (C) 2006 by Michael Margraf
6  email : michael.margraf@alumni.tu-berlin.de
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 #include <QtGui>
18 #include "vhdlfile.h"
19 #include "qucs.h"
20 //Added by qt3to4:
21 #include <QTextStream>
22 #include "main.h"
23 #include "schematic.h"
24 
25 #include <QRegExp>
26 #include <QDir>
27 #include <QFileInfo>
28 
29 
31 {
33  Description = QObject::tr("VHDL file");
34 
35  Props.append(new Property("File", "sub.vhdl", false,
36  QObject::tr("Name of VHDL file")));
37 
38  Model = "VHDL";
39  Name = "X";
40 
41  // Do NOT call createSymbol() here. But create port to let it rotate.
42  Ports.append(new Port(0, 0));
43 }
44 
45 // -------------------------------------------------------
47 {
48  VHDL_File *p = new VHDL_File();
49  p->Props.getFirst()->Value = Props.getFirst()->Value;
50  p->recreate(0);
51  return p;
52 }
53 
54 // -------------------------------------------------------
55 Element* VHDL_File::info(QString& Name, char* &BitmapFile, bool getNewOne)
56 {
57  Name = QObject::tr("VHDL file");
58  BitmapFile = (char *) "vhdlfile";
59 
60  if(getNewOne) {
61  VHDL_File *p = new VHDL_File();
62  p->recreate(0); // createSymbol() is NOT called in constructor !!!
63  return p;
64  }
65  return 0;
66 }
67 
68 // -------------------------------------------------------
69 QString VHDL_File::vhdlCode(int)
70 {
71  QString s;
72  Port *pp = Ports.first();
73  if(pp) {
74  s = " " + Name + ": entity " + EntityName;
75 
76  // output all generic properties
77  Property *pr = Props.at(1);
78  if (pr) {
79  s += " generic map (";
80  s += pr->Value;
81  for(pr = Props.next(); pr != 0; pr = Props.next())
82  s += ", " + pr->Value;
83  s += ")";
84  }
85 
86  // output all node names
87  s += " port map (";
88  if(pp) s += pp->Connection->Name;
89  for(pp = Ports.next(); pp != 0; pp = Ports.next())
90  s += ", "+pp->Connection->Name; // node names
91  s += ");\n";
92  }
93  return s;
94 }
95 
96 // -------------------------------------------------------
97 // Returns a comma separated list of the port names of the last
98 // entity in this file.
100 {
101  QString File(Props.getFirst()->Value);
102  QFileInfo Info(File);
103  if(Info.isRelative())
104  File = QucsSettings.QucsWorkDir.filePath(File);
105 
106  QFile f(File);
107  if(!f.open(QIODevice::ReadOnly))
108  return QString("");
109 
110  QTextStream stream(&f);
111  File = stream.read(); // QString is better for "find" function
112  f.close();
113 
114  // parse ports, i.e. network connections; and generics, i.e. parameters
115  VHDL_File_Info VInfo(File);
116  GenNames = VInfo.GenNames;
117  EntityName = VInfo.EntityName;
118  TypeNames = VInfo.TypeNames;
119  GenTypes = VInfo.GenTypes;
120  GenDefs = VInfo.GenDefs;
121  return VInfo.PortNames;
122 }
123 
124 // -------------------------------------------------------
126 {
127  QFontMetrics metrics(QucsSettings.font); // get size of text
128  int fHeight = metrics.lineSpacing();
129 
130  int No = 0;
131  TypeNames = "";
132  QString tmp, PortNames = loadFile();
133  if(!PortNames.isEmpty())
134  No = PortNames.count(',') + 1;
135 
136  #define HALFWIDTH 17
137  int h = 30*((No-1)/2) + 15;
138  Lines.append(new Line(-HALFWIDTH, -h, HALFWIDTH, -h,QPen(Qt::darkBlue,2)));
139  Lines.append(new Line( HALFWIDTH, -h, HALFWIDTH, h,QPen(Qt::darkBlue,2)));
140  Lines.append(new Line(-HALFWIDTH, h, HALFWIDTH, h,QPen(Qt::darkBlue,2)));
141  Lines.append(new Line(-HALFWIDTH, -h,-HALFWIDTH, h,QPen(Qt::darkBlue,2)));
142 
143  tmp = QObject::tr("vhdl");
144  int w = metrics.width(tmp);
145  Texts.append(new Text(w/-2, fHeight/-2, tmp));
146 
147  int y = 15-h, i = 0;
148  Port *pp;
149  while(i<No) {
150  Lines.append(new Line(-30, y,-HALFWIDTH, y,QPen(Qt::darkBlue,2)));
151  pp = new Port(-30, y);
152  Ports.append(pp);
153  pp->Type = TypeNames.section(',', i, i);
154  tmp = PortNames.section(',', i, i);
155  w = metrics.width(tmp);
156  Texts.append(new Text(-19-w, y-fHeight-2, tmp));
157  i++;
158 
159  if(i == No) break;
160  Lines.append(new Line(HALFWIDTH, y, 30, y,QPen(Qt::darkBlue,2)));
161  pp = new Port( 30, y);
162  Ports.append(pp);
163  pp->Type = TypeNames.section(',', i, i);
164  tmp = PortNames.section(',', i, i);
165  Texts.append(new Text( 20, y-fHeight-2, tmp));
166  y += 60;
167  i++;
168  }
169 
170  x1 = -30; y1 = -h-2;
171  x2 = 30; y2 = h+2;
172  tx = x1+4;
173  ty = y2+4;
174 
175  // now create/modify properties
176  No = 0;
177  if(!GenNames.isEmpty())
178  No = (GenNames.count(',')) + 1;
179  Property * pr = Props.at(1);
180  for(i=0; i<No; i++) {
181  if (!pr) {
182  pr = new Property(GenNames.section(',', i, i),
183  GenDefs.section(',', i, i), true,
184  QObject::tr("generic variable")+
185  " "+QString::number(i+1));
186  Props.append(pr);
187  pr = 0;
188  }
189  else {
190  pr->Description =
191  QObject::tr("generic variable")+" "+QString::number(i+1);
192  pr->Name = GenNames.section(',', i, i);
193  pr = Props.next();
194  }
195  }
196  // remove remaining properties if necessary
197  y=Props.count()-1;
198  for(i=No; i<y; i++) {
199  Props.removeLast();
200  }
201 }
202 
203 // -------------------------------------------------------
205 {
206  // construct full filename
207  QString FileName = Props.getFirst()->Value;
208  return properAbsFileName(FileName);
209 }
210 
211 // -------------------------------------------------------
212 bool VHDL_File::createSubNetlist(QTextStream *stream)
213 {
214  ErrText = "";
215 
216  // check filename
217  QString FileName = Props.getFirst()->Value;
218  if(FileName.isEmpty()) {
219  ErrText += QObject::tr("ERROR: No file name in %1 component \"%2\".").
220  arg(Model).arg(Name);
221  return false;
222  }
223 
224  // construct full filename
225  FileName = getSubcircuitFile();
226 
227  // open file for reading
228  QFile f(FileName);
229  if(!f.open(QIODevice::ReadOnly)) {
230  ErrText += QObject::tr("ERROR: Cannot open %1 file \"%2\".").
231  arg(Model).arg(FileName);
232  return false;
233  }
234 
235  // write the whole VHDL file into the netlist output
236  QByteArray FileContent = f.readAll();
237  f.close();
238  (*stream) << '\n';
239  //? stream->writeRawBytes(FileContent.data(), FileContent.size());
240  (*stream) << FileContent.data();
241  (*stream) << '\n';
242  return true;
243 }
244 
245 // -------------------------------------------------------
247 {
248  EntityName = "";
249  PortNames = "";
250  TypeNames = "";
251  GenTypes = "";
252  GenNames = "";
253  GenDefs = "";
254 }
255 
256 // -------------------------------------------------------
257 VHDL_File_Info::VHDL_File_Info(QString File, bool isfile)
258 {
259  if (isfile) {
260  QFile f(File);
261  if(!f.open(QIODevice::ReadOnly))
262  File = "";
263  else {
264  QByteArray FileContent = f.readAll();
265  File = QString(FileContent);
266  }
267  f.close();
268  }
269 
270  QString s;
271  PortNames = "";
272  int i=0, j, k=0;
273  while((i=File.find("--", i)) >= 0) { // remove all VHDL comments
274  j = File.find('\n', i+2); // This also finds "--" within a ...
275  if(j < 0) // string, but as no strings are ...
276  File = File.left(i); // allowed in entity headers, it ...
277  else // does not matter.
278  File.remove(i, j-i);
279  }
280 
281  QRegExp Expr;
282  Expr.setCaseSensitive(false);
283  for(;;) {
284  k--;
285  Expr.setPattern("\\bentity\\b"); // start of last entity
286  k = File.findRev(Expr, k);
287  if(k < 0)
288  return;
289 
290  Expr.setPattern("\\bend\\b"); // end of last entity
291  i = File.find(Expr, k+7);
292  if(i < 0)
293  return;
294  s = File.mid(k+7, i-k-7); // cut out entity declaration
295 
296  Expr.setPattern("\\b");
297  i = s.find(Expr);
298  if(i < 0)
299  return;
300  j = s.find(Expr, i+1);
301  if(j < 0)
302  return;
303  EntityName = s.mid(i, j-i); // save entity name
304 
305  i = s.find(Expr, j+1);
306  if(i < 0)
307  return;
308  j = s.find(Expr, i+1);
309  if(j < 0)
310  return;
311  if(s.mid(i, j-i).lower() == "is") // really found start of entity ?
312  break;
313 
314  if(k < 1) // already searched the whole text
315  return;
316  }
317 
318  // parse ports, i.e. network connections; and generics, i.e. parameters
319  GenNames = parseGenerics(s,j);
320  PortNames = parsePorts(s,j);
321 }
322 
323 // -------------------------------------------------------
324 QString VHDL_File_Info::parsePorts(QString s, int j)
325 {
326  QRegExp Expr;
327  Expr.setCaseSensitive(false);
328  int i, p, l, k;
329 
330  Expr.setPattern("\\bport\\b"); // start of interface definition
331  i = s.find(Expr, j+1);
332  if(i < 0)
333  return QString("");
334  // find opening (
335  i = s.find('(', i+4) + 1;
336  if(i <= 0)
337  return QString("");
338 
339  // find closing (
340  p = i;
341  j = i-1;
342  do {
343  j = s.find(')', j+1);
344  if(j < 0)
345  return QString("");
346  p = s.find('(', p+1);
347  if(p >= 0 && p > j) p = -1;
348  } while (p >= 0);
349 
350  s = s.mid(i, j-i);
351  s.remove('\n');
352  s.remove('\t');
353 
354  // find port names and types in parameter specification
355  l = i = 0; // remove all VHDL identifiers (e.g. ": out bit;")
356  QString types = "", t;
357  while((i=s.find(':', i)) >= 0) {
358  j = s.find(';', i+2);
359  if(j < 0) {
360  t = s.mid(i+1);
361  t.remove(';');
362  t = t.simplifyWhiteSpace();
363  s = s.left(i);
364  } else {
365  t = s.mid(i+1, j-i);
366  t.remove(';');
367  t = t.simplifyWhiteSpace();
368  s.remove(i, j-i);
369  }
370  if ((k = t.find(' ')) >= 0)
371  t = t.mid(k+1);
372  t = t.simplifyWhiteSpace();
373  k = s.find(';',l+2);
374  k = (s.mid(l,k-l).count(',')) + 1;
375  while (k-->0) types = types + t + ",";
376  i--;
377  l = i;
378  }
379 
380  s.remove(' ');
381  s.replace(';', ',');
382  TypeNames=types=types.left(types.length()-1);
383  return s;
384 }
385 
386 // -------------------------------------------------------
387 QString VHDL_File_Info::parseGenerics(QString s, int j)
388 {
389  QRegExp Expr;
390  Expr.setCaseSensitive(false);
391  int i, p, l, k, n;
392 
393  Expr.setPattern("\\bgeneric\\b");
394  i = s.find(Expr, j+1);
395  if(i < 0)
396  return QString("");
397  // find opening (
398  i = s.find('(', i+4) + 1;
399  if(i <= 0)
400  return QString("");
401 
402  // find closing (
403  p = i;
404  j = i-1;
405  do {
406  j = s.find(')', j+1);
407  if(j < 0)
408  return QString("");
409  p = s.find('(', p+1);
410  if(p >= 0 && p > j) p = -1;
411  } while (p >= 0);
412 
413  s = s.mid(i, j-i);
414  s.remove('\n');
415  s.remove('\t');
416 
417  // find generic names, types and defaults in parameter specification
418  l = i = 0;
419  QString types = "", t, defs = "", d;
420  while((i=s.find(':', i)) >= 0) {
421  j = s.find(';', i+2);
422  n = s.find(":=", i+2);
423  d = "";
424  if(n >= 0 && (n < j || j < 0) ) {
425  j = s.find(';', n+2);
426  if(j < 0) {
427  d = s.mid(n+2);
428  d = d.simplifyWhiteSpace();
429  s = s.left(n);
430  } else {
431  d = s.mid(n+2, j-n-1);
432  d.remove(';');
433  d = d.simplifyWhiteSpace();
434  s.remove(n, j-n);
435  }
436  j = s.find(';', n);
437  }
438  if(j < 0) {
439  t = s.mid(i+1);
440  t.remove(';');
441  t = t.simplifyWhiteSpace();
442  s = s.left(i);
443  } else {
444  t = s.mid(i+1, j-i);
445  t.remove(';');
446  t = t.simplifyWhiteSpace();
447  s.remove(i, j-i);
448  }
449  if ((k = t.find(' ')) >= 0)
450  t = t.mid(k+1);
451  t = t.simplifyWhiteSpace();
452  k = s.find(';',l+2);
453  k = (s.mid(l,k-l).count(',')) + 1;
454  while (k-->0) {
455  types = types + t + ",";
456  defs = defs + d + ",";
457  }
458  i--;
459  l = i;
460  }
461 
462  s.remove(' ');
463  s.replace(';', ',');
464  GenTypes=types=types.left(types.length()-1);
465  GenDefs=defs=defs.left(defs.length()-1);
466  return s;
467 }
QString EntityName
Definition: vhdlfile.h:59
Q3PtrList< Line > Lines
Definition: component.h:67
QDir QucsWorkDir
Definition: main.h:65
int Type
Definition: element.h:152
Node * Connection
Definition: element.h:79
int y1
Definition: element.h:153
QFont font
Definition: main.h:46
QString ErrText
Definition: vhdlfile.h:43
tQucsSettings QucsSettings
Definition: main.cpp:52
int tx
Definition: component.h:78
int y2
Definition: element.h:153
Definition: element.h:72
int x1
Definition: element.h:153
#define HALFWIDTH
QString PortNames
Definition: vhdlfile.h:60
#define isDigitalComponent
Definition: element.h:113
QString TypeNames
Definition: vhdlfile.h:44
QString GenDefs
Definition: vhdlfile.h:47
Definitions and declarations for the main application.
int ty
Definition: component.h:78
QString Value
Definition: element.h:97
QString properAbsFileName(const QString &Name)
Definition: main.cpp:452
QString Type
Definition: element.h:78
Q3PtrList< Property > Props
Definition: component.h:72
bool createSubNetlist(QTextStream *)
Definition: vhdlfile.cpp:212
static Element * info(QString &, char *&, bool getNewOne=false)
Definition: vhdlfile.cpp:55
QString vhdlCode(int)
Definition: vhdlfile.cpp:69
Definition: element.h:82
QString parsePorts(QString, int)
Definition: vhdlfile.cpp:324
Definition: element.h:48
Superclass of all schematic drawing elements.
Definition: element.h:142
void recreate(Schematic *)
Definition: component.cpp:1250
QString loadFile()
Definition: vhdlfile.cpp:99
Q3PtrList< Port > Ports
Definition: component.h:70
QString Name
Definition: element.h:97
QString TypeNames
Definition: vhdlfile.h:61
QString Name
Definition: component.h:80
Q3PtrList< Text > Texts
Definition: component.h:71
QString Model
Definition: component.h:80
QString Name
Definition: node.h:40
QString GenNames
Definition: vhdlfile.h:63
QString getSubcircuitFile()
Definition: vhdlfile.cpp:204
QString GenNames
Definition: vhdlfile.h:46
QString Description
Definition: component.h:81
QString parseGenerics(QString, int)
Definition: vhdlfile.cpp:387
QString GenTypes
Definition: vhdlfile.h:62
QString EntityName
Definition: vhdlfile.h:42
QString Description
Definition: element.h:100
void createSymbol()
Definition: vhdlfile.cpp:125
int x2
Definition: element.h:153
QString GenDefs
Definition: vhdlfile.h:64
QString GenTypes
Definition: vhdlfile.h:45
Component * newOne()
Definition: vhdlfile.cpp:46