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

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