X-Git-Url: https://bilbo.iut-bm.univ-fcomte.fr/and/gitweb/blast.git/blobdiff_plain/48f48e6a26a54751ecd0ab90b10ab972cc5e89cd..4327c2b8817b627249d98d889835726217c81a4e:/AbstractInterface.cpp?ds=sidebyside diff --git a/AbstractInterface.cpp b/AbstractInterface.cpp index 49a937c..3fdd87a 100644 --- a/AbstractInterface.cpp +++ b/AbstractInterface.cpp @@ -1,38 +1,53 @@ #include "AbstractInterface.h" #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; purpose = Data; type = Boolean; + endianess = LittleEndian; associatedIface = NULL; + clkIface = ""; + clkIfaceType = 0; } -AbstractInterface::AbstractInterface(AbstractBlock* _owner, const QString& _name, const QString& _type, const QString& _width, int _direction, int _purpose) { +AbstractInterface::AbstractInterface(AbstractBlock* _owner, const QString& _name, int _direction, int _purpose, const QString& _type, const QString& _width, int _endianess) { owner = _owner; - name = _name; + name = Parameters::normalizeName(_name); width = _width; direction = _direction; purpose = _purpose; type = typeFromString(_type); + endianess = _endianess; associatedIface = NULL; + clkIface = ""; + clkIfaceType = 0; } AbstractInterface::AbstractInterface(AbstractInterface* other) { owner = NULL; - name = other->name; + name = Parameters::normalizeName(other->name); type = other->type; width = other->width; direction = other->direction; purpose = other->purpose; + endianess = LittleEndian; associatedIface = NULL; + clkIface = other->clkIface; + clkIfaceType = other->clkIfaceType; +} + +void AbstractInterface::setName(const QString& _name) { + name = Parameters::normalizeName(_name); } AbstractInterface::~AbstractInterface() { @@ -51,23 +66,115 @@ bool AbstractInterface::isGroupInterface() { return false; } -QString AbstractInterface::getPurposeString() { - QString str; - switch(purpose){ - case AbstractInterface::Data: - str = QString("data"); - break; - case AbstractInterface::Clock: - str = QString("clock"); - break; - case AbstractInterface::Reset: - str = QString("reset"); - break; - case AbstractInterface::Wishbone: - str = QString("wishbone"); - break; +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()); + } } - return str; + 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){ + case AbstractInterface::LittleEndian: + str = QString("little"); + break; + case AbstractInterface::BigEndian: + str = QString("big"); + break; + } + return str; +} + +QString AbstractInterface::getPurposeString() { + QString str; + switch(purpose){ + case AbstractInterface::AnyPurpose: + str = QString("any"); + break; + case AbstractInterface::Data: + str = QString("data"); + break; + case AbstractInterface::Control: + str = QString("control"); + break; + case AbstractInterface::Clock: + str = QString("clock"); + break; + case AbstractInterface::Reset: + str = QString("reset"); + break; + case AbstractInterface::Wishbone: + str = QString("wishbone"); + break; + } + return str; } QString AbstractInterface::getDirectionString() { @@ -86,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)) { @@ -137,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; @@ -164,12 +314,15 @@ QString AbstractInterface::getTypeString() { else if (type == Expression) { return "expression"; } + else if (type == Inherited) { + return "inherited"; + } return "invalid_type"; } int AbstractInterface::typeFromString(const QString &_type) { - int ret; + int ret = Expression; // default type if (_type == "expression") { ret = Expression; } @@ -185,77 +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; - if ((context == BlockParameter::Entity) || (context == BlockParameter::Component)) { + //cout << "iface " << qPrintable(name) << " must be evaluated to vhdl :" << qPrintable(width) << " with type = " << qPrintable(getTypeString()) << endl; - QString formatBool = "%1 : %2 std_logic"; - QString formatVector = "%1 : %2 std_logic_vector(%3 downto %4)"; - if ((flags & BlockParameter::NoComma) == 0) { - formatBool.append(";"); - formatVector.append(";"); - } - QString orientation=""; - if (direction == Input) { - orientation = "in"; - } - else if (direction == Output) { - orientation = "out"; - } - else { - orientation = "inout"; + if (context == Instance) { + if (direction == Output) { + ret = "from_"+owner->getName()+"_"+name; } - if (type == Boolean) { - ret = formatVector.arg(name).arg(orientation); + else if (direction == InOut) { + ret = "fromto_"+owner->getName()+"_"+name; } - 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.append(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"; + } + else { + w--; + wStr.setNum(w); + widthStr = formatWidth.arg(wStr).arg(0); } } - foreach(BlockParameter* p, listPorts) { - QString var = "$"; - var.append(p->getName()); - if (width.contains(var)) { - BlockParameterPort* pp = (BlockParameterPort*)p; - AbstractInterface* iface = owner->getIfaceFromName(pp->getIfaceName()); - - int w = p->getValue().toInt(&ok); - if (!ok) throw(Exception(INVALID_VALUE)); - msb.replace(var,p->getValue().toString()); + 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); + } + } + 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(";"); + } - ret = formatVector.arg(name).arg(orientation).arg("toto").arg("0"); + // 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; }