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;
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;
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 clkIface = other->clkIface;
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(clkIface);
225 double AbstractInterface::getClockFrequency() throw(Exception) {
229 if (clkIfaceType == ParameterName) {
230 BlockParameter* param = owner->getParameterFromName(clkIface);
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);
250 bool AbstractInterface::setClockIface(QString name) {
252 * - this is a Data interface
253 * - this is a Clock output (from a clkrstgen)
255 * iface must correspond to an existing clock interface name
256 * or a user parameter prepend with a $.
258 if ((purpose == Data) || ((purpose == Clock) && (direction == Output))) {
259 if (name.at(0) == '$') {
261 QList<BlockParameter* > params = owner->getUserParameters();
262 foreach(BlockParameter* p, params) {
263 if (p->getName() == name) {
265 clkIfaceType = ParameterName;
269 // error case: cannot found the input clock
273 QList<AbstractInterface*> clocks = owner->getInterfaces(Input, Clock);
274 foreach(AbstractInterface* iface, clocks) {
275 if (iface->getName() == name) {
277 clkIfaceType = ClockName;
281 // error case: cannot found the user paramter
286 clkIfaceType = NoName;
291 int AbstractInterface::getIntDirection(QString str) {
292 if(str == "input") return Input;
293 if(str == "output") return Output;
294 if(str == "inout") return InOut;
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;
306 QString AbstractInterface::getTypeString() {
308 if (type == Boolean) {
311 else if (type == Natural) {
314 else if (type == Expression) {
317 else if (type == Inherited) {
320 return "invalid_type";
323 int AbstractInterface::typeFromString(const QString &_type) {
325 int ret = Expression; // default type
326 if (_type == "expression") {
329 else if (_type == "boolean") {
332 else if (_type == "natural") {
335 else if (_type == "inherited") {
341 QString AbstractInterface::toVHDL(IfaceVHDLContext context, int flags) throw(Exception) {
344 if (isReferenceInterface()) throw(Exception(IFACE_INVALID_TYPE));
351 //cout << "iface " << qPrintable(name) << " must be evaluated to vhdl :" << qPrintable(width) << " with type = " << qPrintable(getTypeString()) << endl;
353 if (context == Instance) {
354 if (direction == Output) {
355 ret = "from_"+owner->getName()+"_"+name;
357 else if (direction == InOut) {
358 ret = "fromto_"+owner->getName()+"_"+name;
363 // create the width part
364 QString widthStr = "";
365 if (type == Boolean) {
366 widthStr = "std_logic";
369 QString formatWidth = "";
370 if (endianess == LittleEndian) formatWidth = "std_logic_vector(%1 downto %2)";
371 else formatWidth = "std_logic_vector(%2 to %1)";
373 if (type == Natural) {
374 w = width.toInt(&ok);
376 throw(Exception(INVALID_VALUE));
381 widthStr = formatWidth.arg(wStr).arg(0);
384 else if (type == Expression) {
386 // NB: if for signal, must retrieve the real size, not the one with generics
387 if (context == Signal) {
389 if (w == -1) throw(Exception(INVALID_VALUE));
391 widthStr = "std_logic";
396 widthStr = formatWidth.arg(wStr).arg(0);
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.
406 QList<BlockParameter*> listGenerics = owner->getGenericParameters();
407 QList<BlockParameter*> listUsers = owner->getUserParameters();
408 QList<BlockParameter*> listPorts = owner->getPortParameters();
409 foreach(BlockParameter* p, listUsers) {
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());
418 foreach(BlockParameter* p, listPorts) {
421 if (width.contains(var)) {
422 wStr.replace(var,p->toVHDL(0,0));
425 foreach(BlockParameter* p, listGenerics) {
428 if (width.contains(var)) {
429 wStr.replace(var,p->getName());
433 widthStr = formatWidth.arg(wStr).arg(0);
436 else if (type == Inherited) {
438 if (w == -1) throw(Exception(INVALID_VALUE));
440 widthStr = "std_logic";
445 widthStr = formatWidth.arg(wStr).arg(0);
450 if ((flags & NoComma) == 0) {
451 widthStr.append(";");
454 // generate for an Entity or Component port
455 if ((context == Entity) || (context == Component)) {
457 QString formatPort = "%1 : %2 ";
459 QString orientation="";
460 if (direction == Input) {
463 else if (direction == Output) {
467 orientation = "inout";
470 ret = formatPort.arg(name).arg(orientation);
473 else if (context == Signal) {
474 if (direction == Output) {
475 ret = "from_"+owner->getName()+"_"+name+" : "+widthStr;
477 else if (direction == InOut) {
478 ret = "fromto_"+owner->getName()+"_"+name+" : "+widthStr;
480 else if (direction == Input) {
481 ret = owner->getName()+"_"+name+" : "+widthStr;