Internals: Parse lifetime directives; still unsupported.

This commit is contained in:
Wilson Snyder 2020-04-26 12:45:06 -04:00
parent 87e1c36e4a
commit 70549e1a64
8 changed files with 116 additions and 30 deletions

View File

@ -94,6 +94,32 @@ inline std::ostream& operator<<(std::ostream& os, const AstType& rhs) { return o
//######################################################################
class VLifetime {
public:
enum en { NONE, AUTOMATIC, STATIC };
enum en m_e;
const char* ascii() const {
static const char* const names[] = {"NONE", "VAUTOM", "VSTATIC"};
return names[m_e];
}
inline VLifetime()
: m_e(NONE) {}
// cppcheck-suppress noExplicitConstructor
inline VLifetime(en _e)
: m_e(_e) {}
explicit inline VLifetime(int _e)
: m_e(static_cast<en>(_e)) {}
operator en() const { return m_e; }
bool isNone() const { return m_e == NONE; }
bool isAutomatic() const { return m_e == AUTOMATIC; }
bool isStatic() const { return m_e == STATIC; }
};
inline bool operator==(const VLifetime& lhs, const VLifetime& rhs) { return lhs.m_e == rhs.m_e; }
inline bool operator==(const VLifetime& lhs, VLifetime::en rhs) { return lhs.m_e == rhs; }
inline bool operator==(VLifetime::en lhs, const VLifetime& rhs) { return lhs == rhs.m_e; }
//######################################################################
class VSigning {
public:
enum en {
@ -2575,6 +2601,7 @@ private:
bool m_dpiTask : 1; // DPI import task (vs. void function)
bool m_isConstructor : 1; // Class constructor
bool m_pure : 1; // DPI import pure (vs. virtual pure)
VLifetime m_lifetime; // Lifetime
public:
AstNodeFTask(AstType t, FileLine* fl, const string& name, AstNode* stmtsp)
: AstNode(t, fl)
@ -2639,6 +2666,8 @@ public:
bool isConstructor() const { return m_isConstructor; }
void pure(bool flag) { m_pure = flag; }
bool pure() const { return m_pure; }
void lifetime(const VLifetime& flag) { m_lifetime = flag; }
VLifetime lifetime() const { return m_lifetime; }
};
class AstNodeFTaskRef : public AstNodeStmt {
@ -2715,6 +2744,7 @@ private:
int m_level; // 1=top module, 2=cell off top module, ...
int m_varNum; // Incrementing variable number
int m_typeNum; // Incrementing implicit type number
VLifetime m_lifetime; // Lifetime
VTimescale m_timeunit; // Global time unit
VOptionBool m_unconnectedDrive; // State of `unconnected_drive
public:
@ -2766,6 +2796,8 @@ public:
bool recursive() const { return m_recursive; }
void recursiveClone(bool flag) { m_recursiveClone = flag; }
bool recursiveClone() const { return m_recursiveClone; }
void lifetime(const VLifetime& flag) { m_lifetime = flag; }
VLifetime lifetime() const { return m_lifetime; }
void timeunit(const VTimescale& flag) { m_timeunit = flag; }
VTimescale timeunit() const { return m_timeunit; }
void unconnectedDrive(const VOptionBool flag) { m_unconnectedDrive = flag; }

View File

@ -1437,6 +1437,7 @@ void AstVar::dump(std::ostream& str) const {
}
if (isDpiOpenArray()) str << " [DPIOPENA]";
if (!attrClocker().unknown()) str << " [" << attrClocker().ascii() << "] ";
if (!lifetime().isNone()) str << " [" << lifetime().ascii() << "] ";
str << " " << varType();
}
void AstSenTree::dump(std::ostream& str) const {

View File

@ -1780,7 +1780,7 @@ private:
bool m_attrSplitVar : 1; // declared with split_var metacomment
bool m_fileDescr : 1; // File descriptor
bool m_isConst : 1; // Table contains constant data
bool m_isStatic : 1; // Static variable
bool m_isStatic : 1; // Static C variable (for Verilog see instead isAutomatic)
bool m_isPulldown : 1; // Tri0
bool m_isPullup : 1; // Tri1
bool m_isIfaceParent : 1; // dtype is reference to interface present in this module
@ -1788,6 +1788,7 @@ private:
bool m_noReset : 1; // Do not do automated reset/randomization
bool m_noSubst : 1; // Do not substitute out references
bool m_trace : 1; // Trace this variable
VLifetime m_lifetime; // Lifetime
VVarAttrClocker m_attrClocker;
MTaskIdSet m_mtaskIds; // MTaskID's that read or write this var
@ -2037,6 +2038,8 @@ public:
bool attrIsolateAssign() const { return m_attrIsolateAssign; }
VVarAttrClocker attrClocker() const { return m_attrClocker; }
virtual string verilogKwd() const;
void lifetime(const VLifetime& flag) { m_lifetime = flag; }
VLifetime lifetime() const { return m_lifetime; }
void propagateAttrFrom(AstVar* fromp) {
// This is getting connected to fromp; keep attributes
// Note the method below too

View File

@ -1006,6 +1006,7 @@ class LinkDotFindVisitor : public AstNVisitor {
AstVar* newvarp = new AstVar(nodep->fileline(), AstVarType::VAR, nodep->name(),
VFlagChildDType(), dtypep); // Not dtype resolved yet
newvarp->direction(VDirection::OUTPUT);
newvarp->lifetime(VLifetime::AUTOMATIC);
newvarp->funcReturn(true);
newvarp->trace(false); // Not user visible
newvarp->attrIsolateAssign(nodep->attrIsolateAssign());

View File

@ -53,6 +53,7 @@ private:
AstClass* m_classp; // Class we're inside
AstNodeFTask* m_ftaskp; // Function or task we're inside
AstNodeCoverOrAssert* m_assertp; // Current assertion
VLifetime m_lifetime; // Propagating lifetime
int m_senitemCvtNum; // Temporary signal counter
// METHODS
@ -67,14 +68,30 @@ private:
UINFO(8, "MODULE " << nodep << endl);
if (nodep->dead()) return;
AstNodeModule* origModp = m_modp;
VLifetime origLifetime = m_lifetime;
int origSenitemCvtNum = m_senitemCvtNum;
{
m_modp = nodep;
m_senitemCvtNum = 0;
m_lifetime = nodep->lifetime();
if (m_lifetime.isNone()) m_lifetime = VLifetime::STATIC;
iterateChildren(nodep);
}
m_modp = origModp;
m_senitemCvtNum = origSenitemCvtNum;
m_lifetime = origLifetime;
}
virtual void visit(AstClass* nodep) VL_OVERRIDE {
AstClass* origClassp = m_classp;
VLifetime origLifetime = m_lifetime;
{
m_classp = nodep;
m_lifetime = nodep->lifetime();
if (m_lifetime.isNone()) m_lifetime = VLifetime::AUTOMATIC;
iterateChildren(nodep);
}
m_classp = origClassp;
m_lifetime = origLifetime;
}
virtual void visit(AstInitial* nodep) VL_OVERRIDE {
iterateChildren(nodep);
@ -90,19 +107,12 @@ private:
iterateChildren(nodep);
m_assertp = NULL;
}
virtual void visit(AstClass* nodep) VL_OVERRIDE {
AstClass* origClassp = m_classp;
{
m_classp = nodep;
iterateChildren(nodep);
}
m_classp = origClassp;
}
virtual void visit(AstVar* nodep) VL_OVERRIDE {
iterateChildren(nodep);
if (m_classp && !nodep->isParam()) nodep->varType(AstVarType::MEMBER);
if (m_classp && nodep->isParam()) nodep->v3error("Unsupported: class parameter");
if (m_ftaskp) nodep->funcLocal(true);
if (nodep->lifetime().isNone()) nodep->lifetime(m_lifetime);
if (nodep->isSigModPublic()) {
nodep->sigModPublic(false); // We're done with this attribute
m_modp->modPublic(true); // Avoid flattening if signals are exposed
@ -119,9 +129,15 @@ private:
// NodeTask: Remember its name for later resolution
// Remember the existing symbol table scope
if (m_classp) nodep->classMethod(true);
m_ftaskp = nodep;
iterateChildren(nodep);
VLifetime origLifetime = m_lifetime;
{
if (!nodep->lifetime().isNone()) m_lifetime = nodep->lifetime();
if (m_lifetime.isNone()) m_lifetime = VLifetime::AUTOMATIC;
m_ftaskp = nodep;
iterateChildren(nodep);
}
m_ftaskp = NULL;
m_lifetime = origLifetime;
if (nodep->dpiExport()) { nodep->scopeNamep(new AstScopeName(nodep->fileline())); }
}
virtual void visit(AstNodeFTaskRef* nodep) VL_OVERRIDE {
@ -472,13 +488,13 @@ private:
public:
// CONSTRUCTORS
explicit LinkResolveVisitor(AstNetlist* rootp) {
explicit LinkResolveVisitor(AstNetlist* rootp)
: m_lifetime(VLifetime::STATIC) { // Static outside a module/class
m_classp = NULL;
m_ftaskp = NULL;
m_modp = NULL;
m_assertp = NULL;
m_senitemCvtNum = 0;
//
iterate(rootp);
}
virtual ~LinkResolveVisitor() {}

View File

@ -183,6 +183,7 @@ AstVar* V3ParseGrammar::createVariable(FileLine* fileline, const string& name,
nodep->addAttrsp(attrsp);
nodep->ansi(m_pinAnsi);
nodep->declTyped(m_varDeclTyped);
nodep->lifetime(m_varLifetime);
if (GRAMMARP->m_varDecl != AstVarType::UNKNOWN) nodep->combineType(GRAMMARP->m_varDecl);
if (GRAMMARP->m_varIO != VDirection::NONE) {
nodep->declDirection(GRAMMARP->m_varIO);

View File

@ -59,6 +59,7 @@ struct V3ParseBisonYYSType {
VSigning::en signstate;
V3ErrorCode::en errcodeen;
AstAttrType::en attrtypeen;
VLifetime::en lifetime;
AstNode* nodep;

View File

@ -50,6 +50,7 @@ public:
AstVarType m_varDecl; // Type for next signal declaration (reg/wire/etc)
bool m_varDeclTyped; // Var got reg/wire for dedup check
VDirection m_varIO; // Direction for next signal declaration (reg/wire/etc)
VLifetime m_varLifetime; // Static/Automatic for next signal
AstVar* m_varAttrp; // Current variable for attribute adding
AstRange* m_gateRangep; // Current range for gate declarations
AstCase* m_caseAttrp; // Current case statement for attribute adding
@ -194,9 +195,11 @@ int V3ParseGrammar::s_modTypeImpNum = 0;
#define VARRESET_NONLIST(decl) { GRAMMARP->m_pinNum=0; GRAMMARP->m_pinAnsi=false; \
VARRESET(); VARDECL(decl); } // Not in a pinlist
#define VARRESET() { VARDECL(UNKNOWN); VARIO(NONE); VARDTYPE_NDECL(NULL); \
GRAMMARP->m_varLifetime = VLifetime::NONE; \
GRAMMARP->m_varDeclTyped = false; }
#define VARDECL(type) { GRAMMARP->setVarDecl(AstVarType::type); }
#define VARIO(type) { GRAMMARP->m_varIO = VDirection::type; }
#define VARLIFE(flag) { GRAMMARP->m_varLifetime = flag; }
#define VARDTYPE(dtypep) { GRAMMARP->setDType(dtypep); GRAMMARP->m_varDeclTyped = true; }
#define VARDTYPE_NDECL(dtypep) { GRAMMARP->setDType(dtypep); } // Port that is range or signed only (not a decl)
@ -794,6 +797,8 @@ class AstSenTree;
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
// Blank lines for type insertion
%start source_text
@ -852,6 +857,7 @@ packageFront<modulep>:
yPACKAGE lifetimeE idAny ';'
{ $$ = new AstPackage($<fl>3, *$3);
$$->inLibrary(true); // packages are always libraries; don't want to make them a "top"
$$->lifetime($2);
$$->modTrace(GRAMMARP->allTracingOn($$->fileline()));
$$->timeunit(PARSEP->timeLastUnit());
PARSEP->rootp()->addModulep($$);
@ -967,6 +973,7 @@ modFront<modulep>:
// // any formal arguments, as the arguments must land in the new scope.
yMODULE lifetimeE idAny
{ $$ = new AstModule($<fl>3,*$3);
$$->lifetime($2);
$$->inLibrary(PARSEP->inLibrary() || PARSEP->inCellDefine());
$$->modTrace(GRAMMARP->allTracingOn($$->fileline()));
$$->timeunit(PARSEP->timeLastUnit());
@ -985,6 +992,7 @@ importsAndParametersE<nodep>: // IEEE: common part of module_declaration, interf
udpFront<modulep>:
yPRIMITIVE lifetimeE idAny
{ $$ = new AstPrimitive($<fl>3, *$3); $$->inLibrary(true);
$$->lifetime($2);
$$->modTrace(false);
$$->addStmtp(new AstPragma($<fl>3, AstPragmaType::INLINE_MODULE));
GRAMMARP->m_tracingParse = false;
@ -1167,6 +1175,7 @@ intFront<modulep>:
yINTERFACE lifetimeE idAny/*new_interface*/
{ $$ = new AstIface($<fl>3, *$3);
$$->inLibrary(true);
$$->lifetime($2);
PARSEP->rootp()->addModulep($$);
SYMP->pushNew($$); }
;
@ -1253,6 +1262,7 @@ program_declaration: // IEEE: program_declaration + program_nonansi_header + pr
pgmFront<modulep>:
yPROGRAM lifetimeE idAny/*new_program*/
{ $$ = new AstModule($<fl>3,*$3);
$$->lifetime($2);
$$->inLibrary(PARSEP->inLibrary() || PARSEP->inCellDefine());
$$->modTrace(GRAMMARP->allTracingOn($$->fileline()));
$$->timeunit(PARSEP->timeLastUnit());
@ -1885,19 +1895,33 @@ data_declarationVarFront: // IEEE: part of data_declaration
//
// // Expanded: "constE yVAR lifetimeE data_type"
// // implicit_type expanded into /*empty*/ or "signingE rangeList"
/**/ yVAR lifetimeE data_type { VARRESET_NONLIST(VAR); VARDTYPE($3); }
| /**/ yVAR lifetimeE { VARRESET_NONLIST(VAR); VARDTYPE(new AstBasicDType($<fl>1, LOGIC_IMPLICIT)); }
| /**/ yVAR lifetimeE signingE rangeList { /*VARRESET-in-ddVar*/ VARDTYPE(GRAMMARP->addRange(new AstBasicDType($<fl>1, LOGIC_IMPLICIT, $3), $4,true)); }
/**/ yVAR lifetimeE data_type
{ VARRESET_NONLIST(VAR); VARLIFE($2); VARDTYPE($3); }
| /**/ yVAR lifetimeE
{ VARRESET_NONLIST(VAR); VARLIFE($2);
VARDTYPE(new AstBasicDType($<fl>1, LOGIC_IMPLICIT)); }
| /**/ yVAR lifetimeE signingE rangeList
{ /*VARRESET-in-ddVar*/ VARLIFE($2);
VARDTYPE(GRAMMARP->addRange(new AstBasicDType($<fl>1, LOGIC_IMPLICIT, $3), $4,true)); }
//
// // implicit_type expanded into /*empty*/ or "signingE rangeList"
| yCONST__ETC yVAR lifetimeE data_type { VARRESET_NONLIST(VAR); VARDTYPE(new AstConstDType($<fl>2, VFlagChildDType(), $4)); }
| yCONST__ETC yVAR lifetimeE { VARRESET_NONLIST(VAR); VARDTYPE(new AstConstDType($<fl>2, VFlagChildDType(), new AstBasicDType($<fl>2, LOGIC_IMPLICIT))); }
| yCONST__ETC yVAR lifetimeE signingE rangeList { VARRESET_NONLIST(VAR); VARDTYPE(new AstConstDType($<fl>2, VFlagChildDType(), GRAMMARP->addRange(new AstBasicDType($<fl>2, LOGIC_IMPLICIT, $4), $5,true))); }
| yCONST__ETC yVAR lifetimeE data_type
{ VARRESET_NONLIST(VAR); VARLIFE($3);
VARDTYPE(new AstConstDType($<fl>2, VFlagChildDType(), $4)); }
| yCONST__ETC yVAR lifetimeE
{ VARRESET_NONLIST(VAR); VARLIFE($3);
VARDTYPE(new AstConstDType($<fl>2, VFlagChildDType(), new AstBasicDType($<fl>2, LOGIC_IMPLICIT))); }
| yCONST__ETC yVAR lifetimeE signingE rangeList
{ VARRESET_NONLIST(VAR); VARLIFE($3);
VARDTYPE(new AstConstDType($<fl>2, VFlagChildDType(),
GRAMMARP->addRange(new AstBasicDType($<fl>2, LOGIC_IMPLICIT, $4), $5,true))); }
//
// // Expanded: "constE lifetimeE data_type"
| /**/ data_type { VARRESET_NONLIST(VAR); VARDTYPE($1); }
| /**/ lifetime data_type { VARRESET_NONLIST(VAR); VARDTYPE($2); }
| yCONST__ETC lifetimeE data_type { VARRESET_NONLIST(VAR); VARDTYPE(new AstConstDType($<fl>1, VFlagChildDType(), $3)); }
| /**/ lifetime data_type { VARRESET_NONLIST(VAR); VARLIFE($1); VARDTYPE($2); }
| yCONST__ETC lifetimeE data_type
{ VARRESET_NONLIST(VAR); VARLIFE($2);
VARDTYPE(new AstConstDType($<fl>1, VFlagChildDType(), $3)); }
// // = class_new is in variable_decl_assignment
;
@ -1905,9 +1929,11 @@ data_declarationVarFrontClass: // IEEE: part of data_declaration (for class_prop
// // VARRESET called before this rule
// // yCONST is removed, added to memberQual rules
// // implicit_type expanded into /*empty*/ or "signingE rangeList"
yVAR lifetimeE data_type { VARRESET_NONLIST(VAR); VARDTYPE($3); }
| yVAR lifetimeE { VARRESET_NONLIST(VAR); }
| yVAR lifetimeE signingE rangeList { /*VARRESET-in-ddVar*/ VARDTYPE(GRAMMARP->addRange(new AstBasicDType($<fl>1, LOGIC_IMPLICIT, $3), $4,true)); }
yVAR lifetimeE data_type { VARRESET_NONLIST(VAR); VARLIFE($2); VARDTYPE($3); }
| yVAR lifetimeE { VARRESET_NONLIST(VAR); VARLIFE($2); }
| yVAR lifetimeE signingE rangeList
{ /*VARRESET-in-ddVar*/ VARDTYPE(GRAMMARP->addRange(new AstBasicDType($<fl>1, LOGIC_IMPLICIT, $3), $4,true));
VARLIFE($2); }
//
// // Expanded: "constE lifetimeE data_type"
| data_type { VARRESET_NONLIST(VAR); VARDTYPE($1); }
@ -3484,6 +3510,7 @@ list_of_argumentsE<nodep>: // IEEE: [list_of_arguments]
task_declaration<ftaskp>: // ==IEEE: task_declaration
yTASK lifetimeE taskId tfGuts yENDTASK endLabelE
{ $$ = $3; $$->addStmtsp($4); SYMP->popScope($$);
$$->lifetime($2);
GRAMMARP->endLabel($<fl>6,$$,$6); }
;
@ -3495,10 +3522,12 @@ task_prototype<ftaskp>: // ==IEEE: task_prototype
function_declaration<ftaskp>: // IEEE: function_declaration + function_body_declaration
yFUNCTION lifetimeE funcId funcIsolateE tfGuts yENDFUNCTION endLabelE
{ $$ = $3; $3->attrIsolateAssign($4); $$->addStmtsp($5);
$$->lifetime($2);
SYMP->popScope($$);
GRAMMARP->endLabel($<fl>7,$$,$7); }
| yFUNCTION lifetimeE funcIdNew funcIsolateE tfGuts yENDFUNCTION endLabelE
{ $$ = $3; $3->attrIsolateAssign($4); $$->addStmtsp($5);
$$->lifetime($2);
SYMP->popScope($$);
GRAMMARP->endLabel($<fl>7,$$,$7); }
;
@ -3523,15 +3552,15 @@ method_prototype:
| function_prototype { }
;
lifetimeE: // IEEE: [lifetime]
/* empty */ { }
| lifetime { }
lifetimeE<lifetime>: // IEEE: [lifetime]
/* empty */ { $$ = VLifetime::NONE; }
| lifetime { $$ = $1; }
;
lifetime: // ==IEEE: lifetime
lifetime<lifetime>: // ==IEEE: lifetime
// // Note lifetime used by members is instead under memberQual
ySTATIC__ETC { BBUNSUP($1, "Unsupported: Static in this context"); }
| yAUTOMATIC { }
ySTATIC__ETC { $$ = VLifetime::STATIC; BBUNSUP($1, "Unsupported: Static in this context"); }
| yAUTOMATIC { $$ = VLifetime::AUTOMATIC; }
;
taskId<ftaskp>:
@ -5481,10 +5510,12 @@ class_declaration<nodep>: // ==IEEE: part of class_declaration
classFront<classp>: // IEEE: part of class_declaration
classVirtualE yCLASS lifetimeE idAny/*class_identifier*/
{ $$ = new AstClass($2, *$4);
$$->lifetime($3);
SYMP->pushNew($<classp>$); }
// // IEEE: part of interface_class_declaration
| yINTERFACE yCLASS lifetimeE idAny/*class_identifier*/
{ $$ = new AstClass($2, *$4);
$$->lifetime($3);
SYMP->pushNew($<classp>$);
BBUNSUP($2, "Unsupported: interface classes"); }
;