Support $fopen as an expression

This commit is contained in:
Wilson Snyder 2023-03-11 18:11:01 -05:00
parent bb45bd048e
commit 259201b352
9 changed files with 57 additions and 105 deletions

View File

@ -13,6 +13,8 @@ Verilator 5.009 devel
**Minor:**
* Support $fopen as an expression.
Verilator 5.008 2023-03-04
==========================

View File

@ -1112,6 +1112,46 @@ public:
bool isPure() const override { return false; } // SPECIAL: $display has 'visual' ordering
bool same(const AstNode* /*samep*/) const override { return true; }
};
class AstFOpen final : public AstNodeExpr {
// @astgen op2 := filenamep : AstNodeExpr
// @astgen op3 := modep : AstNodeExpr
public:
AstFOpen(FileLine* fl, AstNodeExpr* filenamep, AstNodeExpr* modep)
: ASTGEN_SUPER_FOpen(fl) {
this->filenamep(filenamep);
this->modep(modep);
}
ASTGEN_MEMBERS_AstFOpen;
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
string emitC() override { V3ERROR_NA_RETURN(""); }
bool cleanOut() const override { return true; }
string verilogKwd() const override { return "$fopen"; }
bool isGateOptimizable() const override { return false; }
bool isPredictOptimizable() const override { return false; }
bool isPure() const override { return false; }
bool isOutputter() const override { return true; }
bool isUnlikely() const override { return true; }
bool same(const AstNode* /*samep*/) const override { return true; }
};
class AstFOpenMcd final : public AstNodeExpr {
// @astgen op2 := filenamep : AstNodeExpr
public:
AstFOpenMcd(FileLine* fl, AstNodeExpr* filenamep)
: ASTGEN_SUPER_FOpenMcd(fl) {
this->filenamep(filenamep);
}
ASTGEN_MEMBERS_AstFOpenMcd;
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
string emitC() override { V3ERROR_NA_RETURN(""); }
bool cleanOut() const override { return true; }
string verilogKwd() const override { return "$fopen"; }
bool isGateOptimizable() const override { return false; }
bool isPredictOptimizable() const override { return false; }
bool isPure() const override { return false; }
bool isOutputter() const override { return true; }
bool isUnlikely() const override { return true; }
bool same(const AstNode* /*samep*/) const override { return true; }
};
class AstFRead final : public AstNodeExpr {
// @astgen op1 := memp : AstNode // VarRef for result
// @astgen op2 := filep : AstNode // file (must be a VarRef)

View File

@ -2739,46 +2739,6 @@ public:
bool isUnlikely() const override { return true; }
bool same(const AstNode* /*samep*/) const override { return true; }
};
class AstFOpen final : public AstNodeStmt {
// Although a system function in IEEE, here a statement which sets the file pointer (MCD)
// @astgen op1 := filep : AstNodeExpr
// @astgen op2 := filenamep : AstNodeExpr
// @astgen op3 := modep : AstNodeExpr
public:
AstFOpen(FileLine* fl, AstNodeExpr* filep, AstNodeExpr* filenamep, AstNodeExpr* modep)
: ASTGEN_SUPER_FOpen(fl) {
this->filep(filep);
this->filenamep(filenamep);
this->modep(modep);
}
ASTGEN_MEMBERS_AstFOpen;
string verilogKwd() const override { return "$fopen"; }
bool isGateOptimizable() const override { return false; }
bool isPredictOptimizable() const override { return false; }
bool isPure() const override { return false; }
bool isOutputter() const override { return true; }
bool isUnlikely() const override { return true; }
bool same(const AstNode* /*samep*/) const override { return true; }
};
class AstFOpenMcd final : public AstNodeStmt {
// Although a system function in IEEE, here a statement which sets the file pointer (MCD)
// @astgen op1 := filep : AstNodeExpr
// @astgen op2 := filenamep : AstNodeExpr
public:
AstFOpenMcd(FileLine* fl, AstNodeExpr* filep, AstNodeExpr* filenamep)
: ASTGEN_SUPER_FOpenMcd(fl) {
this->filep(filep);
this->filenamep(filenamep);
}
ASTGEN_MEMBERS_AstFOpenMcd;
string verilogKwd() const override { return "$fopen"; }
bool isGateOptimizable() const override { return false; }
bool isPredictOptimizable() const override { return false; }
bool isPure() const override { return false; }
bool isOutputter() const override { return true; }
bool isUnlikely() const override { return true; }
bool same(const AstNode* /*samep*/) const override { return true; }
};
class AstFinish final : public AstNodeStmt {
public:
explicit AstFinish(FileLine* fl)

View File

@ -649,8 +649,7 @@ public:
}
}
void visit(AstFOpen* nodep) override {
iterateAndNextNull(nodep->filep());
puts(" = VL_FOPEN_NN(");
puts("VL_FOPEN_NN(");
emitCvtPackStr(nodep->filenamep());
putbs(", ");
if (nodep->modep()->width() > 4 * 8)
@ -659,8 +658,7 @@ public:
puts(");\n");
}
void visit(AstFOpenMcd* nodep) override {
iterateAndNextNull(nodep->filep());
puts(" = VL_FOPEN_MCD_N(");
puts("VL_FOPEN_MCD_N(");
emitCvtPackStr(nodep->filenamep());
puts(");\n");
}

View File

@ -116,83 +116,43 @@ private:
iterateAndNextNull(nodep->top());
}
}
void visit(AstFOpen* nodep) override {
VL_RESTORER(m_setRefLvalue);
{
m_setRefLvalue = VAccess::WRITE;
iterateAndNextNull(nodep->filep());
m_setRefLvalue = VAccess::NOCHANGE;
iterateAndNextNull(nodep->filenamep());
iterateAndNextNull(nodep->modep());
}
}
void visit(AstFOpenMcd* nodep) override {
VL_RESTORER(m_setRefLvalue);
{
m_setRefLvalue = VAccess::WRITE;
iterateAndNextNull(nodep->filep());
m_setRefLvalue = VAccess::NOCHANGE;
iterateAndNextNull(nodep->filenamep());
}
}
void visit(AstFClose* nodep) override {
VL_RESTORER(m_setRefLvalue);
{
m_setRefLvalue = VAccess::WRITE;
iterateAndNextNull(nodep->filep());
}
}
void visit(AstFError* nodep) override {
VL_RESTORER(m_setRefLvalue);
{
m_setRefLvalue = VAccess::WRITE;
iterateAndNextNull(nodep->filep());
m_setRefLvalue = VAccess::WRITE;
iterateAndNextNull(nodep->strp());
}
}
void visit(AstFFlush* nodep) override {
VL_RESTORER(m_setRefLvalue);
{
m_setRefLvalue = VAccess::WRITE;
iterateAndNextNull(nodep->filep());
}
}
void visit(AstFGetC* nodep) override {
VL_RESTORER(m_setRefLvalue);
{
m_setRefLvalue = VAccess::WRITE;
iterateAndNextNull(nodep->filep());
}
}
void visit(AstFGetS* nodep) override {
VL_RESTORER(m_setRefLvalue);
{
m_setRefLvalue = VAccess::WRITE;
iterateAndNextNull(nodep->filep());
m_setRefLvalue = VAccess::WRITE;
iterateAndNextNull(nodep->strgp());
}
}
void visit(AstFRead* nodep) override {
VL_RESTORER(m_setRefLvalue);
{
iterateAndNextNull(nodep->filep());
m_setRefLvalue = VAccess::WRITE;
iterateAndNextNull(nodep->memp());
iterateAndNextNull(nodep->filep());
}
}
void visit(AstFScanF* nodep) override {
VL_RESTORER(m_setRefLvalue);
{
m_setRefLvalue = VAccess::WRITE;
iterateAndNextNull(nodep->filep());
m_setRefLvalue = VAccess::WRITE;
iterateAndNextNull(nodep->exprsp());
}
}
void visit(AstFUngetC* nodep) override {
VL_RESTORER(m_setRefLvalue);
{
m_setRefLvalue = VAccess::WRITE;
iterateAndNextNull(nodep->filep());
m_setRefLvalue = VAccess::WRITE;
iterateAndNextNull(nodep->rhsp());
}
}

View File

@ -318,14 +318,6 @@ private:
if (filep && filep->varp()) filep->varp()->attrFileDescr(true);
}
void visit(AstFOpen* nodep) override {
iterateChildren(nodep);
expectDescriptor(nodep, VN_CAST(nodep->filep(), NodeVarRef));
}
void visit(AstFOpenMcd* nodep) override {
iterateChildren(nodep);
expectDescriptor(nodep, VN_CAST(nodep->filep(), NodeVarRef));
}
void visit(AstFClose* nodep) override {
iterateChildren(nodep);
expectDescriptor(nodep, VN_CAST(nodep->filep(), NodeVarRef));

View File

@ -4861,15 +4861,13 @@ private:
}
void visit(AstFOpen* nodep) override {
// Although a system function in IEEE, here a statement which sets the file pointer (MCD)
assertAtStatement(nodep);
iterateCheckFileDesc(nodep, nodep->filep(), BOTH);
userIterateAndNext(nodep->filenamep(), WidthVP{SELF, BOTH}.p());
userIterateAndNext(nodep->modep(), WidthVP{SELF, BOTH}.p());
nodep->dtypeSetLogicUnsized(32, 1, VSigning::SIGNED); // Spec says integer return
}
void visit(AstFOpenMcd* nodep) override {
assertAtStatement(nodep);
iterateCheckFileDesc(nodep, nodep->filep(), BOTH);
userIterateAndNext(nodep->filenamep(), WidthVP{SELF, BOTH}.p());
nodep->dtypeSetLogicUnsized(32, 1, VSigning::SIGNED); // Spec says integer return
}
void visit(AstFClose* nodep) override {
assertAtStatement(nodep);

View File

@ -3645,8 +3645,6 @@ statementVerilatorPragmas<nodep>:
foperator_assignment<nodep>: // IEEE: operator_assignment (for first part of expression)
fexprLvalue '=' delay_or_event_controlE expr { $$ = new AstAssign{$2, $1, $4, $3}; }
| fexprLvalue '=' yD_FOPEN '(' expr ')' { $$ = new AstFOpenMcd{$3, $1, $5}; }
| fexprLvalue '=' yD_FOPEN '(' expr ',' expr ')' { $$ = new AstFOpen{$3, $1, $5, $7}; }
//
| fexprLvalue yP_PLUSEQ expr
{ $$ = new AstAssign{$2, $1, new AstAdd{$2, $1->cloneTree(true), $3}}; }
@ -4208,6 +4206,8 @@ system_f_call_or_t<nodeExprp>: // IEEE: part of system_tf_call (can be task
| yD_FERROR '(' expr ',' idClassSel ')' { $$ = new AstFError{$1, $3, $5}; }
| yD_FGETC '(' expr ')' { $$ = new AstFGetC{$1, $3}; }
| yD_FGETS '(' expr ',' expr ')' { $$ = new AstFGetS{$1, $3, $5}; }
| yD_FOPEN '(' expr ')' { $$ = new AstFOpenMcd{$1, $3}; }
| yD_FOPEN '(' expr ',' expr ')' { $$ = new AstFOpen{$1, $3, $5}; }
| yD_FREAD '(' expr ',' expr ')' { $$ = new AstFRead{$1, $3, $5, nullptr, nullptr}; }
| yD_FREAD '(' expr ',' expr ',' expr ')' { $$ = new AstFRead{$1, $3, $5, $7, nullptr}; }
| yD_FREAD '(' expr ',' expr ',' expr ',' expr ')' { $$ = new AstFRead{$1, $3, $5, $7, $9}; }

View File

@ -169,9 +169,11 @@ module Vt_debug_emitv_t;
: $c('sh1e)));
$c(;);
$display("%d", $c(0));
$fopen(72'h2f6465762f6e756c6c);
fd = $fopen(72'h2f6465762f6e756c6c);
;
$fclose(fd);
$fopen(72'h2f6465762f6e756c6c, 8'h72);
fd = $fopen(72'h2f6465762f6e756c6c, 8'h72);
;
$fgetc(fd);
$fflush(fd);
$fscanf(fd, "%d", sum);