Support $fseek, $ftell, $frewind, bug1496.

This commit is contained in:
Wilson Snyder 2019-09-03 21:28:15 -04:00
parent 3bc260c55d
commit 314cd92129
8 changed files with 148 additions and 0 deletions

View File

@ -4,6 +4,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
* Verilator 4.019 devel * Verilator 4.019 devel
*** Support $fseek, $ftell, $frewind, bug1496. [Howard Su]
**** Fix make test with no VERILATOR_ROOT, bug1494. [Ahmed El-Mahmoudy] **** Fix make test with no VERILATOR_ROOT, bug1494. [Ahmed El-Mahmoudy]

View File

@ -6,6 +6,7 @@ Please see the Verilator manual for additional contributors.
Alex Chadwick Alex Chadwick
Gianfranco Costamagna Gianfranco Costamagna
Howard Su
Jeremy Bennett Jeremy Bennett
John Coiner John Coiner
Kanad Kanhere Kanad Kanhere

View File

@ -2876,6 +2876,86 @@ public:
void countp(AstNode* nodep) { setNOp4p(nodep); } void countp(AstNode* nodep) { setNOp4p(nodep); }
}; };
class AstFRewind : public AstNodeMath {
// Parents: stmtlist
// Children: file which must be a varref
public:
AstFRewind(FileLine* fileline, AstNode* filep)
: AstNodeMath(fileline) {
setNOp2p(filep);
}
ASTNODE_NODE_FUNCS(FRewind)
virtual string verilogKwd() const { return "$frewind"; }
virtual string emitVerilog() { V3ERROR_NA; return ""; }
virtual string emitC() { V3ERROR_NA; return ""; }
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 bool cleanOut() { return false; }
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(const AstNode* samep) const { return true; }
AstNode* filep() const { return op2p(); }
void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); }
};
class AstFTell : public AstNodeMath {
// Parents: stmtlist
// Children: file which must be a varref
public:
AstFTell(FileLine* fileline, AstNode* filep)
: AstNodeMath(fileline) {
setNOp2p(filep);
}
ASTNODE_NODE_FUNCS(FTell)
virtual string verilogKwd() const { return "$ftell"; }
virtual string emitVerilog() { V3ERROR_NA; return ""; }
virtual string emitC() { V3ERROR_NA; return ""; }
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 bool cleanOut() { return false; }
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(const AstNode* samep) const { return true; }
AstNode* filep() const { return op2p(); }
void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); }
};
class AstFSeek : public AstNodeMath {
// Parents: expr
// Children: file which must be a varref
// Children: offset
// Children: operation
public:
AstFSeek(FileLine* fileline, AstNode* filep,
AstNode* offset, AstNode* operation)
: AstNodeMath(fileline) {
setOp2p(filep);
setNOp3p(offset);
setNOp4p(operation);
}
ASTNODE_NODE_FUNCS(FSeek)
virtual string verilogKwd() const { return "$fseek"; }
virtual string emitVerilog() { V3ERROR_NA; return ""; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual bool isGateOptimizable() const { return false; }
virtual bool isPredictOptimizable() const { return false; }
virtual bool isPure() const { return false; } // SPECIAL: has 'visual' ordering
virtual bool isOutputter() const { return true; } // SPECIAL: makes output
virtual bool cleanOut() { return false; }
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(const AstNode* samep) const { return true; }
AstNode* filep() const { return op2p(); }
void filep(AstNode* nodep) { setOp2p(nodep); }
AstNode* offset() const { return op3p(); }
void offset(AstNode* nodep) { setNOp3p(nodep); }
AstNode* operation() const { return op4p(); }
void operation(AstNode* nodep) { setNOp4p(nodep); }
};
class AstFScanF : public AstNodeMath { class AstFScanF : public AstNodeMath {
// Parents: expr // Parents: expr
// Children: file which must be a varref // Children: file which must be a varref

View File

@ -395,6 +395,25 @@ public:
puts(")); }\n"); puts(")); }\n");
} }
} }
virtual void visit(AstFSeek* nodep) {
puts("(fseek(VL_CVT_I_FP(");
iterateAndNextNull(nodep->filep());
puts("),");
iterateAndNextNull(nodep->offset());
puts(",");
iterateAndNextNull(nodep->operation());
puts(")==-1?-1:0)");
}
virtual void visit(AstFTell* nodep) {
puts("ftell(VL_CVT_I_FP(");
iterateAndNextNull(nodep->filep());
puts("))");
}
virtual void visit(AstFRewind* nodep) {
puts("(fseek(VL_CVT_I_FP(");
iterateAndNextNull(nodep->filep());
puts("), 0, 0)==-1?-1:0)");
}
virtual void visit(AstFRead* nodep) { virtual void visit(AstFRead* nodep) {
puts("VL_FREAD_I("); puts("VL_FREAD_I(");
puts(cvtToStr(nodep->memp()->widthMin())); // Need real storage width puts(cvtToStr(nodep->memp()->widthMin())); // Need real storage width

View File

@ -2342,6 +2342,20 @@ private:
iterateCheckFileDesc(nodep, nodep->filep(), BOTH); iterateCheckFileDesc(nodep, nodep->filep(), BOTH);
} }
} }
virtual void visit(AstFRewind* nodep) {
iterateCheckFileDesc(nodep, nodep->filep(), BOTH);
nodep->dtypeSetLogicUnsized(32, 1, AstNumeric::SIGNED); // Spec says integer return
}
virtual void visit(AstFTell* nodep) {
iterateCheckFileDesc(nodep, nodep->filep(), BOTH);
nodep->dtypeSetLogicUnsized(32, 1, AstNumeric::SIGNED); // Spec says integer return
}
virtual void visit(AstFSeek* nodep) {
iterateCheckFileDesc(nodep, nodep->filep(), BOTH);
iterateCheckSigned32(nodep, "$fseek offset", nodep->offset(), BOTH);
iterateCheckSigned32(nodep, "$fseek operation", nodep->operation(), BOTH);
nodep->dtypeSetLogicUnsized(32, 1, AstNumeric::SIGNED); // Spec says integer return
}
virtual void visit(AstFGetC* nodep) { virtual void visit(AstFGetC* nodep) {
if (m_vup->prelim()) { if (m_vup->prelim()) {
iterateCheckFileDesc(nodep, nodep->filep(), BOTH); iterateCheckFileDesc(nodep, nodep->filep(), BOTH);

View File

@ -179,6 +179,9 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"$fopen" { FL; return yD_FOPEN; } "$fopen" { FL; return yD_FOPEN; }
"$fread" { FL; return yD_FREAD; } "$fread" { FL; return yD_FREAD; }
"$fscanf" { FL; return yD_FSCANF; } "$fscanf" { FL; return yD_FSCANF; }
"$fseek" { FL; return yD_FSEEK; }
"$ftell" { FL; return yD_FTELL; }
"$frewind" { FL; return yD_FREWIND; }
"$fullskew" { FL; return yaTIMINGSPEC; } "$fullskew" { FL; return yaTIMINGSPEC; }
"$fwrite" { FL; return yD_FWRITE; } "$fwrite" { FL; return yD_FWRITE; }
"$hold" { FL; return yaTIMINGSPEC; } "$hold" { FL; return yaTIMINGSPEC; }

View File

@ -517,7 +517,10 @@ class AstSenTree;
%token<fl> yD_FLOOR "$floor" %token<fl> yD_FLOOR "$floor"
%token<fl> yD_FOPEN "$fopen" %token<fl> yD_FOPEN "$fopen"
%token<fl> yD_FREAD "$fread" %token<fl> yD_FREAD "$fread"
%token<fl> yD_FREWIND "$frewind"
%token<fl> yD_FSCANF "$fscanf" %token<fl> yD_FSCANF "$fscanf"
%token<fl> yD_FSEEK "$fseek"
%token<fl> yD_FTELL "$ftell"
%token<fl> yD_FWRITE "$fwrite" %token<fl> yD_FWRITE "$fwrite"
%token<fl> yD_HIGH "$high" %token<fl> yD_HIGH "$high"
%token<fl> yD_HYPOT "$hypot" %token<fl> yD_HYPOT "$hypot"
@ -2907,8 +2910,11 @@ system_f_call_or_t<nodep>: // IEEE: part of system_tf_call (can be task or func)
| yD_FREAD '(' idClassSel ',' expr ')' { $$ = new AstFRead($1,$3,$5,NULL,NULL); } | yD_FREAD '(' idClassSel ',' expr ')' { $$ = new AstFRead($1,$3,$5,NULL,NULL); }
| yD_FREAD '(' idClassSel ',' expr ',' expr ')' { $$ = new AstFRead($1,$3,$5,$7,NULL); } | yD_FREAD '(' idClassSel ',' expr ',' expr ')' { $$ = new AstFRead($1,$3,$5,$7,NULL); }
| yD_FREAD '(' idClassSel ',' expr ',' expr ',' expr ')' { $$ = new AstFRead($1,$3,$5,$7,$9); } | yD_FREAD '(' idClassSel ',' expr ',' expr ',' expr ')' { $$ = new AstFRead($1,$3,$5,$7,$9); }
| yD_FREWIND '(' idClassSel ')' { $$ = new AstFRewind($1, $3); }
| yD_FLOOR '(' expr ')' { $$ = new AstFloorD($1,$3); } | yD_FLOOR '(' expr ')' { $$ = new AstFloorD($1,$3); }
| yD_FSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstFScanF($1,*$5,$3,$6); } | yD_FSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstFScanF($1,*$5,$3,$6); }
| yD_FSEEK '(' idClassSel ',' expr ',' expr ')' { $$ = new AstFSeek($1,$3,$5,$7); }
| yD_FTELL '(' idClassSel ')' { $$ = new AstFTell($1, $3); }
| yD_HIGH '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_HIGH,$3,NULL); } | yD_HIGH '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_HIGH,$3,NULL); }
| yD_HIGH '(' exprOrDataType ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_HIGH,$3,$5); } | yD_HIGH '(' exprOrDataType ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_HIGH,$3,$5); }
| yD_HYPOT '(' expr ',' expr ')' { $$ = new AstHypotD($1,$3,$5); } | yD_HYPOT '(' expr ',' expr ')' { $$ = new AstHypotD($1,$3,$5); }

View File

@ -24,6 +24,8 @@ module t;
reg [31:0] v_worda; reg [31:0] v_worda;
reg [31:0] v_wordb; reg [31:0] v_wordb;
integer v_length, v_off;
`ifdef TEST_VERBOSE `ifdef TEST_VERBOSE
`define verbose 1'b1 `define verbose 1'b1
`else `else
@ -225,6 +227,27 @@ module t;
if ($fgetc(file) != "\n") $stop; if ($fgetc(file) != "\n") $stop;
v_length = $ftell(file);
$frewind(file);
v_off = $ftell(file);
if (v_off != 0) $stop;
$fseek(file, 10, 0);
v_off = $ftell(file);
if (v_off != 10) $stop;
$fseek(file, 1, 1);
v_off = $ftell(file);
if (v_off != 11) $stop;
$fseek(file, -1, 1);
v_off = $ftell(file);
if (v_off != 10) $stop;
$fseek(file, v_length, 0);
v_off = $ftell(file);
if (v_off != v_length) $stop;
if ($fseek(file, 0, 2) != 0) $stop;
v_off = $ftell(file);
if (v_off < v_length) $stop;
$fclose(file); $fclose(file);
end end