#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() {
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<BlockParameter*> listGenerics = owner->getGenericParameters();
+ QList<BlockParameter*> listUsers = owner->getUserParameters();
+ QList<BlockParameter*> 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() {
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)) {
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<BlockParameter* > 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<AbstractInterface*> 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;
else if (type == Expression) {
return "expression";
}
+ else if (type == Inherited) {
+ return "inherited";
+ }
return "invalid_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<BlockParameter*> listGenerics = owner->getGenericParameters();
- QList<BlockParameter*> listUsers = owner->getUserParameters();
- QList<BlockParameter*> 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<BlockParameter*> listGenerics = owner->getGenericParameters();
+ QList<BlockParameter*> listUsers = owner->getUserParameters();
+ QList<BlockParameter*> 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;
}