Support $ungetc.

This commit is contained in:
Wilson Snyder 2019-11-16 12:55:10 -05:00
parent 8c5aa21a11
commit c36d9a68f5
8 changed files with 46 additions and 3 deletions

View File

@ -4,7 +4,7 @@ The contributors that suggested a given feature are shown in []. Thanks!
* Verilator 4.023 devel
**** Support $rewind.
**** Support $rewind and $ungetc.
**** Add -Wpedantic for compliance testing.

View File

@ -3562,8 +3562,7 @@ MCDs, which includes the mode parameter to $fopen being mandatory.
=item $fscanf, $sscanf
Only integer formats are supported; %e, %f, %m, %r, %v, and %z are not
supported.
The formats %r, %v, and %z are not supported.
=item $fullskew, $hold, $nochange, $period, $recovery, $recrem, $removal,
$setup, $setuphold, $skew, $timeskew, $width

View File

@ -4335,6 +4335,28 @@ public:
AstNode* filep() const { return lhsp(); }
};
class AstFUngetC : public AstNodeBiop {
public:
AstFUngetC(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
: AstNodeBiop(fl, lhsp, rhsp) {}
ASTNODE_NODE_FUNCS(FUngetC)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { V3ERROR_NA; }
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) {
return new AstFUngetC(this->fileline(), lhsp, rhsp); }
virtual string emitVerilog() { return "%f$ungetc(%r, %l)"; }
// Non-existent filehandle returns EOF
virtual string emitC() { return "(%li ? (ungetc(%ri, VL_CVT_I_FP(%li)) >= 0 ? 0 : -1) : -1)"; }
virtual bool cleanOut() const { return false; }
virtual bool cleanLhs() const { return true; }
virtual bool cleanRhs() const { return true; }
virtual bool sizeMattersLhs() const { return false; }
virtual bool sizeMattersRhs() const { return false; }
virtual int instrCount() const { return widthInstrs() * 64; }
virtual bool isPure() const { return false; } // SPECIAL: $display has 'visual' ordering
AstNode* filep() const { return lhsp(); }
AstNode* charp() const { return rhsp(); }
};
class AstNodeSystemUniop : public AstNodeUniop {
public:
AstNodeSystemUniop(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {

View File

@ -149,6 +149,14 @@ private:
}
m_setRefLvalue = last_setRefLvalue;
}
virtual void visit(AstFUngetC* nodep) {
bool last_setRefLvalue = m_setRefLvalue;
{
m_setRefLvalue = true;
iterateAndNextNull(nodep->filep());
}
m_setRefLvalue = last_setRefLvalue;
}
virtual void visit(AstSScanF* nodep) {
bool last_setRefLvalue = m_setRefLvalue;
{

View File

@ -2380,6 +2380,13 @@ private:
userIterateAndNext(nodep->strgp(), WidthVP(SELF, BOTH).p());
}
}
virtual void visit(AstFUngetC* nodep) {
if (m_vup->prelim()) {
iterateCheckFileDesc(nodep, nodep->filep(), BOTH);
iterateCheckSigned32(nodep, "$fungetc character", nodep->charp(), BOTH);
nodep->dtypeSetLogicUnsized(32, 8, AstNumeric::SIGNED); // Spec says integer return
}
}
virtual void visit(AstFRead* nodep) {
if (m_vup->prelim()) {
nodep->dtypeSetSigned32(); // Spec says integer return

View File

@ -220,6 +220,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"$test$plusargs" { FL; return yD_TESTPLUSARGS; }
"$time" { FL; return yD_TIME; }
"$timeskew" { FL; return yaTIMINGSPEC; }
"$ungetc" { FL; return yD_UNGETC; }
"$value$plusargs" { FL; return yD_VALUEPLUSARGS; }
"$width" { FL; return yaTIMINGSPEC; }
"$write" { FL; return yD_WRITE; }

View File

@ -557,6 +557,7 @@ class AstSenTree;
%token<fl> yD_TANH "$tanh"
%token<fl> yD_TESTPLUSARGS "$test$plusargs"
%token<fl> yD_TIME "$time"
%token<fl> yD_UNGETC "$ungetc"
%token<fl> yD_UNIT "$unit"
%token<fl> yD_UNPACKED_DIMENSIONS "$unpacked_dimensions"
%token<fl> yD_UNSIGNED "$unsigned"
@ -2970,6 +2971,7 @@ system_f_call_or_t<nodep>: // IEEE: part of system_tf_call (can be task or func)
| yD_TANH '(' expr ')' { $$ = new AstTanhD($1,$3); }
| yD_TESTPLUSARGS '(' str ')' { $$ = new AstTestPlusArgs($1,*$3); }
| yD_TIME parenE { $$ = new AstTime($1); }
| yD_UNGETC '(' expr ',' expr ')' { $$ = new AstFUngetC($1, $5, $3); } // Arg swap to file first
| yD_UNPACKED_DIMENSIONS '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_UNPK_DIMENSIONS,$3); }
| yD_UNSIGNED '(' expr ')' { $$ = new AstUnsigned($1,$3); }
| yD_VALUEPLUSARGS '(' expr ',' expr ')' { $$ = new AstValuePlusArgs($1,$3,$5); }

View File

@ -90,6 +90,10 @@ module t;
if ($fgetc(file) != "i") $stop;
if ($fgetc(file) != "\n") $stop;
// $ungetc
if ($ungetc("x", file) != 0) $stop;
if ($fgetc(file) != "x") $stop;
// $fgets
chars = $fgets(letterl, file);
if (`verbose) $write("c=%0d l=%s\n", chars, letterl);