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:**
|
||||
|
||||
* Support $fopen as an expression.
|
||||
|
||||
|
||||
Verilator 5.008 2023-03-04
|
||||
==========================
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
@ -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}; }
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user