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
|
||||
|
||||
*** Support $fseek, $ftell, $frewind, bug1496. [Howard Su]
|
||||
|
||||
**** 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
|
||||
Gianfranco Costamagna
|
||||
Howard Su
|
||||
Jeremy Bennett
|
||||
John Coiner
|
||||
Kanad Kanhere
|
||||
|
|
|
|||
|
|
@ -2876,6 +2876,86 @@ public:
|
|||
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 {
|
||||
// Parents: expr
|
||||
// Children: file which must be a varref
|
||||
|
|
|
|||
|
|
@ -395,6 +395,25 @@ public:
|
|||
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) {
|
||||
puts("VL_FREAD_I(");
|
||||
puts(cvtToStr(nodep->memp()->widthMin())); // Need real storage width
|
||||
|
|
|
|||
|
|
@ -2342,6 +2342,20 @@ private:
|
|||
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) {
|
||||
if (m_vup->prelim()) {
|
||||
iterateCheckFileDesc(nodep, nodep->filep(), BOTH);
|
||||
|
|
|
|||
|
|
@ -179,6 +179,9 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
|||
"$fopen" { FL; return yD_FOPEN; }
|
||||
"$fread" { FL; return yD_FREAD; }
|
||||
"$fscanf" { FL; return yD_FSCANF; }
|
||||
"$fseek" { FL; return yD_FSEEK; }
|
||||
"$ftell" { FL; return yD_FTELL; }
|
||||
"$frewind" { FL; return yD_FREWIND; }
|
||||
"$fullskew" { FL; return yaTIMINGSPEC; }
|
||||
"$fwrite" { FL; return yD_FWRITE; }
|
||||
"$hold" { FL; return yaTIMINGSPEC; }
|
||||
|
|
|
|||
|
|
@ -517,7 +517,10 @@ class AstSenTree;
|
|||
%token<fl> yD_FLOOR "$floor"
|
||||
%token<fl> yD_FOPEN "$fopen"
|
||||
%token<fl> yD_FREAD "$fread"
|
||||
%token<fl> yD_FREWIND "$frewind"
|
||||
%token<fl> yD_FSCANF "$fscanf"
|
||||
%token<fl> yD_FSEEK "$fseek"
|
||||
%token<fl> yD_FTELL "$ftell"
|
||||
%token<fl> yD_FWRITE "$fwrite"
|
||||
%token<fl> yD_HIGH "$high"
|
||||
%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 ',' expr ')' { $$ = new AstFRead($1,$3,$5,$7,NULL); }
|
||||
| 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_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 ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_HIGH,$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_wordb;
|
||||
|
||||
integer v_length, v_off;
|
||||
|
||||
`ifdef TEST_VERBOSE
|
||||
`define verbose 1'b1
|
||||
`else
|
||||
|
|
@ -225,6 +227,27 @@ module t;
|
|||
|
||||
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);
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue