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

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