#include "AbstractInterface.h"
#include "BlockParameterPort.h"
#include "AbstractBlock.h"
+#include "Parameters.h"
AbstractInterface::AbstractInterface(AbstractBlock* _owner) {
type = Boolean;
endianess = LittleEndian;
associatedIface = NULL;
+ clkIface = "";
+ clkIfaceType = 0;
}
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;
}
+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());
+ }
+ }
+ 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){
return true;
}
+AbstractInterface* AbstractInterface::getClockIface() {
+ if (clkIfaceType == ClockName) {
+ return owner->getIfaceFromName(clkIface);
+ }
+ return NULL;
+}
+
+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;
- 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";
- }
- else if (direction == Output) {
- orientation = "out";
- }
- else {
- orientation = "inout";
+ if (context == Instance) {
+ if (direction == Output) {
+ ret = "from_"+owner->getName()+"_"+name;
}
- if (type == Boolean) {
- ret = formatBool.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 += 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<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);
}
- msb += "-1";
- cout << "iface size :" << qPrintable(msb) << endl;
- ret = formatVector.arg(name).arg(orientation).arg(msb).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;
}