Internals: Move code out of verilog.y. No functional change.

This commit is contained in:
Wilson Snyder 2019-06-11 21:19:44 -04:00
parent dd8d5ef687
commit 77c2d49d1a
2 changed files with 230 additions and 212 deletions

View File

@ -22,5 +22,233 @@
#include "V3Ast.h" // This must be before V3ParseBison.cpp, as we don't want #defines to conflict
//======================================================================
// The guts came from bison
// The guts come from bison output
#include "V3ParseBison.c"
//======================================================================
// V3ParseImp functions requiring bison state
int V3ParseImp::bisonParse() {
// Use --debugi-bison 9 to enable this
if (PARSEP->debugBison()>=9) yydebug = 1;
return yyparse();
}
const char* V3ParseImp::tokenName(int token) {
#if YYDEBUG || YYERROR_VERBOSE
static const char** nameTablep = NULL;
if (!nameTablep) {
int size;
for (size = 0; yytname[size]; ++size) ;
nameTablep = new const char* [size];
// Workaround bug in bison's which have '!' in yytname but not token values
int iout = 0;
for (int i = 0; yytname[i]; ++i) {
if (yytname[i][0] == '\'') continue;
nameTablep[iout++] = yytname[i];
}
}
if (token >= 255) {
return nameTablep[token-255];
} else {
static char ch[2]; ch[0] = token; ch[1] = '\0';
return ch;
}
#else
return "";
#endif
}
void V3ParseImp::parserClear() {
// Clear up any dynamic memory V3Parser required
VARDTYPE(NULL);
}
//======================================================================
// V3ParseGrammar functions requiring bison state
void V3ParseGrammar::argWrapList(AstNodeFTaskRef* nodep) {
// Convert list of expressions to list of arguments
AstNode* outp = NULL;
while (nodep->pinsp()) {
AstNode* exprp = nodep->pinsp()->unlinkFrBack();
// addNext can handle nulls:
outp = AstNode::addNext(outp, new AstArg(exprp->fileline(), "", exprp));
}
if (outp) nodep->addPinsp(outp);
}
AstNode* V3ParseGrammar::createSupplyExpr(FileLine* fileline, string name, int value) {
return new AstAssignW(fileline, new AstVarRef(fileline, name, true),
new AstConst(fileline, AstConst::StringToParse(),
(value ? "'1" : "'0")));
}
AstRange* V3ParseGrammar::scrubRange(AstNodeRange* nrangep) {
// Remove any UnsizedRange's from list
for (AstNodeRange* nodep = nrangep, *nextp; nodep; nodep = nextp) {
nextp = VN_CAST(nrangep->nextp(), NodeRange);
if (!VN_IS(nodep, Range)) {
nodep->v3error("Unsupported or syntax error: Unsized range in cell or other declaration");
nodep->unlinkFrBack(); nodep->deleteTree(); VL_DANGLING(nodep);
}
}
return VN_CAST(nrangep, Range);
}
AstNodeDType* V3ParseGrammar::createArray(AstNodeDType* basep,
AstNodeRange* nrangep, bool isPacked) {
// Split RANGE0-RANGE1-RANGE2
// into ARRAYDTYPE0(ARRAYDTYPE1(ARRAYDTYPE2(BASICTYPE3), RANGE), RANGE)
AstNodeDType* arrayp = basep;
if (nrangep) { // Maybe no range - return unmodified base type
while (nrangep->nextp()) nrangep = VN_CAST(nrangep->nextp(), NodeRange);
while (nrangep) {
AstNodeRange* prevp = VN_CAST(nrangep->backp(), NodeRange);
if (prevp) nrangep->unlinkFrBack();
AstRange* rangep = VN_CAST(nrangep, Range);
if (!rangep) {
if (!VN_IS(nrangep, UnsizedRange)) {
nrangep->v3fatalSrc("Expected range or unsized range");
}
arrayp = new AstUnsizedArrayDType
(nrangep->fileline(), VFlagChildDType(), arrayp);
} else if (isPacked) {
arrayp = new AstPackArrayDType
(rangep->fileline(), VFlagChildDType(), arrayp, rangep);
} else {
arrayp = new AstUnpackArrayDType
(rangep->fileline(), VFlagChildDType(), arrayp, rangep);
}
nrangep = prevp;
}
}
return arrayp;
}
AstVar* V3ParseGrammar::createVariable(FileLine* fileline, string name,
AstNodeRange* arrayp, AstNode* attrsp) {
AstNodeDType* dtypep = GRAMMARP->m_varDTypep;
UINFO(5," creVar "<<name<<" decl="<<GRAMMARP->m_varDecl
<<" io="<<GRAMMARP->m_varIO<<" dt="<<(dtypep?"set":"")<<endl);
if (GRAMMARP->m_varIO == VDirection::NONE
&& GRAMMARP->m_varDecl == AstVarType::PORT) {
// Just a port list with variable name (not v2k format); AstPort already created
if (dtypep) fileline->v3error("Unsupported: Ranges ignored in port-lists");
return NULL;
}
if (GRAMMARP->m_varDecl == AstVarType::WREAL) {
// dtypep might not be null, might be implicit LOGIC before we knew better
dtypep = new AstBasicDType(fileline, AstBasicDTypeKwd::DOUBLE);
}
if (!dtypep) { // Created implicitly
dtypep = new AstBasicDType(fileline, LOGIC_IMPLICIT);
} else { // May make new variables with same type, so clone
dtypep = dtypep->cloneTree(false);
}
//UINFO(0,"CREVAR "<<fileline->ascii()<<" decl="<<GRAMMARP->m_varDecl.ascii()<<" io="<<GRAMMARP->m_varIO.ascii()<<endl);
AstVarType type = GRAMMARP->m_varDecl;
if (type == AstVarType::UNKNOWN) {
if (GRAMMARP->m_varIO.isAny()) {
type = AstVarType::PORT;
} else {
fileline->v3fatalSrc("Unknown signal type declared");
}
}
if (type == AstVarType::GENVAR) {
if (arrayp) fileline->v3error("Genvars may not be arrayed: "<<name);
}
// Split RANGE0-RANGE1-RANGE2 into
// ARRAYDTYPE0(ARRAYDTYPE1(ARRAYDTYPE2(BASICTYPE3), RANGE), RANGE)
AstNodeDType* arrayDTypep = createArray(dtypep, arrayp, false);
AstVar* nodep = new AstVar(fileline, type, name, VFlagChildDType(), arrayDTypep);
nodep->addAttrsp(attrsp);
if (GRAMMARP->m_varDecl != AstVarType::UNKNOWN) nodep->combineType(GRAMMARP->m_varDecl);
if (GRAMMARP->m_varIO != VDirection::NONE) {
nodep->declDirection(GRAMMARP->m_varIO);
nodep->direction(GRAMMARP->m_varIO);
}
if (GRAMMARP->m_varDecl == AstVarType::SUPPLY0) {
nodep->addNext(V3ParseGrammar::createSupplyExpr(fileline, nodep->name(), 0));
}
if (GRAMMARP->m_varDecl == AstVarType::SUPPLY1) {
nodep->addNext(V3ParseGrammar::createSupplyExpr(fileline, nodep->name(), 1));
}
if (VN_IS(dtypep, ParseTypeDType)) {
// Parser needs to know what is a type
AstNode* newp = new AstTypedefFwd(fileline, name);
nodep->addNext(newp);
SYMP->reinsert(newp);
}
// Don't set dtypep in the ranging;
// We need to autosize parameters and integers separately
//
// Propagate from current module tracing state
if (nodep->isGenVar()) nodep->trace(false);
else if (nodep->isParam() && !v3Global.opt.traceParams()) nodep->trace(false);
else nodep->trace(allTracingOn(nodep->fileline()));
// Remember the last variable created, so we can attach attributes to it in later parsing
GRAMMARP->m_varAttrp = nodep;
PARSEP->tagNodep(GRAMMARP->m_varAttrp);
return nodep;
}
string V3ParseGrammar::deQuote(FileLine* fileline, string text) {
// Fix up the quoted strings the user put in, for example "\"" becomes "
// Reverse is V3OutFormatter::quoteNameControls(...)
bool quoted = false;
string newtext;
unsigned char octal_val = 0;
int octal_digits = 0;
for (string::const_iterator cp = text.begin(); cp != text.end(); ++cp) {
if (quoted) {
if (isdigit(*cp)) {
octal_val = octal_val*8 + (*cp-'0');
if (++octal_digits == 3) {
octal_digits = 0;
quoted = false;
newtext += octal_val;
}
} else {
if (octal_digits) {
// Spec allows 1-3 digits
octal_digits = 0;
quoted = false;
newtext += octal_val;
--cp; // Backup to reprocess terminating character as non-escaped
continue;
}
quoted = false;
if (*cp == 'n') newtext += '\n';
else if (*cp == 'a') newtext += '\a'; // SystemVerilog 3.1
else if (*cp == 'f') newtext += '\f'; // SystemVerilog 3.1
else if (*cp == 'r') newtext += '\r';
else if (*cp == 't') newtext += '\t';
else if (*cp == 'v') newtext += '\v'; // SystemVerilog 3.1
else if (*cp == 'x' && isxdigit(cp[1]) && isxdigit(cp[2])) { // SystemVerilog 3.1
#define vl_decodexdigit(c) ((isdigit(c)?((c)-'0'):(tolower((c))-'a'+10)))
newtext += (char)(16*vl_decodexdigit(cp[1]) + vl_decodexdigit(cp[2]));
cp += 2;
}
else if (isalnum(*cp)) {
fileline->v3error("Unknown escape sequence: \\"<<*cp);
break;
}
else newtext += *cp;
}
}
else if (*cp == '\\') {
quoted = true;
octal_digits = 0;
}
else if (*cp != '"') {
newtext += *cp;
}
}
return newtext;
}

View File

@ -4042,217 +4042,7 @@ vltOnFront<errcodeen>:
//**********************************************************************
%%
int V3ParseImp::bisonParse() {
// Use --debugi-bison 9 to enable this
if (PARSEP->debugBison()>=9) yydebug = 1;
return yyparse();
}
const char* V3ParseImp::tokenName(int token) {
#if YYDEBUG || YYERROR_VERBOSE
static const char** nameTablep = NULL;
if (!nameTablep) {
int size;
for (size=0; yytname[size]; ++size) ;
nameTablep = new const char* [size];
// Workaround bug in bison's which have '!' in yytname but not token values
int iout = 0;
for (int i=0; yytname[i]; ++i) {
if (yytname[i][0] == '\'') continue;
nameTablep[iout++] = yytname[i];
}
}
if (token >= 255) {
return nameTablep[token-255];
} else {
static char ch[2]; ch[0]=token; ch[1]='\0';
return ch;
}
#else
return "";
#endif
}
void V3ParseImp::parserClear() {
// Clear up any dynamic memory V3Parser required
VARDTYPE(NULL);
}
void V3ParseGrammar::argWrapList(AstNodeFTaskRef* nodep) {
// Convert list of expressions to list of arguments
AstNode* outp = NULL;
while (nodep->pinsp()) {
AstNode* exprp = nodep->pinsp()->unlinkFrBack();
// addNext can handle nulls:
outp = AstNode::addNext(outp, new AstArg(exprp->fileline(), "", exprp));
}
if (outp) nodep->addPinsp(outp);
}
AstNode* V3ParseGrammar::createSupplyExpr(FileLine* fileline, string name, int value) {
return new AstAssignW(fileline, new AstVarRef(fileline, name, true),
new AstConst(fileline, AstConst::StringToParse(),
(value ? "'1" : "'0")));
}
AstRange* V3ParseGrammar::scrubRange(AstNodeRange* nrangep) {
// Remove any UnsizedRange's from list
for (AstNodeRange* nodep = nrangep, *nextp; nodep; nodep=nextp) {
nextp = VN_CAST(nrangep->nextp(), NodeRange);
if (!VN_IS(nodep, Range)) {
nodep->v3error("Unsupported or syntax error: Unsized range in cell or other declaration");
nodep->unlinkFrBack(); nodep->deleteTree(); VL_DANGLING(nodep);
}
}
return VN_CAST(nrangep, Range);
}
AstNodeDType* V3ParseGrammar::createArray(AstNodeDType* basep, AstNodeRange* nrangep, bool isPacked) {
// Split RANGE0-RANGE1-RANGE2 into ARRAYDTYPE0(ARRAYDTYPE1(ARRAYDTYPE2(BASICTYPE3),RANGE),RANGE)
AstNodeDType* arrayp = basep;
if (nrangep) { // Maybe no range - return unmodified base type
while (nrangep->nextp()) nrangep = VN_CAST(nrangep->nextp(), NodeRange);
while (nrangep) {
AstNodeRange* prevp = VN_CAST(nrangep->backp(), NodeRange);
if (prevp) nrangep->unlinkFrBack();
AstRange* rangep = VN_CAST(nrangep, Range);
if (!rangep) {
if (!VN_IS(nrangep, UnsizedRange)) nrangep->v3fatalSrc("Expected range or unsized range");
arrayp = new AstUnsizedArrayDType(nrangep->fileline(), VFlagChildDType(), arrayp);
} else if (isPacked) {
arrayp = new AstPackArrayDType(rangep->fileline(), VFlagChildDType(), arrayp, rangep);
} else {
arrayp = new AstUnpackArrayDType(rangep->fileline(), VFlagChildDType(), arrayp, rangep);
}
nrangep = prevp;
}
}
return arrayp;
}
AstVar* V3ParseGrammar::createVariable(FileLine* fileline, string name, AstNodeRange* arrayp, AstNode* attrsp) {
AstNodeDType* dtypep = GRAMMARP->m_varDTypep;
UINFO(5," creVar "<<name<<" decl="<<GRAMMARP->m_varDecl<<" io="<<GRAMMARP->m_varIO<<" dt="<<(dtypep?"set":"")<<endl);
if (GRAMMARP->m_varIO == VDirection::NONE
&& GRAMMARP->m_varDecl == AstVarType::PORT) {
// Just a port list with variable name (not v2k format); AstPort already created
if (dtypep) fileline->v3error("Unsupported: Ranges ignored in port-lists");
return NULL;
}
if (GRAMMARP->m_varDecl == AstVarType::WREAL) {
// dtypep might not be null, might be implicit LOGIC before we knew better
dtypep = new AstBasicDType(fileline,AstBasicDTypeKwd::DOUBLE);
}
if (!dtypep) { // Created implicitly
dtypep = new AstBasicDType(fileline, LOGIC_IMPLICIT);
} else { // May make new variables with same type, so clone
dtypep = dtypep->cloneTree(false);
}
//UINFO(0,"CREVAR "<<fileline->ascii()<<" decl="<<GRAMMARP->m_varDecl.ascii()<<" io="<<GRAMMARP->m_varIO.ascii()<<endl);
AstVarType type = GRAMMARP->m_varDecl;
if (type == AstVarType::UNKNOWN) {
if (GRAMMARP->m_varIO.isAny()) {
type = AstVarType::PORT;
} else {
fileline->v3fatalSrc("Unknown signal type declared");
}
}
if (type == AstVarType::GENVAR) {
if (arrayp) fileline->v3error("Genvars may not be arrayed: "<<name);
}
// Split RANGE0-RANGE1-RANGE2 into ARRAYDTYPE0(ARRAYDTYPE1(ARRAYDTYPE2(BASICTYPE3),RANGE),RANGE)
AstNodeDType* arrayDTypep = createArray(dtypep, arrayp, false);
AstVar* nodep = new AstVar(fileline, type, name, VFlagChildDType(), arrayDTypep);
nodep->addAttrsp(attrsp);
if (GRAMMARP->m_varDecl != AstVarType::UNKNOWN) nodep->combineType(GRAMMARP->m_varDecl);
if (GRAMMARP->m_varIO != VDirection::NONE) {
nodep->declDirection(GRAMMARP->m_varIO);
nodep->direction(GRAMMARP->m_varIO);
}
if (GRAMMARP->m_varDecl == AstVarType::SUPPLY0) {
nodep->addNext(V3ParseGrammar::createSupplyExpr(fileline, nodep->name(), 0));
}
if (GRAMMARP->m_varDecl == AstVarType::SUPPLY1) {
nodep->addNext(V3ParseGrammar::createSupplyExpr(fileline, nodep->name(), 1));
}
if (VN_IS(dtypep, ParseTypeDType)) {
// Parser needs to know what is a type
AstNode* newp = new AstTypedefFwd(fileline, name);
nodep->addNext(newp);
SYMP->reinsert(newp);
}
// Don't set dtypep in the ranging;
// We need to autosize parameters and integers separately
//
// Propagate from current module tracing state
if (nodep->isGenVar()) nodep->trace(false);
else if (nodep->isParam() && !v3Global.opt.traceParams()) nodep->trace(false);
else nodep->trace(allTracingOn(nodep->fileline()));
// Remember the last variable created, so we can attach attributes to it in later parsing
GRAMMARP->m_varAttrp = nodep;
PARSEP->tagNodep(GRAMMARP->m_varAttrp);
return nodep;
}
string V3ParseGrammar::deQuote(FileLine* fileline, string text) {
// Fix up the quoted strings the user put in, for example "\"" becomes "
// Reverse is V3OutFormatter::quoteNameControls(...)
bool quoted = false;
string newtext;
unsigned char octal_val = 0;
int octal_digits = 0;
for (string::const_iterator cp=text.begin(); cp!=text.end(); ++cp) {
if (quoted) {
if (isdigit(*cp)) {
octal_val = octal_val*8 + (*cp-'0');
if (++octal_digits == 3) {
octal_digits = 0;
quoted = false;
newtext += octal_val;
}
} else {
if (octal_digits) {
// Spec allows 1-3 digits
octal_digits = 0;
quoted = false;
newtext += octal_val;
--cp; // Backup to reprocess terminating character as non-escaped
continue;
}
quoted = false;
if (*cp == 'n') newtext += '\n';
else if (*cp == 'a') newtext += '\a'; // SystemVerilog 3.1
else if (*cp == 'f') newtext += '\f'; // SystemVerilog 3.1
else if (*cp == 'r') newtext += '\r';
else if (*cp == 't') newtext += '\t';
else if (*cp == 'v') newtext += '\v'; // SystemVerilog 3.1
else if (*cp == 'x' && isxdigit(cp[1]) && isxdigit(cp[2])) { // SystemVerilog 3.1
#define vl_decodexdigit(c) ((isdigit(c)?((c)-'0'):(tolower((c))-'a'+10)))
newtext += (char)(16*vl_decodexdigit(cp[1]) + vl_decodexdigit(cp[2]));
cp += 2;
}
else if (isalnum(*cp)) {
fileline->v3error("Unknown escape sequence: \\"<<*cp);
break;
}
else newtext += *cp;
}
}
else if (*cp == '\\') {
quoted = true;
octal_digits = 0;
}
else if (*cp != '"') {
newtext += *cp;
}
}
return newtext;
}
// For implementation functions see V3ParseGrammar.cpp
//YACC = /kits/sources/bison-2.4.1/src/bison --report=lookahead
// --report=lookahead