]> AND Private Git Repository - blast.git/blob - AbstractInterface.cpp
Logo AND Algorithmique Numérique Distribuée

Private GIT Repository
finished testbench generation
[blast.git] / AbstractInterface.cpp
1 #include "AbstractInterface.h"
2 #include "BlockParameterPort.h"
3 #include "AbstractBlock.h"
4 #include "Parameters.h"
5 #include "Graph.h"
6
7 AbstractInterface::AbstractInterface(AbstractBlock* _owner) {
8
9   owner = _owner;  
10   name = "";
11   width = "1";
12   direction = Input;
13   purpose = Data;  
14   type = Boolean;
15   endianess = LittleEndian;
16   associatedIface = NULL;
17   clkIfaceName = "";
18   clkIfaceType = NoName;
19
20 }
21
22 AbstractInterface::AbstractInterface(AbstractBlock* _owner, const QString& _name, int _direction, int _purpose, const QString& _type, const QString& _width, int _endianess) {
23
24   owner = _owner;  
25   name = Parameters::normalizeName(_name);
26   width = _width;
27   direction = _direction;
28   purpose = _purpose;
29   type = typeFromString(_type);
30   endianess = _endianess;
31   associatedIface = NULL;
32   clkIfaceName = "";
33   clkIfaceType = NoName;
34 }
35
36 AbstractInterface::AbstractInterface(AbstractInterface* other) {
37   owner = NULL;
38   name = Parameters::normalizeName(other->name);
39   type = other->type;
40   width = other->width;
41   direction = other->direction;
42   purpose = other->purpose;
43   endianess = LittleEndian;
44   associatedIface = NULL;
45   clkIfaceName = other->clkIfaceName;
46   clkIfaceType = other->clkIfaceType;
47 }
48
49 void AbstractInterface::setName(const QString& _name) {
50   name = Parameters::normalizeName(_name);
51 }
52
53 AbstractInterface::~AbstractInterface() {
54
55 }
56
57 bool AbstractInterface::isReferenceInterface() {
58   return false;
59 }
60
61 bool AbstractInterface::isFunctionalInterface() {
62   return false;
63 }
64
65 bool AbstractInterface::isGroupInterface() {
66   return false;
67 }
68
69 int AbstractInterface::getWidth() {
70
71   bool ok;
72   int w = -1;
73
74   QString expr = width;
75
76   /* CAUTION :
77
78      Since VHDL allows to write std_logic_vector(O downto 0)
79      which is different from std_logic, we have to differentiate
80      a size of 1 that is really a boolean and thus a std_logic, from
81      a std_logic_vector of size 1.
82
83      For this reason, if it is boolean, 0 is returned instead of 1.
84    */
85   if (type == Boolean) {
86     return 0;
87   }
88   else if (type == Natural) {
89     w = width.toInt(&ok);
90     if (!ok) return -1;
91   }
92   else if (type == Expression) {
93
94     QList<BlockParameter*> listGenerics = owner->getGenericParameters();
95     QList<BlockParameter*> listUsers = owner->getUserParameters();
96     QList<BlockParameter*> listPorts = owner->getPortParameters();
97
98     foreach(BlockParameter* p, listUsers) {
99       QString var = "$";
100       var += p->getName();
101       if (width.contains(var)) {
102         int tmp = p->getValue().toInt(&ok);
103         if (!ok) return -1; // user parameter cannot be converted to an int
104         expr.replace(var,p->getValue().toString());
105       }
106     }
107     foreach(BlockParameter* p, listPorts) {
108       QString var = "$";
109       var += p->getName();
110       if (width.contains(var)) {
111         expr.replace(var,p->toVHDL(0,0));
112       }
113     }
114     foreach(BlockParameter* p, listGenerics) {
115       QString var = "$";
116       var += p->getName();
117       if (width.contains(var)) {
118         int tmp = p->getValue().toInt(&ok);
119         if (!ok) return -1;
120         QString s="";
121         s.setNum(tmp);
122         expr.replace(var,s);
123       }
124     }
125     // now evaluate the whole expression
126     ArithmeticEvaluator evaluator;
127
128     try {
129       evaluator.setVariableMarkers("$");
130       evaluator.setExpression(expr);
131       w = (int)(evaluator.evaluate());
132       cout << "iface size :" << w << endl;
133     }
134     catch(int e) {
135       cerr << "invalid expression in size of interface " << qPrintable(name) << " at character " << e << endl;
136       w = -1;
137     }
138   }
139   return w;
140 }
141
142 QString AbstractInterface::getEndianessString() {
143   QString str="unknown";
144   switch(endianess){
145   case AbstractInterface::LittleEndian:
146     str = QString("little");
147     break;
148   case AbstractInterface::BigEndian:
149     str = QString("big");
150     break;
151   }
152   return str;
153 }
154
155 QString AbstractInterface::getPurposeString() {
156   QString str;
157   switch(purpose){
158   case AbstractInterface::AnyPurpose:
159     str = QString("any");
160     break;
161   case AbstractInterface::Data:
162     str = QString("data");
163     break;
164   case AbstractInterface::Control:
165     str = QString("control");
166     break;
167   case AbstractInterface::Clock:
168     str = QString("clock");
169     break;
170   case AbstractInterface::Reset:
171     str = QString("reset");
172     break;
173   case AbstractInterface::Wishbone:
174     str = QString("wishbone");
175     break;
176   }
177   return str;
178 }
179
180 QString AbstractInterface::getDirectionString() {
181     QString str;
182     switch(direction){
183         case AbstractInterface::Input:
184             str = QString("input");
185             break;
186         case AbstractInterface::Output:
187             str = QString("output");
188             break;
189         case AbstractInterface::InOut:
190             str = QString("inout");
191             break;
192     }
193     return str;
194 }
195
196
197 void AbstractInterface::setPurpose(int _purpose) {
198   if ((_purpose>=Data) && (_purpose <= Wishbone)) {
199     purpose = _purpose;
200   }
201 }
202
203 void AbstractInterface::setDirection(int _direction) {
204   if ((_direction > Input) && (_direction <= InOut)) {
205     direction = _direction;
206   }
207 }
208
209 bool AbstractInterface::setAssociatedIface(AbstractInterface* iface) {
210   if (purpose != Control) return false;
211   if (iface->purpose != Data) return false;
212   associatedIface = iface;
213   iface->associatedIface = this;  
214   return true;
215 }
216
217 AbstractInterface* AbstractInterface::getClockIface() {
218   if (clkIfaceType == ClockName) {
219     return owner->getIfaceFromName(clkIfaceName);
220   }
221   return NULL;
222 }
223
224
225 double AbstractInterface::getClockFrequency() throw(Exception) {
226
227   int idClock = -1;
228
229   if (clkIfaceType == ParameterName) {
230     BlockParameter* param = owner->getParameterFromName(clkIfaceName);
231     if (!param->isUserParameter()) throw(Exception(IFACE_INVALID_CLKFREQ,this));
232     bool ok;
233     double freq = param->getDoubleValue(&ok);
234     if (!ok) throw(Exception(IFACE_INVALID_CLKFREQ,this));
235     return freq;
236   }
237   else {
238     try {
239       idClock = getClockDomain();
240     }
241     catch(Exception e) {
242       throw(e);
243     }
244     return owner->getGraph()->getClock(idClock);
245   }
246   return 0.0;
247 }
248
249
250
251 int AbstractInterface::getIntDirection(QString str) {
252     if(str == "input") return Input;
253     if(str == "output") return Output;
254     if(str == "inout") return InOut;
255     return -1;
256 }
257
258 int AbstractInterface::getIntPurpose(QString str) {
259     if(str == "data") return Data;
260     else if(str == "clock") return Clock;
261     else if(str == "reset") return Reset;
262     else if(str == "wishbone") return Wishbone;
263     return -1;
264 }
265
266 QString AbstractInterface::getTypeString() {
267
268   if (type == Boolean) {
269     return "boolean";
270   }
271   else if (type == Natural) {
272     return "natural";
273   }
274   else if (type == Expression) {
275     return "expression";
276   }
277   else if (type == Inherited) {
278     return "inherited";
279   }
280   return "invalid_type";
281 }
282
283 int AbstractInterface::typeFromString(const QString &_type) {
284
285   int ret = Expression; // default type
286   if (_type == "expression") {
287     ret = Expression;
288   }
289   else if (_type == "boolean") {
290     ret = Boolean;
291   }
292   else if (_type == "natural") {
293     ret = Natural;
294   }
295   else if (_type == "inherited") {
296     ret = Inherited;
297   }
298   return ret;
299 }
300
301 QString AbstractInterface::toVHDL(IfaceVHDLContext context, int flags) throw(Exception) {
302
303
304   if (isReferenceInterface()) throw(Exception(IFACE_INVALID_TYPE));
305
306   int w;
307   QString wStr = "";
308   QString ret="";
309
310   bool ok;
311   //cout << "iface " << qPrintable(name) << " must be evaluated to vhdl :" << qPrintable(width) << " with type = " << qPrintable(getTypeString()) << endl;
312
313   if (context == Instance) {
314     if (direction == Input) {
315       ret = owner->getName()+"_"+name;
316     }
317     else if (direction == Output) {
318       ret = "from_"+owner->getName()+"_"+name;
319     }
320     else if (direction == InOut) {
321       ret = "fromto_"+owner->getName()+"_"+name;
322     }
323     return ret;
324   }
325
326   // create the width part
327   QString widthStr = "";
328   if (type == Boolean) {
329     widthStr = "std_logic";
330   }
331   else {
332     QString formatWidth = "";
333     if (endianess == LittleEndian) formatWidth = "std_logic_vector(%1 downto %2)";
334     else formatWidth = "std_logic_vector(%2 to %1)";
335
336     if (type == Natural) {
337       w = width.toInt(&ok);
338       if (!ok) {
339         throw(Exception(INVALID_VALUE));
340       }
341       else {
342         w -= 1;
343         wStr.setNum(w);
344         widthStr = formatWidth.arg(wStr).arg(0);
345       }
346     }
347     else if (type == Expression) {
348
349       // NB: if for signal, must retrieve the real size, not the one with generics
350       if (context == Signal) {
351         w = getWidth();
352         if (w == -1) throw(Exception(INVALID_VALUE));
353         if (w == 0) {
354           widthStr = "std_logic";
355         }
356         else {
357           w--;
358           wStr.setNum(w);
359           widthStr = formatWidth.arg(wStr).arg(0);
360         }
361       }
362       else {
363
364         /* must check the following conditions :
365                - if it contains user/port parameters : must evaluate their numeric value
366                - if it contains generic parameters : just remove the $ -> the expression is not arithmetically evaluated.
367           */
368         wStr = width;
369         QList<BlockParameter*> listGenerics = owner->getGenericParameters();
370         QList<BlockParameter*> listUsers = owner->getUserParameters();
371         QList<BlockParameter*> listPorts = owner->getPortParameters();
372         foreach(BlockParameter* p, listUsers) {
373           QString var = "$";
374           var += p->getName();
375           if (width.contains(var)) {
376             w = p->getValue().toInt(&ok);
377             if (!ok) throw(Exception(INVALID_VALUE));
378             wStr.replace(var,p->getValue().toString());
379           }
380         }
381         foreach(BlockParameter* p, listPorts) {
382           QString var = "$";
383           var += p->getName();
384           if (width.contains(var)) {
385             wStr.replace(var,p->toVHDL(0,0));
386           }
387         }
388         foreach(BlockParameter* p, listGenerics) {
389           QString var = "$";
390           var += p->getName();
391           if (width.contains(var)) {
392             wStr.replace(var,p->getName());
393           }
394         }
395         wStr += "-1";
396         widthStr = formatWidth.arg(wStr).arg(0);
397       }
398     }
399     else if (type == Inherited) {
400       w = getWidth();
401       if (w == -1) throw(Exception(INVALID_VALUE));
402       if (w == 0) {
403         widthStr = "std_logic";
404       }
405       else {
406         w--;
407         wStr.setNum(w);
408         widthStr = formatWidth.arg(wStr).arg(0);
409       }
410     }
411   }
412
413   if ((flags & NoComma) == 0) {
414     widthStr.append(";");
415   }
416
417   // generate for an Entity or Component port
418   if ((context == Entity) || (context == Component)) {
419
420     QString formatPort = "%1 : %2 ";
421
422     QString orientation="";
423     if (direction == Input) {
424       orientation = "in";
425     }
426     else if (direction == Output) {
427       orientation = "out";
428     }
429     else {
430       orientation = "inout";
431     }
432
433     ret = formatPort.arg(name).arg(orientation);
434     ret += widthStr;
435   }
436   else if (context == Signal) {
437     if (direction == Output) {
438       ret = "from_"+owner->getName()+"_"+name+" : "+widthStr;
439     }
440     else if (direction == InOut) {
441       ret = "fromto_"+owner->getName()+"_"+name+" : "+widthStr;
442     }
443     else if (direction == Input) {
444       ret = owner->getName()+"_"+name+" : "+widthStr;
445     }
446   }
447
448   return ret;
449 }
450