X-Git-Url: https://bilbo.iut-bm.univ-fcomte.fr/and/gitweb/blast.git/blobdiff_plain/c85843afb9bd492b46d6fe87a8287157097483f5..4327c2b8817b627249d98d889835726217c81a4e:/AbstractInterface.cpp?ds=sidebyside diff --git a/AbstractInterface.cpp b/AbstractInterface.cpp index a32f78e..3fdd87a 100644 --- a/AbstractInterface.cpp +++ b/AbstractInterface.cpp @@ -2,10 +2,11 @@ #include "BlockParameterPort.h" #include "AbstractBlock.h" #include "Parameters.h" +#include "Graph.h" AbstractInterface::AbstractInterface(AbstractBlock* _owner) { - owner = _owner; + owner = _owner; name = ""; width = "1"; direction = Input; @@ -13,6 +14,8 @@ AbstractInterface::AbstractInterface(AbstractBlock* _owner) { type = Boolean; endianess = LittleEndian; associatedIface = NULL; + clkIface = ""; + clkIfaceType = 0; } @@ -26,6 +29,8 @@ AbstractInterface::AbstractInterface(AbstractBlock* _owner, const QString& _name type = typeFromString(_type); endianess = _endianess; associatedIface = NULL; + clkIface = ""; + clkIfaceType = 0; } AbstractInterface::AbstractInterface(AbstractInterface* other) { @@ -37,6 +42,8 @@ AbstractInterface::AbstractInterface(AbstractInterface* other) { purpose = other->purpose; endianess = LittleEndian; associatedIface = NULL; + clkIface = other->clkIface; + clkIfaceType = other->clkIfaceType; } void AbstractInterface::setName(const QString& _name) { @@ -59,6 +66,79 @@ bool AbstractInterface::isGroupInterface() { return false; } +int AbstractInterface::getWidth() { + + bool ok; + int w = -1; + + QString expr = width; + + /* CAUTION : + + Since VHDL allows to write std_logic_vector(O downto 0) + which is different from std_logic, we have to differentiate + a size of 1 that is really a boolean and thus a std_logic, from + a std_logic_vector of size 1. + + For this reason, if it is boolean, 0 is returned instead of 1. + */ + if (type == Boolean) { + return 0; + } + else if (type == Natural) { + w = width.toInt(&ok); + if (!ok) return -1; + } + else if (type == Expression) { + + QList listGenerics = owner->getGenericParameters(); + QList listUsers = owner->getUserParameters(); + QList listPorts = owner->getPortParameters(); + + foreach(BlockParameter* p, listUsers) { + QString var = "$"; + var += p->getName(); + if (width.contains(var)) { + int tmp = p->getValue().toInt(&ok); + if (!ok) return -1; // user parameter cannot be converted to an int + expr.replace(var,p->getValue().toString()); + } + } + foreach(BlockParameter* p, listPorts) { + QString var = "$"; + var += p->getName(); + if (width.contains(var)) { + expr.replace(var,p->toVHDL(0,0)); + } + } + foreach(BlockParameter* p, listGenerics) { + QString var = "$"; + var += p->getName(); + if (width.contains(var)) { + int tmp = p->getValue().toInt(&ok); + if (!ok) return -1; + QString s=""; + s.setNum(tmp); + expr.replace(var,s); + } + } + // now evaluate the whole expression + ArithmeticEvaluator evaluator; + + try { + evaluator.setVariableMarkers("$"); + evaluator.setExpression(expr); + w = (int)(evaluator.evaluate()); + cout << "iface size :" << w << endl; + } + catch(int e) { + cerr << "invalid expression in size of interface " << qPrintable(name) << " at character " << e << endl; + w = -1; + } + } + return w; +} + QString AbstractInterface::getEndianessString() { QString str="unknown"; switch(endianess){ @@ -113,36 +193,6 @@ QString AbstractInterface::getDirectionString() { return str; } -double AbstractInterface::getDoubleWidth() throw(QException) { - - static QString fctName = "AbstractInterface::getDoubleWidth()"; - #ifdef DEBUG_FCTNAME - cout << "call to " << qPrintable(fctName) << endl; - #endif - - /* - cout << "start AbstractInterface::getDoubleWidth()" << endl; - bool ok; - double width = getWidth().toDouble(&ok); - - if(!ok){ - ArithmeticEvaluator *evaluator = new ArithmeticEvaluator; - cout << "evaluator created!" << endl; - evaluator->setExpression(getWidth()); - cout << "expression defined!" << endl; - foreach(BlockParameter *param, getOwner()->getParameters()){ - evaluator->setVariableValue(param->getName(), param->getIntValue()); - cout << "param : " << param->getName().toStdString() << " evaluated!" << endl; - } - width = evaluator->evaluate(); - cout << "expression evaluated succefully!" << endl; - } - cout << "real width : " << width << endl; - return width; - */ - - return 1.0; -} void AbstractInterface::setPurpose(int _purpose) { if ((_purpose>=Data) && (_purpose <= Wishbone)) { @@ -164,6 +214,79 @@ bool AbstractInterface::setAssociatedIface(AbstractInterface* iface) { return true; } +AbstractInterface* AbstractInterface::getClockIface() { + if (clkIfaceType == ClockName) { + return owner->getIfaceFromName(clkIface); + } + return NULL; +} + + +double AbstractInterface::getClockFrequency() throw(Exception) { + + int idClock = -1; + + if (clkIfaceType == ParameterName) { + BlockParameter* param = owner->getParameterFromName(clkIface); + if (!param->isUserParameter()) throw(Exception(IFACE_INVALID_CLKFREQ,this)); + bool ok; + double freq = param->getDoubleValue(&ok); + if (!ok) throw(Exception(IFACE_INVALID_CLKFREQ,this)); + return freq; + } + else { + try { + idClock = getClockDomain(); + } + catch(Exception e) { + throw(e); + } + return owner->getGraph()->getClock(idClock); + } + return 0.0; +} + + +bool AbstractInterface::setClockIface(QString name) { + /* 2 cases : + * - this is a Data interface + * - this is a Clock output (from a clkrstgen) + * + * iface must correspond to an existing clock interface name + * or a user parameter prepend with a $. + */ + if ((purpose == Data) || ((purpose == Clock) && (direction == Output))) { + if (name.at(0) == '$') { + name.remove(0,1); + QList params = owner->getUserParameters(); + foreach(BlockParameter* p, params) { + if (p->getName() == name) { + clkIface = name; + clkIfaceType = ParameterName; + return true; + } + } + // error case: cannot found the input clock + return false; + } + else { + QList clocks = owner->getInterfaces(Input, Clock); + foreach(AbstractInterface* iface, clocks) { + if (iface->getName() == name) { + clkIface = name; + clkIfaceType = ClockName; + return true; + } + } + // error case: cannot found the user paramter + return false; + } + } + clkIface = ""; + clkIfaceType = NoName; + return true; +} + int AbstractInterface::getIntDirection(QString str) { if(str == "input") return Input; @@ -191,6 +314,9 @@ QString AbstractInterface::getTypeString() { else if (type == Expression) { return "expression"; } + else if (type == Inherited) { + return "inherited"; + } return "invalid_type"; } @@ -212,88 +338,150 @@ int AbstractInterface::typeFromString(const QString &_type) { return ret; } -QString AbstractInterface::toVHDL(int context, int flags) throw(Exception) { +QString AbstractInterface::toVHDL(IfaceVHDLContext context, int flags) throw(Exception) { if (isReferenceInterface()) throw(Exception(IFACE_INVALID_TYPE)); - QString msb = width; + int w; + QString wStr = ""; QString ret=""; - bool ok; - cout << "iface " << qPrintable(name) << " must be evaluated to vhdl :" << qPrintable(msb) << " with type = " << qPrintable(getTypeString()) << endl; - if ((context == BlockParameter::Entity) || (context == BlockParameter::Component)) { - - QString formatBool = "%1 : %2 std_logic"; - QString formatVector = ""; - if (endianess == LittleEndian) formatVector = "%1 : %2 std_logic_vector(%3 downto %4)"; - else formatVector = "%1 : %2 std_logic_vector(%4 to %3)"; + bool ok; + //cout << "iface " << qPrintable(name) << " must be evaluated to vhdl :" << qPrintable(width) << " with type = " << qPrintable(getTypeString()) << endl; - if ((flags & BlockParameter::NoComma) == 0) { - formatBool.append(";"); - formatVector.append(";"); - } - QString orientation=""; - if (direction == Input) { - orientation = "in"; + if (context == Instance) { + if (direction == Output) { + ret = "from_"+owner->getName()+"_"+name; } - else if (direction == Output) { - orientation = "out"; + else if (direction == InOut) { + ret = "fromto_"+owner->getName()+"_"+name; } - else { - orientation = "inout"; - } - if (type == Boolean) { - ret = formatBool.arg(name).arg(orientation); - } - else if (type == Natural) { - int w = width.toInt(&ok); + return ret; + } + + // create the width part + QString widthStr = ""; + if (type == Boolean) { + widthStr = "std_logic"; + } + else { + QString formatWidth = ""; + if (endianess == LittleEndian) formatWidth = "std_logic_vector(%1 downto %2)"; + else formatWidth = "std_logic_vector(%2 to %1)"; + + if (type == Natural) { + w = width.toInt(&ok); if (!ok) { throw(Exception(INVALID_VALUE)); } else { w -= 1; - ret = formatVector.arg(name).arg(orientation).arg(w).arg("0"); + wStr.setNum(w); + widthStr = formatWidth.arg(wStr).arg(0); } } else if (type == Expression) { - - /* must check the following conditions : - - if it contains user/port parameters : must evaluate their numeric value - - if it contains generic parameters : just remove the $ -> the expression is not arithmetically evaluated. - */ - QList listGenerics = owner->getGenericParameters(); - QList listUsers = owner->getUserParameters(); - QList listPorts = owner->getPortParameters(); - foreach(BlockParameter* p, listUsers) { - QString var = "$"; - var += p->getName(); - if (width.contains(var)) { - int w = p->getValue().toInt(&ok); - if (!ok) throw(Exception(INVALID_VALUE)); - msb.replace(var,p->getValue().toString()); + // NB: if for signal, must retrieve the real size, not the one with generics + if (context == Signal) { + w = getWidth(); + if (w == -1) throw(Exception(INVALID_VALUE)); + if (w == 0) { + widthStr = "std_logic"; } - } - foreach(BlockParameter* p, listPorts) { - QString var = "$"; - var += p->getName(); - if (width.contains(var)) { - msb.replace(var,p->toVHDL(0,0)); + else { + w--; + wStr.setNum(w); + widthStr = formatWidth.arg(wStr).arg(0); } } - foreach(BlockParameter* p, listGenerics) { - QString var = "$"; - var += p->getName(); - if (width.contains(var)) { - msb.replace(var,p->getName()); + else { + + /* must check the following conditions : + - if it contains user/port parameters : must evaluate their numeric value + - if it contains generic parameters : just remove the $ -> the expression is not arithmetically evaluated. + */ + wStr = width; + QList listGenerics = owner->getGenericParameters(); + QList listUsers = owner->getUserParameters(); + QList listPorts = owner->getPortParameters(); + foreach(BlockParameter* p, listUsers) { + QString var = "$"; + var += p->getName(); + if (width.contains(var)) { + w = p->getValue().toInt(&ok); + if (!ok) throw(Exception(INVALID_VALUE)); + wStr.replace(var,p->getValue().toString()); + } + } + foreach(BlockParameter* p, listPorts) { + QString var = "$"; + var += p->getName(); + if (width.contains(var)) { + wStr.replace(var,p->toVHDL(0,0)); + } + } + foreach(BlockParameter* p, listGenerics) { + QString var = "$"; + var += p->getName(); + if (width.contains(var)) { + wStr.replace(var,p->getName()); + } } + wStr += "-1"; + widthStr = formatWidth.arg(wStr).arg(0); } - msb += "-1"; - cout << "iface size :" << qPrintable(msb) << endl; - ret = formatVector.arg(name).arg(orientation).arg(msb).arg("0"); + } + else if (type == Inherited) { + w = getWidth(); + if (w == -1) throw(Exception(INVALID_VALUE)); + if (w == 0) { + widthStr = "std_logic"; + } + else { + w--; + wStr.setNum(w); + widthStr = formatWidth.arg(wStr).arg(0); + } + } + } + + if ((flags & NoComma) == 0) { + widthStr.append(";"); + } + + // generate for an Entity or Component port + if ((context == Entity) || (context == Component)) { + + QString formatPort = "%1 : %2 "; + + QString orientation=""; + if (direction == Input) { + orientation = "in"; + } + else if (direction == Output) { + orientation = "out"; + } + else { + orientation = "inout"; + } + + ret = formatPort.arg(name).arg(orientation); + ret += widthStr; + } + else if (context == Signal) { + if (direction == Output) { + ret = "from_"+owner->getName()+"_"+name+" : "+widthStr; + } + else if (direction == InOut) { + ret = "fromto_"+owner->getName()+"_"+name+" : "+widthStr; + } + else if (direction == Input) { + ret = owner->getName()+"_"+name+" : "+widthStr; } } + return ret; }