mirror of
https://github.com/verilator/verilator.git
synced 2026-09-04 00:30:34 +02:00
Support multi-channel descriptor (MCD) I/O (#2197)
This commit is contained in:
@@ -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
@@ -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(");
|
||||
|
||||
@@ -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
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
{
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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
@@ -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 }
|
||||
|
||||
Reference in New Issue
Block a user