1 #include "AbstractInterface.h"
2 #include "BlockParameterPort.h"
3 #include "AbstractBlock.h"
4 #include "Parameters.h"
7 AbstractInterface::AbstractInterface(AbstractBlock* _owner) {
15 endianess = LittleEndian;
16 associatedIface = NULL;
18 clkIfaceType = NoName;
22 AbstractInterface::AbstractInterface(AbstractBlock* _owner, const QString& _name, int _direction, int _purpose, const QString& _type, const QString& _width, int _endianess) {
25 name = Parameters::normalizeName(_name);
27 direction = _direction;
29 type = typeFromString(_type);
30 endianess = _endianess;
31 associatedIface = NULL;
33 clkIfaceType = NoName;
36 AbstractInterface::AbstractInterface(AbstractInterface* other) {
38 name = Parameters::normalizeName(other->name);
41 direction = other->direction;
42 purpose = other->purpose;
43 endianess = LittleEndian;
44 associatedIface = NULL;
45 clkIfaceName = other->clkIfaceName;
46 clkIfaceType = other->clkIfaceType;
49 void AbstractInterface::setName(const QString& _name) {
50 name = Parameters::normalizeName(_name);
53 AbstractInterface::~AbstractInterface() {
57 bool AbstractInterface::isReferenceInterface() {
61 bool AbstractInterface::isFunctionalInterface() {
65 bool AbstractInterface::isGroupInterface() {
69 int AbstractInterface::getWidth() {
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.
83 For this reason, if it is boolean, 0 is returned instead of 1.
85 if (type == Boolean) {
88 else if (type == Natural) {
92 else if (type == Expression) {
94 QList<BlockParameter*> listGenerics = owner->getGenericParameters();
95 QList<BlockParameter*> listUsers = owner->getUserParameters();
96 QList<BlockParameter*> listPorts = owner->getPortParameters();
98 foreach(BlockParameter* p, listUsers) {
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());
107 foreach(BlockParameter* p, listPorts) {
110 if (width.contains(var)) {
111 expr.replace(var,p->toVHDL(0,0));
114 foreach(BlockParameter* p, listGenerics) {
117 if (width.contains(var)) {
118 int tmp = p->getValue().toInt(&ok);
125 // now evaluate the whole expression
126 ArithmeticEvaluator evaluator;
129 evaluator.setVariableMarkers("$");
130 evaluator.setExpression(expr);
131 w = (int)(evaluator.evaluate());
132 cout << "iface size :" << w << endl;
135 cerr << "invalid expression in size of interface " << qPrintable(name) << " at character " << e << endl;
142 QString AbstractInterface::getEndianessString() {
143 QString str="unknown";
145 case AbstractInterface::LittleEndian:
146 str = QString("little");
148 case AbstractInterface::BigEndian:
149 str = QString("big");
155 QString AbstractInterface::getPurposeString() {
158 case AbstractInterface::AnyPurpose:
159 str = QString("any");
161 case AbstractInterface::Data:
162 str = QString("data");
164 case AbstractInterface::Control:
165 str = QString("control");
167 case AbstractInterface::Clock:
168 str = QString("clock");
170 case AbstractInterface::Reset:
171 str = QString("reset");
173 case AbstractInterface::Wishbone:
174 str = QString("wishbone");
180 QString AbstractInterface::getDirectionString() {
183 case AbstractInterface::Input:
184 str = QString("input");
186 case AbstractInterface::Output:
187 str = QString("output");
189 case AbstractInterface::InOut:
190 str = QString("inout");
197 void AbstractInterface::setPurpose(int _purpose) {
198 if ((_purpose>=Data) && (_purpose <= Wishbone)) {
203 void AbstractInterface::setDirection(int _direction) {
204 if ((_direction > Input) && (_direction <= InOut)) {
205 direction = _direction;
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;
217 AbstractInterface* AbstractInterface::getClockIface() {
218 if (clkIfaceType == ClockName) {
219 return owner->getIfaceFromName(clkIfaceName);
225 double AbstractInterface::getClockFrequency() throw(Exception) {
229 if (clkIfaceType == ParameterName) {
230 BlockParameter* param = owner->getParameterFromName(clkIfaceName);
231 if (!param->isUserParameter()) throw(Exception(IFACE_INVALID_CLKFREQ,this));
233 double freq = param->getDoubleValue(&ok);
234 if (!ok) throw(Exception(IFACE_INVALID_CLKFREQ,this));
239 idClock = getClockDomain();
244 return owner->getGraph()->getClock(idClock);
251 int AbstractInterface::getIntDirection(QString str) {
252 if(str == "input") return Input;
253 if(str == "output") return Output;
254 if(str == "inout") return InOut;
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;
266 QString AbstractInterface::getTypeString() {
268 if (type == Boolean) {
271 else if (type == Natural) {
274 else if (type == Expression) {
277 else if (type == Inherited) {
280 return "invalid_type";
283 int AbstractInterface::typeFromString(const QString &_type) {
285 int ret = Expression; // default type
286 if (_type == "expression") {
289 else if (_type == "boolean") {
292 else if (_type == "natural") {
295 else if (_type == "inherited") {
301 QString AbstractInterface::toVHDL(IfaceVHDLContext context, int flags) throw(Exception) {
304 if (isReferenceInterface()) throw(Exception(IFACE_INVALID_TYPE));
311 //cout << "iface " << qPrintable(name) << " must be evaluated to vhdl :" << qPrintable(width) << " with type = " << qPrintable(getTypeString()) << endl;
313 if (context == Instance) {
314 if (direction == Input) {
315 ret = owner->getName()+"_"+name;
317 else if (direction == Output) {
318 ret = "from_"+owner->getName()+"_"+name;
320 else if (direction == InOut) {
321 ret = "fromto_"+owner->getName()+"_"+name;
326 // create the width part
327 QString widthStr = "";
328 if (type == Boolean) {
329 widthStr = "std_logic";
332 QString formatWidth = "";
333 if (endianess == LittleEndian) formatWidth = "std_logic_vector(%1 downto %2)";
334 else formatWidth = "std_logic_vector(%2 to %1)";
336 if (type == Natural) {
337 w = width.toInt(&ok);
339 throw(Exception(INVALID_VALUE));
344 widthStr = formatWidth.arg(wStr).arg(0);
347 else if (type == Expression) {
349 // NB: if for signal, must retrieve the real size, not the one with generics
350 if (context == Signal) {
352 if (w == -1) throw(Exception(INVALID_VALUE));
354 widthStr = "std_logic";
359 widthStr = formatWidth.arg(wStr).arg(0);
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.
369 QList<BlockParameter*> listGenerics = owner->getGenericParameters();
370 QList<BlockParameter*> listUsers = owner->getUserParameters();
371 QList<BlockParameter*> listPorts = owner->getPortParameters();
372 foreach(BlockParameter* p, listUsers) {
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());
381 foreach(BlockParameter* p, listPorts) {
384 if (width.contains(var)) {
385 wStr.replace(var,p->toVHDL(0,0));
388 foreach(BlockParameter* p, listGenerics) {
391 if (width.contains(var)) {
392 wStr.replace(var,p->getName());
396 widthStr = formatWidth.arg(wStr).arg(0);
399 else if (type == Inherited) {
401 if (w == -1) throw(Exception(INVALID_VALUE));
403 widthStr = "std_logic";
408 widthStr = formatWidth.arg(wStr).arg(0);
413 if ((flags & NoComma) == 0) {
414 widthStr.append(";");
417 // generate for an Entity or Component port
418 if ((context == Entity) || (context == Component)) {
420 QString formatPort = "%1 : %2 ";
422 QString orientation="";
423 if (direction == Input) {
426 else if (direction == Output) {
430 orientation = "inout";
433 ret = formatPort.arg(name).arg(orientation);
436 else if (context == Signal) {
437 if (direction == Output) {
438 ret = "from_"+owner->getName()+"_"+name+" : "+widthStr;
440 else if (direction == InOut) {
441 ret = "fromto_"+owner->getName()+"_"+name+" : "+widthStr;
443 else if (direction == Input) {
444 ret = owner->getName()+"_"+name+" : "+widthStr;