#include "AbstractInterface.h"
#include "BlockParameterPort.h"
#include "AbstractBlock.h"
+#include "Parameters.h"
AbstractInterface::AbstractInterface(AbstractBlock* _owner) {
name = "";
width = "1";
direction = Input;
- purpose = Data;
- level = Basic;
+ purpose = Data;
type = Boolean;
+ endianess = LittleEndian;
+ associatedIface = NULL;
}
-AbstractInterface::AbstractInterface(AbstractBlock* _owner, const QString& _name, const QString& _type, const QString& _width, int _direction, int _purpose, int _level) {
+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;
- level = _level;
- if (direction == InOut) {
- level = Top;
- }
type = typeFromString(_type);
+ endianess = _endianess;
+ associatedIface = NULL;
}
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;
- level = other->level;
+ endianess = LittleEndian;
+ associatedIface = NULL;
+}
+
+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;
}
-QString AbstractInterface::getLevelString() {
- QString str;
- switch(level){
- case AbstractInterface::Basic:
- str = QString("basic");
- break;
- case AbstractInterface::Top:
- str = QString("top");
- break;
- }
- return str;
-}
-
double AbstractInterface::getDoubleWidth() throw(QException) {
static QString fctName = "AbstractInterface::getDoubleWidth()";
if ((_direction > Input) && (_direction <= InOut)) {
direction = _direction;
}
- if (direction == InOut) {
- level = Top;
- }
}
-void AbstractInterface::setLevel(int _level) {
- if ((_level >= Basic) << (_level < Top)) {
- level = _level;
- }
- if (direction == InOut) {
- level = Top;
- }
+bool AbstractInterface::setAssociatedIface(AbstractInterface* iface) {
+ if (purpose != Control) return false;
+ if (iface->purpose != Data) return false;
+ associatedIface = iface;
+ iface->associatedIface = this;
+ return true;
}
-
-int AbstractInterface::getIntDirection(QString str)
-{
+int AbstractInterface::getIntDirection(QString str) {
if(str == "input") return Input;
if(str == "output") return Output;
- if(str == "inOut") return InOut;
+ if(str == "inout") return InOut;
return -1;
}
-int AbstractInterface::getIntLevel(QString str)
-{
- if(str == "basic") return Basic;
- if(str == "top") return Top;
+int AbstractInterface::getIntPurpose(QString str) {
+ if(str == "data") return Data;
+ else if(str == "clock") return Clock;
+ else if(str == "reset") return Reset;
+ else if(str == "wishbone") return Wishbone;
return -1;
}
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;
}
else if (_type == "natural") {
ret = Natural;
}
+ else if (_type == "inherited") {
+ ret = Inherited;
+ }
return ret;
}
QString AbstractInterface::toVHDL(int 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 (type == Boolean) {
- ret = formatVector.arg(name).arg(orientation);
- }
- else if (type == Natural) {
- int w = width.toInt(&ok);
+ // 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);
+ }
+ }
+ }
- ret = formatVector.arg(name).arg(orientation).arg("toto").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) {
+ ret = widthStr;
}
+ else if (context == Architecture) {
+
+ }
+
return ret;
}