Support $fseek, $ftell, $frewind, bug1496.
This commit is contained in:
parent
3bc260c55d
commit
314cd92129
2
Changes
2
Changes
|
|
@ -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]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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; }
|
||||||
|
|
|
||||||
|
|
@ -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); }
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue