Support multi-channel descriptor (MCD) I/O (#2197)

This commit is contained in:
Stephen Henry
2020-05-14 18:03:00 -04:00
committed by GitHub
parent 38d11ecabe
commit 1a0da2e4ec
19 changed files with 344 additions and 89 deletions
+21
View File
@@ -3801,6 +3801,27 @@ public:
AstNode* modep() const { return op3p(); }
};
class AstFOpenMcd : public AstNodeStmt {
// Although a system function in IEEE, here a statement which sets the file pointer (MCD)
public:
AstFOpenMcd(FileLine* fl, AstNode* filep, AstNode* filenamep)
: ASTGEN_SUPER(fl) {
setOp1p(filep);
setOp2p(filenamep);
}
ASTNODE_NODE_FUNCS(FOpenMcd)
virtual string verilogKwd() const { return "$fopen"; }
virtual bool isGateOptimizable() const { return false; }
virtual bool isPredictOptimizable() const { return false; }
virtual bool isPure() const { return false; }
virtual bool isOutputter() const { return true; }
virtual bool isUnlikely() const { return true; }
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(const AstNode* samep) const { return true; }
AstNode* filep() const { return op1p(); }
AstNode* filenamep() const { return op2p(); }
};
class AstFFlush : public AstNodeStmt {
// Parents: stmtlist
// Children: file which must be a varref
+18 -20
View File
@@ -526,20 +526,18 @@ public:
}
virtual void visit(AstFOpen* nodep) VL_OVERRIDE {
iterateAndNextNull(nodep->filep());
puts(" = VL_FOPEN_");
emitIQW(nodep->filenamep());
emitIQW(nodep->modep());
puts(" = VL_FOPEN_NN(");
emitCvtPackStr(nodep->filenamep());
putbs(", ");
if (nodep->modep()->width() > 4 * 8)
nodep->modep()->v3error("$fopen mode should be <= 4 characters");
puts("(");
if (nodep->filenamep()->isWide()) {
puts(cvtToStr(nodep->filenamep()->widthWords()));
putbs(", ");
}
checkMaxWords(nodep->filenamep());
iterateAndNextNull(nodep->filenamep());
putbs(", ");
iterateAndNextNull(nodep->modep());
emitCvtPackStr(nodep->modep());
puts(");\n");
}
virtual void visit(AstFOpenMcd* nodep) VL_OVERRIDE {
iterateAndNextNull(nodep->filep());
puts(" = VL_FOPEN_MCD_N(");
emitCvtPackStr(nodep->filenamep());
puts(");\n");
}
virtual void visit(AstNodeReadWriteMem* nodep) VL_OVERRIDE {
@@ -599,29 +597,29 @@ public:
} else {
puts("if (");
iterateAndNextNull(nodep->filep());
puts(") { fflush(VL_CVT_I_FP(");
puts(") { VL_FFLUSH_I(");
iterateAndNextNull(nodep->filep());
puts(")); }\n");
puts("); }\n");
}
}
virtual void visit(AstFSeek* nodep) VL_OVERRIDE {
puts("(fseek(VL_CVT_I_FP(");
puts("(VL_FSEEK_I(");
iterateAndNextNull(nodep->filep());
puts("),");
puts(",");
iterateAndNextNull(nodep->offset());
puts(",");
iterateAndNextNull(nodep->operation());
puts(")==-1?-1:0)");
}
virtual void visit(AstFTell* nodep) VL_OVERRIDE {
puts("ftell(VL_CVT_I_FP(");
puts("VL_FTELL_I(");
iterateAndNextNull(nodep->filep());
puts("))");
puts(")");
}
virtual void visit(AstFRewind* nodep) VL_OVERRIDE {
puts("(fseek(VL_CVT_I_FP(");
puts("(VL_FSEEK_I(");
iterateAndNextNull(nodep->filep());
puts("), 0, 0)==-1?-1:0)");
puts(", 0, 0)==-1?-1:0)");
}
virtual void visit(AstFRead* nodep) VL_OVERRIDE {
puts("VL_FREAD_I(");
+8
View File
@@ -100,6 +100,14 @@ class EmitCInlines : EmitCBaseVisitor {
v3Global.needHeavy(true);
iterateChildren(nodep);
}
virtual void visit(AstFOpen* nodep) VL_OVERRIDE {
v3Global.needHeavy(true);
iterateChildren(nodep);
}
virtual void visit(AstFOpenMcd* nodep) VL_OVERRIDE {
v3Global.needHeavy(true);
iterateChildren(nodep);
}
//---------------------------------------
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
+9 -5
View File
@@ -252,12 +252,16 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
}
virtual void visit(AstFOpen* nodep) VL_OVERRIDE {
putfs(nodep, nodep->verilogKwd());
putbs(" (");
if (nodep->filep()) iterateAndNextNull(nodep->filep());
putbs("(");
iterateAndNextNull(nodep->filenamep());
putbs(",");
if (nodep->filenamep()) iterateAndNextNull(nodep->filenamep());
putbs(",");
if (nodep->modep()) iterateAndNextNull(nodep->modep());
iterateAndNextNull(nodep->modep());
puts(");\n");
}
virtual void visit(AstFOpenMcd* nodep) VL_OVERRIDE {
putfs(nodep, nodep->verilogKwd());
putbs("(");
iterateAndNextNull(nodep->filenamep());
puts(");\n");
}
virtual void visit(AstFClose* nodep) VL_OVERRIDE {
+10
View File
@@ -91,6 +91,16 @@ private:
}
m_setRefLvalue = last_setRefLvalue;
}
virtual void visit(AstFOpenMcd* nodep) VL_OVERRIDE {
bool last_setRefLvalue = m_setRefLvalue;
{
m_setRefLvalue = true;
iterateAndNextNull(nodep->filep());
m_setRefLvalue = false;
iterateAndNextNull(nodep->filenamep());
}
m_setRefLvalue = last_setRefLvalue;
}
virtual void visit(AstFClose* nodep) VL_OVERRIDE {
bool last_setRefLvalue = m_setRefLvalue;
{
+4
View File
@@ -397,6 +397,10 @@ private:
iterateChildren(nodep);
expectDescriptor(nodep, VN_CAST(nodep->filep(), NodeVarRef));
}
virtual void visit(AstFOpenMcd* nodep) VL_OVERRIDE {
iterateChildren(nodep);
expectDescriptor(nodep, VN_CAST(nodep->filep(), NodeVarRef));
}
virtual void visit(AstFClose* nodep) VL_OVERRIDE {
iterateChildren(nodep);
expectDescriptor(nodep, VN_CAST(nodep->filep(), NodeVarRef));
+5
View File
@@ -3317,6 +3317,11 @@ private:
userIterateAndNext(nodep->filenamep(), WidthVP(SELF, BOTH).p());
userIterateAndNext(nodep->modep(), WidthVP(SELF, BOTH).p());
}
virtual void visit(AstFOpenMcd* nodep) VL_OVERRIDE {
assertAtStatement(nodep);
iterateCheckFileDesc(nodep, nodep->filep(), BOTH);
userIterateAndNext(nodep->filenamep(), WidthVP(SELF, BOTH).p());
}
virtual void visit(AstFClose* nodep) VL_OVERRIDE {
assertAtStatement(nodep);
iterateCheckFileDesc(nodep, nodep->filep(), BOTH);
+1 -1
View File
@@ -2936,7 +2936,7 @@ statementVerilatorPragmas<nodep>:
foperator_assignment<nodep>: // IEEE: operator_assignment (for first part of expression)
fexprLvalue '=' delayE expr { $$ = new AstAssign($2,$1,$4); }
| fexprLvalue '=' yD_FOPEN '(' expr ')' { $$ = NULL; BBUNSUP($3, "Unsupported: $fopen with multichannel descriptor. Add ,\"w\" as second argument to open a file descriptor."); }
| fexprLvalue '=' yD_FOPEN '(' expr ')' { $$ = new AstFOpenMcd($3,$1,$5); }
| fexprLvalue '=' yD_FOPEN '(' expr ',' expr ')' { $$ = new AstFOpen($3,$1,$5,$7); }
//
//UNSUP ~f~exprLvalue '=' delay_or_event_controlE expr { UNSUP }