Internals: Refactor input/output to new class in prep for ref support.
This commit is contained in:
parent
dc26815b1c
commit
b8098098d8
81
src/V3Ast.h
81
src/V3Ast.h
|
|
@ -464,18 +464,56 @@ public:
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
|
|
||||||
|
class VDirection {
|
||||||
|
public:
|
||||||
|
enum en {
|
||||||
|
NONE,
|
||||||
|
INPUT,
|
||||||
|
OUTPUT,
|
||||||
|
INOUT
|
||||||
|
};
|
||||||
|
enum en m_e;
|
||||||
|
inline VDirection() : m_e(NONE) {}
|
||||||
|
// cppcheck-suppress noExplicitConstructor
|
||||||
|
inline VDirection(en _e) : m_e(_e) {}
|
||||||
|
explicit inline VDirection(int _e) : m_e(static_cast<en>(_e)) {}
|
||||||
|
operator en() const { return m_e; }
|
||||||
|
const char* ascii() const {
|
||||||
|
static const char* const names[] = {
|
||||||
|
"NONE", "INPUT", "OUTPUT", "INOUT"};
|
||||||
|
return names[m_e]; }
|
||||||
|
string verilogKwd() const {
|
||||||
|
static const char* const names[] = {
|
||||||
|
"", "input", "output", "inout"};
|
||||||
|
return names[m_e]; }
|
||||||
|
string xmlKwd() const { // For historical reasons no "put" suffix
|
||||||
|
static const char* const names[] = {
|
||||||
|
"", "in", "out", "inout"};
|
||||||
|
return names[m_e]; }
|
||||||
|
string prettyName() const { return verilogKwd(); }
|
||||||
|
bool isAny() const { return m_e != NONE; }
|
||||||
|
// Looks like inout - "ish" because not identical to being an INOUT
|
||||||
|
bool isInoutish() const { return m_e == INOUT; }
|
||||||
|
bool isNonOutput() const { return m_e == INPUT || m_e == INOUT; }
|
||||||
|
bool isReadOnly() const { return m_e == INPUT; }
|
||||||
|
bool isWritable() const { return m_e == OUTPUT || m_e == INOUT; }
|
||||||
|
};
|
||||||
|
inline bool operator== (VDirection lhs, VDirection rhs) { return (lhs.m_e == rhs.m_e); }
|
||||||
|
inline bool operator== (VDirection lhs, VDirection::en rhs) { return (lhs.m_e == rhs); }
|
||||||
|
inline bool operator== (VDirection::en lhs, VDirection rhs) { return (lhs == rhs.m_e); }
|
||||||
|
inline std::ostream& operator<<(std::ostream& os, const VDirection& rhs) { return os<<rhs.ascii(); }
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
|
||||||
class AstVarType {
|
class AstVarType {
|
||||||
public:
|
public:
|
||||||
enum en {
|
enum en {
|
||||||
UNKNOWN,
|
UNKNOWN,
|
||||||
GPARAM,
|
GPARAM,
|
||||||
LPARAM,
|
LPARAM,
|
||||||
GENVAR,
|
GENVAR,
|
||||||
VAR, // Reg, integer, logic, etc
|
VAR, // Reg, integer, logic, etc
|
||||||
INPUT,
|
SUPPLY0,
|
||||||
OUTPUT,
|
|
||||||
INOUT,
|
|
||||||
SUPPLY0,
|
|
||||||
SUPPLY1,
|
SUPPLY1,
|
||||||
WIRE,
|
WIRE,
|
||||||
WREAL,
|
WREAL,
|
||||||
|
|
@ -497,20 +535,19 @@ public:
|
||||||
explicit inline AstVarType(int _e) : m_e(static_cast<en>(_e)) {}
|
explicit inline AstVarType(int _e) : m_e(static_cast<en>(_e)) {}
|
||||||
operator en() const { return m_e; }
|
operator en() const { return m_e; }
|
||||||
const char* ascii() const {
|
const char* ascii() const {
|
||||||
static const char* const names[] = {
|
static const char* const names[] = {
|
||||||
"?","GPARAM","LPARAM","GENVAR",
|
"?", "GPARAM", "LPARAM", "GENVAR", "VAR",
|
||||||
"VAR","INPUT","OUTPUT","INOUT",
|
"SUPPLY0", "SUPPLY1", "WIRE", "WREAL", "IMPLICITWIRE",
|
||||||
"SUPPLY0","SUPPLY1","WIRE","WREAL","IMPLICITWIRE",
|
"TRIWIRE", "TRI0", "TRI1",
|
||||||
"TRIWIRE","TRI0","TRI1",
|
"PORT",
|
||||||
"PORT",
|
"BLOCKTEMP", "MODULETEMP", "STMTTEMP", "XTEMP",
|
||||||
"BLOCKTEMP","MODULETEMP","STMTTEMP","XTEMP",
|
"IFACEREF"};
|
||||||
"IFACEREF"};
|
return names[m_e]; }
|
||||||
return names[m_e]; }
|
|
||||||
bool isSignal() const { return (m_e==WIRE || m_e==WREAL || m_e==IMPLICITWIRE
|
bool isSignal() const { return (m_e==WIRE || m_e==WREAL || m_e==IMPLICITWIRE
|
||||||
|| m_e==TRIWIRE
|
|| m_e==TRIWIRE
|
||||||
|| m_e==TRI0 || m_e==TRI1
|
|| m_e==TRI0 || m_e==TRI1 || m_e==PORT
|
||||||
|| m_e==SUPPLY0 || m_e==SUPPLY1
|
|| m_e==SUPPLY0 || m_e==SUPPLY1
|
||||||
|| m_e==VAR); }
|
|| m_e==VAR); }
|
||||||
};
|
};
|
||||||
inline bool operator== (AstVarType lhs, AstVarType rhs) { return (lhs.m_e == rhs.m_e); }
|
inline bool operator== (AstVarType lhs, AstVarType rhs) { return (lhs.m_e == rhs.m_e); }
|
||||||
inline bool operator== (AstVarType lhs, AstVarType::en rhs) { return (lhs.m_e == rhs); }
|
inline bool operator== (AstVarType lhs, AstVarType::en rhs) { return (lhs.m_e == rhs); }
|
||||||
|
|
|
||||||
|
|
@ -178,40 +178,30 @@ void AstVar::combineType(AstVarType type) {
|
||||||
// These flags get combined with the existing settings of the flags.
|
// These flags get combined with the existing settings of the flags.
|
||||||
// We don't test varType for certain types, instead set flags since
|
// We don't test varType for certain types, instead set flags since
|
||||||
// when we combine wires cross-hierarchy we need a union of all characteristics.
|
// when we combine wires cross-hierarchy we need a union of all characteristics.
|
||||||
m_varType=type; // For debugging prints only
|
m_varType = type;
|
||||||
// These flags get combined with the existing settings of the flags.
|
// These flags get combined with the existing settings of the flags.
|
||||||
if (type==AstVarType::INPUT || type==AstVarType::INOUT) {
|
if (type==AstVarType::TRIWIRE || type==AstVarType::TRI0 || type==AstVarType::TRI1) {
|
||||||
m_input = true;
|
m_tristate = true;
|
||||||
m_declInput = true;
|
|
||||||
}
|
}
|
||||||
if (type==AstVarType::OUTPUT || type==AstVarType::INOUT) {
|
if (type==AstVarType::TRI0) {
|
||||||
m_output = true;
|
m_isPulldown = true;
|
||||||
m_declOutput = true;
|
}
|
||||||
|
if (type==AstVarType::TRI1) {
|
||||||
|
m_isPullup = true;
|
||||||
}
|
}
|
||||||
if (type==AstVarType::INOUT || type==AstVarType::TRIWIRE
|
|
||||||
|| type==AstVarType::TRI0 || type==AstVarType::TRI1)
|
|
||||||
m_tristate = true;
|
|
||||||
if (type==AstVarType::TRI0)
|
|
||||||
m_isPulldown = true;
|
|
||||||
if (type==AstVarType::TRI1)
|
|
||||||
m_isPullup = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string AstVar::verilogKwd() const {
|
string AstVar::verilogKwd() const {
|
||||||
if (isInout()) {
|
if (isIO()) {
|
||||||
return "inout";
|
return direction().verilogKwd();
|
||||||
} else if (isInput()) {
|
|
||||||
return "input";
|
|
||||||
} else if (isOutput()) {
|
|
||||||
return "output";
|
|
||||||
} else if (isTristate()) {
|
} else if (isTristate()) {
|
||||||
return "tri";
|
return "tri";
|
||||||
} else if (varType()==AstVarType::WIRE) {
|
} else if (varType()==AstVarType::WIRE) {
|
||||||
return "wire";
|
return "wire";
|
||||||
} else if (varType()==AstVarType::WREAL) {
|
} else if (varType()==AstVarType::WREAL) {
|
||||||
return "wreal";
|
return "wreal";
|
||||||
} else {
|
} else {
|
||||||
return dtypep()->name();
|
return dtypep()->name();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -219,7 +209,7 @@ string AstVar::vlArgType(bool named, bool forReturn, bool forFunc) const {
|
||||||
if (forReturn) named=false;
|
if (forReturn) named=false;
|
||||||
if (forReturn) v3fatalSrc("verilator internal data is never passed as return, but as first argument");
|
if (forReturn) v3fatalSrc("verilator internal data is never passed as return, but as first argument");
|
||||||
string arg;
|
string arg;
|
||||||
if (isWide() && isInOnly()) arg += "const ";
|
if (isWide() && isReadOnly()) arg += "const ";
|
||||||
AstBasicDType* bdtypep = basicp();
|
AstBasicDType* bdtypep = basicp();
|
||||||
bool strtype = bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::STRING;
|
bool strtype = bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::STRING;
|
||||||
if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::CHARPTR) {
|
if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::CHARPTR) {
|
||||||
|
|
@ -231,8 +221,8 @@ string AstVar::vlArgType(bool named, bool forReturn, bool forFunc) const {
|
||||||
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::FLOAT) {
|
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::FLOAT) {
|
||||||
arg += "float";
|
arg += "float";
|
||||||
} else if (strtype) {
|
} else if (strtype) {
|
||||||
if (isInOnly()) arg += "const ";
|
if (isReadOnly()) arg += "const ";
|
||||||
arg += "std::string";
|
arg += "std::string";
|
||||||
} else if (widthMin() <= 8) {
|
} else if (widthMin() <= 8) {
|
||||||
arg += "CData";
|
arg += "CData";
|
||||||
} else if (widthMin() <= 16) {
|
} else if (widthMin() <= 16) {
|
||||||
|
|
@ -257,8 +247,9 @@ string AstVar::vlArgType(bool named, bool forReturn, bool forFunc) const {
|
||||||
arg += "["+cvtToStr(widthWords())+"]";
|
arg += "["+cvtToStr(widthWords())+"]";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (forFunc && (isOutput() || (strtype && isInput()))) arg += "&";
|
if (forFunc && (isWritable()
|
||||||
if (named) arg += " "+name();
|
|| (strtype && isNonOutput()))) arg += "&";
|
||||||
|
if (named) arg += " "+name();
|
||||||
}
|
}
|
||||||
return arg;
|
return arg;
|
||||||
}
|
}
|
||||||
|
|
@ -290,12 +281,12 @@ string AstVar::vlEnumType() const {
|
||||||
|
|
||||||
string AstVar::vlEnumDir() const {
|
string AstVar::vlEnumDir() const {
|
||||||
string out;
|
string out;
|
||||||
if (isInout()) {
|
if (isInoutish()) {
|
||||||
out = "VLVD_INOUT";
|
out = "VLVD_INOUT";
|
||||||
} else if (isInOnly()) {
|
} else if (isWritable()) {
|
||||||
out = "VLVD_IN";
|
|
||||||
} else if (isOutOnly()) {
|
|
||||||
out = "VLVD_OUT";
|
out = "VLVD_OUT";
|
||||||
|
} else if (isNonOutput()) {
|
||||||
|
out = "VLVD_IN";
|
||||||
} else {
|
} else {
|
||||||
out = "VLVD_NODIR";
|
out = "VLVD_NODIR";
|
||||||
}
|
}
|
||||||
|
|
@ -336,7 +327,7 @@ string AstVar::vlPropInit() const {
|
||||||
string AstVar::cPubArgType(bool named, bool forReturn) const {
|
string AstVar::cPubArgType(bool named, bool forReturn) const {
|
||||||
if (forReturn) named=false;
|
if (forReturn) named=false;
|
||||||
string arg;
|
string arg;
|
||||||
if (isWide() && isInOnly()) arg += "const ";
|
if (isWide() && isReadOnly()) arg += "const ";
|
||||||
if (widthMin() == 1) {
|
if (widthMin() == 1) {
|
||||||
arg += "bool";
|
arg += "bool";
|
||||||
} else if (widthMin() <= VL_WORDSIZE) {
|
} else if (widthMin() <= VL_WORDSIZE) {
|
||||||
|
|
@ -351,8 +342,8 @@ string AstVar::cPubArgType(bool named, bool forReturn) const {
|
||||||
arg += " (& "+name();
|
arg += " (& "+name();
|
||||||
arg += ")["+cvtToStr(widthWords())+"]";
|
arg += ")["+cvtToStr(widthWords())+"]";
|
||||||
} else {
|
} else {
|
||||||
if (isOutput() && !forReturn) arg += "&";
|
if (!forReturn && isWritable()) arg += "&";
|
||||||
if (named) arg += " "+name();
|
if (named) arg += " "+name();
|
||||||
}
|
}
|
||||||
return arg;
|
return arg;
|
||||||
}
|
}
|
||||||
|
|
@ -367,11 +358,11 @@ string AstVar::dpiArgType(bool named, bool forReturn) const {
|
||||||
} else if (basicp()->keyword().isDpiBitVal()) {
|
} else if (basicp()->keyword().isDpiBitVal()) {
|
||||||
if (widthMin() == 1) {
|
if (widthMin() == 1) {
|
||||||
arg = "unsigned char";
|
arg = "unsigned char";
|
||||||
if (!forReturn && isOutput()) arg += "*";
|
if (!forReturn && isWritable()) arg += "*";
|
||||||
} else {
|
} else {
|
||||||
if (forReturn) {
|
if (forReturn) {
|
||||||
arg = "svBitVecVal";
|
arg = "svBitVecVal";
|
||||||
} else if (isInOnly()) {
|
} else if (isReadOnly()) {
|
||||||
arg = "const svBitVecVal*";
|
arg = "const svBitVecVal*";
|
||||||
} else {
|
} else {
|
||||||
arg = "svBitVecVal*";
|
arg = "svBitVecVal*";
|
||||||
|
|
@ -380,11 +371,11 @@ string AstVar::dpiArgType(bool named, bool forReturn) const {
|
||||||
} else if (basicp()->keyword().isDpiLogicVal()) {
|
} else if (basicp()->keyword().isDpiLogicVal()) {
|
||||||
if (widthMin() == 1) {
|
if (widthMin() == 1) {
|
||||||
arg = "unsigned char";
|
arg = "unsigned char";
|
||||||
if (!forReturn && isOutput()) arg += "*";
|
if (!forReturn && isWritable()) arg += "*";
|
||||||
} else {
|
} else {
|
||||||
if (forReturn) {
|
if (forReturn) {
|
||||||
arg = "svLogicVecVal";
|
arg = "svLogicVecVal";
|
||||||
} else if (isInOnly()) {
|
} else if (isReadOnly()) {
|
||||||
arg = "const svLogicVecVal*";
|
arg = "const svLogicVecVal*";
|
||||||
} else {
|
} else {
|
||||||
arg = "svLogicVecVal*";
|
arg = "svLogicVecVal*";
|
||||||
|
|
@ -394,8 +385,8 @@ string AstVar::dpiArgType(bool named, bool forReturn) const {
|
||||||
arg = basicp()->keyword().dpiType();
|
arg = basicp()->keyword().dpiType();
|
||||||
if (basicp()->keyword().isDpiUnsignable() && !basicp()->isSigned()) {
|
if (basicp()->keyword().isDpiUnsignable() && !basicp()->isSigned()) {
|
||||||
arg = "unsigned "+arg;
|
arg = "unsigned "+arg;
|
||||||
}
|
}
|
||||||
if (!forReturn && isOutput()) arg += "*";
|
if (!forReturn && isWritable()) arg += "*";
|
||||||
}
|
}
|
||||||
if (named) arg += " "+name();
|
if (named) arg += " "+name();
|
||||||
return arg;
|
return arg;
|
||||||
|
|
@ -898,7 +889,7 @@ void AstModportFTaskRef::dump(std::ostream& str) {
|
||||||
}
|
}
|
||||||
void AstModportVarRef::dump(std::ostream& str) {
|
void AstModportVarRef::dump(std::ostream& str) {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
str<<" "<<varType();
|
if (direction().isAny()) str<<" "<<direction();
|
||||||
if (varp()) { str<<" -> "; varp()->dump(str); }
|
if (varp()) { str<<" -> "; varp()->dump(str); }
|
||||||
else { str<<" -> UNLINKED"; }
|
else { str<<" -> UNLINKED"; }
|
||||||
}
|
}
|
||||||
|
|
@ -1061,12 +1052,8 @@ void AstVarRef::dump(std::ostream& str) {
|
||||||
void AstVar::dump(std::ostream& str) {
|
void AstVar::dump(std::ostream& str) {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
if (isSc()) str<<" [SC]";
|
if (isSc()) str<<" [SC]";
|
||||||
if (isPrimaryIO()) str<<(isInout()?" [PIO]":(isInput()?" [PI]":" [PO]"));
|
if (isPrimaryIO()) str<<(isInoutish()?" [PIO]":(isWritable()?" [PO]":" [PI]"));
|
||||||
else {
|
if (isIO()) str<<" "<<direction().ascii();
|
||||||
if (isInout()) str<<" [IO]";
|
|
||||||
else if (isInput()) str<<" [I]";
|
|
||||||
else if (isOutput()) str<<" [O]";
|
|
||||||
}
|
|
||||||
if (isConst()) str<<" [CONST]";
|
if (isConst()) str<<" [CONST]";
|
||||||
if (isPullup()) str<<" [PULLUP]";
|
if (isPullup()) str<<" [PULLUP]";
|
||||||
if (isPulldown()) str<<" [PULLDOWN]";
|
if (isPulldown()) str<<" [PULLDOWN]";
|
||||||
|
|
|
||||||
|
|
@ -1096,12 +1096,10 @@ private:
|
||||||
string m_origName; // Original name before dot addition
|
string m_origName; // Original name before dot addition
|
||||||
string m_tag; // Holds the string of the verilator tag -- used in XML output.
|
string m_tag; // Holds the string of the verilator tag -- used in XML output.
|
||||||
AstVarType m_varType; // Type of variable
|
AstVarType m_varType; // Type of variable
|
||||||
|
VDirection m_direction; // Direction input/output etc
|
||||||
|
VDirection m_declDirection; // Declared direction input/output etc
|
||||||
AstBasicDTypeKwd m_declKwd; // Keyword at declaration time
|
AstBasicDTypeKwd m_declKwd; // Keyword at declaration time
|
||||||
bool m_input:1; // Input or inout
|
|
||||||
bool m_output:1; // Output or inout
|
|
||||||
bool m_tristate:1; // Inout or triwire or trireg
|
bool m_tristate:1; // Inout or triwire or trireg
|
||||||
bool m_declInput:1; // Inout or input before tristate and inline resolution
|
|
||||||
bool m_declOutput:1; // Inout or output before tristate and inline resolution
|
|
||||||
bool m_primaryIO:1; // In/out to top level (or directly assigned from same)
|
bool m_primaryIO:1; // In/out to top level (or directly assigned from same)
|
||||||
bool m_sc:1; // SystemC variable
|
bool m_sc:1; // SystemC variable
|
||||||
bool m_scClocked:1; // SystemC sc_clk<> needed
|
bool m_scClocked:1; // SystemC sc_clk<> needed
|
||||||
|
|
@ -1132,10 +1130,9 @@ private:
|
||||||
AstVarAttrClocker m_attrClocker;
|
AstVarAttrClocker m_attrClocker;
|
||||||
MTaskIdSet m_mtaskIds; // MTaskID's that read or write this var
|
MTaskIdSet m_mtaskIds; // MTaskID's that read or write this var
|
||||||
|
|
||||||
void init() {
|
void init() {
|
||||||
m_input=false; m_output=false; m_tristate=false; m_declInput=false; m_declOutput=false;
|
m_tristate=false; m_primaryIO=false;
|
||||||
m_primaryIO=false;
|
m_sc=false; m_scClocked=false; m_scSensitive=false;
|
||||||
m_sc=false; m_scClocked=false; m_scSensitive=false;
|
|
||||||
m_usedClock=false; m_usedParam=false; m_usedLoopIdx=false;
|
m_usedClock=false; m_usedParam=false; m_usedLoopIdx=false;
|
||||||
m_sigPublic=false; m_sigModPublic=false; m_sigUserRdPublic=false; m_sigUserRWPublic=false;
|
m_sigPublic=false; m_sigModPublic=false; m_sigUserRdPublic=false; m_sigUserRWPublic=false;
|
||||||
m_funcLocal=false; m_funcReturn=false;
|
m_funcLocal=false; m_funcReturn=false;
|
||||||
|
|
@ -1201,9 +1198,16 @@ public:
|
||||||
string origName() const { return m_origName; } // * = Original name
|
string origName() const { return m_origName; } // * = Original name
|
||||||
void origName(const string& name) { m_origName = name; }
|
void origName(const string& name) { m_origName = name; }
|
||||||
AstVarType varType() const { return m_varType; } // * = Type of variable
|
AstVarType varType() const { return m_varType; } // * = Type of variable
|
||||||
|
void direction(const VDirection& flag) {
|
||||||
|
m_direction = flag;
|
||||||
|
if (m_direction == VDirection::INOUT) m_tristate = true; }
|
||||||
|
VDirection direction() const { return m_direction; }
|
||||||
|
bool isIO() const { return m_direction != VDirection::NONE; }
|
||||||
|
void declDirection(const VDirection& flag) { m_declDirection = flag; }
|
||||||
|
VDirection declDirection() const { return m_declDirection; }
|
||||||
void varType(AstVarType type) { m_varType = type; }
|
void varType(AstVarType type) { m_varType = type; }
|
||||||
void varType2Out() { m_tristate=0; m_input=0; m_output=1; }
|
void varType2Out() { m_tristate=0; m_direction=VDirection::OUTPUT; }
|
||||||
void varType2In() { m_tristate=0; m_input=1; m_output=0; }
|
void varType2In() { m_tristate=0; m_direction=VDirection::INPUT; }
|
||||||
AstBasicDTypeKwd declKwd() const { return m_declKwd; }
|
AstBasicDTypeKwd declKwd() const { return m_declKwd; }
|
||||||
string scType() const; // Return SysC type: bool, uint32_t, uint64_t, sc_bv
|
string scType() const; // Return SysC type: bool, uint32_t, uint64_t, sc_bv
|
||||||
string cPubArgType(bool named, bool forReturn) const; // Return C /*public*/ type for argument: bool, uint32_t, uint64_t, etc.
|
string cPubArgType(bool named, bool forReturn) const; // Return C /*public*/ type for argument: bool, uint32_t, uint64_t, etc.
|
||||||
|
|
@ -1258,19 +1262,13 @@ public:
|
||||||
virtual void name(const string& name) { m_name = name; }
|
virtual void name(const string& name) { m_name = name; }
|
||||||
virtual void tag(const string& text) { m_tag = text;}
|
virtual void tag(const string& text) { m_tag = text;}
|
||||||
virtual string tag() const { return m_tag; }
|
virtual string tag() const { return m_tag; }
|
||||||
virtual string directionName() const { return (isInout() ? "inout" : isInput() ? "input"
|
bool isInoutish() const { return m_direction.isInoutish(); }
|
||||||
: isOutput() ? "output" : varType().ascii()); }
|
bool isNonOutput() const { return m_direction.isNonOutput(); }
|
||||||
bool isInput() const { return m_input; }
|
bool isReadOnly() const { return m_direction.isReadOnly(); }
|
||||||
bool isOutput() const { return m_output; }
|
bool isWritable() const { return m_direction.isWritable(); }
|
||||||
bool isInOnly() const { return m_input && !m_output; }
|
|
||||||
bool isOutOnly() const { return m_output && !m_input; }
|
|
||||||
bool isInout() const { return m_input && m_output; }
|
|
||||||
bool isTristate() const { return m_tristate; }
|
bool isTristate() const { return m_tristate; }
|
||||||
bool isDeclInput() const { return m_declInput; }
|
bool isPrimaryIO() const { return m_primaryIO; }
|
||||||
bool isDeclOutput() const { return m_declOutput; }
|
bool isPrimaryInish() const { return isPrimaryIO() && isNonOutput(); }
|
||||||
bool isPrimaryIO() const { return m_primaryIO; }
|
|
||||||
bool isPrimaryIn() const { return isPrimaryIO() && isInput(); }
|
|
||||||
bool isIO() const { return (m_input||m_output); }
|
|
||||||
bool isIfaceRef() const { return (varType()==AstVarType::IFACEREF); }
|
bool isIfaceRef() const { return (varType()==AstVarType::IFACEREF); }
|
||||||
bool isIfaceParent() const { return m_isIfaceParent; }
|
bool isIfaceParent() const { return m_isIfaceParent; }
|
||||||
bool isSignal() const { return varType().isSignal(); }
|
bool isSignal() const { return varType().isSignal(); }
|
||||||
|
|
@ -1326,8 +1324,9 @@ public:
|
||||||
// Ok to gate optimize; must return false if propagateAttrFrom would do anything
|
// Ok to gate optimize; must return false if propagateAttrFrom would do anything
|
||||||
return (!attrClockEn() && !isUsedClock());
|
return (!attrClockEn() && !isUsedClock());
|
||||||
}
|
}
|
||||||
void combineType(AstVar* typevarp) {
|
void combineType(AstVar* typevarp) {
|
||||||
// This is same as typevarp (for combining input & reg decls)
|
// This is same as typevarp (for combining input & reg decls)
|
||||||
|
// "this" is the input var. typevarp is the reg var.
|
||||||
propagateAttrFrom(typevarp);
|
propagateAttrFrom(typevarp);
|
||||||
combineType(typevarp->varType());
|
combineType(typevarp->varType());
|
||||||
if (typevarp->isSigPublic()) sigPublic(true);
|
if (typevarp->isSigPublic()) sigPublic(true);
|
||||||
|
|
@ -1337,9 +1336,11 @@ public:
|
||||||
if (typevarp->attrScClocked()) attrScClocked(true);
|
if (typevarp->attrScClocked()) attrScClocked(true);
|
||||||
}
|
}
|
||||||
void inlineAttrReset(const string& name) {
|
void inlineAttrReset(const string& name) {
|
||||||
m_input=m_output=false; m_name = name;
|
if (direction()==VDirection::INOUT && varType()==AstVarType::WIRE) {
|
||||||
if (varType()==AstVarType::INOUT) m_varType = AstVarType::TRIWIRE;
|
m_varType = AstVarType::TRIWIRE;
|
||||||
if (varType()==AstVarType::INPUT || varType()==AstVarType::OUTPUT) m_varType = AstVarType::WIRE;
|
}
|
||||||
|
m_direction = VDirection::NONE;
|
||||||
|
m_name = name;
|
||||||
}
|
}
|
||||||
static AstVar* scVarRecurse(AstNode* nodep);
|
static AstVar* scVarRecurse(AstNode* nodep);
|
||||||
void addProducingMTaskId(int id) { m_mtaskIds.insert(id); }
|
void addProducingMTaskId(int id) { m_mtaskIds.insert(id); }
|
||||||
|
|
@ -1577,10 +1578,13 @@ public:
|
||||||
return NULL; }
|
return NULL; }
|
||||||
virtual string name() const { return m_name; } // * = Pin name, ""=go by number
|
virtual string name() const { return m_name; } // * = Pin name, ""=go by number
|
||||||
virtual void name(const string& name) { m_name = name; }
|
virtual void name(const string& name) { m_name = name; }
|
||||||
virtual string prettyOperatorName() const { return modVarp()
|
virtual string prettyOperatorName() const {
|
||||||
? (modVarp()->directionName()+" port connection '"+modVarp()->prettyName()+"'")
|
return modVarp() ? ((modVarp()->direction().isAny()
|
||||||
: "port connection"; }
|
? modVarp()->direction().prettyName()+" "
|
||||||
bool dotStar() const { return name() == ".*"; } // Special fake name for .* connections until linked
|
: "")
|
||||||
|
+"port connection '"+modVarp()->prettyName()+"'")
|
||||||
|
: "port connection"; }
|
||||||
|
bool dotStar() const { return name() == ".*"; } // Fake name for .* connections until linked
|
||||||
int pinNum() const { return m_pinNum; }
|
int pinNum() const { return m_pinNum; }
|
||||||
void exprp(AstNode* nodep) { addOp1p(nodep); }
|
void exprp(AstNode* nodep) { addOp1p(nodep); }
|
||||||
AstNode* exprp() const { return op1p(); } // op1 = Expression connected to pin, NULL if unconnected
|
AstNode* exprp() const { return op1p(); } // op1 = Expression connected to pin, NULL if unconnected
|
||||||
|
|
@ -1730,19 +1734,18 @@ class AstModportVarRef : public AstNode {
|
||||||
// PARENT: AstModport
|
// PARENT: AstModport
|
||||||
private:
|
private:
|
||||||
string m_name; // Name of the variable referenced
|
string m_name; // Name of the variable referenced
|
||||||
AstVarType m_type; // Type of the variable (in/out)
|
VDirection m_direction; // Direction of the variable (in/out)
|
||||||
AstVar* m_varp; // Link to the actual Var
|
AstVar* m_varp; // Link to the actual Var
|
||||||
public:
|
public:
|
||||||
AstModportVarRef(FileLine* fl, const string& name, AstVarType::en type)
|
AstModportVarRef(FileLine* fl, const string& name, VDirection::en direction)
|
||||||
: AstNode(fl), m_name(name), m_type(type), m_varp(NULL) { }
|
: AstNode(fl), m_name(name), m_direction(direction), m_varp(NULL) { }
|
||||||
ASTNODE_NODE_FUNCS(ModportVarRef)
|
ASTNODE_NODE_FUNCS(ModportVarRef)
|
||||||
virtual const char* broken() const { BROKEN_RTN(m_varp && !m_varp->brokeExists()); return NULL; }
|
virtual const char* broken() const { BROKEN_RTN(m_varp && !m_varp->brokeExists()); return NULL; }
|
||||||
virtual void dump(std::ostream& str);
|
virtual void dump(std::ostream& str);
|
||||||
virtual void cloneRelink() { if (m_varp && m_varp->clonep()) m_varp = m_varp->clonep(); }
|
virtual void cloneRelink() { if (m_varp && m_varp->clonep()) m_varp = m_varp->clonep(); }
|
||||||
virtual string name() const { return m_name; }
|
virtual string name() const { return m_name; }
|
||||||
AstVarType varType() const { return m_type; } // * = Type of variable
|
void direction(const VDirection& flag) { m_direction = flag; }
|
||||||
bool isInput() const { return (varType()==AstVarType::INPUT || varType()==AstVarType::INOUT); }
|
VDirection direction() const { return m_direction; }
|
||||||
bool isOutput() const { return (varType()==AstVarType::OUTPUT || varType()==AstVarType::INOUT); }
|
|
||||||
AstVar* varp() const { return m_varp; } // [After Link] Pointer to variable
|
AstVar* varp() const { return m_varp; } // [After Link] Pointer to variable
|
||||||
void varp(AstVar* varp) { m_varp=varp; }
|
void varp(AstVar* varp) { m_varp=varp; }
|
||||||
};
|
};
|
||||||
|
|
@ -3367,8 +3370,7 @@ private:
|
||||||
uint32_t m_codeInc; // Code increment
|
uint32_t m_codeInc; // Code increment
|
||||||
AstVarType m_varType; // Type of variable (for localparam vs. param)
|
AstVarType m_varType; // Type of variable (for localparam vs. param)
|
||||||
AstBasicDTypeKwd m_declKwd; // Keyword at declaration time
|
AstBasicDTypeKwd m_declKwd; // Keyword at declaration time
|
||||||
bool m_declInput:1; // Input or inout
|
VDirection m_declDirection; // Declared direction input/output etc
|
||||||
bool m_declOutput:1; // Output or inout
|
|
||||||
public:
|
public:
|
||||||
AstTraceDecl(FileLine* fl, const string& showname,
|
AstTraceDecl(FileLine* fl, const string& showname,
|
||||||
AstVar* varp, // For input/output state etc
|
AstVar* varp, // For input/output state etc
|
||||||
|
|
@ -3382,8 +3384,7 @@ public:
|
||||||
* valuep->dtypep()->widthWords());
|
* valuep->dtypep()->widthWords());
|
||||||
m_varType = varp->varType();
|
m_varType = varp->varType();
|
||||||
m_declKwd = varp->declKwd();
|
m_declKwd = varp->declKwd();
|
||||||
m_declInput = varp->isDeclInput();
|
m_declDirection = varp->declDirection();
|
||||||
m_declOutput = varp->isDeclOutput();
|
|
||||||
}
|
}
|
||||||
virtual int instrCount() const { return 100; } // Large...
|
virtual int instrCount() const { return 100; } // Large...
|
||||||
ASTNODE_NODE_FUNCS(TraceDecl)
|
ASTNODE_NODE_FUNCS(TraceDecl)
|
||||||
|
|
@ -3400,9 +3401,7 @@ public:
|
||||||
const VNumRange& arrayRange() const { return m_arrayRange; }
|
const VNumRange& arrayRange() const { return m_arrayRange; }
|
||||||
AstVarType varType() const { return m_varType; }
|
AstVarType varType() const { return m_varType; }
|
||||||
AstBasicDTypeKwd declKwd() const { return m_declKwd; }
|
AstBasicDTypeKwd declKwd() const { return m_declKwd; }
|
||||||
bool declInput() const { return m_declInput; }
|
VDirection declDirection() const { return m_declDirection; }
|
||||||
bool declOutput() const { return m_declOutput; }
|
|
||||||
bool declInout() const { return m_declInput && m_declOutput; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class AstTraceInc : public AstNodeStmt {
|
class AstTraceInc : public AstNodeStmt {
|
||||||
|
|
|
||||||
|
|
@ -114,7 +114,7 @@ void V3CCtors::evalAsserts() {
|
||||||
modp->addStmtp(funcp);
|
modp->addStmtp(funcp);
|
||||||
for (AstNode* np = modp->stmtsp(); np; np = np->nextp()) {
|
for (AstNode* np = modp->stmtsp(); np; np = np->nextp()) {
|
||||||
if (AstVar* varp = VN_CAST(np, Var)) {
|
if (AstVar* varp = VN_CAST(np, Var)) {
|
||||||
if (varp->isPrimaryIn() && !varp->isSc()) {
|
if (varp->isPrimaryInish() && !varp->isSc()) {
|
||||||
if (AstBasicDType* basicp = VN_CAST(varp->dtypeSkipRefp(), BasicDType)) {
|
if (AstBasicDType* basicp = VN_CAST(varp->dtypeSkipRefp(), BasicDType)) {
|
||||||
int storedWidth = basicp->widthAlignBytes() * 8;
|
int storedWidth = basicp->widthAlignBytes() * 8;
|
||||||
int lastWordWidth = varp->width() % storedWidth;
|
int lastWordWidth = varp->width() % storedWidth;
|
||||||
|
|
|
||||||
|
|
@ -258,13 +258,13 @@ private:
|
||||||
// Create IO vertex - note it's relative to the pointed to var, not where we are now
|
// Create IO vertex - note it's relative to the pointed to var, not where we are now
|
||||||
// This allows reporting to easily print the input statement
|
// This allows reporting to easily print the input statement
|
||||||
CdcLogicVertex* ioVertexp = new CdcLogicVertex(&m_graph, varscp->scopep(), varscp->varp(), NULL);
|
CdcLogicVertex* ioVertexp = new CdcLogicVertex(&m_graph, varscp->scopep(), varscp->varp(), NULL);
|
||||||
if (varscp->varp()->isInput()) {
|
if (varscp->varp()->isWritable()) {
|
||||||
new V3GraphEdge(&m_graph, ioVertexp, vertexp, 1);
|
new V3GraphEdge(&m_graph, vertexp, ioVertexp, 1);
|
||||||
} else {
|
} else {
|
||||||
new V3GraphEdge(&m_graph, vertexp, ioVertexp, 1);
|
new V3GraphEdge(&m_graph, ioVertexp, vertexp, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m_inSenItem) {
|
if (m_inSenItem) {
|
||||||
varscp->user2(true); // It's like a clock...
|
varscp->user2(true); // It's like a clock...
|
||||||
// TODO: In the future we could mark it here and do normal clock tree glitch checks also
|
// TODO: In the future we could mark it here and do normal clock tree glitch checks also
|
||||||
|
|
@ -372,9 +372,9 @@ private:
|
||||||
}
|
}
|
||||||
else if (CdcVarVertex* vvertexp = dynamic_cast<CdcVarVertex*>(vertexp)) {
|
else if (CdcVarVertex* vvertexp = dynamic_cast<CdcVarVertex*>(vertexp)) {
|
||||||
if (mark) vvertexp->asyncPath(true);
|
if (mark) vvertexp->asyncPath(true);
|
||||||
// If primary I/O, it's ok here back
|
// If primary I/O, it's ok here back
|
||||||
if (vvertexp->varScp()->varp()->isPrimaryIn()) {
|
if (vvertexp->varScp()->varp()->isPrimaryInish()) {
|
||||||
// Show the source "input" statement if it exists
|
// Show the source "input" statement if it exists
|
||||||
for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) {
|
for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) {
|
||||||
CdcEitherVertex* eFromVertexp = static_cast<CdcEitherVertex*>(edgep->fromp());
|
CdcEitherVertex* eFromVertexp = static_cast<CdcEitherVertex*>(edgep->fromp());
|
||||||
eFromVertexp->asyncPath(true);
|
eFromVertexp->asyncPath(true);
|
||||||
|
|
@ -501,8 +501,8 @@ private:
|
||||||
if (CdcVarVertex* vvertexp = dynamic_cast<CdcVarVertex*>(itp)) {
|
if (CdcVarVertex* vvertexp = dynamic_cast<CdcVarVertex*>(itp)) {
|
||||||
AstVar* varp = vvertexp->varScp()->varp();
|
AstVar* varp = vvertexp->varScp()->varp();
|
||||||
if (1) { // varp->isPrimaryIO()
|
if (1) { // varp->isPrimaryIO()
|
||||||
const char* whatp = "wire";
|
string what = "wire";
|
||||||
if (varp->isPrimaryIO()) whatp = (varp->isInout()?"inout":varp->isInput()?"input":"output");
|
if (varp->isPrimaryIO()) what = varp->direction().prettyName();
|
||||||
|
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
os.setf(std::ios::left);
|
os.setf(std::ios::left);
|
||||||
|
|
@ -510,7 +510,7 @@ private:
|
||||||
// so we assume the modulename matches the filebasename
|
// so we assume the modulename matches the filebasename
|
||||||
string fname = vvertexp->varScp()->fileline()->filebasename() + ":";
|
string fname = vvertexp->varScp()->fileline()->filebasename() + ":";
|
||||||
os<<" "<<std::setw(20)<<fname;
|
os<<" "<<std::setw(20)<<fname;
|
||||||
os<<" "<<std::setw(8)<<whatp;
|
os<<" "<<std::setw(8)<<what;
|
||||||
os<<" "<<std::setw(40)<<vvertexp->varScp()->prettyName();
|
os<<" "<<std::setw(40)<<vvertexp->varScp()->prettyName();
|
||||||
os<<" SRC=";
|
os<<" SRC=";
|
||||||
if (vvertexp->srcDomainp()) V3EmitV::verilogForTree(vvertexp->srcDomainp(), os);
|
if (vvertexp->srcDomainp()) V3EmitV::verilogForTree(vvertexp->srcDomainp(), os);
|
||||||
|
|
@ -545,10 +545,12 @@ private:
|
||||||
else if (CdcVarVertex* vvertexp = dynamic_cast<CdcVarVertex*>(vertexp)) {
|
else if (CdcVarVertex* vvertexp = dynamic_cast<CdcVarVertex*>(vertexp)) {
|
||||||
// If primary I/O, give it domain of the input
|
// If primary I/O, give it domain of the input
|
||||||
AstVar* varp = vvertexp->varScp()->varp();
|
AstVar* varp = vvertexp->varScp()->varp();
|
||||||
if (varp->isPrimaryIO() && varp->isInput() && !traceDests) {
|
if (varp->isPrimaryIO() && varp->isNonOutput() && !traceDests) {
|
||||||
senouts.insert(new AstSenTree(varp->fileline(), new AstSenItem(varp->fileline(), AstSenItem::Combo())));
|
senouts.insert(
|
||||||
}
|
new AstSenTree(varp->fileline(),
|
||||||
}
|
new AstSenItem(varp->fileline(), AstSenItem::Combo())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Now combine domains of sources/dests
|
// Now combine domains of sources/dests
|
||||||
if (traceDests) {
|
if (traceDests) {
|
||||||
|
|
|
||||||
|
|
@ -1538,9 +1538,10 @@ private:
|
||||||
&& ((!m_params // Can reduce constant wires into equations
|
&& ((!m_params // Can reduce constant wires into equations
|
||||||
&& m_doNConst
|
&& m_doNConst
|
||||||
&& v3Global.opt.oConst()
|
&& v3Global.opt.oConst()
|
||||||
&& !(nodep->varp()->isFuncLocal() // Default value, not a "known" constant for this usage
|
// Default value, not a "known" constant for this usage
|
||||||
&& nodep->varp()->isInput())
|
&& !(nodep->varp()->isFuncLocal()
|
||||||
&& !nodep->varp()->noSubst()
|
&& nodep->varp()->isNonOutput())
|
||||||
|
&& !nodep->varp()->noSubst()
|
||||||
&& !nodep->varp()->isSigPublic())
|
&& !nodep->varp()->isSigPublic())
|
||||||
|| nodep->varp()->isParam())) {
|
|| nodep->varp()->isParam())) {
|
||||||
if (operandConst(valuep)) {
|
if (operandConst(valuep)) {
|
||||||
|
|
|
||||||
|
|
@ -183,13 +183,14 @@ private:
|
||||||
AstNode* argsp = NULL;
|
AstNode* argsp = NULL;
|
||||||
for (AstNode* stmtp = newfuncp->argsp(); stmtp; stmtp=stmtp->nextp()) {
|
for (AstNode* stmtp = newfuncp->argsp(); stmtp; stmtp=stmtp->nextp()) {
|
||||||
if (AstVar* portp = VN_CAST(stmtp, Var)) {
|
if (AstVar* portp = VN_CAST(stmtp, Var)) {
|
||||||
if (portp->isIO() && !portp->isFuncReturn()) {
|
if (portp->isIO() && !portp->isFuncReturn()) {
|
||||||
AstNode* newp = new AstVarRef(portp->fileline(), portp, portp->isOutput());
|
AstNode* newp = new AstVarRef(portp->fileline(),
|
||||||
if (argsp) argsp = argsp->addNextNull(newp);
|
portp, portp->isWritable());
|
||||||
else argsp = newp;
|
if (argsp) argsp = argsp->addNextNull(newp);
|
||||||
}
|
else argsp = newp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
AstNode* returnp = new AstCReturn(funcp->fileline(),
|
AstNode* returnp = new AstCReturn(funcp->fileline(),
|
||||||
new AstCCall(funcp->fileline(),
|
new AstCCall(funcp->fileline(),
|
||||||
|
|
|
||||||
|
|
@ -1211,13 +1211,13 @@ void EmitCStmts::emitVarDecl(const AstVar* nodep, const string& prefixIfImp) {
|
||||||
if (nodep->isIO()) {
|
if (nodep->isIO()) {
|
||||||
if (nodep->isSc()) {
|
if (nodep->isSc()) {
|
||||||
m_ctorVarsVec.push_back(nodep);
|
m_ctorVarsVec.push_back(nodep);
|
||||||
if (nodep->attrScClocked() && nodep->isInput()) {
|
if (nodep->attrScClocked() && nodep->isReadOnly()) {
|
||||||
puts("sc_in_clk ");
|
puts("sc_in_clk ");
|
||||||
} else {
|
} else {
|
||||||
if (nodep->isInout()) puts("sc_inout<");
|
if (nodep->isInoutish()) puts("sc_inout<");
|
||||||
else if (nodep->isInput()) puts("sc_in<");
|
else if (nodep->isWritable()) puts("sc_out<");
|
||||||
else if (nodep->isOutput()) puts("sc_out<");
|
else if (nodep->isNonOutput()) puts("sc_in<");
|
||||||
else nodep->v3fatalSrc("Unknown type");
|
else nodep->v3fatalSrc("Unknown type");
|
||||||
|
|
||||||
puts(nodep->scType());
|
puts(nodep->scType());
|
||||||
puts("> ");
|
puts("> ");
|
||||||
|
|
@ -1230,11 +1230,11 @@ void EmitCStmts::emitVarDecl(const AstVar* nodep, const string& prefixIfImp) {
|
||||||
puts(nodep->vlArgType(true,false,false));
|
puts(nodep->vlArgType(true,false,false));
|
||||||
emitDeclArrayBrackets(nodep);
|
emitDeclArrayBrackets(nodep);
|
||||||
puts(";\n");
|
puts(";\n");
|
||||||
} else { // C++ signals
|
} else { // C++ signals
|
||||||
if (nodep->isInout()) puts("VL_INOUT");
|
if (nodep->isInoutish()) puts("VL_INOUT");
|
||||||
else if (nodep->isInput()) puts("VL_IN");
|
else if (nodep->isWritable()) puts("VL_OUT");
|
||||||
else if (nodep->isOutput()) puts("VL_OUT");
|
else if (nodep->isNonOutput()) puts("VL_IN");
|
||||||
else nodep->v3fatalSrc("Unknown type");
|
else nodep->v3fatalSrc("Unknown type");
|
||||||
|
|
||||||
if (nodep->isQuad()) puts("64");
|
if (nodep->isQuad()) puts("64");
|
||||||
else if (nodep->widthMin() <= 8) puts("8");
|
else if (nodep->widthMin() <= 8) puts("8");
|
||||||
|
|
@ -1990,9 +1990,10 @@ void EmitCImp::emitSensitives() {
|
||||||
puts("SC_METHOD(eval);\n");
|
puts("SC_METHOD(eval);\n");
|
||||||
for (AstNode* nodep=m_modp->stmtsp(); nodep; nodep = nodep->nextp()) {
|
for (AstNode* nodep=m_modp->stmtsp(); nodep; nodep = nodep->nextp()) {
|
||||||
if (const AstVar* varp = VN_CAST(nodep, Var)) {
|
if (const AstVar* varp = VN_CAST(nodep, Var)) {
|
||||||
if (varp->isInput() && (varp->isScSensitive() || varp->isUsedClock())) {
|
if (varp->isNonOutput() && (varp->isScSensitive()
|
||||||
int vects = 0;
|
|| varp->isUsedClock())) {
|
||||||
// This isn't very robust and may need cleanup for other data types
|
int vects = 0;
|
||||||
|
// This isn't very robust and may need cleanup for other data types
|
||||||
for (AstUnpackArrayDType* arrayp=VN_CAST(varp->dtypeSkipRefp(), UnpackArrayDType);
|
for (AstUnpackArrayDType* arrayp=VN_CAST(varp->dtypeSkipRefp(), UnpackArrayDType);
|
||||||
arrayp;
|
arrayp;
|
||||||
arrayp = VN_CAST(arrayp->subDTypep()->skipRefp(), UnpackArrayDType)) {
|
arrayp = VN_CAST(arrayp->subDTypep()->skipRefp(), UnpackArrayDType)) {
|
||||||
|
|
@ -2852,9 +2853,9 @@ class EmitCTrace : EmitCStmts {
|
||||||
if (v3Global.opt.traceFormat() == TraceFormat::FST) {
|
if (v3Global.opt.traceFormat() == TraceFormat::FST) {
|
||||||
puts(","+cvtToStr(enumNum));
|
puts(","+cvtToStr(enumNum));
|
||||||
// fstVarDir
|
// fstVarDir
|
||||||
if (nodep->declInout()) puts(",FST_VD_INOUT");
|
if (nodep->declDirection().isInoutish()) puts(",FST_VD_INOUT");
|
||||||
else if (nodep->declInput()) puts(",FST_VD_INPUT");
|
else if (nodep->declDirection().isWritable()) puts(",FST_VD_OUTPUT");
|
||||||
else if (nodep->declOutput()) puts(",FST_VD_OUTPUT");
|
else if (nodep->declDirection().isNonOutput()) puts(",FST_VD_INPUT");
|
||||||
else puts(",FST_VD_IMPLICIT");
|
else puts(",FST_VD_IMPLICIT");
|
||||||
//
|
//
|
||||||
// fstVarType
|
// fstVarType
|
||||||
|
|
@ -2875,6 +2876,7 @@ class EmitCTrace : EmitCStmts {
|
||||||
else if (vartype == AstVarType::TRI1) fstvt = "FST_VT_VCD_TRI1";
|
else if (vartype == AstVarType::TRI1) fstvt = "FST_VT_VCD_TRI1";
|
||||||
else if (vartype == AstVarType::TRIWIRE) fstvt = "FST_VT_VCD_TRI";
|
else if (vartype == AstVarType::TRIWIRE) fstvt = "FST_VT_VCD_TRI";
|
||||||
else if (vartype == AstVarType::WIRE) fstvt = "FST_VT_VCD_WIRE";
|
else if (vartype == AstVarType::WIRE) fstvt = "FST_VT_VCD_WIRE";
|
||||||
|
else if (vartype == AstVarType::PORT) fstvt = "FST_VT_VCD_WIRE";
|
||||||
//
|
//
|
||||||
else if (kwd == AstBasicDTypeKwd::INTEGER) fstvt = "FST_VT_VCD_INTEGER";
|
else if (kwd == AstBasicDTypeKwd::INTEGER) fstvt = "FST_VT_VCD_INTEGER";
|
||||||
else if (kwd == AstBasicDTypeKwd::BIT) fstvt = "FST_VT_SV_BIT";
|
else if (kwd == AstBasicDTypeKwd::BIT) fstvt = "FST_VT_SV_BIT";
|
||||||
|
|
|
||||||
|
|
@ -113,16 +113,14 @@ class EmitXmlFileVisitor : public AstNVisitor {
|
||||||
outputChildrenEnd(nodep, "");
|
outputChildrenEnd(nodep, "");
|
||||||
}
|
}
|
||||||
virtual void visit(AstPin* nodep) {
|
virtual void visit(AstPin* nodep) {
|
||||||
// What we call a pin in verilator is a port in the IEEE spec.
|
// What we call a pin in verilator is a port in the IEEE spec.
|
||||||
outputTag(nodep, "port"); // IEEE: vpiPort
|
outputTag(nodep, "port"); // IEEE: vpiPort
|
||||||
if (nodep->modVarp()->isInOnly()) {
|
if (nodep->modVarp()->isIO()) {
|
||||||
puts(" direction=\"in\"");
|
puts(" direction=\""+nodep->modVarp()->direction().xmlKwd()+"\"");
|
||||||
} else if (nodep->modVarp()->isOutOnly()) {
|
}
|
||||||
puts(" direction=\"out\"");
|
puts(" portIndex=\""+cvtToStr(nodep->pinNum())+"\""); // IEEE: vpiPortIndex
|
||||||
} else puts(" direction=\"inout\"");
|
// Children includes vpiHighConn and vpiLowConn; we don't support port bits (yet?)
|
||||||
puts(" portIndex=\""+cvtToStr(nodep->pinNum())+"\""); // IEEE: vpiPortIndex
|
outputChildrenEnd(nodep, "port");
|
||||||
// Children includes vpiHighConn and vpiLowConn; we don't support port bits (yet?)
|
|
||||||
outputChildrenEnd(nodep, "port");
|
|
||||||
}
|
}
|
||||||
virtual void visit(AstSenItem* nodep) {
|
virtual void visit(AstSenItem* nodep) {
|
||||||
outputTag(nodep, "");
|
outputTag(nodep, "");
|
||||||
|
|
|
||||||
|
|
@ -1131,11 +1131,11 @@ void GateVisitor::dedupe() {
|
||||||
}
|
}
|
||||||
// Traverse starting from each of the outputs
|
// Traverse starting from each of the outputs
|
||||||
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) {
|
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) {
|
||||||
if (GateVarVertex* vvertexp = dynamic_cast<GateVarVertex*>(itp)) {
|
if (GateVarVertex* vvertexp = dynamic_cast<GateVarVertex*>(itp)) {
|
||||||
if (vvertexp->isTop() && vvertexp->varScp()->varp()->isOutput()) {
|
if (vvertexp->isTop() && vvertexp->varScp()->varp()->isWritable()) {
|
||||||
deduper.dedupeTree(vvertexp);
|
deduper.dedupeTree(vvertexp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_statDedupLogic += deduper.numDeduped();
|
m_statDedupLogic += deduper.numDeduped();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -317,23 +317,26 @@ private:
|
||||||
// Public variable at the lower module end - we need to make sure we propagate
|
// Public variable at the lower module end - we need to make sure we propagate
|
||||||
// the logic changes up and down; if we aliased, we might remove the change detection
|
// the logic changes up and down; if we aliased, we might remove the change detection
|
||||||
// on the output variable.
|
// on the output variable.
|
||||||
UINFO(9,"public pin assign: "<<exprvarrefp<<endl);
|
UINFO(9,"public pin assign: "<<exprvarrefp<<endl);
|
||||||
if (nodep->isInput()) nodep->v3fatalSrc("Outputs only - inputs use AssignAlias");
|
if (nodep->isNonOutput()) nodep->v3fatalSrc("Outputs only - inputs use AssignAlias");
|
||||||
m_modp->addStmtp(new AstAssignW(nodep->fileline(),
|
m_modp->addStmtp(
|
||||||
new AstVarRef(nodep->fileline(), exprvarrefp->varp(), true),
|
new AstAssignW(nodep->fileline(),
|
||||||
new AstVarRef(nodep->fileline(), nodep, false)));
|
new AstVarRef(nodep->fileline(), exprvarrefp->varp(), true),
|
||||||
} else if (nodep->isIfaceRef()) {
|
new AstVarRef(nodep->fileline(), nodep, false)));
|
||||||
m_modp->addStmtp(new AstAssignVarScope(nodep->fileline(),
|
} else if (nodep->isIfaceRef()) {
|
||||||
new AstVarRef(nodep->fileline(), nodep, true),
|
m_modp->addStmtp(
|
||||||
new AstVarRef(nodep->fileline(), exprvarrefp->varp(), false)));
|
new AstAssignVarScope(nodep->fileline(),
|
||||||
AstNode* nodebp=exprvarrefp->varp();
|
new AstVarRef(nodep->fileline(), nodep, true),
|
||||||
nodep ->fileline()->modifyStateInherit(nodebp->fileline());
|
new AstVarRef(nodep->fileline(), exprvarrefp->varp(), false)));
|
||||||
nodebp->fileline()->modifyStateInherit(nodep ->fileline());
|
AstNode* nodebp=exprvarrefp->varp();
|
||||||
} else {
|
nodep ->fileline()->modifyStateInherit(nodebp->fileline());
|
||||||
// Do to inlining child's variable now within the same module, so a AstVarRef not AstVarXRef below
|
nodebp->fileline()->modifyStateInherit(nodep ->fileline());
|
||||||
m_modp->addStmtp(new AstAssignAlias(nodep->fileline(),
|
} else {
|
||||||
new AstVarRef(nodep->fileline(), nodep, true),
|
// Do to inlining child's variable now within the same module, so a AstVarRef not AstVarXRef below
|
||||||
new AstVarRef(nodep->fileline(), exprvarrefp->varp(), false)));
|
m_modp->addStmtp(
|
||||||
|
new AstAssignAlias(nodep->fileline(),
|
||||||
|
new AstVarRef(nodep->fileline(), nodep, true),
|
||||||
|
new AstVarRef(nodep->fileline(), exprvarrefp->varp(), false)));
|
||||||
AstNode* nodebp=exprvarrefp->varp();
|
AstNode* nodebp=exprvarrefp->varp();
|
||||||
nodep ->fileline()->modifyStateInherit(nodebp->fileline());
|
nodep ->fileline()->modifyStateInherit(nodebp->fileline());
|
||||||
nodebp->fileline()->modifyStateInherit(nodep ->fileline());
|
nodebp->fileline()->modifyStateInherit(nodep ->fileline());
|
||||||
|
|
@ -549,11 +552,12 @@ private:
|
||||||
|
|
||||||
AstNode* connectRefp = pinp->exprp();
|
AstNode* connectRefp = pinp->exprp();
|
||||||
if (!VN_IS(connectRefp, Const) && !VN_IS(connectRefp, VarRef)) {
|
if (!VN_IS(connectRefp, Const) && !VN_IS(connectRefp, VarRef)) {
|
||||||
pinp->v3fatalSrc("Unknown interconnect type; pinReconnectSimple should have cleared up");
|
pinp->v3fatalSrc("Unknown interconnect type; pinReconnectSimple should have cleared up");
|
||||||
}
|
}
|
||||||
if (pinNewVarp->isOutOnly() && VN_IS(connectRefp, Const)) {
|
if (pinNewVarp->direction() == VDirection::OUTPUT
|
||||||
pinp->v3error("Output port is connected to a constant pin, electrical short");
|
&& VN_IS(connectRefp, Const)) {
|
||||||
}
|
pinp->v3error("Output port is connected to a constant pin, electrical short");
|
||||||
|
}
|
||||||
|
|
||||||
// Propagate any attributes across the interconnect
|
// Propagate any attributes across the interconnect
|
||||||
pinNewVarp->propagateAttrFrom(pinOldVarp);
|
pinNewVarp->propagateAttrFrom(pinOldVarp);
|
||||||
|
|
@ -567,11 +571,13 @@ private:
|
||||||
UINFO(6,"One-to-one "<<connectRefp<<endl);
|
UINFO(6,"One-to-one "<<connectRefp<<endl);
|
||||||
UINFO(6," -to "<<pinNewVarp<<endl);
|
UINFO(6," -to "<<pinNewVarp<<endl);
|
||||||
pinNewVarp->user2p(connectRefp);
|
pinNewVarp->user2p(connectRefp);
|
||||||
// Public output inside the cell must go via an assign rather than alias
|
// Public output inside the cell must go via an assign rather
|
||||||
// Else the public logic will set the alias, losing the value to be propagated up
|
// than alias. Else the public logic will set the alias, losing
|
||||||
// (InOnly isn't a problem as the AssignAlias will create the assignment for us)
|
// the value to be propagated up (InOnly isn't a problem as the
|
||||||
pinNewVarp->user3(pinNewVarp->isSigUserRWPublic() && pinNewVarp->isOutOnly());
|
// AssignAlias will create the assignment for us)
|
||||||
}
|
pinNewVarp->user3(pinNewVarp->isSigUserRWPublic()
|
||||||
|
&& pinNewVarp->direction()==VDirection::OUTPUT);
|
||||||
|
}
|
||||||
// Cleanup var names, etc, to not conflict
|
// Cleanup var names, etc, to not conflict
|
||||||
{ InlineRelinkVisitor(newmodp, m_modp, nodep); }
|
{ InlineRelinkVisitor(newmodp, m_modp, nodep); }
|
||||||
// Move statements to top module
|
// Move statements to top module
|
||||||
|
|
|
||||||
|
|
@ -63,28 +63,31 @@ private:
|
||||||
m_cellp = NULL;
|
m_cellp = NULL;
|
||||||
}
|
}
|
||||||
virtual void visit(AstPin* nodep) {
|
virtual void visit(AstPin* nodep) {
|
||||||
// PIN(p,expr) -> ASSIGNW(VARXREF(p),expr) (if sub's input)
|
// PIN(p,expr) -> ASSIGNW(VARXREF(p),expr) (if sub's input)
|
||||||
// or ASSIGNW(expr,VARXREF(p)) (if sub's output)
|
// or ASSIGNW(expr,VARXREF(p)) (if sub's output)
|
||||||
UINFO(4," PIN "<<nodep<<endl);
|
UINFO(4," PIN "<<nodep<<endl);
|
||||||
if (!nodep->exprp()) return; // No-connect
|
if (!nodep->exprp()) return; // No-connect
|
||||||
if (debug()>=9) nodep->dumpTree(cout," Pin_oldb: ");
|
if (debug()>=9) nodep->dumpTree(cout," Pin_oldb: ");
|
||||||
if (nodep->modVarp()->isOutOnly() && VN_IS(nodep->exprp(), Const))
|
if (nodep->modVarp()->direction() == VDirection::OUTPUT
|
||||||
nodep->v3error("Output port is connected to a constant pin, electrical short");
|
&& VN_IS(nodep->exprp(), Const)) {
|
||||||
// Use user1p on the PIN to indicate we created an assign for this pin
|
nodep->v3error("Output port is connected to a constant pin, electrical short");
|
||||||
if (!nodep->user1SetOnce()) {
|
}
|
||||||
// Simplify it
|
// Use user1p on the PIN to indicate we created an assign for this pin
|
||||||
|
if (!nodep->user1SetOnce()) {
|
||||||
|
// Simplify it
|
||||||
V3Inst::pinReconnectSimple(nodep, m_cellp, false);
|
V3Inst::pinReconnectSimple(nodep, m_cellp, false);
|
||||||
// Make an ASSIGNW (expr, pin)
|
// Make an ASSIGNW (expr, pin)
|
||||||
AstNode* exprp = nodep->exprp()->cloneTree(false);
|
AstNode* exprp = nodep->exprp()->cloneTree(false);
|
||||||
if (exprp->width() != nodep->modVarp()->width())
|
if (exprp->width() != nodep->modVarp()->width()) {
|
||||||
nodep->v3fatalSrc("Width mismatch, should have been handled in pinReconnectSimple");
|
nodep->v3fatalSrc("Width mismatch, should have been handled in pinReconnectSimple");
|
||||||
if (nodep->modVarp()->isInout()) {
|
}
|
||||||
nodep->v3fatalSrc("Unsupported: Verilator is a 2-state simulator");
|
if (nodep->modVarp()->isInoutish()) {
|
||||||
} else if (nodep->modVarp()->isOutput()) {
|
nodep->v3fatalSrc("Unsupported: Verilator is a 2-state simulator");
|
||||||
|
} else if (nodep->modVarp()->isWritable()) {
|
||||||
AstNode* rhsp = new AstVarXRef(exprp->fileline(), nodep->modVarp(), m_cellp->name(), false);
|
AstNode* rhsp = new AstVarXRef(exprp->fileline(), nodep->modVarp(), m_cellp->name(), false);
|
||||||
AstAssignW* assp = new AstAssignW(exprp->fileline(), exprp, rhsp);
|
AstAssignW* assp = new AstAssignW(exprp->fileline(), exprp, rhsp);
|
||||||
m_cellp->addNextHere(assp);
|
m_cellp->addNextHere(assp);
|
||||||
} else if (nodep->modVarp()->isInput()) {
|
} else if (nodep->modVarp()->isNonOutput()) {
|
||||||
// Don't bother moving constants now,
|
// Don't bother moving constants now,
|
||||||
// we'll be pushing the const down to the cell soon enough.
|
// we'll be pushing the const down to the cell soon enough.
|
||||||
AstNode* assp = new AstAssignW
|
AstNode* assp = new AstAssignW
|
||||||
|
|
@ -332,8 +335,8 @@ private:
|
||||||
nodep->v3warn(LITENDIAN,"Little endian cell range connecting to vector: MSB < LSB of cell range: "
|
nodep->v3warn(LITENDIAN,"Little endian cell range connecting to vector: MSB < LSB of cell range: "
|
||||||
<<m_cellRangep->lsbConst()<<":"<<m_cellRangep->msbConst());
|
<<m_cellRangep->lsbConst()<<":"<<m_cellRangep->msbConst());
|
||||||
}
|
}
|
||||||
AstNode* exprp = nodep->exprp()->unlinkFrBack();
|
AstNode* exprp = nodep->exprp()->unlinkFrBack();
|
||||||
bool inputPin = nodep->modVarp()->isInput();
|
bool inputPin = nodep->modVarp()->isNonOutput();
|
||||||
if (!inputPin && !VN_IS(exprp, VarRef)
|
if (!inputPin && !VN_IS(exprp, VarRef)
|
||||||
&& !VN_IS(exprp, Concat) // V3Const will collapse the SEL with the one we're about to make
|
&& !VN_IS(exprp, Concat) // V3Const will collapse the SEL with the one we're about to make
|
||||||
&& !VN_IS(exprp, Sel)) { // V3Const will collapse the SEL with the one we're about to make
|
&& !VN_IS(exprp, Sel)) { // V3Const will collapse the SEL with the one we're about to make
|
||||||
|
|
@ -512,25 +515,29 @@ public:
|
||||||
// Make a new temp wire
|
// Make a new temp wire
|
||||||
//if (1||debug()>=9) { pinp->dumpTree(cout,"-in_pin:"); }
|
//if (1||debug()>=9) { pinp->dumpTree(cout,"-in_pin:"); }
|
||||||
AstNode* pinexprp = pinp->exprp()->unlinkFrBack();
|
AstNode* pinexprp = pinp->exprp()->unlinkFrBack();
|
||||||
string newvarname = (string(pinVarp->isOutput() ? "__Vcellout" : "__Vcellinp")
|
string newvarname = (string(pinVarp->isWritable() ? "__Vcellout" : "__Vcellinp")
|
||||||
+(forTristate?"t":"") // Prevent name conflict if both tri & non-tri add signals
|
// Prevent name conflict if both tri & non-tri add signals
|
||||||
+"__"+cellp->name()+"__"+pinp->name());
|
+(forTristate?"t":"")
|
||||||
AstVar* newvarp = new AstVar(pinVarp->fileline(), AstVarType::MODULETEMP, newvarname, pinVarp);
|
+"__"+cellp->name()+"__"+pinp->name());
|
||||||
// Important to add statement next to cell, in case there is a generate with same named cell
|
AstVar* newvarp = new AstVar(pinVarp->fileline(),
|
||||||
cellp->addNextHere(newvarp);
|
AstVarType::MODULETEMP, newvarname, pinVarp);
|
||||||
if (pinVarp->isInout()) {
|
// Important to add statement next to cell, in case there is a
|
||||||
|
// generate with same named cell
|
||||||
|
cellp->addNextHere(newvarp);
|
||||||
|
if (pinVarp->isInoutish()) {
|
||||||
pinVarp->v3fatalSrc("Unsupported: Inout connections to pins must be"
|
pinVarp->v3fatalSrc("Unsupported: Inout connections to pins must be"
|
||||||
" direct one-to-one connection (without any expression)");
|
" direct one-to-one connection (without any expression)");
|
||||||
} else if (pinVarp->isOutput()) {
|
} else if (pinVarp->isWritable()) {
|
||||||
// See also V3Inst
|
// See also V3Inst
|
||||||
AstNode* rhsp = new AstVarRef(pinp->fileline(), newvarp, false);
|
AstNode* rhsp = new AstVarRef(pinp->fileline(), newvarp, false);
|
||||||
UINFO(5,"pinRecon width "<<pinVarp->width()<<" >? "<<rhsp->width()<<" >? "<<pinexprp->width()<<endl);
|
UINFO(5,"pinRecon width "<<pinVarp->width()<<" >? "
|
||||||
|
<<rhsp->width()<<" >? "<<pinexprp->width()<<endl);
|
||||||
rhsp = extendOrSel(pinp->fileline(), rhsp, pinVarp);
|
rhsp = extendOrSel(pinp->fileline(), rhsp, pinVarp);
|
||||||
pinp->exprp(new AstVarRef(newvarp->fileline(), newvarp, true));
|
pinp->exprp(new AstVarRef(newvarp->fileline(), newvarp, true));
|
||||||
AstNode* rhsSelp = extendOrSel(pinp->fileline(), rhsp, pinexprp);
|
AstNode* rhsSelp = extendOrSel(pinp->fileline(), rhsp, pinexprp);
|
||||||
assignp = new AstAssignW(pinp->fileline(), pinexprp, rhsSelp);
|
assignp = new AstAssignW(pinp->fileline(), pinexprp, rhsSelp);
|
||||||
} else {
|
} else {
|
||||||
// V3 width should have range/extended to make the widths correct
|
// V3 width should have range/extended to make the widths correct
|
||||||
assignp = new AstAssignW(pinp->fileline(),
|
assignp = new AstAssignW(pinp->fileline(),
|
||||||
new AstVarRef(pinp->fileline(), newvarp, true),
|
new AstVarRef(pinp->fileline(), newvarp, true),
|
||||||
pinexprp);
|
pinexprp);
|
||||||
|
|
|
||||||
|
|
@ -871,8 +871,9 @@ class LinkDotFindVisitor : public AstNVisitor {
|
||||||
// also return the class reference.
|
// also return the class reference.
|
||||||
if (dtypep) dtypep->unlinkFrBack();
|
if (dtypep) dtypep->unlinkFrBack();
|
||||||
else dtypep = new AstBasicDType(nodep->fileline(), AstBasicDTypeKwd::LOGIC);
|
else dtypep = new AstBasicDType(nodep->fileline(), AstBasicDTypeKwd::LOGIC);
|
||||||
AstVar* newvarp = new AstVar(nodep->fileline(), AstVarType::OUTPUT, nodep->name(),
|
AstVar* newvarp = new AstVar(nodep->fileline(), AstVarType::WIRE, nodep->name(),
|
||||||
VFlagChildDType(), dtypep); // Not dtype resolved yet
|
VFlagChildDType(), dtypep); // Not dtype resolved yet
|
||||||
|
newvarp->direction(VDirection::OUTPUT);
|
||||||
newvarp->funcReturn(true);
|
newvarp->funcReturn(true);
|
||||||
newvarp->trace(false); // Not user visible
|
newvarp->trace(false); // Not user visible
|
||||||
newvarp->attrIsolateAssign(nodep->attrIsolateAssign());
|
newvarp->attrIsolateAssign(nodep->attrIsolateAssign());
|
||||||
|
|
@ -1537,10 +1538,10 @@ private:
|
||||||
} else if (VN_IS(symp->nodep(), ModportVarRef)) {
|
} else if (VN_IS(symp->nodep(), ModportVarRef)) {
|
||||||
AstModportVarRef* snodep = VN_CAST(symp->nodep(), ModportVarRef);
|
AstModportVarRef* snodep = VN_CAST(symp->nodep(), ModportVarRef);
|
||||||
AstVar* varp = snodep->varp();
|
AstVar* varp = snodep->varp();
|
||||||
if (lvalue && snodep->isInput()) {
|
if (lvalue && snodep->direction().isReadOnly()) {
|
||||||
nodep->v3error("Attempt to drive input-only modport: "<<nodep->prettyName());
|
nodep->v3error("Attempt to drive input-only modport: "<<nodep->prettyName());
|
||||||
} // else other simulators don't warn about reading, and IEEE doesn't say illegal
|
} // else other simulators don't warn about reading, and IEEE doesn't say illegal
|
||||||
return varp;
|
return varp;
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,21 +56,21 @@ private:
|
||||||
nodep->lvalue(true);
|
nodep->lvalue(true);
|
||||||
}
|
}
|
||||||
if (nodep->varp()) {
|
if (nodep->varp()) {
|
||||||
if (nodep->lvalue() && nodep->varp()->isInOnly()) {
|
if (nodep->lvalue() && !m_ftaskp
|
||||||
if (!m_ftaskp) {
|
&& nodep->varp()->isReadOnly()) {
|
||||||
nodep->v3warn(ASSIGNIN,"Assigning to input variable: "<<nodep->prettyName());
|
nodep->v3warn(ASSIGNIN,"Assigning to input/const variable: "
|
||||||
}
|
<<nodep->prettyName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nodes that start propagating down lvalues
|
// Nodes that start propagating down lvalues
|
||||||
virtual void visit(AstPin* nodep) {
|
virtual void visit(AstPin* nodep) {
|
||||||
if (nodep->modVarp() && nodep->modVarp()->isOutput()) {
|
if (nodep->modVarp() && nodep->modVarp()->isWritable()) {
|
||||||
// When the varref's were created, we didn't know the I/O state
|
// When the varref's were created, we didn't know the I/O state
|
||||||
// Now that we do, and it's from a output, we know it's a lvalue
|
// Now that we do, and it's from a output, we know it's a lvalue
|
||||||
m_setRefLvalue = true;
|
m_setRefLvalue = true;
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
m_setRefLvalue = false;
|
m_setRefLvalue = false;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -238,14 +238,14 @@ private:
|
||||||
if (!taskp) return;
|
if (!taskp) return;
|
||||||
for (AstNode* stmtp = taskp->stmtsp(); stmtp && pinp; stmtp=stmtp->nextp()) {
|
for (AstNode* stmtp = taskp->stmtsp(); stmtp && pinp; stmtp=stmtp->nextp()) {
|
||||||
if (const AstVar* portp = VN_CAST(stmtp, Var)) {
|
if (const AstVar* portp = VN_CAST(stmtp, Var)) {
|
||||||
if (portp->isIO()) {
|
if (portp->isIO()) {
|
||||||
if (portp->isInput()) {
|
if (portp->isWritable()) {
|
||||||
|
m_setRefLvalue = true;
|
||||||
iterate(pinp);
|
iterate(pinp);
|
||||||
} else { // Output or Inout
|
m_setRefLvalue = false;
|
||||||
m_setRefLvalue = true;
|
} else {
|
||||||
iterate(pinp);
|
iterate(pinp);
|
||||||
m_setRefLvalue = false;
|
}
|
||||||
}
|
|
||||||
// Advance pin
|
// Advance pin
|
||||||
pinp = pinp->nextp();
|
pinp = pinp->nextp();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -126,10 +126,10 @@ void V3LinkLevel::wrapTopCell(AstNetlist* rootp) {
|
||||||
AstVar* varp = oldvarp->cloneTree(false);
|
AstVar* varp = oldvarp->cloneTree(false);
|
||||||
newmodp->addStmtp(varp);
|
newmodp->addStmtp(varp);
|
||||||
varp->sigPublic(true); // User needs to be able to get to it...
|
varp->sigPublic(true); // User needs to be able to get to it...
|
||||||
if (oldvarp->isIO()) {
|
if (oldvarp->isIO()) {
|
||||||
oldvarp->primaryIO(true);
|
oldvarp->primaryIO(false);
|
||||||
varp->primaryIO(true);
|
varp->primaryIO(true);
|
||||||
}
|
}
|
||||||
if (varp->isIO() && v3Global.opt.systemC()) {
|
if (varp->isIO() && v3Global.opt.systemC()) {
|
||||||
varp->sc(true);
|
varp->sc(true);
|
||||||
// User can see trace one level down from the wrapper
|
// User can see trace one level down from the wrapper
|
||||||
|
|
@ -138,9 +138,9 @@ void V3LinkLevel::wrapTopCell(AstNetlist* rootp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
AstPin* pinp = new AstPin(oldvarp->fileline(),0,oldvarp->name(),
|
AstPin* pinp = new AstPin(oldvarp->fileline(),0,oldvarp->name(),
|
||||||
new AstVarRef(varp->fileline(),
|
new AstVarRef(varp->fileline(),
|
||||||
varp, oldvarp->isOutput()));
|
varp, oldvarp->isWritable()));
|
||||||
// Skip length and width comp; we know it's a direct assignment
|
// Skip length and width comp; we know it's a direct assignment
|
||||||
pinp->modVarp(oldvarp);
|
pinp->modVarp(oldvarp);
|
||||||
cellp->addPinsp(pinp);
|
cellp->addPinsp(pinp);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -198,9 +198,9 @@ private:
|
||||||
// A variable with an = value can be three things:
|
// A variable with an = value can be three things:
|
||||||
FileLine* fl = nodep->valuep()->fileline();
|
FileLine* fl = nodep->valuep()->fileline();
|
||||||
// 1. Parameters and function inputs: It's a default to use if not overridden
|
// 1. Parameters and function inputs: It's a default to use if not overridden
|
||||||
if (nodep->isParam() || (m_ftaskp && nodep->isInOnly())) {
|
if (nodep->isParam() || (m_ftaskp && nodep->isNonOutput())) {
|
||||||
}
|
}
|
||||||
else if (!m_ftaskp && nodep->isInOnly()) {
|
else if (!m_ftaskp && nodep->isNonOutput()) {
|
||||||
nodep->v3error("Unsupported: Default value on module input: "<<nodep->prettyName());
|
nodep->v3error("Unsupported: Default value on module input: "<<nodep->prettyName());
|
||||||
nodep->valuep()->unlinkFrBack()->deleteTree();
|
nodep->valuep()->unlinkFrBack()->deleteTree();
|
||||||
} // 2. Under modules, it's an initial value to be loaded at time 0 via an AstInitial
|
} // 2. Under modules, it's an initial value to be loaded at time 0 via an AstInitial
|
||||||
|
|
|
||||||
|
|
@ -405,14 +405,17 @@ private:
|
||||||
AstVar* varoutp = NULL;
|
AstVar* varoutp = NULL;
|
||||||
for (AstNode* stmtp = m_modp->stmtsp(); stmtp; stmtp=stmtp->nextp()) {
|
for (AstNode* stmtp = m_modp->stmtsp(); stmtp; stmtp=stmtp->nextp()) {
|
||||||
if (AstVar* varp = VN_CAST(stmtp, Var)) {
|
if (AstVar* varp = VN_CAST(stmtp, Var)) {
|
||||||
if (varp->isInput()) {
|
if (varp->isReadOnly()) {
|
||||||
} else if (varp->isOutput()) {
|
} else if (varp->isWritable()) {
|
||||||
if (varoutp) { varp->v3error("Multiple outputs not allowed in udp modules"); }
|
if (varoutp) {
|
||||||
varoutp = varp;
|
varp->v3error("Multiple outputs not allowed in udp modules");
|
||||||
// Tie off
|
}
|
||||||
m_modp->addStmtp(new AstAssignW(varp->fileline(),
|
varoutp = varp;
|
||||||
new AstVarRef(varp->fileline(), varp, true),
|
// Tie off
|
||||||
new AstConst(varp->fileline(), AstConst::LogicFalse())));
|
m_modp->addStmtp(new AstAssignW(
|
||||||
|
varp->fileline(),
|
||||||
|
new AstVarRef(varp->fileline(), varp, true),
|
||||||
|
new AstConst(varp->fileline(), AstConst::LogicFalse())));
|
||||||
} else {
|
} else {
|
||||||
varp->v3error("Only inputs and outputs are allowed in udp modules");
|
varp->v3error("Only inputs and outputs are allowed in udp modules");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1017,9 +1017,9 @@ private:
|
||||||
m_inClocked = false;
|
m_inClocked = false;
|
||||||
}
|
}
|
||||||
virtual void visit(AstVarScope* nodep) {
|
virtual void visit(AstVarScope* nodep) {
|
||||||
// Create links to all input signals
|
// Create links to all input signals
|
||||||
if (m_modp->isTop() && nodep->varp()->isInput()) {
|
if (m_modp->isTop() && nodep->varp()->isNonOutput()) {
|
||||||
OrderVarVertex* varVxp = newVarUserVertex(nodep, WV_STD);
|
OrderVarVertex* varVxp = newVarUserVertex(nodep, WV_STD);
|
||||||
new OrderEdge(&m_graph, m_inputsVxp, varVxp, WEIGHT_INPUT);
|
new OrderEdge(&m_graph, m_inputsVxp, varVxp, WEIGHT_INPUT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1463,9 +1463,9 @@ void OrderVisitor::processSensitive() {
|
||||||
// Sc sensitives are required on all inputs that go to a combo
|
// Sc sensitives are required on all inputs that go to a combo
|
||||||
// block. (Not inputs that go only to clocked blocks.)
|
// block. (Not inputs that go only to clocked blocks.)
|
||||||
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) {
|
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) {
|
||||||
if (OrderVarStdVertex* vvertexp = dynamic_cast<OrderVarStdVertex*>(itp)) {
|
if (OrderVarStdVertex* vvertexp = dynamic_cast<OrderVarStdVertex*>(itp)) {
|
||||||
if (vvertexp->varScp()->varp()->isInput()) {
|
if (vvertexp->varScp()->varp()->isNonOutput()) {
|
||||||
//UINFO(0," scsen "<<vvertexp<<endl);
|
//UINFO(0," scsen "<<vvertexp<<endl);
|
||||||
for (V3GraphEdge* edgep = vvertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
|
for (V3GraphEdge* edgep = vvertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
|
||||||
if (OrderEitherVertex* toVertexp = dynamic_cast<OrderEitherVertex*>(edgep->top())) {
|
if (OrderEitherVertex* toVertexp = dynamic_cast<OrderEitherVertex*>(edgep->top())) {
|
||||||
if (edgep->weight() && toVertexp->domainp()) {
|
if (edgep->weight() && toVertexp->domainp()) {
|
||||||
|
|
@ -1501,8 +1501,8 @@ void OrderVisitor::processDomainsIterate(OrderEitherVertex* vertexp) {
|
||||||
OrderVarVertex* vvertexp = dynamic_cast<OrderVarVertex*>(vertexp);
|
OrderVarVertex* vvertexp = dynamic_cast<OrderVarVertex*>(vertexp);
|
||||||
AstSenTree* domainp = NULL;
|
AstSenTree* domainp = NULL;
|
||||||
UASSERT(m_comboDomainp, "not preset");
|
UASSERT(m_comboDomainp, "not preset");
|
||||||
if (vvertexp && vvertexp->varScp()->varp()->isInput()) {
|
if (vvertexp && vvertexp->varScp()->varp()->isNonOutput()) {
|
||||||
domainp = m_comboDomainp;
|
domainp = m_comboDomainp;
|
||||||
}
|
}
|
||||||
if (vvertexp && vvertexp->varScp()->isCircular()) {
|
if (vvertexp && vvertexp->varScp()->isCircular()) {
|
||||||
domainp = m_comboDomainp;
|
domainp = m_comboDomainp;
|
||||||
|
|
|
||||||
|
|
@ -785,11 +785,11 @@ private:
|
||||||
AstVar* portp = it->first;
|
AstVar* portp = it->first;
|
||||||
AstNode* pinp = it->second->exprp();
|
AstNode* pinp = it->second->exprp();
|
||||||
if (pinp) { // Else too few arguments in function call - ignore it
|
if (pinp) { // Else too few arguments in function call - ignore it
|
||||||
if (portp->isOutput()) {
|
if (portp->isWritable()) {
|
||||||
clearOptimizable(portp,"Language violation: Outputs not allowed in constant functions");
|
clearOptimizable(portp, "Language violation: Outputs/refs not allowed in constant functions");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Evaluate pin value
|
// Evaluate pin value
|
||||||
iterate(pinp);
|
iterate(pinp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -332,9 +332,9 @@ private:
|
||||||
AstVarScope* createInputVar(AstCFunc* funcp, const string& name, AstBasicDTypeKwd kwd) {
|
AstVarScope* createInputVar(AstCFunc* funcp, const string& name, AstBasicDTypeKwd kwd) {
|
||||||
AstVar* newvarp = new AstVar(funcp->fileline(), AstVarType::BLOCKTEMP, name,
|
AstVar* newvarp = new AstVar(funcp->fileline(), AstVarType::BLOCKTEMP, name,
|
||||||
funcp->findBasicDType(kwd));
|
funcp->findBasicDType(kwd));
|
||||||
newvarp->funcLocal(true);
|
newvarp->funcLocal(true);
|
||||||
newvarp->combineType(AstVarType::INPUT);
|
newvarp->direction(VDirection::INPUT);
|
||||||
funcp->addArgsp(newvarp);
|
funcp->addArgsp(newvarp);
|
||||||
AstVarScope* newvscp = new AstVarScope(funcp->fileline(), m_scopep, newvarp);
|
AstVarScope* newvscp = new AstVarScope(funcp->fileline(), m_scopep, newvarp);
|
||||||
m_scopep->addVarp(newvscp);
|
m_scopep->addVarp(newvscp);
|
||||||
return newvscp;
|
return newvscp;
|
||||||
|
|
@ -378,10 +378,13 @@ private:
|
||||||
pinp->unlinkFrBack(); // Relinked to assignment below
|
pinp->unlinkFrBack(); // Relinked to assignment below
|
||||||
argp->unlinkFrBack()->deleteTree(); // Args no longer needed
|
argp->unlinkFrBack()->deleteTree(); // Args no longer needed
|
||||||
//
|
//
|
||||||
if ((portp->isInout() || portp->isOutput()) && VN_IS(pinp, Const)) {
|
if (portp->isWritable() && VN_IS(pinp, Const)) {
|
||||||
pinp->v3error("Function/task output connected to constant instead of variable: "+portp->prettyName());
|
pinp->v3error("Function/task "
|
||||||
}
|
+portp->direction().prettyName() // e.g. "output"
|
||||||
else if (portp->isInout()) {
|
+" connected to constant instead of variable: "
|
||||||
|
+portp->prettyName());
|
||||||
|
}
|
||||||
|
else if (portp->isInoutish()) {
|
||||||
// Correct lvalue; see comments below
|
// Correct lvalue; see comments below
|
||||||
V3LinkLValue::linkLValueSet(pinp);
|
V3LinkLValue::linkLValueSet(pinp);
|
||||||
|
|
||||||
|
|
@ -393,9 +396,9 @@ private:
|
||||||
} else {
|
} else {
|
||||||
pinp->v3warn(E_TASKNSVAR,"Unsupported: Function/task input argument is not simple variable");
|
pinp->v3warn(E_TASKNSVAR,"Unsupported: Function/task input argument is not simple variable");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (portp->isOutput()) {
|
else if (portp->isWritable()) {
|
||||||
// Make output variables
|
// Make output variables
|
||||||
// Correct lvalue; we didn't know when we linked
|
// Correct lvalue; we didn't know when we linked
|
||||||
// This is slightly scary; are we sure no decisions were made
|
// This is slightly scary; are we sure no decisions were made
|
||||||
// before here based on this not being a lvalue?
|
// before here based on this not being a lvalue?
|
||||||
|
|
@ -412,9 +415,9 @@ private:
|
||||||
assp->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true); // Ok if in <= block
|
assp->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true); // Ok if in <= block
|
||||||
// Put assignment BEHIND of all other statements
|
// Put assignment BEHIND of all other statements
|
||||||
beginp->addNext(assp);
|
beginp->addNext(assp);
|
||||||
}
|
}
|
||||||
else if (portp->isInput()) {
|
else if (portp->isNonOutput()) {
|
||||||
// Make input variable
|
// Make input variable
|
||||||
AstVarScope* inVscp = createVarScope(portp, namePrefix+"__"+portp->shortName());
|
AstVarScope* inVscp = createVarScope(portp, namePrefix+"__"+portp->shortName());
|
||||||
portp->user2p(inVscp);
|
portp->user2p(inVscp);
|
||||||
AstAssign* assp = new AstAssign(pinp->fileline(),
|
AstAssign* assp = new AstAssign(pinp->fileline(),
|
||||||
|
|
@ -483,10 +486,13 @@ private:
|
||||||
} else {
|
} else {
|
||||||
UINFO(9, " Port "<<portp<<endl);
|
UINFO(9, " Port "<<portp<<endl);
|
||||||
UINFO(9, " pin "<<pinp<<endl);
|
UINFO(9, " pin "<<pinp<<endl);
|
||||||
if ((portp->isInout() || portp->isOutput()) && VN_IS(pinp, Const)) {
|
if (portp->isWritable() && VN_IS(pinp, Const)) {
|
||||||
pinp->v3error("Function/task output connected to constant instead of variable: "+portp->prettyName());
|
pinp->v3error("Function/task "
|
||||||
}
|
+portp->direction().prettyName() // e.g. "output"
|
||||||
else if (portp->isInout()) {
|
+" connected to constant instead of variable: "
|
||||||
|
+portp->prettyName());
|
||||||
|
}
|
||||||
|
else if (portp->isInoutish()) {
|
||||||
// Correct lvalue; see comments below
|
// Correct lvalue; see comments below
|
||||||
V3LinkLValue::linkLValueSet(pinp);
|
V3LinkLValue::linkLValueSet(pinp);
|
||||||
|
|
||||||
|
|
@ -495,9 +501,9 @@ private:
|
||||||
} else {
|
} else {
|
||||||
pinp->v3warn(E_TASKNSVAR,"Unsupported: Function/task input argument is not simple variable");
|
pinp->v3warn(E_TASKNSVAR,"Unsupported: Function/task input argument is not simple variable");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (portp->isOutput()) {
|
else if (portp->isWritable()) {
|
||||||
// Make output variables
|
// Make output variables
|
||||||
// Correct lvalue; we didn't know when we linked
|
// Correct lvalue; we didn't know when we linked
|
||||||
// This is slightly scary; are we sure no decisions were made
|
// This is slightly scary; are we sure no decisions were made
|
||||||
// before here based on this not being a lvalue?
|
// before here based on this not being a lvalue?
|
||||||
|
|
@ -718,12 +724,17 @@ private:
|
||||||
// No createDpiTemp; we make a real internal variable instead
|
// No createDpiTemp; we make a real internal variable instead
|
||||||
// SAME CODE BELOW
|
// SAME CODE BELOW
|
||||||
args+= ", ";
|
args+= ", ";
|
||||||
if (args != "") { argnodesp = argnodesp->addNext(new AstText(portp->fileline(), args, true)); args=""; }
|
if (args != "") {
|
||||||
|
argnodesp = argnodesp->addNext(
|
||||||
|
new AstText(portp->fileline(), args, true));
|
||||||
|
args="";
|
||||||
|
}
|
||||||
AstVarScope* outvscp = createFuncVar(dpip, portp->name()+"__Vcvt", portp);
|
AstVarScope* outvscp = createFuncVar(dpip, portp->name()+"__Vcvt", portp);
|
||||||
AstVarRef* refp = new AstVarRef(portp->fileline(), outvscp, portp->isOutput());
|
AstVarRef* refp = new AstVarRef(portp->fileline(), outvscp,
|
||||||
argnodesp = argnodesp->addNextNull(refp);
|
portp->isWritable());
|
||||||
|
argnodesp = argnodesp->addNextNull(refp);
|
||||||
|
|
||||||
if (portp->isInput()) {
|
if (portp->isNonOutput()) {
|
||||||
dpip->addStmtsp(createAssignDpiToInternal(outvscp, portp->name(), false));
|
dpip->addStmtsp(createAssignDpiToInternal(outvscp, portp->name(), false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -736,9 +747,9 @@ private:
|
||||||
args+= ", ";
|
args+= ", ";
|
||||||
if (args != "") { argnodesp = argnodesp->addNext(new AstText(portp->fileline(), args, true)); args=""; }
|
if (args != "") { argnodesp = argnodesp->addNext(new AstText(portp->fileline(), args, true)); args=""; }
|
||||||
AstVarScope* outvscp = createFuncVar(dpip, portp->name()+"__Vcvt", portp);
|
AstVarScope* outvscp = createFuncVar(dpip, portp->name()+"__Vcvt", portp);
|
||||||
AstVarRef* refp = new AstVarRef(portp->fileline(), outvscp, portp->isOutput());
|
AstVarRef* refp = new AstVarRef(portp->fileline(), outvscp, portp->isWritable());
|
||||||
argnodesp = argnodesp->addNextNull(refp);
|
argnodesp = argnodesp->addNextNull(refp);
|
||||||
}
|
}
|
||||||
|
|
||||||
{// Call the user function
|
{// Call the user function
|
||||||
// Add the variables referenced as VarRef's so that lifetime analysis
|
// Add the variables referenced as VarRef's so that lifetime analysis
|
||||||
|
|
@ -755,11 +766,11 @@ private:
|
||||||
// Convert output/inout arguments back to internal type
|
// Convert output/inout arguments back to internal type
|
||||||
for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp=stmtp->nextp()) {
|
for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp=stmtp->nextp()) {
|
||||||
if (AstVar* portp = VN_CAST(stmtp, Var)) {
|
if (AstVar* portp = VN_CAST(stmtp, Var)) {
|
||||||
if (portp->isIO() && portp->isOutput() && !portp->isFuncReturn()) {
|
if (portp->isIO() && portp->isWritable() && !portp->isFuncReturn()) {
|
||||||
dpip->addStmtsp(createAssignInternalToDpi(portp,false,true,"__Vcvt",""));
|
dpip->addStmtsp(createAssignInternalToDpi(portp,false,true,"__Vcvt",""));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rtnvarp) {
|
if (rtnvarp) {
|
||||||
dpip->addStmtsp(createDpiTemp(rtnvarp,""));
|
dpip->addStmtsp(createDpiTemp(rtnvarp,""));
|
||||||
|
|
@ -867,14 +878,14 @@ private:
|
||||||
else {
|
else {
|
||||||
if (bitvec) {}
|
if (bitvec) {}
|
||||||
else if (logicvec) {}
|
else if (logicvec) {}
|
||||||
else if (portp->isOutput()) args += "&";
|
else if (portp->isWritable()) args += "&";
|
||||||
else if (portp->basicp() && portp->basicp()->keyword().isDpiBitVal()
|
else if (portp->basicp() && portp->basicp()->keyword().isDpiBitVal()
|
||||||
&& portp->width() != 1) args += "&"; // it's a svBitVecVal (2-32 bits wide)
|
&& portp->width() != 1) args += "&"; // it's a svBitVecVal (2-32 bits wide)
|
||||||
|
|
||||||
args += portp->name()+"__Vcvt";
|
args += portp->name()+"__Vcvt";
|
||||||
|
|
||||||
cfuncp->addStmtsp(createDpiTemp(portp,"__Vcvt"));
|
cfuncp->addStmtsp(createDpiTemp(portp,"__Vcvt"));
|
||||||
if (portp->isInput()) {
|
if (portp->isNonOutput()) {
|
||||||
cfuncp->addStmtsp(createAssignInternalToDpi(portp,false,false,"","__Vcvt"));
|
cfuncp->addStmtsp(createAssignInternalToDpi(portp,false,false,"","__Vcvt"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -900,7 +911,7 @@ private:
|
||||||
// Convert output/inout arguments back to internal type
|
// Convert output/inout arguments back to internal type
|
||||||
for (AstNode* stmtp = cfuncp->argsp(); stmtp; stmtp=stmtp->nextp()) {
|
for (AstNode* stmtp = cfuncp->argsp(); stmtp; stmtp=stmtp->nextp()) {
|
||||||
if (AstVar* portp = VN_CAST(stmtp, Var)) {
|
if (AstVar* portp = VN_CAST(stmtp, Var)) {
|
||||||
if (portp->isIO() && (portp->isOutput() || portp->isFuncReturn())
|
if (portp->isIO() && (portp->isWritable() || portp->isFuncReturn())
|
||||||
&& !portp->isDpiOpenArray()) {
|
&& !portp->isDpiOpenArray()) {
|
||||||
AstVarScope* portvscp = VN_CAST(portp->user2p(), VarScope); // Remembered when we created it earlier
|
AstVarScope* portvscp = VN_CAST(portp->user2p(), VarScope); // Remembered when we created it earlier
|
||||||
cfuncp->addStmtsp(createAssignDpiToInternal(portvscp,portp->name()+"__Vcvt",true));
|
cfuncp->addStmtsp(createAssignDpiToInternal(portvscp,portp->name()+"__Vcvt",true));
|
||||||
|
|
|
||||||
|
|
@ -699,11 +699,11 @@ private:
|
||||||
}
|
}
|
||||||
V3GraphVertex* traceVtxp = m_tracep->user1u().toGraphVertex();
|
V3GraphVertex* traceVtxp = m_tracep->user1u().toGraphVertex();
|
||||||
new V3GraphEdge(&m_graph, varVtxp, traceVtxp, 1);
|
new V3GraphEdge(&m_graph, varVtxp, traceVtxp, 1);
|
||||||
if (nodep->varp()->isPrimaryIn() // Always need to trace primary inputs
|
if (nodep->varp()->isPrimaryInish() // Always need to trace primary inputs
|
||||||
|| nodep->varp()->isSigPublic()) { // Or ones user can change
|
|| nodep->varp()->isSigPublic()) { // Or ones user can change
|
||||||
new V3GraphEdge(&m_graph, m_alwaysVtxp, traceVtxp, 1);
|
new V3GraphEdge(&m_graph, m_alwaysVtxp, traceVtxp, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (m_funcp && m_finding && nodep->lvalue()) {
|
else if (m_funcp && m_finding && nodep->lvalue()) {
|
||||||
if (!nodep->varScopep()) nodep->v3fatalSrc("No var scope?");
|
if (!nodep->varScopep()) nodep->v3fatalSrc("No var scope?");
|
||||||
V3GraphVertex* funcVtxp = getCFuncVertexp(m_funcp);
|
V3GraphVertex* funcVtxp = getCFuncVertexp(m_funcp);
|
||||||
|
|
|
||||||
|
|
@ -27,9 +27,9 @@
|
||||||
// Over each module, from child to parent:
|
// Over each module, from child to parent:
|
||||||
// Build a graph, connecting signals together so we can propagate tristates
|
// Build a graph, connecting signals together so we can propagate tristates
|
||||||
// Variable becomes tristate with
|
// Variable becomes tristate with
|
||||||
// VAR->isInout
|
// VAR->isInoutish
|
||||||
// VAR->isPullup/isPulldown (converted to AstPullup/AstPulldown
|
// VAR->isPullup/isPulldown (converted to AstPullup/AstPulldown
|
||||||
// BufIf0/1
|
// BufIf0/1
|
||||||
// All variables on the LHS need to become tristate when there is:
|
// All variables on the LHS need to become tristate when there is:
|
||||||
// CONST-> with Z value on the RHS of an assignment
|
// CONST-> with Z value on the RHS of an assignment
|
||||||
// AstPin with lower connection a tristate
|
// AstPin with lower connection a tristate
|
||||||
|
|
@ -1067,18 +1067,20 @@ class TristateVisitor : public TristateBaseVisitor {
|
||||||
UINFO(9,dbgState()<<nodep<<endl);
|
UINFO(9,dbgState()<<nodep<<endl);
|
||||||
if (debug()>=9) nodep->dumpTree(cout,"-pin-pre: ");
|
if (debug()>=9) nodep->dumpTree(cout,"-pin-pre: ");
|
||||||
|
|
||||||
// Empty/in-only; need Z to propagate
|
// Empty/in-only; need Z to propagate
|
||||||
bool inDeclProcessing = (nodep->exprp()
|
bool inDeclProcessing = (nodep->exprp()
|
||||||
&& nodep->modVarp()->isInOnly()
|
&& nodep->modVarp()->direction() == VDirection::INPUT
|
||||||
// Need to consider the original state instead of current state
|
// Need to consider the original state
|
||||||
// as we converted tristates to inputs, which do not want to have this.
|
// instead of current state as we converted
|
||||||
&& !nodep->modVarp()->isDeclOutput());
|
// tristates to inputs, which do not want
|
||||||
if (!nodep->exprp()) { // No-connect; covert to empty connection
|
// to have this.
|
||||||
UINFO(5,"Unconnected pin terminate "<<nodep<<endl);
|
&& !nodep->modVarp()->declDirection().isWritable());
|
||||||
AstVar* ucVarp = getCreateUnconnVarp(nodep, nodep->modVarp()->dtypep());
|
if (!nodep->exprp()) { // No-connect; covert to empty connection
|
||||||
nodep->exprp(new AstVarRef(nodep->fileline(), ucVarp,
|
UINFO(5,"Unconnected pin terminate "<<nodep<<endl);
|
||||||
// We converted, so use declaration output state
|
AstVar* ucVarp = getCreateUnconnVarp(nodep, nodep->modVarp()->dtypep());
|
||||||
nodep->modVarp()->isDeclOutput()));
|
nodep->exprp(new AstVarRef(nodep->fileline(), ucVarp,
|
||||||
|
// We converted, so use declaration output state
|
||||||
|
nodep->modVarp()->declDirection().isWritable()));
|
||||||
m_tgraph.setTristate(ucVarp);
|
m_tgraph.setTristate(ucVarp);
|
||||||
// We don't need a driver on the wire; the lack of one will default to tristate
|
// We don't need a driver on the wire; the lack of one will default to tristate
|
||||||
} else if (inDeclProcessing) { // Not an input that was a converted tristate
|
} else if (inDeclProcessing) { // Not an input that was a converted tristate
|
||||||
|
|
@ -1245,11 +1247,12 @@ class TristateVisitor : public TristateBaseVisitor {
|
||||||
nodep->addNextHere(newp);
|
nodep->addNextHere(newp);
|
||||||
// We'll iterate on the new AstPull later
|
// We'll iterate on the new AstPull later
|
||||||
}
|
}
|
||||||
if (nodep->isInout()
|
if (nodep->isInoutish()
|
||||||
//|| varp->isOutput()
|
//|| varp->isOutput()
|
||||||
// Note unconnected output only changes behavior vs. previous versions and causes outputs
|
// Note unconnected output only changes behavior vs. previous
|
||||||
// that don't come from anywhere to possibly create connection errors.
|
// versions and causes outputs that don't come from anywhere to
|
||||||
// One example of problems is this: "output z; task t; z <= {something}; endtask"
|
// possibly create connection errors.
|
||||||
|
// One example of problems is this: "output z; task t; z <= {something}; endtask"
|
||||||
) {
|
) {
|
||||||
UINFO(9," setTristate-inout "<<nodep<<endl);
|
UINFO(9," setTristate-inout "<<nodep<<endl);
|
||||||
m_tgraph.setTristate(nodep);
|
m_tgraph.setTristate(nodep);
|
||||||
|
|
|
||||||
|
|
@ -272,12 +272,12 @@ private:
|
||||||
// For assigns and non-combo always, do just usr==1, to look for module-wide undriven etc
|
// For assigns and non-combo always, do just usr==1, to look for module-wide undriven etc
|
||||||
// For non-combo always, run both usr==1 for above, and also usr==2 for always-only checks
|
// For non-combo always, run both usr==1 for above, and also usr==2 for always-only checks
|
||||||
UndrivenVarEntry* entryp = getEntryp(nodep, usr);
|
UndrivenVarEntry* entryp = getEntryp(nodep, usr);
|
||||||
if (nodep->isInput()
|
if (nodep->isNonOutput()
|
||||||
|| nodep->isSigPublic() || nodep->isSigUserRWPublic()
|
|| nodep->isSigPublic() || nodep->isSigUserRWPublic()
|
||||||
|| (m_taskp && (m_taskp->dpiImport() || m_taskp->dpiExport()))) {
|
|| (m_taskp && (m_taskp->dpiImport() || m_taskp->dpiExport()))) {
|
||||||
entryp->drivenWhole();
|
entryp->drivenWhole();
|
||||||
}
|
}
|
||||||
if (nodep->isOutput()
|
if (nodep->isWritable()
|
||||||
|| nodep->isSigPublic() || nodep->isSigUserRWPublic()
|
|| nodep->isSigPublic() || nodep->isSigUserRWPublic()
|
||||||
|| nodep->isSigUserRdPublic()
|
|| nodep->isSigUserRdPublic()
|
||||||
|| (m_taskp && (m_taskp->dpiImport() || m_taskp->dpiExport()))) {
|
|| (m_taskp && (m_taskp->dpiImport() || m_taskp->dpiExport()))) {
|
||||||
|
|
|
||||||
|
|
@ -2557,7 +2557,7 @@ private:
|
||||||
AstArg* argp = it->second;
|
AstArg* argp = it->second;
|
||||||
AstNode* pinp = argp->exprp();
|
AstNode* pinp = argp->exprp();
|
||||||
if (!pinp) continue; // Argument error we'll find later
|
if (!pinp) continue; // Argument error we'll find later
|
||||||
if ((portp->isOutput() || portp->isInout())
|
if (portp->isWritable()
|
||||||
&& pinp->width() != portp->width()) {
|
&& pinp->width() != portp->width()) {
|
||||||
pinp->v3error("Unsupported: Function output argument '"<<portp->prettyName()<<"'"
|
pinp->v3error("Unsupported: Function output argument '"<<portp->prettyName()<<"'"
|
||||||
<<" requires "<<portp->width()
|
<<" requires "<<portp->width()
|
||||||
|
|
@ -3344,8 +3344,9 @@ private:
|
||||||
AstNodeAssign* assignp = VN_CAST(nodep, NodeAssign);
|
AstNodeAssign* assignp = VN_CAST(nodep, NodeAssign);
|
||||||
AstPin* pinp = VN_CAST(nodep, Pin);
|
AstPin* pinp = VN_CAST(nodep, Pin);
|
||||||
if (assignp && VN_IS(assignp->lhsp(), NodeStream)) {
|
if (assignp && VN_IS(assignp->lhsp(), NodeStream)) {
|
||||||
} else if (pinp && !pinp->modVarp()->isInput()) { // V3Inst::pinReconnectSimple must deal
|
} else if (pinp && pinp->modVarp()->direction() != VDirection::INPUT) {
|
||||||
UINFO(5,"pinInSizeMismatch: "<<pinp);
|
// V3Inst::pinReconnectSimple must deal
|
||||||
|
UINFO(5,"pinInSizeMismatch: "<<pinp);
|
||||||
} else {
|
} else {
|
||||||
fixWidthExtend(underp, expDTypep, extendRule); VL_DANGLING(underp);//Changed
|
fixWidthExtend(underp, expDTypep, extendRule); VL_DANGLING(underp);//Changed
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ class V3ParseGrammar {
|
||||||
public:
|
public:
|
||||||
bool m_impliedDecl; // Allow implied wire declarations
|
bool m_impliedDecl; // Allow implied wire declarations
|
||||||
AstVarType m_varDecl; // Type for next signal declaration (reg/wire/etc)
|
AstVarType m_varDecl; // Type for next signal declaration (reg/wire/etc)
|
||||||
AstVarType m_varIO; // Type for next signal declaration (input/output/etc)
|
VDirection m_varIO; // Direction for next signal declaration (reg/wire/etc)
|
||||||
AstVar* m_varAttrp; // Current variable for attribute adding
|
AstVar* m_varAttrp; // Current variable for attribute adding
|
||||||
AstRange* m_gateRangep; // Current range for gate declarations
|
AstRange* m_gateRangep; // Current range for gate declarations
|
||||||
AstCase* m_caseAttrp; // Current case statement for attribute adding
|
AstCase* m_caseAttrp; // Current case statement for attribute adding
|
||||||
|
|
@ -68,7 +68,7 @@ public:
|
||||||
V3ParseGrammar() {
|
V3ParseGrammar() {
|
||||||
m_impliedDecl = false;
|
m_impliedDecl = false;
|
||||||
m_varDecl = AstVarType::UNKNOWN;
|
m_varDecl = AstVarType::UNKNOWN;
|
||||||
m_varIO = AstVarType::UNKNOWN;
|
m_varIO = VDirection::NONE;
|
||||||
m_varDTypep = NULL;
|
m_varDTypep = NULL;
|
||||||
m_gateRangep = NULL;
|
m_gateRangep = NULL;
|
||||||
m_memDTypep = NULL;
|
m_memDTypep = NULL;
|
||||||
|
|
@ -182,9 +182,9 @@ int V3ParseGrammar::s_modTypeImpNum = 0;
|
||||||
|
|
||||||
#define VARRESET_LIST(decl) { GRAMMARP->m_pinNum=1; VARRESET(); VARDECL(decl); } // Start of pinlist
|
#define VARRESET_LIST(decl) { GRAMMARP->m_pinNum=1; VARRESET(); VARDECL(decl); } // Start of pinlist
|
||||||
#define VARRESET_NONLIST(decl) { GRAMMARP->m_pinNum=0; VARRESET(); VARDECL(decl); } // Not in a pinlist
|
#define VARRESET_NONLIST(decl) { GRAMMARP->m_pinNum=0; VARRESET(); VARDECL(decl); } // Not in a pinlist
|
||||||
#define VARRESET() { VARDECL(UNKNOWN); VARIO(UNKNOWN); VARDTYPE(NULL); }
|
#define VARRESET() { VARDECL(UNKNOWN); VARIO(NONE); VARDTYPE(NULL); }
|
||||||
#define VARDECL(type) { GRAMMARP->m_varDecl = AstVarType::type; }
|
#define VARDECL(type) { GRAMMARP->m_varDecl = AstVarType::type; }
|
||||||
#define VARIO(type) { GRAMMARP->m_varIO = AstVarType::type; }
|
#define VARIO(type) { GRAMMARP->m_varIO = VDirection::type; }
|
||||||
#define VARDTYPE(dtypep) { GRAMMARP->setDType(dtypep); }
|
#define VARDTYPE(dtypep) { GRAMMARP->setDType(dtypep); }
|
||||||
|
|
||||||
#define VARDONEA(fl,name,array,attrs) GRAMMARP->createVariable((fl),(name),(array),(attrs))
|
#define VARDONEA(fl,name,array,attrs) GRAMMARP->createVariable((fl),(name),(array),(attrs))
|
||||||
|
|
@ -899,11 +899,11 @@ port<nodep>: // ==IEEE: port
|
||||||
// // Expanded interface_port_header
|
// // Expanded interface_port_header
|
||||||
// // We use instantCb here because the non-port form looks just like a module instantiation
|
// // We use instantCb here because the non-port form looks just like a module instantiation
|
||||||
portDirNetE id/*interface*/ portSig variable_dimensionListE sigAttrListE
|
portDirNetE id/*interface*/ portSig variable_dimensionListE sigAttrListE
|
||||||
{ $$ = $3; VARDECL(AstVarType::IFACEREF); VARIO(UNKNOWN);
|
{ $$ = $3; VARDECL(AstVarType::IFACEREF); VARIO(NONE);
|
||||||
VARDTYPE(new AstIfaceRefDType($<fl>2,"",*$2));
|
VARDTYPE(new AstIfaceRefDType($<fl>2,"",*$2));
|
||||||
$$->addNextNull(VARDONEP($$,$4,$5)); }
|
$$->addNextNull(VARDONEP($$,$4,$5)); }
|
||||||
| portDirNetE id/*interface*/ '.' idAny/*modport*/ portSig variable_dimensionListE sigAttrListE
|
| portDirNetE id/*interface*/ '.' idAny/*modport*/ portSig variable_dimensionListE sigAttrListE
|
||||||
{ $$ = $5; VARDECL(AstVarType::IFACEREF); VARIO(UNKNOWN);
|
{ $$ = $5; VARDECL(AstVarType::IFACEREF); VARIO(NONE);
|
||||||
VARDTYPE(new AstIfaceRefDType($<fl>2,"",*$2,*$4));
|
VARDTYPE(new AstIfaceRefDType($<fl>2,"",*$2,*$4));
|
||||||
$$->addNextNull(VARDONEP($$,$6,$7)); }
|
$$->addNextNull(VARDONEP($$,$6,$7)); }
|
||||||
| portDirNetE yINTERFACE portSig rangeListE sigAttrListE
|
| portDirNetE yINTERFACE portSig rangeListE sigAttrListE
|
||||||
|
|
@ -3993,13 +3993,12 @@ AstNodeDType* V3ParseGrammar::createArray(AstNodeDType* basep, AstNodeRange* nra
|
||||||
AstVar* V3ParseGrammar::createVariable(FileLine* fileline, string name, AstNodeRange* arrayp, AstNode* attrsp) {
|
AstVar* V3ParseGrammar::createVariable(FileLine* fileline, string name, AstNodeRange* arrayp, AstNode* attrsp) {
|
||||||
AstNodeDType* dtypep = GRAMMARP->m_varDTypep;
|
AstNodeDType* dtypep = GRAMMARP->m_varDTypep;
|
||||||
UINFO(5," creVar "<<name<<" decl="<<GRAMMARP->m_varDecl<<" io="<<GRAMMARP->m_varIO<<" dt="<<(dtypep?"set":"")<<endl);
|
UINFO(5," creVar "<<name<<" decl="<<GRAMMARP->m_varDecl<<" io="<<GRAMMARP->m_varIO<<" dt="<<(dtypep?"set":"")<<endl);
|
||||||
if (GRAMMARP->m_varIO == AstVarType::UNKNOWN
|
if (GRAMMARP->m_varIO == VDirection::NONE
|
||||||
&& GRAMMARP->m_varDecl == AstVarType::PORT) {
|
&& GRAMMARP->m_varDecl == AstVarType::PORT) {
|
||||||
// Just a port list with variable name (not v2k format); AstPort already created
|
// Just a port list with variable name (not v2k format); AstPort already created
|
||||||
if (dtypep) fileline->v3error("Unsupported: Ranges ignored in port-lists");
|
if (dtypep) fileline->v3error("Unsupported: Ranges ignored in port-lists");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
AstVarType type = GRAMMARP->m_varIO;
|
|
||||||
if (GRAMMARP->m_varDecl == AstVarType::WREAL) {
|
if (GRAMMARP->m_varDecl == AstVarType::WREAL) {
|
||||||
// dtypep might not be null, might be implicit LOGIC before we knew better
|
// dtypep might not be null, might be implicit LOGIC before we knew better
|
||||||
dtypep = new AstBasicDType(fileline,AstBasicDTypeKwd::DOUBLE);
|
dtypep = new AstBasicDType(fileline,AstBasicDTypeKwd::DOUBLE);
|
||||||
|
|
@ -4010,21 +4009,28 @@ AstVar* V3ParseGrammar::createVariable(FileLine* fileline, string name, AstNodeR
|
||||||
dtypep = dtypep->cloneTree(false);
|
dtypep = dtypep->cloneTree(false);
|
||||||
}
|
}
|
||||||
//UINFO(0,"CREVAR "<<fileline->ascii()<<" decl="<<GRAMMARP->m_varDecl.ascii()<<" io="<<GRAMMARP->m_varIO.ascii()<<endl);
|
//UINFO(0,"CREVAR "<<fileline->ascii()<<" decl="<<GRAMMARP->m_varDecl.ascii()<<" io="<<GRAMMARP->m_varIO.ascii()<<endl);
|
||||||
if (type == AstVarType::UNKNOWN
|
AstVarType type = GRAMMARP->m_varDecl;
|
||||||
|| (type == AstVarType::PORT && GRAMMARP->m_varDecl != AstVarType::UNKNOWN))
|
if (type == AstVarType::UNKNOWN) {
|
||||||
type = GRAMMARP->m_varDecl;
|
if (GRAMMARP->m_varIO.isAny()) {
|
||||||
if (type == AstVarType::UNKNOWN) fileline->v3fatalSrc("Unknown signal type declared");
|
type = AstVarType::PORT;
|
||||||
|
} else {
|
||||||
|
fileline->v3fatalSrc("Unknown signal type declared");
|
||||||
|
}
|
||||||
|
}
|
||||||
if (type == AstVarType::GENVAR) {
|
if (type == AstVarType::GENVAR) {
|
||||||
if (arrayp) fileline->v3error("Genvars may not be arrayed: "<<name);
|
if (arrayp) fileline->v3error("Genvars may not be arrayed: "<<name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Split RANGE0-RANGE1-RANGE2 into ARRAYDTYPE0(ARRAYDTYPE1(ARRAYDTYPE2(BASICTYPE3),RANGE),RANGE)
|
// Split RANGE0-RANGE1-RANGE2 into ARRAYDTYPE0(ARRAYDTYPE1(ARRAYDTYPE2(BASICTYPE3),RANGE),RANGE)
|
||||||
AstNodeDType* arrayDTypep = createArray(dtypep,arrayp,false);
|
AstNodeDType* arrayDTypep = createArray(dtypep, arrayp, false);
|
||||||
|
|
||||||
AstVar* nodep = new AstVar(fileline, type, name, VFlagChildDType(), arrayDTypep);
|
AstVar* nodep = new AstVar(fileline, type, name, VFlagChildDType(), arrayDTypep);
|
||||||
nodep->addAttrsp(attrsp);
|
nodep->addAttrsp(attrsp);
|
||||||
if (GRAMMARP->m_varDecl != AstVarType::UNKNOWN) nodep->combineType(GRAMMARP->m_varDecl);
|
if (GRAMMARP->m_varDecl != AstVarType::UNKNOWN) nodep->combineType(GRAMMARP->m_varDecl);
|
||||||
if (GRAMMARP->m_varIO != AstVarType::UNKNOWN) nodep->combineType(GRAMMARP->m_varIO);
|
if (GRAMMARP->m_varIO != VDirection::NONE) {
|
||||||
|
nodep->declDirection(GRAMMARP->m_varIO);
|
||||||
|
nodep->direction(GRAMMARP->m_varIO);
|
||||||
|
}
|
||||||
|
|
||||||
if (GRAMMARP->m_varDecl == AstVarType::SUPPLY0) {
|
if (GRAMMARP->m_varDecl == AstVarType::SUPPLY0) {
|
||||||
nodep->addNext(V3ParseGrammar::createSupplyExpr(fileline, nodep->name(), 0));
|
nodep->addNext(V3ParseGrammar::createSupplyExpr(fileline, nodep->name(), 0));
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ compile(
|
||||||
fails => 1,
|
fails => 1,
|
||||||
expect =>
|
expect =>
|
||||||
q{%Error: t/t_func_const_bad.v:11: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_bad_output'
|
q{%Error: t/t_func_const_bad.v:11: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_bad_output'
|
||||||
%Error: t/t_func_const_bad.v:12: ... Location of non-constant VAR 'o': Language violation: Outputs not allowed in constant functions
|
%Error: t/t_func_const_bad.v:12: ... Location of non-constant VAR 'o': Language violation: Outputs/refs not allowed in constant functions
|
||||||
%Error: t/t_func_const_bad.v:20: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_bad_dotted'
|
%Error: t/t_func_const_bad.v:20: Expecting expression to be constant, but can't determine constant for FUNCREF 'f_bad_dotted'
|
||||||
%Error: t/t_func_const_bad.v:22: ... Location of non-constant VARXREF 'EIGHT': Language violation: Dotted hierarchical references not allowed in constant functions
|
%Error: t/t_func_const_bad.v:22: ... Location of non-constant VARXREF 'EIGHT': Language violation: Dotted hierarchical references not allowed in constant functions
|
||||||
Called from:
|
Called from:
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,8 @@ scenarios(simulator => 1);
|
||||||
compile(
|
compile(
|
||||||
fails => 1,
|
fails => 1,
|
||||||
expect =>
|
expect =>
|
||||||
q{%Error: t/t_interface_size_bad.v:\d+: Illegal IFACEREF port connection 'foo', mismatch between port which is an interface array of size 5, and expression which is an interface array of size 4.
|
q{%Error: t/t_interface_size_bad.v:\d+: Illegal port connection 'foo', mismatch between port which is an interface array of size 5, and expression which is an interface array of size 4.
|
||||||
%Error: t/t_interface_size_bad.v:\d+: Illegal IFACEREF port connection 'foo', mismatch between port which is an interface array of size 5, and expression which is an interface array of size 6.
|
%Error: t/t_interface_size_bad.v:\d+: Illegal port connection 'foo', mismatch between port which is an interface array of size 5, and expression which is an interface array of size 6.
|
||||||
%Error: Exiting due to.*},
|
%Error: Exiting due to.*},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
$date
|
$date
|
||||||
Thu Oct 4 19:33:38 2018
|
Sun Oct 21 21:57:08 2018
|
||||||
|
|
||||||
$end
|
$end
|
||||||
$version
|
$version
|
||||||
|
|
@ -9,7 +9,7 @@ $timescale
|
||||||
1ns
|
1ns
|
||||||
$end
|
$end
|
||||||
$scope module top $end
|
$scope module top $end
|
||||||
$var bit 1 ! clk $end
|
$var wire 1 ! clk $end
|
||||||
$scope module t $end
|
$scope module t $end
|
||||||
$var wire 1 ! clk $end
|
$var wire 1 ! clk $end
|
||||||
$var integer 32 " cyc $end
|
$var integer 32 " cyc $end
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
$date
|
$date
|
||||||
Mon Oct 8 07:13:10 2018
|
Sun Oct 21 21:56:13 2018
|
||||||
|
|
||||||
$end
|
$end
|
||||||
$version
|
$version
|
||||||
|
|
@ -9,7 +9,7 @@ $timescale
|
||||||
1ns
|
1ns
|
||||||
$end
|
$end
|
||||||
$scope module top $end
|
$scope module top $end
|
||||||
$var bit 1 ! clk $end
|
$var wire 1 ! clk $end
|
||||||
$scope module t $end
|
$scope module t $end
|
||||||
$var wire 1 ! clk $end
|
$var wire 1 ! clk $end
|
||||||
$var integer 32 " cyc $end
|
$var integer 32 " cyc $end
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
$date
|
$date
|
||||||
Mon Oct 8 07:13:11 2018
|
Sun Oct 21 21:56:26 2018
|
||||||
|
|
||||||
$end
|
$end
|
||||||
$version
|
$version
|
||||||
|
|
@ -9,7 +9,7 @@ $timescale
|
||||||
1ns
|
1ns
|
||||||
$end
|
$end
|
||||||
$scope module top $end
|
$scope module top $end
|
||||||
$var bit 1 ! clk $end
|
$var wire 1 ! clk $end
|
||||||
$scope module t $end
|
$scope module t $end
|
||||||
$var wire 1 ! clk $end
|
$var wire 1 ! clk $end
|
||||||
$var integer 32 " cyc $end
|
$var integer 32 " cyc $end
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
$date
|
$date
|
||||||
Mon Oct 8 07:13:12 2018
|
Sun Oct 21 21:56:37 2018
|
||||||
|
|
||||||
$end
|
$end
|
||||||
$version
|
$version
|
||||||
|
|
@ -9,7 +9,7 @@ $timescale
|
||||||
1ns
|
1ns
|
||||||
$end
|
$end
|
||||||
$scope module top $end
|
$scope module top $end
|
||||||
$var bit 1 ! clk $end
|
$var wire 1 ! clk $end
|
||||||
$scope module t $end
|
$scope module t $end
|
||||||
$var wire 1 ! clk $end
|
$var wire 1 ! clk $end
|
||||||
$var integer 32 " cyc $end
|
$var integer 32 " cyc $end
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
$date
|
$date
|
||||||
Thu Oct 4 19:26:16 2018
|
Sun Oct 21 21:55:42 2018
|
||||||
|
|
||||||
$end
|
$end
|
||||||
$version
|
$version
|
||||||
|
|
@ -9,8 +9,8 @@ $timescale
|
||||||
1ns
|
1ns
|
||||||
$end
|
$end
|
||||||
$scope module top $end
|
$scope module top $end
|
||||||
$var bit 1 ! clk $end
|
$var wire 1 ! clk $end
|
||||||
$var logic 5 " state $end
|
$var wire 5 " state $end
|
||||||
$scope module t $end
|
$scope module t $end
|
||||||
$var wire 1 ! clk $end
|
$var wire 1 ! clk $end
|
||||||
$var int 32 # cyc $end
|
$var int 32 # cyc $end
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
$date
|
$date
|
||||||
Thu Oct 4 19:33:41 2018
|
Sun Oct 21 21:56:54 2018
|
||||||
|
|
||||||
$end
|
$end
|
||||||
$version
|
$version
|
||||||
|
|
@ -9,7 +9,7 @@ $timescale
|
||||||
1ns
|
1ns
|
||||||
$end
|
$end
|
||||||
$scope module top $end
|
$scope module top $end
|
||||||
$var bit 1 ! clk $end
|
$var wire 1 ! clk $end
|
||||||
$scope module t $end
|
$scope module t $end
|
||||||
$var wire 1 ! clk $end
|
$var wire 1 ! clk $end
|
||||||
$var int 32 " cnt $end
|
$var int 32 " cnt $end
|
||||||
|
|
|
||||||
|
|
@ -7,14 +7,14 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
||||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
# Version 2.0.
|
# Version 2.0.
|
||||||
|
|
||||||
scenarios(vlt_all => 1);
|
scenarios(vlt => 1);
|
||||||
|
|
||||||
compile(
|
compile(
|
||||||
v_flags2 => ["--lint-only --Mdir obj_lint_only"],
|
v_flags2 => ["--lint-only --Mdir obj_lint_only"],
|
||||||
fails => 1,
|
fails => 1,
|
||||||
expect =>
|
expect =>
|
||||||
'%Error-ASSIGNIN: t/t_var_in_assign_bad.v:\d+: Assigning to input variable: value
|
'%Error-ASSIGNIN: t/t_var_in_assign_bad.v:\d+: Assigning to input/const variable: value
|
||||||
%Error-ASSIGNIN: t/t_var_in_assign_bad.v:\d+: Assigning to input variable: valueSub
|
%Error-ASSIGNIN: t/t_var_in_assign_bad.v:\d+: Assigning to input/const variable: valueSub
|
||||||
%Error: Exiting due to.*',
|
%Error: Exiting due to.*',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue