forked from github/verilator
Support $fopen as an expression
This commit is contained in:
parent
bb45bd048e
commit
259201b352
2
Changes
2
Changes
@ -13,6 +13,8 @@ Verilator 5.009 devel
|
|||||||
|
|
||||||
**Minor:**
|
**Minor:**
|
||||||
|
|
||||||
|
* Support $fopen as an expression.
|
||||||
|
|
||||||
|
|
||||||
Verilator 5.008 2023-03-04
|
Verilator 5.008 2023-03-04
|
||||||
==========================
|
==========================
|
||||||
|
@ -1112,6 +1112,46 @@ public:
|
|||||||
bool isPure() const override { return false; } // SPECIAL: $display has 'visual' ordering
|
bool isPure() const override { return false; } // SPECIAL: $display has 'visual' ordering
|
||||||
bool same(const AstNode* /*samep*/) const override { return true; }
|
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 {
|
class AstFRead final : public AstNodeExpr {
|
||||||
// @astgen op1 := memp : AstNode // VarRef for result
|
// @astgen op1 := memp : AstNode // VarRef for result
|
||||||
// @astgen op2 := filep : AstNode // file (must be a VarRef)
|
// @astgen op2 := filep : AstNode // file (must be a VarRef)
|
||||||
|
@ -2739,46 +2739,6 @@ public:
|
|||||||
bool isUnlikely() const override { return true; }
|
bool isUnlikely() const override { return true; }
|
||||||
bool same(const AstNode* /*samep*/) 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 {
|
class AstFinish final : public AstNodeStmt {
|
||||||
public:
|
public:
|
||||||
explicit AstFinish(FileLine* fl)
|
explicit AstFinish(FileLine* fl)
|
||||||
|
@ -649,8 +649,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
void visit(AstFOpen* nodep) override {
|
void visit(AstFOpen* nodep) override {
|
||||||
iterateAndNextNull(nodep->filep());
|
puts("VL_FOPEN_NN(");
|
||||||
puts(" = VL_FOPEN_NN(");
|
|
||||||
emitCvtPackStr(nodep->filenamep());
|
emitCvtPackStr(nodep->filenamep());
|
||||||
putbs(", ");
|
putbs(", ");
|
||||||
if (nodep->modep()->width() > 4 * 8)
|
if (nodep->modep()->width() > 4 * 8)
|
||||||
@ -659,8 +658,7 @@ public:
|
|||||||
puts(");\n");
|
puts(");\n");
|
||||||
}
|
}
|
||||||
void visit(AstFOpenMcd* nodep) override {
|
void visit(AstFOpenMcd* nodep) override {
|
||||||
iterateAndNextNull(nodep->filep());
|
puts("VL_FOPEN_MCD_N(");
|
||||||
puts(" = VL_FOPEN_MCD_N(");
|
|
||||||
emitCvtPackStr(nodep->filenamep());
|
emitCvtPackStr(nodep->filenamep());
|
||||||
puts(");\n");
|
puts(");\n");
|
||||||
}
|
}
|
||||||
|
@ -116,83 +116,43 @@ private:
|
|||||||
iterateAndNextNull(nodep->top());
|
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 {
|
void visit(AstFError* nodep) override {
|
||||||
VL_RESTORER(m_setRefLvalue);
|
VL_RESTORER(m_setRefLvalue);
|
||||||
{
|
{
|
||||||
m_setRefLvalue = VAccess::WRITE;
|
|
||||||
iterateAndNextNull(nodep->filep());
|
iterateAndNextNull(nodep->filep());
|
||||||
|
m_setRefLvalue = VAccess::WRITE;
|
||||||
iterateAndNextNull(nodep->strp());
|
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 {
|
void visit(AstFGetS* nodep) override {
|
||||||
VL_RESTORER(m_setRefLvalue);
|
VL_RESTORER(m_setRefLvalue);
|
||||||
{
|
{
|
||||||
m_setRefLvalue = VAccess::WRITE;
|
|
||||||
iterateAndNextNull(nodep->filep());
|
iterateAndNextNull(nodep->filep());
|
||||||
|
m_setRefLvalue = VAccess::WRITE;
|
||||||
iterateAndNextNull(nodep->strgp());
|
iterateAndNextNull(nodep->strgp());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void visit(AstFRead* nodep) override {
|
void visit(AstFRead* nodep) override {
|
||||||
VL_RESTORER(m_setRefLvalue);
|
VL_RESTORER(m_setRefLvalue);
|
||||||
{
|
{
|
||||||
|
iterateAndNextNull(nodep->filep());
|
||||||
m_setRefLvalue = VAccess::WRITE;
|
m_setRefLvalue = VAccess::WRITE;
|
||||||
iterateAndNextNull(nodep->memp());
|
iterateAndNextNull(nodep->memp());
|
||||||
iterateAndNextNull(nodep->filep());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void visit(AstFScanF* nodep) override {
|
void visit(AstFScanF* nodep) override {
|
||||||
VL_RESTORER(m_setRefLvalue);
|
VL_RESTORER(m_setRefLvalue);
|
||||||
{
|
{
|
||||||
m_setRefLvalue = VAccess::WRITE;
|
|
||||||
iterateAndNextNull(nodep->filep());
|
iterateAndNextNull(nodep->filep());
|
||||||
|
m_setRefLvalue = VAccess::WRITE;
|
||||||
iterateAndNextNull(nodep->exprsp());
|
iterateAndNextNull(nodep->exprsp());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void visit(AstFUngetC* nodep) override {
|
void visit(AstFUngetC* nodep) override {
|
||||||
VL_RESTORER(m_setRefLvalue);
|
VL_RESTORER(m_setRefLvalue);
|
||||||
{
|
{
|
||||||
m_setRefLvalue = VAccess::WRITE;
|
|
||||||
iterateAndNextNull(nodep->filep());
|
iterateAndNextNull(nodep->filep());
|
||||||
|
m_setRefLvalue = VAccess::WRITE;
|
||||||
iterateAndNextNull(nodep->rhsp());
|
iterateAndNextNull(nodep->rhsp());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -318,14 +318,6 @@ private:
|
|||||||
if (filep && filep->varp()) filep->varp()->attrFileDescr(true);
|
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 {
|
void visit(AstFClose* nodep) override {
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
expectDescriptor(nodep, VN_CAST(nodep->filep(), NodeVarRef));
|
expectDescriptor(nodep, VN_CAST(nodep->filep(), NodeVarRef));
|
||||||
|
@ -4861,15 +4861,13 @@ private:
|
|||||||
}
|
}
|
||||||
void visit(AstFOpen* nodep) override {
|
void visit(AstFOpen* nodep) override {
|
||||||
// Although a system function in IEEE, here a statement which sets the file pointer (MCD)
|
// 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->filenamep(), WidthVP{SELF, BOTH}.p());
|
||||||
userIterateAndNext(nodep->modep(), 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 {
|
void visit(AstFOpenMcd* nodep) override {
|
||||||
assertAtStatement(nodep);
|
|
||||||
iterateCheckFileDesc(nodep, nodep->filep(), BOTH);
|
|
||||||
userIterateAndNext(nodep->filenamep(), WidthVP{SELF, BOTH}.p());
|
userIterateAndNext(nodep->filenamep(), WidthVP{SELF, BOTH}.p());
|
||||||
|
nodep->dtypeSetLogicUnsized(32, 1, VSigning::SIGNED); // Spec says integer return
|
||||||
}
|
}
|
||||||
void visit(AstFClose* nodep) override {
|
void visit(AstFClose* nodep) override {
|
||||||
assertAtStatement(nodep);
|
assertAtStatement(nodep);
|
||||||
|
@ -3645,8 +3645,6 @@ statementVerilatorPragmas<nodep>:
|
|||||||
|
|
||||||
foperator_assignment<nodep>: // IEEE: operator_assignment (for first part of expression)
|
foperator_assignment<nodep>: // IEEE: operator_assignment (for first part of expression)
|
||||||
fexprLvalue '=' delay_or_event_controlE expr { $$ = new AstAssign{$2, $1, $4, $3}; }
|
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
|
| fexprLvalue yP_PLUSEQ expr
|
||||||
{ $$ = new AstAssign{$2, $1, new AstAdd{$2, $1->cloneTree(true), $3}}; }
|
{ $$ = 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_FERROR '(' expr ',' idClassSel ')' { $$ = new AstFError{$1, $3, $5}; }
|
||||||
| yD_FGETC '(' expr ')' { $$ = new AstFGetC{$1, $3}; }
|
| yD_FGETC '(' expr ')' { $$ = new AstFGetC{$1, $3}; }
|
||||||
| yD_FGETS '(' expr ',' expr ')' { $$ = new AstFGetS{$1, $3, $5}; }
|
| 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 ')' { $$ = new AstFRead{$1, $3, $5, nullptr, nullptr}; }
|
||||||
| yD_FREAD '(' expr ',' expr ',' expr ')' { $$ = new AstFRead{$1, $3, $5, $7, 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}; }
|
| yD_FREAD '(' expr ',' expr ',' expr ',' expr ')' { $$ = new AstFRead{$1, $3, $5, $7, $9}; }
|
||||||
|
@ -169,9 +169,11 @@ module Vt_debug_emitv_t;
|
|||||||
: $c('sh1e)));
|
: $c('sh1e)));
|
||||||
$c(;);
|
$c(;);
|
||||||
$display("%d", $c(0));
|
$display("%d", $c(0));
|
||||||
$fopen(72'h2f6465762f6e756c6c);
|
fd = $fopen(72'h2f6465762f6e756c6c);
|
||||||
|
;
|
||||||
$fclose(fd);
|
$fclose(fd);
|
||||||
$fopen(72'h2f6465762f6e756c6c, 8'h72);
|
fd = $fopen(72'h2f6465762f6e756c6c, 8'h72);
|
||||||
|
;
|
||||||
$fgetc(fd);
|
$fgetc(fd);
|
||||||
$fflush(fd);
|
$fflush(fd);
|
||||||
$fscanf(fd, "%d", sum);
|
$fscanf(fd, "%d", sum);
|
||||||
|
Loading…
Reference in New Issue
Block a user