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

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