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

Private GIT Repository
3fdd87ad152912f9a850b4ea96799c8f9a2ff6db
[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   clkIface = "";
18   clkIfaceType = 0;
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   clkIface = "";
33   clkIfaceType = 0;
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   clkIface = other->clkIface;
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(clkIface);
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(clkIface);
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 bool AbstractInterface::setClockIface(QString name) {
251   /* 2 cases :
252    *  - this is a Data interface
253    *  - this is a Clock output (from a clkrstgen)
254    *
255    *   iface must correspond to an existing clock interface name
256    * or a user parameter prepend with a $.
257    */
258   if ((purpose == Data) || ((purpose == Clock) && (direction == Output))) {
259     if (name.at(0) == '$') {
260       name.remove(0,1);
261       QList<BlockParameter* > params = owner->getUserParameters();
262       foreach(BlockParameter* p, params) {
263         if (p->getName() == name) {
264           clkIface = name;
265           clkIfaceType = ParameterName;
266           return true;
267         }
268       }
269       // error case: cannot found the input clock
270       return false;
271     }
272     else {
273       QList<AbstractInterface*> clocks = owner->getInterfaces(Input, Clock);
274       foreach(AbstractInterface* iface, clocks) {
275         if (iface->getName() == name) {
276           clkIface = name;
277           clkIfaceType = ClockName;
278           return true;
279         }
280       }
281       // error case: cannot found the user paramter
282       return false;
283     }
284   }
285   clkIface = "";
286   clkIfaceType = NoName;
287   return true;
288 }
289
290
291 int AbstractInterface::getIntDirection(QString str) {
292     if(str == "input") return Input;
293     if(str == "output") return Output;
294     if(str == "inout") return InOut;
295     return -1;
296 }
297
298 int AbstractInterface::getIntPurpose(QString str) {
299     if(str == "data") return Data;
300     else if(str == "clock") return Clock;
301     else if(str == "reset") return Reset;
302     else if(str == "wishbone") return Wishbone;
303     return -1;
304 }
305
306 QString AbstractInterface::getTypeString() {
307
308   if (type == Boolean) {
309     return "boolean";
310   }
311   else if (type == Natural) {
312     return "natural";
313   }
314   else if (type == Expression) {
315     return "expression";
316   }
317   else if (type == Inherited) {
318     return "inherited";
319   }
320   return "invalid_type";
321 }
322
323 int AbstractInterface::typeFromString(const QString &_type) {
324
325   int ret = Expression; // default type
326   if (_type == "expression") {
327     ret = Expression;
328   }
329   else if (_type == "boolean") {
330     ret = Boolean;
331   }
332   else if (_type == "natural") {
333     ret = Natural;
334   }
335   else if (_type == "inherited") {
336     ret = Inherited;
337   }
338   return ret;
339 }
340
341 QString AbstractInterface::toVHDL(IfaceVHDLContext context, int flags) throw(Exception) {
342
343
344   if (isReferenceInterface()) throw(Exception(IFACE_INVALID_TYPE));
345
346   int w;
347   QString wStr = "";
348   QString ret="";
349
350   bool ok;
351   //cout << "iface " << qPrintable(name) << " must be evaluated to vhdl :" << qPrintable(width) << " with type = " << qPrintable(getTypeString()) << endl;
352
353   if (context == Instance) {
354     if (direction == Output) {
355       ret = "from_"+owner->getName()+"_"+name;
356     }
357     else if (direction == InOut) {
358       ret = "fromto_"+owner->getName()+"_"+name;
359     }
360     return ret;
361   }
362
363   // create the width part
364   QString widthStr = "";
365   if (type == Boolean) {
366     widthStr = "std_logic";
367   }
368   else {
369     QString formatWidth = "";
370     if (endianess == LittleEndian) formatWidth = "std_logic_vector(%1 downto %2)";
371     else formatWidth = "std_logic_vector(%2 to %1)";
372
373     if (type == Natural) {
374       w = width.toInt(&ok);
375       if (!ok) {
376         throw(Exception(INVALID_VALUE));
377       }
378       else {
379         w -= 1;
380         wStr.setNum(w);
381         widthStr = formatWidth.arg(wStr).arg(0);
382       }
383     }
384     else if (type == Expression) {
385
386       // NB: if for signal, must retrieve the real size, not the one with generics
387       if (context == Signal) {
388         w = getWidth();
389         if (w == -1) throw(Exception(INVALID_VALUE));
390         if (w == 0) {
391           widthStr = "std_logic";
392         }
393         else {
394           w--;
395           wStr.setNum(w);
396           widthStr = formatWidth.arg(wStr).arg(0);
397         }
398       }
399       else {
400
401         /* must check the following conditions :
402                - if it contains user/port parameters : must evaluate their numeric value
403                - if it contains generic parameters : just remove the $ -> the expression is not arithmetically evaluated.
404           */
405         wStr = width;
406         QList<BlockParameter*> listGenerics = owner->getGenericParameters();
407         QList<BlockParameter*> listUsers = owner->getUserParameters();
408         QList<BlockParameter*> listPorts = owner->getPortParameters();
409         foreach(BlockParameter* p, listUsers) {
410           QString var = "$";
411           var += p->getName();
412           if (width.contains(var)) {
413             w = p->getValue().toInt(&ok);
414             if (!ok) throw(Exception(INVALID_VALUE));
415             wStr.replace(var,p->getValue().toString());
416           }
417         }
418         foreach(BlockParameter* p, listPorts) {
419           QString var = "$";
420           var += p->getName();
421           if (width.contains(var)) {
422             wStr.replace(var,p->toVHDL(0,0));
423           }
424         }
425         foreach(BlockParameter* p, listGenerics) {
426           QString var = "$";
427           var += p->getName();
428           if (width.contains(var)) {
429             wStr.replace(var,p->getName());
430           }
431         }
432         wStr += "-1";
433         widthStr = formatWidth.arg(wStr).arg(0);
434       }
435     }
436     else if (type == Inherited) {
437       w = getWidth();
438       if (w == -1) throw(Exception(INVALID_VALUE));
439       if (w == 0) {
440         widthStr = "std_logic";
441       }
442       else {
443         w--;
444         wStr.setNum(w);
445         widthStr = formatWidth.arg(wStr).arg(0);
446       }
447     }
448   }
449
450   if ((flags & NoComma) == 0) {
451     widthStr.append(";");
452   }
453
454   // generate for an Entity or Component port
455   if ((context == Entity) || (context == Component)) {
456
457     QString formatPort = "%1 : %2 ";
458
459     QString orientation="";
460     if (direction == Input) {
461       orientation = "in";
462     }
463     else if (direction == Output) {
464       orientation = "out";
465     }
466     else {
467       orientation = "inout";
468     }
469
470     ret = formatPort.arg(name).arg(orientation);
471     ret += widthStr;
472   }
473   else if (context == Signal) {
474     if (direction == Output) {
475       ret = "from_"+owner->getName()+"_"+name+" : "+widthStr;
476     }
477     else if (direction == InOut) {
478       ret = "fromto_"+owner->getName()+"_"+name+" : "+widthStr;
479     }
480     else if (direction == Input) {
481       ret = owner->getName()+"_"+name+" : "+widthStr;
482     }
483   }
484
485   return ret;
486 }
487