2022-09-15 14:10:39 +02:00
|
|
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
// DESCRIPTION: Verilator: AstNode sub-types representing expressions
|
|
|
|
|
//
|
|
|
|
|
// Code available from: https://verilator.org
|
|
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
//
|
|
|
|
|
// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
|
|
|
|
|
// can redistribute it and/or modify it under the terms of either the GNU
|
|
|
|
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
|
|
|
|
// Version 2.0.
|
|
|
|
|
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
|
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
//
|
|
|
|
|
// This files contains all 'AstNode' sub-types that representing expressions,
|
|
|
|
|
// i.e.: those constructs that evaluate to [a possible void/unit] value. The
|
|
|
|
|
// root of the hierarchy is 'AstNodeMath', which could also be called
|
|
|
|
|
// 'AstNodeExpr'.
|
|
|
|
|
//
|
|
|
|
|
// Warning: Although the above is what we are aiming for, currently there are
|
|
|
|
|
// some 'AstNode' sub-types defined elsewhere, that represent expressions but
|
|
|
|
|
// are not part of the `AstNodeMath` hierarchy (e.g.: 'AstNodeCall' and its
|
|
|
|
|
// sub-types). These should eventually be fixed and moved under 'AstNodeMath'.
|
|
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
|
|
|
|
|
#ifndef VERILATOR_V3ASTNODEMATH_H_
|
|
|
|
|
#define VERILATOR_V3ASTNODEMATH_H_
|
|
|
|
|
|
|
|
|
|
#ifndef VERILATOR_V3AST_H_
|
|
|
|
|
#error "Use V3Ast.h as the include"
|
|
|
|
|
#include "V3Ast.h" // This helps code analysis tools pick up symbols in V3Ast.h
|
|
|
|
|
#define VL_NOT_FINAL // This #define fixes broken code folding in the CLion IDE
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// === Abstract base node types (AstNode*) =====================================
|
|
|
|
|
|
|
|
|
|
class AstNodeMath VL_NOT_FINAL : public AstNode {
|
|
|
|
|
// Math -- anything that's part of an expression tree
|
|
|
|
|
protected:
|
|
|
|
|
AstNodeMath(VNType t, FileLine* fl)
|
|
|
|
|
: AstNode{t, fl} {}
|
|
|
|
|
|
|
|
|
|
public:
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstNodeMath;
|
2022-09-15 14:10:39 +02:00
|
|
|
// METHODS
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str) const override;
|
|
|
|
|
bool hasDType() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
virtual string emitVerilog() = 0; /// Format string for verilog writing; see V3EmitV
|
|
|
|
|
// For documentation on emitC format see EmitCFunc::emitOpName
|
|
|
|
|
virtual string emitC() = 0;
|
|
|
|
|
virtual string emitSimpleOperator() { return ""; } // "" means not ok to use
|
|
|
|
|
virtual bool emitCheckMaxWords() { return false; } // Check VL_MULS_MAX_WORDS
|
|
|
|
|
virtual bool cleanOut() const = 0; // True if output has extra upper bits zero
|
|
|
|
|
// Someday we will generically support data types on every math node
|
|
|
|
|
// Until then isOpaque indicates we shouldn't constant optimize this node type
|
|
|
|
|
bool isOpaque() const { return VN_IS(this, CvtPackString); }
|
|
|
|
|
};
|
|
|
|
|
class AstNodeBiop VL_NOT_FINAL : public AstNodeMath {
|
2022-09-15 20:43:56 +02:00
|
|
|
// Binary expression
|
|
|
|
|
// @astgen op1 := lhsp : AstNode
|
|
|
|
|
// @astgen op2 := rhsp : AstNode
|
2022-09-15 14:10:39 +02:00
|
|
|
protected:
|
2022-09-15 20:43:56 +02:00
|
|
|
AstNodeBiop(VNType t, FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
2022-09-15 14:10:39 +02:00
|
|
|
: AstNodeMath{t, fl} {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->lhsp(lhsp);
|
|
|
|
|
this->rhsp(rhsp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstNodeBiop;
|
2022-09-15 14:10:39 +02:00
|
|
|
// Clone single node, just get same type back.
|
|
|
|
|
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) = 0;
|
|
|
|
|
// METHODS
|
|
|
|
|
// Set out to evaluation of a AstConst'ed
|
|
|
|
|
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) = 0;
|
|
|
|
|
virtual bool cleanLhs() const = 0; // True if LHS must have extra upper bits zero
|
|
|
|
|
virtual bool cleanRhs() const = 0; // True if RHS must have extra upper bits zero
|
|
|
|
|
virtual bool sizeMattersLhs() const = 0; // True if output result depends on lhs size
|
|
|
|
|
virtual bool sizeMattersRhs() const = 0; // True if output result depends on rhs size
|
|
|
|
|
virtual bool doubleFlavor() const { return false; } // D flavor of nodes with both flavors?
|
|
|
|
|
// Signed flavor of nodes with both flavors?
|
|
|
|
|
virtual bool signedFlavor() const { return false; }
|
|
|
|
|
virtual bool stringFlavor() const { return false; } // N flavor of nodes with both flavors?
|
2022-09-16 12:22:11 +02:00
|
|
|
int instrCount() const override { return widthInstrs(); }
|
|
|
|
|
bool same(const AstNode*) const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstNodeBiCom VL_NOT_FINAL : public AstNodeBiop {
|
|
|
|
|
// Binary math with commutative properties
|
|
|
|
|
protected:
|
|
|
|
|
AstNodeBiCom(VNType t, FileLine* fl, AstNode* lhs, AstNode* rhs)
|
|
|
|
|
: AstNodeBiop{t, fl, lhs, rhs} {}
|
|
|
|
|
|
|
|
|
|
public:
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstNodeBiCom;
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstNodeBiComAsv VL_NOT_FINAL : public AstNodeBiCom {
|
|
|
|
|
// Binary math with commutative & associative properties
|
|
|
|
|
protected:
|
|
|
|
|
AstNodeBiComAsv(VNType t, FileLine* fl, AstNode* lhs, AstNode* rhs)
|
|
|
|
|
: AstNodeBiCom{t, fl, lhs, rhs} {}
|
|
|
|
|
|
|
|
|
|
public:
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstNodeBiComAsv;
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstNodeSel VL_NOT_FINAL : public AstNodeBiop {
|
|
|
|
|
// Single bit range extraction, perhaps with non-constant selection or array selection
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen alias op1 := fromp // Expression we are indexing into
|
|
|
|
|
// @astgen alias op2 := bitp // The index // TOOD: rename to idxp
|
2022-09-15 14:10:39 +02:00
|
|
|
protected:
|
|
|
|
|
AstNodeSel(VNType t, FileLine* fl, AstNode* fromp, AstNode* bitp)
|
|
|
|
|
: AstNodeBiop{t, fl, fromp, bitp} {}
|
|
|
|
|
|
|
|
|
|
public:
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstNodeSel;
|
2022-09-15 14:10:39 +02:00
|
|
|
int bitConst() const;
|
2022-09-16 12:22:11 +02:00
|
|
|
bool hasDType() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstNodeStream VL_NOT_FINAL : public AstNodeBiop {
|
|
|
|
|
// Verilog {rhs{lhs}} - Note rhsp() is the slice size, not the lhsp()
|
|
|
|
|
protected:
|
|
|
|
|
AstNodeStream(VNType t, FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: AstNodeBiop{t, fl, lhsp, rhsp} {
|
|
|
|
|
if (lhsp->dtypep()) dtypeSetLogicSized(lhsp->dtypep()->width(), VSigning::UNSIGNED);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstNodeStream;
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstNodeSystemBiop VL_NOT_FINAL : public AstNodeBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstNodeSystemBiop(VNType t, FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: AstNodeBiop(t, fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetDouble();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstNodeSystemBiop;
|
2022-09-16 12:22:11 +02:00
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool cleanRhs() const override { return false; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return INSTR_COUNT_DBL_TRIG; }
|
|
|
|
|
bool doubleFlavor() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstNodeQuadop VL_NOT_FINAL : public AstNodeMath {
|
2022-09-15 20:43:56 +02:00
|
|
|
// 4-ary expression
|
|
|
|
|
// @astgen op1 := lhsp : AstNode
|
|
|
|
|
// @astgen op2 := rhsp : AstNode
|
|
|
|
|
// @astgen op3 := thsp : AstNode
|
|
|
|
|
// @astgen op4 := fhsp : AstNode
|
2022-09-15 14:10:39 +02:00
|
|
|
protected:
|
2022-09-15 20:43:56 +02:00
|
|
|
AstNodeQuadop(VNType t, FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* thsp,
|
|
|
|
|
AstNode* fhsp)
|
2022-09-15 14:10:39 +02:00
|
|
|
: AstNodeMath{t, fl} {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->lhsp(lhsp);
|
|
|
|
|
this->rhsp(rhsp);
|
|
|
|
|
this->thsp(thsp);
|
|
|
|
|
this->fhsp(fhsp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstNodeQuadop;
|
2022-09-15 14:10:39 +02:00
|
|
|
// METHODS
|
|
|
|
|
// Set out to evaluation of a AstConst'ed
|
|
|
|
|
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs,
|
|
|
|
|
const V3Number& ths, const V3Number& fhs)
|
|
|
|
|
= 0;
|
|
|
|
|
virtual bool cleanLhs() const = 0; // True if LHS must have extra upper bits zero
|
|
|
|
|
virtual bool cleanRhs() const = 0; // True if RHS must have extra upper bits zero
|
|
|
|
|
virtual bool cleanThs() const = 0; // True if THS must have extra upper bits zero
|
|
|
|
|
virtual bool cleanFhs() const = 0; // True if THS must have extra upper bits zero
|
|
|
|
|
virtual bool sizeMattersLhs() const = 0; // True if output result depends on lhs size
|
|
|
|
|
virtual bool sizeMattersRhs() const = 0; // True if output result depends on rhs size
|
|
|
|
|
virtual bool sizeMattersThs() const = 0; // True if output result depends on ths size
|
|
|
|
|
virtual bool sizeMattersFhs() const = 0; // True if output result depends on ths size
|
2022-09-16 12:22:11 +02:00
|
|
|
int instrCount() const override { return widthInstrs(); }
|
|
|
|
|
bool same(const AstNode*) const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstNodeTermop VL_NOT_FINAL : public AstNodeMath {
|
|
|
|
|
// Terminal operator -- a operator with no "inputs"
|
|
|
|
|
protected:
|
|
|
|
|
AstNodeTermop(VNType t, FileLine* fl)
|
|
|
|
|
: AstNodeMath{t, fl} {}
|
|
|
|
|
|
|
|
|
|
public:
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstNodeTermop;
|
2022-09-15 14:10:39 +02:00
|
|
|
// Know no children, and hot function, so skip iterator for speed
|
|
|
|
|
// cppcheck-suppress functionConst
|
|
|
|
|
void iterateChildren(VNVisitor& v) {}
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str) const override;
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstNodeTriop VL_NOT_FINAL : public AstNodeMath {
|
2022-09-15 20:43:56 +02:00
|
|
|
// Ternary expression
|
|
|
|
|
// @astgen op1 := lhsp : AstNode
|
|
|
|
|
// @astgen op2 := rhsp : AstNode
|
|
|
|
|
// @astgen op3 := thsp : AstNode
|
2022-09-15 14:10:39 +02:00
|
|
|
protected:
|
2022-09-15 20:43:56 +02:00
|
|
|
AstNodeTriop(VNType t, FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* thsp)
|
2022-09-15 14:10:39 +02:00
|
|
|
: AstNodeMath{t, fl} {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->lhsp(lhsp);
|
|
|
|
|
this->rhsp(rhsp);
|
|
|
|
|
this->thsp(thsp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstNodeTriop;
|
2022-09-15 14:10:39 +02:00
|
|
|
// METHODS
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str) const override;
|
2022-09-15 14:10:39 +02:00
|
|
|
// Set out to evaluation of a AstConst'ed
|
|
|
|
|
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs,
|
|
|
|
|
const V3Number& ths)
|
|
|
|
|
= 0;
|
|
|
|
|
virtual bool cleanLhs() const = 0; // True if LHS must have extra upper bits zero
|
|
|
|
|
virtual bool cleanRhs() const = 0; // True if RHS must have extra upper bits zero
|
|
|
|
|
virtual bool cleanThs() const = 0; // True if THS must have extra upper bits zero
|
|
|
|
|
virtual bool sizeMattersLhs() const = 0; // True if output result depends on lhs size
|
|
|
|
|
virtual bool sizeMattersRhs() const = 0; // True if output result depends on rhs size
|
|
|
|
|
virtual bool sizeMattersThs() const = 0; // True if output result depends on ths size
|
2022-09-16 12:22:11 +02:00
|
|
|
int instrCount() const override { return widthInstrs(); }
|
|
|
|
|
bool same(const AstNode*) const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstNodeCond VL_NOT_FINAL : public AstNodeTriop {
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen alias op1 := condp
|
|
|
|
|
// @astgen alias op2 := thenp
|
|
|
|
|
// @astgen alias op3 := elsep
|
2022-09-15 14:10:39 +02:00
|
|
|
protected:
|
2022-09-15 20:43:56 +02:00
|
|
|
AstNodeCond(VNType t, FileLine* fl, AstNode* condp, AstNode* thenp, AstNode* elsep)
|
|
|
|
|
: AstNodeTriop{t, fl, condp, thenp, elsep} {
|
|
|
|
|
if (thenp) {
|
|
|
|
|
dtypeFrom(thenp);
|
|
|
|
|
} else if (elsep) {
|
|
|
|
|
dtypeFrom(elsep);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstNodeCond;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs,
|
|
|
|
|
const V3Number& ths) override;
|
|
|
|
|
string emitVerilog() override { return "%k(%l %f? %r %k: %t)"; }
|
|
|
|
|
string emitC() override { return "VL_COND_%nq%lq%rq%tq(%nw, %P, %li, %ri, %ti)"; }
|
|
|
|
|
bool cleanOut() const override { return false; } // clean if e1 & e2 clean
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return false; }
|
|
|
|
|
bool cleanThs() const override { return false; } // Propagates up
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
bool sizeMattersThs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return INSTR_COUNT_BRANCH; }
|
2022-09-15 20:43:56 +02:00
|
|
|
virtual AstNode* cloneType(AstNode* condp, AstNode* thenp, AstNode* elsep) = 0;
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstNodeUniop VL_NOT_FINAL : public AstNodeMath {
|
2022-09-15 20:43:56 +02:00
|
|
|
// Unary expression
|
|
|
|
|
// @astgen op1 := lhsp : AstNode
|
2022-09-15 14:10:39 +02:00
|
|
|
protected:
|
|
|
|
|
AstNodeUniop(VNType t, FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: AstNodeMath{t, fl} {
|
|
|
|
|
dtypeFrom(lhsp);
|
2022-09-15 20:43:56 +02:00
|
|
|
this->lhsp(lhsp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstNodeUniop;
|
2022-09-15 14:10:39 +02:00
|
|
|
// METHODS
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str) const override;
|
2022-09-15 14:10:39 +02:00
|
|
|
// Set out to evaluation of a AstConst'ed lhs
|
|
|
|
|
virtual void numberOperate(V3Number& out, const V3Number& lhs) = 0;
|
|
|
|
|
virtual bool cleanLhs() const = 0;
|
|
|
|
|
virtual bool sizeMattersLhs() const = 0; // True if output result depends on lhs size
|
|
|
|
|
virtual bool doubleFlavor() const { return false; } // D flavor of nodes with both flavors?
|
|
|
|
|
// Signed flavor of nodes with both flavors?
|
|
|
|
|
virtual bool signedFlavor() const { return false; }
|
|
|
|
|
virtual bool stringFlavor() const { return false; } // N flavor of nodes with both flavors?
|
2022-09-16 12:22:11 +02:00
|
|
|
int instrCount() const override { return widthInstrs(); }
|
|
|
|
|
bool same(const AstNode*) const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstNodeSystemUniop VL_NOT_FINAL : public AstNodeUniop {
|
|
|
|
|
public:
|
|
|
|
|
AstNodeSystemUniop(VNType t, FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: AstNodeUniop(t, fl, lhsp) {
|
|
|
|
|
dtypeSetDouble();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstNodeSystemUniop;
|
2022-09-16 12:22:11 +02:00
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return INSTR_COUNT_DBL_TRIG; }
|
|
|
|
|
bool doubleFlavor() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstNodeVarRef VL_NOT_FINAL : public AstNodeMath {
|
|
|
|
|
// An AstVarRef or AstVarXRef
|
|
|
|
|
private:
|
|
|
|
|
VAccess m_access; // Left hand side assignment
|
|
|
|
|
AstVar* m_varp; // [AfterLink] Pointer to variable itself
|
|
|
|
|
AstVarScope* m_varScopep = nullptr; // Varscope for hierarchy
|
|
|
|
|
AstNodeModule* m_classOrPackagep = nullptr; // Package hierarchy
|
|
|
|
|
string m_name; // Name of variable
|
|
|
|
|
string m_selfPointer; // Output code object pointer (e.g.: 'this')
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
AstNodeVarRef(VNType t, FileLine* fl, const string& name, const VAccess& access)
|
|
|
|
|
: AstNodeMath{t, fl}
|
|
|
|
|
, m_access{access}
|
|
|
|
|
, m_name{name} {
|
|
|
|
|
varp(nullptr);
|
|
|
|
|
}
|
|
|
|
|
AstNodeVarRef(VNType t, FileLine* fl, const string& name, AstVar* varp, const VAccess& access)
|
|
|
|
|
: AstNodeMath{t, fl}
|
|
|
|
|
, m_access{access}
|
|
|
|
|
, m_name{name} {
|
|
|
|
|
// May have varp==nullptr
|
|
|
|
|
this->varp(varp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstNodeVarRef;
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str) const override;
|
|
|
|
|
bool hasDType() const override { return true; }
|
|
|
|
|
const char* broken() const override;
|
|
|
|
|
int instrCount() const override { return widthInstrs(); }
|
|
|
|
|
void cloneRelink() override;
|
|
|
|
|
string name() const override { return m_name; } // * = Var name
|
|
|
|
|
void name(const string& name) override { m_name = name; }
|
2022-09-15 14:10:39 +02:00
|
|
|
VAccess access() const { return m_access; }
|
|
|
|
|
void access(const VAccess& flag) { m_access = flag; } // Avoid using this; Set in constructor
|
|
|
|
|
AstVar* varp() const { return m_varp; } // [After Link] Pointer to variable
|
2022-09-16 14:17:38 +02:00
|
|
|
void varp(AstVar* varp) {
|
|
|
|
|
m_varp = varp;
|
|
|
|
|
dtypeFrom((AstNode*)varp);
|
|
|
|
|
}
|
2022-09-15 14:10:39 +02:00
|
|
|
AstVarScope* varScopep() const { return m_varScopep; }
|
|
|
|
|
void varScopep(AstVarScope* varscp) { m_varScopep = varscp; }
|
|
|
|
|
string selfPointer() const { return m_selfPointer; }
|
|
|
|
|
void selfPointer(const string& value) { m_selfPointer = value; }
|
|
|
|
|
string selfPointerProtect(bool useSelfForThis) const;
|
|
|
|
|
AstNodeModule* classOrPackagep() const { return m_classOrPackagep; }
|
|
|
|
|
void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; }
|
|
|
|
|
// Know no children, and hot function, so skip iterator for speed
|
|
|
|
|
// cppcheck-suppress functionConst
|
|
|
|
|
void iterateChildren(VNVisitor& v) {}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// === Concrete node types =====================================================
|
|
|
|
|
|
|
|
|
|
// === AstNodeMath ===
|
|
|
|
|
class AstAddrOfCFunc final : public AstNodeMath {
|
|
|
|
|
// Get address of CFunc
|
|
|
|
|
private:
|
|
|
|
|
AstCFunc* m_funcp; // Pointer to function itself
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
AstAddrOfCFunc(FileLine* fl, AstCFunc* funcp)
|
|
|
|
|
: ASTGEN_SUPER_AddrOfCFunc(fl)
|
|
|
|
|
, m_funcp{funcp} {
|
|
|
|
|
dtypep(findCHandleDType());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstAddrOfCFunc;
|
2022-09-16 12:22:11 +02:00
|
|
|
void cloneRelink() override;
|
|
|
|
|
const char* broken() const override;
|
|
|
|
|
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
AstCFunc* funcp() const { return m_funcp; }
|
|
|
|
|
};
|
|
|
|
|
class AstCMath final : public AstNodeMath {
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := exprsp : List[AstNode] // Expressions to print
|
2022-09-15 14:10:39 +02:00
|
|
|
private:
|
|
|
|
|
const bool m_cleanOut;
|
|
|
|
|
bool m_pure; // Pure optimizable
|
|
|
|
|
public:
|
|
|
|
|
// Emit C textual math function (like AstUCFunc)
|
|
|
|
|
AstCMath(FileLine* fl, AstNode* exprsp)
|
|
|
|
|
: ASTGEN_SUPER_CMath(fl)
|
|
|
|
|
, m_cleanOut{true}
|
|
|
|
|
, m_pure{false} {
|
2022-09-15 20:43:56 +02:00
|
|
|
addExprsp(exprsp);
|
2022-09-15 14:10:39 +02:00
|
|
|
dtypeFrom(exprsp);
|
|
|
|
|
}
|
|
|
|
|
inline AstCMath(FileLine* fl, const string& textStmt, int setwidth, bool cleanOut = true);
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstCMath;
|
2022-09-16 12:22:11 +02:00
|
|
|
bool isGateOptimizable() const override { return m_pure; }
|
|
|
|
|
bool isPredictOptimizable() const override { return m_pure; }
|
|
|
|
|
bool cleanOut() const override { return m_cleanOut; }
|
|
|
|
|
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool same(const AstNode* /*samep*/) const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool pure() const { return m_pure; }
|
|
|
|
|
void pure(bool flag) { m_pure = flag; }
|
|
|
|
|
};
|
|
|
|
|
class AstConsAssoc final : public AstNodeMath {
|
|
|
|
|
// Construct an assoc array and return object, '{}
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := defaultp : Optional[AstNode]
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
AstConsAssoc(FileLine* fl, AstNode* defaultp)
|
|
|
|
|
: ASTGEN_SUPER_ConsAssoc(fl) {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->defaultp(defaultp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstConsAssoc;
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "'{}"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
int instrCount() const override { return widthInstrs(); }
|
|
|
|
|
bool same(const AstNode* /*samep*/) const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstConsDynArray final : public AstNodeMath {
|
|
|
|
|
// Construct a queue and return object, '{}. '{lhs}, '{lhs. rhs}
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := lhsp : Optional[AstNode]
|
|
|
|
|
// @astgen op2 := rhsp : Optional[AstNode]
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
explicit AstConsDynArray(FileLine* fl, AstNode* lhsp = nullptr, AstNode* rhsp = nullptr)
|
|
|
|
|
: ASTGEN_SUPER_ConsDynArray(fl) {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->lhsp(lhsp);
|
|
|
|
|
this->rhsp(rhsp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstConsDynArray;
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "'{%l, %r}"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
int instrCount() const override { return widthInstrs(); }
|
|
|
|
|
bool same(const AstNode* /*samep*/) const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstConsQueue final : public AstNodeMath {
|
|
|
|
|
// Construct a queue and return object, '{}. '{lhs}, '{lhs. rhs}
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := lhsp : Optional[AstNode]
|
|
|
|
|
// @astgen op2 := rhsp : Optional[AstNode]
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
explicit AstConsQueue(FileLine* fl, AstNode* lhsp = nullptr, AstNode* rhsp = nullptr)
|
|
|
|
|
: ASTGEN_SUPER_ConsQueue(fl) {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->lhsp(lhsp);
|
|
|
|
|
this->rhsp(rhsp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstConsQueue;
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "'{%l, %r}"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
int instrCount() const override { return widthInstrs(); }
|
|
|
|
|
bool same(const AstNode* /*samep*/) const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstConsWildcard final : public AstNodeMath {
|
|
|
|
|
// Construct a wildcard assoc array and return object, '{}
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := defaultp : Optional[AstNode]
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
AstConsWildcard(FileLine* fl, AstNode* defaultp)
|
|
|
|
|
: ASTGEN_SUPER_ConsWildcard(fl) {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->defaultp(defaultp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstConsWildcard;
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "'{}"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
int instrCount() const override { return widthInstrs(); }
|
|
|
|
|
bool same(const AstNode* /*samep*/) const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstConst final : public AstNodeMath {
|
|
|
|
|
// A constant
|
|
|
|
|
private:
|
|
|
|
|
V3Number m_num; // Constant value
|
|
|
|
|
void initWithNumber() {
|
|
|
|
|
if (m_num.isDouble()) {
|
|
|
|
|
dtypeSetDouble();
|
|
|
|
|
} else if (m_num.isString()) {
|
|
|
|
|
dtypeSetString();
|
|
|
|
|
} else {
|
|
|
|
|
dtypeSetLogicUnsized(m_num.width(), (m_num.sized() ? 0 : m_num.widthMin()),
|
|
|
|
|
VSigning::fromBool(m_num.isSigned()));
|
|
|
|
|
}
|
|
|
|
|
m_num.nodep(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
AstConst(FileLine* fl, const V3Number& num)
|
|
|
|
|
: ASTGEN_SUPER_Const(fl)
|
|
|
|
|
, m_num(num) {
|
|
|
|
|
initWithNumber();
|
|
|
|
|
}
|
|
|
|
|
class WidthedValue {}; // for creator type-overload selection
|
|
|
|
|
AstConst(FileLine* fl, WidthedValue, int width, uint32_t value)
|
|
|
|
|
: ASTGEN_SUPER_Const(fl)
|
|
|
|
|
, m_num(this, width, value) {
|
|
|
|
|
initWithNumber();
|
|
|
|
|
}
|
|
|
|
|
class DTyped {}; // for creator type-overload selection
|
|
|
|
|
// Zero/empty constant with a type matching nodetypep
|
|
|
|
|
AstConst(FileLine* fl, DTyped, const AstNodeDType* nodedtypep)
|
|
|
|
|
: ASTGEN_SUPER_Const(fl)
|
|
|
|
|
, m_num(this, nodedtypep) {
|
|
|
|
|
initWithNumber();
|
|
|
|
|
}
|
|
|
|
|
class StringToParse {}; // for creator type-overload selection
|
|
|
|
|
AstConst(FileLine* fl, StringToParse, const char* sourcep)
|
|
|
|
|
: ASTGEN_SUPER_Const(fl)
|
|
|
|
|
, m_num(this, sourcep) {
|
|
|
|
|
initWithNumber();
|
|
|
|
|
}
|
|
|
|
|
class VerilogStringLiteral {}; // for creator type-overload selection
|
|
|
|
|
AstConst(FileLine* fl, VerilogStringLiteral, const string& str)
|
|
|
|
|
: ASTGEN_SUPER_Const(fl)
|
|
|
|
|
, m_num(V3Number::VerilogStringLiteral(), this, str) {
|
|
|
|
|
initWithNumber();
|
|
|
|
|
}
|
|
|
|
|
AstConst(FileLine* fl, uint32_t num)
|
|
|
|
|
: ASTGEN_SUPER_Const(fl)
|
|
|
|
|
, m_num(this, 32, num) {
|
|
|
|
|
dtypeSetLogicUnsized(m_num.width(), 0, VSigning::UNSIGNED);
|
|
|
|
|
}
|
|
|
|
|
class Unsized32 {}; // for creator type-overload selection
|
|
|
|
|
AstConst(FileLine* fl, Unsized32, uint32_t num) // Unsized 32-bit integer of specified value
|
|
|
|
|
: ASTGEN_SUPER_Const(fl)
|
|
|
|
|
, m_num(this, 32, num) {
|
|
|
|
|
m_num.width(32, false);
|
|
|
|
|
dtypeSetLogicUnsized(32, m_num.widthMin(), VSigning::UNSIGNED);
|
|
|
|
|
}
|
|
|
|
|
class Signed32 {}; // for creator type-overload selection
|
|
|
|
|
AstConst(FileLine* fl, Signed32, int32_t num) // Signed 32-bit integer of specified value
|
|
|
|
|
: ASTGEN_SUPER_Const(fl)
|
|
|
|
|
, m_num(this, 32, num) {
|
|
|
|
|
m_num.width(32, true);
|
|
|
|
|
dtypeSetLogicUnsized(32, m_num.widthMin(), VSigning::SIGNED);
|
|
|
|
|
}
|
|
|
|
|
class Unsized64 {}; // for creator type-overload selection
|
|
|
|
|
AstConst(FileLine* fl, Unsized64, uint64_t num)
|
|
|
|
|
: ASTGEN_SUPER_Const(fl)
|
|
|
|
|
, m_num(this, 64, 0) {
|
|
|
|
|
m_num.setQuad(num);
|
|
|
|
|
dtypeSetLogicSized(64, VSigning::UNSIGNED);
|
|
|
|
|
}
|
|
|
|
|
class SizedEData {}; // for creator type-overload selection
|
|
|
|
|
AstConst(FileLine* fl, SizedEData, uint64_t num)
|
|
|
|
|
: ASTGEN_SUPER_Const(fl)
|
|
|
|
|
, m_num(this, VL_EDATASIZE, 0) {
|
|
|
|
|
m_num.setQuad(num);
|
|
|
|
|
dtypeSetLogicSized(VL_EDATASIZE, VSigning::UNSIGNED);
|
|
|
|
|
}
|
|
|
|
|
class RealDouble {}; // for creator type-overload selection
|
|
|
|
|
AstConst(FileLine* fl, RealDouble, double num)
|
|
|
|
|
: ASTGEN_SUPER_Const(fl)
|
|
|
|
|
, m_num(this, 64) {
|
|
|
|
|
m_num.setDouble(num);
|
|
|
|
|
dtypeSetDouble();
|
|
|
|
|
}
|
|
|
|
|
class String {}; // for creator type-overload selection
|
|
|
|
|
AstConst(FileLine* fl, String, const string& num)
|
|
|
|
|
: ASTGEN_SUPER_Const(fl)
|
|
|
|
|
, m_num(V3Number::String(), this, num) {
|
|
|
|
|
dtypeSetString();
|
|
|
|
|
}
|
|
|
|
|
class BitFalse {};
|
|
|
|
|
AstConst(FileLine* fl, BitFalse) // Shorthand const 0, dtype should be a logic of size 1
|
|
|
|
|
: ASTGEN_SUPER_Const(fl)
|
|
|
|
|
, m_num(this, 1, 0) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
|
|
|
|
// Shorthand const 1 (or with argument 0/1), dtype should be a logic of size 1
|
|
|
|
|
class BitTrue {};
|
|
|
|
|
AstConst(FileLine* fl, BitTrue, bool on = true)
|
|
|
|
|
: ASTGEN_SUPER_Const(fl)
|
|
|
|
|
, m_num(this, 1, on) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
|
|
|
|
class Null {};
|
|
|
|
|
AstConst(FileLine* fl, Null)
|
|
|
|
|
: ASTGEN_SUPER_Const(fl)
|
|
|
|
|
, m_num(V3Number::Null{}, this) {
|
|
|
|
|
dtypeSetBit(); // Events 1 bit, objects 64 bits, so autoExtend=1 and use bit here
|
|
|
|
|
initWithNumber();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstConst;
|
2022-09-16 12:22:11 +02:00
|
|
|
string name() const override { return num().ascii(); } // * = Value
|
2022-10-18 23:07:09 +02:00
|
|
|
const V3Number& num() const VL_MT_SAFE { return m_num; } // * = Value
|
2022-09-15 14:10:39 +02:00
|
|
|
V3Number& num() { return m_num; } // * = Value
|
|
|
|
|
uint32_t toUInt() const { return num().toUInt(); }
|
2022-10-18 23:07:09 +02:00
|
|
|
int32_t toSInt() const VL_MT_SAFE { return num().toSInt(); }
|
2022-09-15 14:10:39 +02:00
|
|
|
uint64_t toUQuad() const { return num().toUQuad(); }
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool same(const AstNode* samep) const override {
|
2022-09-15 14:10:39 +02:00
|
|
|
const AstConst* const sp = static_cast<const AstConst*>(samep);
|
|
|
|
|
return num().isCaseEq(sp->num());
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
int instrCount() const override { return widthInstrs(); }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool isEqAllOnes() const { return num().isEqAllOnes(width()); }
|
|
|
|
|
bool isEqAllOnesV() const { return num().isEqAllOnes(widthMinV()); }
|
|
|
|
|
// Parse string and create appropriate type of AstConst.
|
|
|
|
|
// May return nullptr on parse failure.
|
|
|
|
|
static AstConst* parseParamLiteral(FileLine* fl, const string& literal);
|
|
|
|
|
};
|
|
|
|
|
class AstEmptyQueue final : public AstNodeMath {
|
|
|
|
|
public:
|
|
|
|
|
explicit AstEmptyQueue(FileLine* fl)
|
|
|
|
|
: ASTGEN_SUPER_EmptyQueue(fl) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstEmptyQueue;
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitVerilog() override { return "{}"; }
|
|
|
|
|
bool same(const AstNode* /*samep*/) const override { return true; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstEnumItemRef final : public AstNodeMath {
|
|
|
|
|
private:
|
|
|
|
|
AstEnumItem* m_itemp; // [AfterLink] Pointer to item
|
|
|
|
|
AstNodeModule* m_classOrPackagep; // Package hierarchy
|
|
|
|
|
public:
|
|
|
|
|
AstEnumItemRef(FileLine* fl, AstEnumItem* itemp, AstNodeModule* classOrPackagep)
|
|
|
|
|
: ASTGEN_SUPER_EnumItemRef(fl)
|
|
|
|
|
, m_itemp{itemp}
|
|
|
|
|
, m_classOrPackagep{classOrPackagep} {
|
|
|
|
|
dtypeFrom(m_itemp);
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstEnumItemRef;
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str) const override;
|
|
|
|
|
string name() const override { return itemp()->name(); }
|
|
|
|
|
int instrCount() const override { return 0; }
|
2022-09-15 14:10:39 +02:00
|
|
|
const char* broken() const override;
|
2022-09-16 12:22:11 +02:00
|
|
|
void cloneRelink() override {
|
2022-09-15 14:10:39 +02:00
|
|
|
if (m_itemp->clonep()) m_itemp = m_itemp->clonep();
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
bool same(const AstNode* samep) const override {
|
2022-09-15 14:10:39 +02:00
|
|
|
const AstEnumItemRef* const sp = static_cast<const AstEnumItemRef*>(samep);
|
|
|
|
|
return itemp() == sp->itemp();
|
|
|
|
|
}
|
|
|
|
|
AstEnumItem* itemp() const { return m_itemp; }
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
AstNodeModule* classOrPackagep() const { return m_classOrPackagep; }
|
|
|
|
|
void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; }
|
|
|
|
|
};
|
|
|
|
|
class AstExprStmt final : public AstNodeMath {
|
|
|
|
|
// Perform a statement, often assignment inside an expression/math node,
|
|
|
|
|
// the parent gets passed the 'resultp()'.
|
|
|
|
|
// resultp is evaluated AFTER the statement(s).
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := stmtsp : List[AstNode]
|
|
|
|
|
// @astgen op2 := resultp : AstNode
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
AstExprStmt(FileLine* fl, AstNode* stmtsp, AstNode* resultp)
|
|
|
|
|
: ASTGEN_SUPER_ExprStmt(fl) {
|
2022-09-15 20:43:56 +02:00
|
|
|
addStmtsp(stmtsp);
|
|
|
|
|
this->resultp(resultp);
|
2022-09-15 14:10:39 +02:00
|
|
|
dtypeFrom(resultp);
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstExprStmt;
|
2022-09-15 14:10:39 +02:00
|
|
|
// METHODS
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool same(const AstNode*) const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstFError final : public AstNodeMath {
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := filep : AstNode
|
|
|
|
|
// @astgen op2 := strp : AstNode
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
AstFError(FileLine* fl, AstNode* filep, AstNode* strp)
|
|
|
|
|
: ASTGEN_SUPER_FError(fl) {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->filep(filep);
|
|
|
|
|
this->strp(strp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstFError;
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%f$ferror(%l, %r)"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
virtual bool cleanLhs() const { return true; }
|
|
|
|
|
virtual bool sizeMattersLhs() const { return false; }
|
2022-09-16 12:22:11 +02:00
|
|
|
int instrCount() const override { return widthInstrs() * 64; }
|
|
|
|
|
bool isPure() const override { return false; } // SPECIAL: $display has 'visual' ordering
|
|
|
|
|
bool same(const AstNode* /*samep*/) const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstFRead final : public AstNodeMath {
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := memp : AstNode // VarRef for result
|
|
|
|
|
// @astgen op2 := filep : AstNode // file (must be a VarRef)
|
|
|
|
|
// @astgen op3 := startp : Optional[AstNode] // Offset
|
|
|
|
|
// @astgen op4 := countp : Optional[AstNode] // Size
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
AstFRead(FileLine* fl, AstNode* memp, AstNode* filep, AstNode* startp, AstNode* countp)
|
|
|
|
|
: ASTGEN_SUPER_FRead(fl) {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->memp(memp);
|
|
|
|
|
this->filep(filep);
|
|
|
|
|
this->startp(startp);
|
|
|
|
|
this->countp(countp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstFRead;
|
2022-09-16 12:22:11 +02:00
|
|
|
string verilogKwd() const override { return "$fread"; }
|
|
|
|
|
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool isGateOptimizable() const override { return false; }
|
|
|
|
|
bool isPredictOptimizable() const override { return false; }
|
|
|
|
|
bool isPure() const override { return false; } // SPECIAL: has 'visual' ordering
|
|
|
|
|
bool isOutputter() const override { return true; } // SPECIAL: makes output
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool same(const AstNode* /*samep*/) const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstFRewind final : public AstNodeMath {
|
|
|
|
|
// Parents: stmtlist
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := filep : Optional[AstNode]
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
AstFRewind(FileLine* fl, AstNode* filep)
|
|
|
|
|
: ASTGEN_SUPER_FRewind(fl) {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->filep(filep);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstFRewind;
|
2022-09-16 12:22:11 +02:00
|
|
|
string verilogKwd() const override { return "$frewind"; }
|
|
|
|
|
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
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 cleanOut() const override { return false; }
|
|
|
|
|
bool same(const AstNode* /*samep*/) const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstFScanF final : public AstNodeMath {
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := exprsp : List[AstNode] // VarRefs for results
|
|
|
|
|
// @astgen op2 := filep : Optional[AstNode] // file (must be a VarRef)
|
2022-09-15 14:10:39 +02:00
|
|
|
private:
|
|
|
|
|
string m_text;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
AstFScanF(FileLine* fl, const string& text, AstNode* filep, AstNode* exprsp)
|
|
|
|
|
: ASTGEN_SUPER_FScanF(fl)
|
|
|
|
|
, m_text{text} {
|
2022-09-15 20:43:56 +02:00
|
|
|
addExprsp(exprsp);
|
|
|
|
|
this->filep(filep);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstFScanF;
|
2022-09-16 12:22:11 +02:00
|
|
|
string name() const override { return m_text; }
|
|
|
|
|
string verilogKwd() const override { return "$fscanf"; }
|
|
|
|
|
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool isGateOptimizable() const override { return false; }
|
|
|
|
|
bool isPredictOptimizable() const override { return false; }
|
|
|
|
|
bool isPure() const override { return false; } // SPECIAL: has 'visual' ordering
|
|
|
|
|
bool isOutputter() const override { return true; } // SPECIAL: makes output
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool same(const AstNode* samep) const override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return text() == static_cast<const AstFScanF*>(samep)->text();
|
|
|
|
|
}
|
|
|
|
|
string text() const { return m_text; } // * = Text to display
|
|
|
|
|
void text(const string& text) { m_text = text; }
|
|
|
|
|
};
|
|
|
|
|
class AstFSeek final : public AstNodeMath {
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := filep : AstNode // file (must be a VarRef)
|
|
|
|
|
// @astgen op2 := offset : Optional[AstNode]
|
|
|
|
|
// @astgen op3 := operation : Optional[AstNode]
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
AstFSeek(FileLine* fl, AstNode* filep, AstNode* offset, AstNode* operation)
|
|
|
|
|
: ASTGEN_SUPER_FSeek(fl) {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->filep(filep);
|
|
|
|
|
this->offset(offset);
|
|
|
|
|
this->operation(operation);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstFSeek;
|
2022-09-16 12:22:11 +02:00
|
|
|
string verilogKwd() const override { return "$fseek"; }
|
|
|
|
|
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool isGateOptimizable() const override { return false; }
|
|
|
|
|
bool isPredictOptimizable() const override { return false; }
|
|
|
|
|
bool isPure() const override { return false; } // SPECIAL: has 'visual' ordering
|
|
|
|
|
bool isOutputter() const override { return true; } // SPECIAL: makes output
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool same(const AstNode* /*samep*/) const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstFTell final : public AstNodeMath {
|
|
|
|
|
// Parents: stmtlist
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := filep : AstNode // file (must be a VarRef)
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
AstFTell(FileLine* fl, AstNode* filep)
|
|
|
|
|
: ASTGEN_SUPER_FTell(fl) {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->filep(filep);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstFTell;
|
2022-09-16 12:22:11 +02:00
|
|
|
string verilogKwd() const override { return "$ftell"; }
|
|
|
|
|
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
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 cleanOut() const override { return false; }
|
|
|
|
|
bool same(const AstNode* /*samep*/) const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstFell final : public AstNodeMath {
|
|
|
|
|
// Verilog $fell
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := exprp : AstNode
|
|
|
|
|
// @astgen op2 := sentreep : Optional[AstSenTree]
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
AstFell(FileLine* fl, AstNode* exprp)
|
|
|
|
|
: ASTGEN_SUPER_Fell(fl) {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->exprp(exprp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstFell;
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "$fell(%l)"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
int instrCount() const override { return widthInstrs(); }
|
|
|
|
|
bool same(const AstNode* /*samep*/) const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstGatePin final : public AstNodeMath {
|
|
|
|
|
// Possibly expand a gate primitive input pin value to match the range of the gate primitive
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := exprp : AstNode // Pin expression
|
|
|
|
|
// @astgen op2 := rangep : AstRange // Range of pin
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
2022-09-15 20:43:56 +02:00
|
|
|
AstGatePin(FileLine* fl, AstNode* exprp, AstRange* rangep)
|
2022-09-15 14:10:39 +02:00
|
|
|
: ASTGEN_SUPER_GatePin(fl) {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->exprp(exprp);
|
|
|
|
|
this->rangep(rangep);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstGatePin;
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%l"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstImplication final : public AstNodeMath {
|
|
|
|
|
// Verilog |-> |=>
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := lhsp : AstNode
|
|
|
|
|
// @astgen op2 := rhsp : AstNode
|
2022-09-21 16:24:17 +02:00
|
|
|
// @astgen op3 := sentreep : Optional[AstSenTree]
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
2022-09-15 20:43:56 +02:00
|
|
|
AstImplication(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
2022-09-15 14:10:39 +02:00
|
|
|
: ASTGEN_SUPER_Implication(fl) {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->lhsp(lhsp);
|
|
|
|
|
this->rhsp(rhsp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstImplication;
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
int instrCount() const override { return widthInstrs(); }
|
|
|
|
|
bool same(const AstNode* /*samep*/) const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstInside final : public AstNodeMath {
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := exprp : AstNode
|
|
|
|
|
// @astgen op2 := itemsp : List[AstNode]
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
AstInside(FileLine* fl, AstNode* exprp, AstNode* itemsp)
|
|
|
|
|
: ASTGEN_SUPER_Inside(fl) {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->exprp(exprp);
|
|
|
|
|
this->addItemsp(itemsp);
|
2022-09-15 14:10:39 +02:00
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstInside;
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%l inside { %r }"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { return false; } // NA
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstInsideRange final : public AstNodeMath {
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := lhsp : AstNode
|
|
|
|
|
// @astgen op2 := rhsp : AstNode
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
AstInsideRange(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_InsideRange(fl) {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->lhsp(lhsp);
|
|
|
|
|
this->rhsp(rhsp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstInsideRange;
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "[%l:%r]"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { return false; } // NA
|
2022-09-15 14:10:39 +02:00
|
|
|
// Create AstAnd(AstGte(...), AstLte(...))
|
|
|
|
|
AstNode* newAndFromInside(AstNode* exprp, AstNode* lhsp, AstNode* rhsp);
|
|
|
|
|
};
|
|
|
|
|
class AstLambdaArgRef final : public AstNodeMath {
|
|
|
|
|
// Lambda argument usage
|
|
|
|
|
// These are not AstVarRefs because we need to be able to delete/clone lambdas during
|
|
|
|
|
// optimizations and AstVar's are painful to remove.
|
|
|
|
|
private:
|
|
|
|
|
string m_name; // Name of variable
|
|
|
|
|
bool m_index; // Index, not value
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
AstLambdaArgRef(FileLine* fl, const string& name, bool index)
|
|
|
|
|
: ASTGEN_SUPER_LambdaArgRef(fl)
|
|
|
|
|
, m_name{name}
|
|
|
|
|
, m_index(index) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstLambdaArgRef;
|
2022-09-16 12:22:11 +02:00
|
|
|
bool same(const AstNode* /*samep*/) const override { return true; }
|
|
|
|
|
string emitVerilog() override { return name(); }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool hasDType() const override { return true; }
|
|
|
|
|
int instrCount() const override { return widthInstrs(); }
|
|
|
|
|
string name() const override { return m_name; } // * = Var name
|
|
|
|
|
void name(const string& name) override { m_name = name; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool index() const { return m_index; }
|
|
|
|
|
};
|
|
|
|
|
class AstMemberSel final : public AstNodeMath {
|
|
|
|
|
// Parents: math|stmt
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := fromp : AstNode
|
2022-09-15 14:10:39 +02:00
|
|
|
private:
|
|
|
|
|
// Don't need the class we are extracting from, as the "fromp()"'s datatype can get us to it
|
|
|
|
|
string m_name;
|
|
|
|
|
AstVar* m_varp = nullptr; // Post link, variable within class that is target of selection
|
|
|
|
|
public:
|
|
|
|
|
AstMemberSel(FileLine* fl, AstNode* fromp, VFlagChildDType, const string& name)
|
|
|
|
|
: ASTGEN_SUPER_MemberSel(fl)
|
|
|
|
|
, m_name{name} {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->fromp(fromp);
|
2022-09-15 14:10:39 +02:00
|
|
|
dtypep(nullptr); // V3Width will resolve
|
|
|
|
|
}
|
|
|
|
|
AstMemberSel(FileLine* fl, AstNode* fromp, AstNodeDType* dtp)
|
|
|
|
|
: ASTGEN_SUPER_MemberSel(fl)
|
|
|
|
|
, m_name{dtp->name()} {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->fromp(fromp);
|
2022-09-15 14:10:39 +02:00
|
|
|
dtypep(dtp);
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstMemberSel;
|
2022-09-15 14:10:39 +02:00
|
|
|
void cloneRelink() override;
|
|
|
|
|
const char* broken() const override;
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str) const override;
|
|
|
|
|
string name() const override { return m_name; }
|
|
|
|
|
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool same(const AstNode* samep) const override { return true; } // dtype comparison does it
|
|
|
|
|
int instrCount() const override { return widthInstrs(); }
|
2022-09-15 14:10:39 +02:00
|
|
|
AstVar* varp() const { return m_varp; }
|
|
|
|
|
void varp(AstVar* nodep) { m_varp = nodep; }
|
|
|
|
|
};
|
|
|
|
|
class AstNewCopy final : public AstNodeMath {
|
|
|
|
|
// New as shallow copy
|
|
|
|
|
// Parents: math|stmt
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := rhsp : AstNode
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
AstNewCopy(FileLine* fl, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_NewCopy(fl) {
|
|
|
|
|
dtypeFrom(rhsp); // otherwise V3Width will resolve
|
2022-09-15 20:43:56 +02:00
|
|
|
this->rhsp(rhsp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstNewCopy;
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "new"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool same(const AstNode* /*samep*/) const override { return true; }
|
|
|
|
|
int instrCount() const override { return widthInstrs(); }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstNewDynamic final : public AstNodeMath {
|
|
|
|
|
// New for dynamic array
|
|
|
|
|
// Parents: math|stmt
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := sizep : AstNode
|
|
|
|
|
// @astgen op2 := rhsp : Optional[AstNode]
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
AstNewDynamic(FileLine* fl, AstNode* sizep, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_NewDynamic(fl) {
|
|
|
|
|
dtypeFrom(rhsp); // otherwise V3Width will resolve
|
2022-09-15 20:43:56 +02:00
|
|
|
this->sizep(sizep);
|
|
|
|
|
this->rhsp(rhsp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstNewDynamic;
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "new"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool same(const AstNode* /*samep*/) const override { return true; }
|
|
|
|
|
int instrCount() const override { return widthInstrs(); }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstPast final : public AstNodeMath {
|
|
|
|
|
// Verilog $past
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := exprp : AstNode
|
|
|
|
|
// @astgen op2 := ticksp : Optional[AstNode]
|
|
|
|
|
// @astgen op3 := sentreep : Optional[AstSenTree]
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
AstPast(FileLine* fl, AstNode* exprp, AstNode* ticksp)
|
|
|
|
|
: ASTGEN_SUPER_Past(fl) {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->exprp(exprp);
|
|
|
|
|
this->ticksp(ticksp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstPast;
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
int instrCount() const override { return widthInstrs(); }
|
|
|
|
|
bool same(const AstNode* /*samep*/) const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstPatMember final : public AstNodeMath {
|
|
|
|
|
// Verilog '{a} or '{a{b}}
|
|
|
|
|
// Parents: AstPattern
|
|
|
|
|
// Children: expression, AstPattern, replication count
|
2022-09-15 20:43:56 +02:00
|
|
|
// Expression to assign or another AstPattern (list if replicated)
|
|
|
|
|
// @astgen op1 := lhssp : List[AstNode]
|
|
|
|
|
// @astgen op2 := keyp : Optional[AstNode]
|
|
|
|
|
// @astgen op3 := repp : Optional[AstNode] // replication count, or nullptr for count 1
|
2022-09-15 14:10:39 +02:00
|
|
|
private:
|
|
|
|
|
bool m_default = false;
|
|
|
|
|
|
|
|
|
|
public:
|
2022-09-15 20:43:56 +02:00
|
|
|
AstPatMember(FileLine* fl, AstNode* lhssp, AstNode* keyp, AstNode* repp)
|
2022-09-15 14:10:39 +02:00
|
|
|
: ASTGEN_SUPER_PatMember(fl) {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->addLhssp(lhssp);
|
|
|
|
|
this->keyp(keyp);
|
|
|
|
|
this->repp(repp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstPatMember;
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return lhssp() ? "%f{%r{%k%l}}" : "%l"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
int instrCount() const override { return widthInstrs() * 2; }
|
|
|
|
|
void dump(std::ostream& str = std::cout) const override;
|
2022-09-15 14:10:39 +02:00
|
|
|
bool isDefault() const { return m_default; }
|
|
|
|
|
void isDefault(bool flag) { m_default = flag; }
|
|
|
|
|
};
|
|
|
|
|
class AstPattern final : public AstNodeMath {
|
|
|
|
|
// Verilog '{a,b,c,d...}
|
|
|
|
|
// Parents: AstNodeAssign, AstPattern, ...
|
|
|
|
|
// Children: expression, AstPattern, AstPatReplicate
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := childDTypep : Optional[AstNodeDType]
|
|
|
|
|
// @astgen op2 := itemsp : List[AstNode] // AstPatReplicate, AstPatMember, etc
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
AstPattern(FileLine* fl, AstNode* itemsp)
|
|
|
|
|
: ASTGEN_SUPER_Pattern(fl) {
|
2022-09-15 20:43:56 +02:00
|
|
|
addItemsp(itemsp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstPattern;
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
int instrCount() const override { return widthInstrs(); }
|
|
|
|
|
AstNodeDType* getChildDTypep() const override { return childDTypep(); }
|
2022-09-15 14:10:39 +02:00
|
|
|
virtual AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); }
|
|
|
|
|
};
|
|
|
|
|
class AstRand final : public AstNodeMath {
|
|
|
|
|
// $random/$random(seed) or $urandom/$urandom(seed)
|
|
|
|
|
// Return a random number, based upon width()
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := seedp : Optional[AstNode]
|
2022-09-15 14:10:39 +02:00
|
|
|
private:
|
|
|
|
|
const bool m_urandom = false; // $urandom vs $random
|
|
|
|
|
const bool m_reset = false; // Random reset, versus always random
|
|
|
|
|
public:
|
|
|
|
|
class Reset {};
|
|
|
|
|
AstRand(FileLine* fl, Reset, AstNodeDType* dtp, bool reset)
|
|
|
|
|
: ASTGEN_SUPER_Rand(fl)
|
|
|
|
|
, m_reset{reset} {
|
|
|
|
|
dtypep(dtp);
|
|
|
|
|
}
|
|
|
|
|
AstRand(FileLine* fl, AstNode* seedp, bool urandom)
|
|
|
|
|
: ASTGEN_SUPER_Rand(fl)
|
2022-09-15 14:54:04 +02:00
|
|
|
, m_urandom{urandom} {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->seedp(seedp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstRand;
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return seedp() ? (m_urandom ? "%f$urandom(%l)" : "%f$random(%l)")
|
|
|
|
|
: (m_urandom ? "%f$urandom()" : "%f$random()");
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitC() override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return m_reset ? "VL_RAND_RESET_%nq(%nw, %P)"
|
|
|
|
|
: seedp()
|
|
|
|
|
? (urandom() ? "VL_URANDOM_SEEDED_%nq%lq(%li)" : "VL_RANDOM_SEEDED_%nq%lq(%li)")
|
|
|
|
|
: isWide() ? "VL_RANDOM_%nq(%nw, %P)" //
|
|
|
|
|
: "VL_RANDOM_%nq()";
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool isGateOptimizable() const override { return false; }
|
|
|
|
|
bool isPredictOptimizable() const override { return false; }
|
|
|
|
|
int instrCount() const override { return INSTR_COUNT_PLI; }
|
|
|
|
|
bool same(const AstNode* /*samep*/) const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool combinable(const AstRand* samep) const {
|
|
|
|
|
return !seedp() && !samep->seedp() && reset() == samep->reset()
|
|
|
|
|
&& urandom() == samep->urandom();
|
|
|
|
|
}
|
|
|
|
|
bool reset() const { return m_reset; }
|
|
|
|
|
bool urandom() const { return m_urandom; }
|
|
|
|
|
};
|
|
|
|
|
class AstRose final : public AstNodeMath {
|
|
|
|
|
// Verilog $rose
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := exprp : AstNode
|
|
|
|
|
// @astgen op2 := sentreep : Optional[AstSenTree]
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
AstRose(FileLine* fl, AstNode* exprp)
|
|
|
|
|
: ASTGEN_SUPER_Rose(fl) {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->exprp(exprp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstRose;
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "$rose(%l)"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
int instrCount() const override { return widthInstrs(); }
|
|
|
|
|
bool same(const AstNode* /*samep*/) const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstSScanF final : public AstNodeMath {
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := exprsp : List[AstNode] // VarRefs for results
|
|
|
|
|
// @astgen op2 := fromp : AstNode
|
2022-09-15 14:10:39 +02:00
|
|
|
private:
|
|
|
|
|
string m_text;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
AstSScanF(FileLine* fl, const string& text, AstNode* fromp, AstNode* exprsp)
|
|
|
|
|
: ASTGEN_SUPER_SScanF(fl)
|
|
|
|
|
, m_text{text} {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->addExprsp(exprsp);
|
|
|
|
|
this->fromp(fromp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstSScanF;
|
2022-09-16 12:22:11 +02:00
|
|
|
string name() const override { return m_text; }
|
|
|
|
|
string verilogKwd() const override { return "$sscanf"; }
|
|
|
|
|
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool isGateOptimizable() const override { return false; }
|
|
|
|
|
bool isPredictOptimizable() const override { return false; }
|
|
|
|
|
bool isPure() const override { return false; } // SPECIAL: has 'visual' ordering
|
|
|
|
|
bool isOutputter() const override { return true; } // SPECIAL: makes output
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool same(const AstNode* samep) const override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return text() == static_cast<const AstSScanF*>(samep)->text();
|
|
|
|
|
}
|
|
|
|
|
string text() const { return m_text; } // * = Text to display
|
|
|
|
|
void text(const string& text) { m_text = text; }
|
|
|
|
|
};
|
|
|
|
|
class AstSampled final : public AstNodeMath {
|
|
|
|
|
// Verilog $sampled
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := exprp : AstNode
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
AstSampled(FileLine* fl, AstNode* exprp)
|
|
|
|
|
: ASTGEN_SUPER_Sampled(fl) {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->exprp(exprp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstSampled;
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "$sampled(%l)"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
int instrCount() const override { return 0; }
|
|
|
|
|
bool same(const AstNode* /*samep*/) const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstScopeName final : public AstNodeMath {
|
|
|
|
|
// For display %m and DPI context imports
|
|
|
|
|
// Parents: DISPLAY
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := scopeAttrp : List[AstText]
|
|
|
|
|
// @astgen op2 := scopeEntrp : List[AstText]
|
2022-09-15 14:10:39 +02:00
|
|
|
private:
|
|
|
|
|
bool m_dpiExport = false; // Is for dpiExport
|
|
|
|
|
const bool m_forFormat = false; // Is for a format %m
|
|
|
|
|
string scopeNameFormatter(AstText* scopeTextp) const;
|
|
|
|
|
string scopePrettyNameFormatter(AstText* scopeTextp) const;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
class ForFormat {};
|
|
|
|
|
AstScopeName(FileLine* fl, bool forFormat)
|
|
|
|
|
: ASTGEN_SUPER_ScopeName(fl)
|
|
|
|
|
, m_forFormat{forFormat} {
|
|
|
|
|
dtypeSetUInt64();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstScopeName;
|
2022-09-16 12:22:11 +02:00
|
|
|
bool same(const AstNode* samep) const override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return (m_dpiExport == static_cast<const AstScopeName*>(samep)->m_dpiExport
|
|
|
|
|
&& m_forFormat == static_cast<const AstScopeName*>(samep)->m_forFormat);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return ""; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
void dump(std::ostream& str = std::cout) const override;
|
2022-09-15 14:10:39 +02:00
|
|
|
string scopeSymName() const { // Name for __Vscope variable including children
|
|
|
|
|
return scopeNameFormatter(scopeAttrp());
|
|
|
|
|
}
|
|
|
|
|
string scopeDpiName() const { // Name for DPI import scope
|
|
|
|
|
return scopeNameFormatter(scopeEntrp());
|
|
|
|
|
}
|
|
|
|
|
string scopePrettySymName() const { // Name for __Vscope variable including children
|
|
|
|
|
return scopePrettyNameFormatter(scopeAttrp());
|
|
|
|
|
}
|
|
|
|
|
string scopePrettyDpiName() const { // Name for __Vscope variable including children
|
|
|
|
|
return scopePrettyNameFormatter(scopeEntrp());
|
|
|
|
|
}
|
|
|
|
|
bool dpiExport() const { return m_dpiExport; }
|
|
|
|
|
void dpiExport(bool flag) { m_dpiExport = flag; }
|
|
|
|
|
bool forFormat() const { return m_forFormat; }
|
|
|
|
|
};
|
|
|
|
|
class AstSetAssoc final : public AstNodeMath {
|
|
|
|
|
// Set an assoc array element and return object, '{}
|
|
|
|
|
// Parents: math
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := lhsp : AstNode
|
|
|
|
|
// @astgen op2 := keyp : Optional[AstNode]
|
|
|
|
|
// @astgen op3 := valuep : AstNode
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
AstSetAssoc(FileLine* fl, AstNode* lhsp, AstNode* keyp, AstNode* valuep)
|
|
|
|
|
: ASTGEN_SUPER_SetAssoc(fl) {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->lhsp(lhsp);
|
|
|
|
|
this->keyp(keyp);
|
|
|
|
|
this->valuep(valuep);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstSetAssoc;
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "'{}"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
int instrCount() const override { return widthInstrs(); }
|
|
|
|
|
bool same(const AstNode* /*samep*/) const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstSetWildcard final : public AstNodeMath {
|
|
|
|
|
// Set a wildcard assoc array element and return object, '{}
|
|
|
|
|
// Parents: math
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := lhsp : AstNode
|
|
|
|
|
// @astgen op2 := keyp : Optional[AstNode]
|
|
|
|
|
// @astgen op3 := valuep : AstNode
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
AstSetWildcard(FileLine* fl, AstNode* lhsp, AstNode* keyp, AstNode* valuep)
|
|
|
|
|
: ASTGEN_SUPER_SetWildcard(fl) {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->lhsp(lhsp);
|
|
|
|
|
this->keyp(keyp);
|
|
|
|
|
this->valuep(valuep);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstSetWildcard;
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "'{}"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
int instrCount() const override { return widthInstrs(); }
|
|
|
|
|
bool same(const AstNode* /*samep*/) const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstStable final : public AstNodeMath {
|
|
|
|
|
// Verilog $stable
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := exprp : AstNode
|
|
|
|
|
// @astgen op2 := sentreep : Optional[AstSenTree]
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
AstStable(FileLine* fl, AstNode* exprp)
|
|
|
|
|
: ASTGEN_SUPER_Stable(fl) {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->exprp(exprp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstStable;
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "$stable(%l)"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
int instrCount() const override { return widthInstrs(); }
|
|
|
|
|
bool same(const AstNode* /*samep*/) const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstSystemF final : public AstNodeMath {
|
|
|
|
|
// $system used as function
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := lhsp : AstNode
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
AstSystemF(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_SystemF(fl) {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->lhsp(lhsp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstSystemF;
|
2022-09-16 12:22:11 +02:00
|
|
|
string verilogKwd() const override { return "$system"; }
|
|
|
|
|
string emitVerilog() override { return verilogKwd(); }
|
|
|
|
|
string emitC() override { return "VL_SYSTEM_%nq(%lw, %P)"; }
|
|
|
|
|
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 cleanOut() const override { return true; }
|
|
|
|
|
bool same(const AstNode* /*samep*/) const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstTestPlusArgs final : public AstNodeMath {
|
2022-09-15 20:43:56 +02:00
|
|
|
// Search expression. If nullptr then this is a $test$plusargs instead of $value$plusargs.
|
|
|
|
|
// @astgen op1 := searchp : Optional[AstNode]
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
AstTestPlusArgs(FileLine* fl, AstNode* searchp)
|
|
|
|
|
: ASTGEN_SUPER_TestPlusArgs(fl) {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->searchp(searchp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstTestPlusArgs;
|
2022-09-16 12:22:11 +02:00
|
|
|
string verilogKwd() const override { return "$test$plusargs"; }
|
|
|
|
|
string emitVerilog() override { return verilogKwd(); }
|
|
|
|
|
string emitC() override { return "VL_VALUEPLUSARGS_%nq(%lw, %P, nullptr)"; }
|
|
|
|
|
bool isGateOptimizable() const override { return false; }
|
|
|
|
|
bool isPredictOptimizable() const override { return false; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool same(const AstNode* /*samep*/) const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
2022-10-14 14:55:55 +02:00
|
|
|
class AstThisRef final : public AstNodeMath {
|
|
|
|
|
// Reference to 'this'.
|
|
|
|
|
// @astgen op1 := childDTypep : Optional[AstClassRefDType] // dtype of the node
|
|
|
|
|
public:
|
|
|
|
|
explicit AstThisRef(FileLine* fl, AstClassRefDType* dtypep)
|
|
|
|
|
: ASTGEN_SUPER_ThisRef(fl) {
|
|
|
|
|
childDTypep(dtypep);
|
|
|
|
|
}
|
|
|
|
|
ASTGEN_MEMBERS_AstThisRef;
|
|
|
|
|
string emitC() override { return "this"; }
|
|
|
|
|
string emitVerilog() override { return "this"; }
|
|
|
|
|
bool same(const AstNode* /*samep*/) const override { return true; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
AstNodeDType* getChildDTypep() const override { return childDTypep(); }
|
|
|
|
|
virtual AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); }
|
|
|
|
|
};
|
2022-09-15 14:10:39 +02:00
|
|
|
class AstUCFunc final : public AstNodeMath {
|
|
|
|
|
// User's $c function
|
|
|
|
|
// Perhaps this should be an AstNodeListop; but there's only one list math right now
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := exprsp : List[AstNode] // Expressions to print
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
AstUCFunc(FileLine* fl, AstNode* exprsp)
|
|
|
|
|
: ASTGEN_SUPER_UCFunc(fl) {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->addExprsp(exprsp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstUCFunc;
|
2022-09-16 12:22:11 +02:00
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs
|
|
|
|
|
bool isOutputter() const override { return true; }
|
|
|
|
|
bool isGateOptimizable() const override { return false; }
|
|
|
|
|
bool isSubstOptimizable() const override { return false; }
|
|
|
|
|
bool isPredictOptimizable() const override { return false; }
|
|
|
|
|
int instrCount() const override { return INSTR_COUNT_PLI; }
|
|
|
|
|
bool same(const AstNode* /*samep*/) const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstUnbounded final : public AstNodeMath {
|
|
|
|
|
// A $ in the parser, used for unbounded and queues
|
|
|
|
|
// Due to where is used, treated as Signed32
|
|
|
|
|
public:
|
|
|
|
|
explicit AstUnbounded(FileLine* fl)
|
|
|
|
|
: ASTGEN_SUPER_Unbounded(fl) {
|
|
|
|
|
dtypeSetSigned32();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstUnbounded;
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "$"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstValuePlusArgs final : public AstNodeMath {
|
2022-09-15 20:43:56 +02:00
|
|
|
// Search expression. If nullptr then this is a $test$plusargs instead of $value$plusargs.
|
|
|
|
|
// @astgen op1 := searchp : Optional[AstNode]
|
|
|
|
|
// @astgen op2 := outp : AstNode // VarRef for result
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
AstValuePlusArgs(FileLine* fl, AstNode* searchp, AstNode* outp)
|
|
|
|
|
: ASTGEN_SUPER_ValuePlusArgs(fl) {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->searchp(searchp);
|
|
|
|
|
this->outp(outp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstValuePlusArgs;
|
2022-09-16 12:22:11 +02:00
|
|
|
string verilogKwd() const override { return "$value$plusargs"; }
|
|
|
|
|
string emitVerilog() override { return "%f$value$plusargs(%l, %k%r)"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool isGateOptimizable() const override { return false; }
|
|
|
|
|
bool isPredictOptimizable() const override { return false; }
|
|
|
|
|
bool isPure() const override { return !outp(); }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool same(const AstNode* /*samep*/) const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// === AstNodeBiop ===
|
|
|
|
|
class AstBufIf1 final : public AstNodeBiop {
|
|
|
|
|
// lhs is enable, rhs is data to drive
|
|
|
|
|
// Note unlike the Verilog bufif1() UDP, this allows any width; each lhsp
|
|
|
|
|
// bit enables respective rhsp bit
|
|
|
|
|
public:
|
|
|
|
|
AstBufIf1(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_BufIf1(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeFrom(lhsp);
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstBufIf1;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstBufIf1(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opBufIf1(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "bufif(%r,%l)"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); } // Lclean || Rclean
|
|
|
|
|
string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } // Lclean || Rclean
|
|
|
|
|
bool cleanOut() const override { V3ERROR_NA_RETURN(""); } // Lclean || Rclean
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool cleanRhs() const override { return false; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstCastDynamic final : public AstNodeBiop {
|
|
|
|
|
// Verilog $cast used as a function
|
|
|
|
|
// Task usage of $cast is converted during parse to assert($cast(...))
|
|
|
|
|
// Parents: MATH
|
|
|
|
|
// Children: MATH
|
|
|
|
|
// lhsp() is value (we are converting FROM) to match AstCCast etc, this
|
|
|
|
|
// is opposite of $cast's order, because the first access is to the
|
|
|
|
|
// value reading from. Suggest use fromp()/top() instead of lhsp/rhsp().
|
|
|
|
|
public:
|
|
|
|
|
AstCastDynamic(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_CastDynamic(fl, lhsp, rhsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstCastDynamic;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
V3ERROR_NA;
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstCastDynamic(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%f$cast(%r, %l)"; }
|
|
|
|
|
string emitC() override { return "VL_DYNAMIC_CAST(%r, %l)"; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return widthInstrs() * 20; }
|
|
|
|
|
bool isPure() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
AstNode* fromp() const { return lhsp(); }
|
|
|
|
|
AstNode* top() const { return rhsp(); }
|
|
|
|
|
};
|
|
|
|
|
class AstCompareNN final : public AstNodeBiop {
|
|
|
|
|
// Verilog str.compare() and str.icompare()
|
|
|
|
|
private:
|
|
|
|
|
const bool m_ignoreCase; // True for str.icompare()
|
|
|
|
|
public:
|
|
|
|
|
AstCompareNN(FileLine* fl, AstNode* lhsp, AstNode* rhsp, bool ignoreCase)
|
|
|
|
|
: ASTGEN_SUPER_CompareNN(fl, lhsp, rhsp)
|
|
|
|
|
, m_ignoreCase{ignoreCase} {
|
|
|
|
|
dtypeSetUInt32();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstCompareNN;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstCompareNN(this->fileline(), lhsp, rhsp, m_ignoreCase);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opCompareNN(lhs, rhs, m_ignoreCase);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string name() const override { return m_ignoreCase ? "icompare" : "compare"; }
|
|
|
|
|
string emitVerilog() override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return m_ignoreCase ? "%k(%l.icompare(%r))" : "%k(%l.compare(%r))";
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitC() override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return m_ignoreCase ? "VL_CMP_NN(%li,%ri,true)" : "VL_CMP_NN(%li,%ri,false)";
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitSimpleOperator() override { return ""; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstConcat final : public AstNodeBiop {
|
|
|
|
|
// If you're looking for {#{}}, see AstReplicate
|
|
|
|
|
public:
|
|
|
|
|
AstConcat(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_Concat(fl, lhsp, rhsp) {
|
|
|
|
|
if (lhsp->dtypep() && rhsp->dtypep()) {
|
|
|
|
|
dtypeSetLogicSized(lhsp->dtypep()->width() + rhsp->dtypep()->width(),
|
|
|
|
|
VSigning::UNSIGNED);
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstConcat;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstConcat(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%f{%l, %k%r}"; }
|
|
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opConcat(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitC() override { return "VL_CONCAT_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return widthInstrs() * 2; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstConcatN final : public AstNodeBiop {
|
|
|
|
|
// String concatenate
|
|
|
|
|
public:
|
|
|
|
|
AstConcatN(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_ConcatN(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetString();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstConcatN;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstConcatN(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%f{%l, %k%r}"; }
|
|
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opConcatN(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitC() override { return "VL_CONCATN_NNN(%li, %ri)"; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return INSTR_COUNT_STR; }
|
|
|
|
|
bool stringFlavor() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstDiv final : public AstNodeBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstDiv(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_Div(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeFrom(lhsp);
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstDiv;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstDiv(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opDiv(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f/ %r)"; }
|
|
|
|
|
string emitC() override { return "VL_DIV_%nq%lq%rq(%lw, %P, %li, %ri)"; }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersRhs() const override { return true; }
|
|
|
|
|
int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_DIV; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstDivD final : public AstNodeBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstDivD(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_DivD(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetDouble();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstDivD;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstDivD(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opDivD(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f/ %r)"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitSimpleOperator() override { return "/"; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool cleanRhs() const override { return false; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return INSTR_COUNT_DBL_DIV; }
|
|
|
|
|
bool doubleFlavor() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstDivS final : public AstNodeBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstDivS(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_DivS(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeFrom(lhsp);
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstDivS;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstDivS(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opDivS(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f/ %r)"; }
|
|
|
|
|
string emitC() override { return "VL_DIVS_%nq%lq%rq(%lw, %P, %li, %ri)"; }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersRhs() const override { return true; }
|
|
|
|
|
int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_DIV; }
|
|
|
|
|
bool signedFlavor() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstEqWild final : public AstNodeBiop {
|
|
|
|
|
// Note wildcard operator rhs differs from lhs
|
|
|
|
|
public:
|
|
|
|
|
AstEqWild(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_EqWild(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstEqWild;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstEqWild(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
|
|
|
|
static AstNodeBiop* newTyped(FileLine* fl, AstNode* lhsp,
|
|
|
|
|
AstNode* rhsp); // Return AstEqWild/AstEqD
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opWildEq(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f==? %r)"; }
|
|
|
|
|
string emitC() override { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; }
|
|
|
|
|
string emitSimpleOperator() override { return "=="; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstFGetS final : public AstNodeBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstFGetS(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_FGetS(fl, lhsp, rhsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstFGetS;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstFGetS(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
V3ERROR_NA;
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%f$fgets(%l,%r)"; }
|
|
|
|
|
string emitC() override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return strgp()->dtypep()->basicp()->isString() ? "VL_FGETS_NI(%li, %ri)"
|
|
|
|
|
: "VL_FGETS_%nqX%rq(%lw, %P, &(%li), %ri)";
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return widthInstrs() * 64; }
|
2022-09-15 14:10:39 +02:00
|
|
|
AstNode* strgp() const { return lhsp(); }
|
|
|
|
|
AstNode* filep() const { return rhsp(); }
|
|
|
|
|
};
|
|
|
|
|
class AstFUngetC final : public AstNodeBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstFUngetC(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_FUngetC(fl, lhsp, rhsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstFUngetC;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
V3ERROR_NA;
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstFUngetC(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%f$ungetc(%r, %l)"; }
|
2022-09-15 14:10:39 +02:00
|
|
|
// Non-existent filehandle returns EOF
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitC() override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return "(%li ? (ungetc(%ri, VL_CVT_I_FP(%li)) >= 0 ? 0 : -1) : -1)";
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return widthInstrs() * 64; }
|
|
|
|
|
bool isPure() const override { return false; } // SPECIAL: $display has 'visual' ordering
|
2022-09-15 14:10:39 +02:00
|
|
|
AstNode* filep() const { return lhsp(); }
|
|
|
|
|
AstNode* charp() const { return rhsp(); }
|
|
|
|
|
};
|
|
|
|
|
class AstGetcN final : public AstNodeBiop {
|
|
|
|
|
// Verilog string.getc()
|
|
|
|
|
public:
|
|
|
|
|
AstGetcN(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_GetcN(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetBitSized(8, VSigning::UNSIGNED);
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstGetcN;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstGetcN(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opGetcN(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string name() const override { return "getc"; }
|
|
|
|
|
string emitVerilog() override { return "%k(%l.getc(%r))"; }
|
|
|
|
|
string emitC() override { return "VL_GETC_N(%li,%ri)"; }
|
|
|
|
|
string emitSimpleOperator() override { return ""; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstGetcRefN final : public AstNodeBiop {
|
|
|
|
|
// Verilog string[#] on the left-hand-side of assignment
|
|
|
|
|
// Spec says is of type byte (not string of single character)
|
|
|
|
|
public:
|
|
|
|
|
AstGetcRefN(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_GetcRefN(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetBitSized(8, VSigning::UNSIGNED);
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstGetcRefN;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstGetcRefN(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
V3ERROR_NA;
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k%l[%r]"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitSimpleOperator() override { return ""; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstGt final : public AstNodeBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstGt(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_Gt(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstGt;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstGt(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opGt(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f> %r)"; }
|
|
|
|
|
string emitC() override { return "VL_GT_%lq(%lW, %P, %li, %ri)"; }
|
|
|
|
|
string emitSimpleOperator() override { return ">"; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstGtD final : public AstNodeBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstGtD(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_GtD(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstGtD;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstGtD(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opGtD(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f> %r)"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitSimpleOperator() override { return ">"; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool cleanRhs() const override { return false; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return INSTR_COUNT_DBL; }
|
|
|
|
|
bool doubleFlavor() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstGtN final : public AstNodeBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstGtN(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_GtN(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstGtN;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstGtN(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opGtN(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f> %r)"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitSimpleOperator() override { return ">"; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool cleanRhs() const override { return false; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return INSTR_COUNT_STR; }
|
|
|
|
|
bool stringFlavor() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstGtS final : public AstNodeBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstGtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_GtS(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstGtS;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstGtS(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opGtS(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f> %r)"; }
|
|
|
|
|
string emitC() override { return "VL_GTS_%nq%lq%rq(%lw, %P, %li, %ri)"; }
|
|
|
|
|
string emitSimpleOperator() override { return ""; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
bool signedFlavor() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstGte final : public AstNodeBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstGte(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_Gte(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstGte;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstGte(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opGte(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f>= %r)"; }
|
|
|
|
|
string emitC() override { return "VL_GTE_%lq(%lW, %P, %li, %ri)"; }
|
|
|
|
|
string emitSimpleOperator() override { return ">="; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstGteD final : public AstNodeBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstGteD(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_GteD(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstGteD;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstGteD(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opGteD(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f>= %r)"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitSimpleOperator() override { return ">="; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool cleanRhs() const override { return false; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return INSTR_COUNT_DBL; }
|
|
|
|
|
bool doubleFlavor() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstGteN final : public AstNodeBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstGteN(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_GteN(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstGteN;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstGteN(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opGteN(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f>= %r)"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitSimpleOperator() override { return ">="; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool cleanRhs() const override { return false; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return INSTR_COUNT_STR; }
|
|
|
|
|
bool stringFlavor() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstGteS final : public AstNodeBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstGteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_GteS(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstGteS;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstGteS(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opGteS(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f>= %r)"; }
|
|
|
|
|
string emitC() override { return "VL_GTES_%nq%lq%rq(%lw, %P, %li, %ri)"; }
|
|
|
|
|
string emitSimpleOperator() override { return ""; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
bool signedFlavor() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstLogAnd final : public AstNodeBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstLogAnd(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_LogAnd(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstLogAnd;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstLogAnd(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opLogAnd(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f&& %r)"; }
|
|
|
|
|
string emitC() override { return "VL_LOGAND_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
|
|
|
|
string emitSimpleOperator() override { return "&&"; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstLogIf final : public AstNodeBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstLogIf(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_LogIf(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstLogIf;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstLogIf(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opLogIf(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f-> %r)"; }
|
|
|
|
|
string emitC() override { return "VL_LOGIF_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
|
|
|
|
string emitSimpleOperator() override { return "->"; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstLogOr final : public AstNodeBiop {
|
|
|
|
|
// LOGOR with optional side effects
|
|
|
|
|
// Side effects currently used in some V3Width code
|
|
|
|
|
// TBD if this concept is generally adopted for side-effect tracking
|
|
|
|
|
// versus V3Const tracking it itself
|
|
|
|
|
bool m_sideEffect = false; // Has side effect, relies on short-circuiting
|
|
|
|
|
public:
|
|
|
|
|
AstLogOr(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_LogOr(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstLogOr;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstLogOr(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opLogOr(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
bool same(const AstNode* samep) const override {
|
2022-09-15 14:10:39 +02:00
|
|
|
const AstLogOr* const sp = static_cast<const AstLogOr*>(samep);
|
|
|
|
|
return m_sideEffect == sp->m_sideEffect;
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str = std::cout) const override;
|
|
|
|
|
string emitVerilog() override { return "%k(%l %f|| %r)"; }
|
|
|
|
|
string emitC() override { return "VL_LOGOR_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
|
|
|
|
string emitSimpleOperator() override { return "||"; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; }
|
|
|
|
|
bool isPure() const override { return !m_sideEffect; }
|
2022-09-15 14:10:39 +02:00
|
|
|
void sideEffect(bool flag) { m_sideEffect = flag; }
|
|
|
|
|
bool sideEffect() const { return m_sideEffect; }
|
|
|
|
|
};
|
|
|
|
|
class AstLt final : public AstNodeBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstLt(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_Lt(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstLt;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstLt(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opLt(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f< %r)"; }
|
|
|
|
|
string emitC() override { return "VL_LT_%lq(%lW, %P, %li, %ri)"; }
|
|
|
|
|
string emitSimpleOperator() override { return "<"; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstLtD final : public AstNodeBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstLtD(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_LtD(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstLtD;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstLtD(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opLtD(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f< %r)"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitSimpleOperator() override { return "<"; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool cleanRhs() const override { return false; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return INSTR_COUNT_DBL; }
|
|
|
|
|
bool doubleFlavor() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstLtN final : public AstNodeBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstLtN(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_LtN(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstLtN;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstLtN(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opLtN(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f< %r)"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitSimpleOperator() override { return "<"; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool cleanRhs() const override { return false; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return INSTR_COUNT_STR; }
|
|
|
|
|
bool stringFlavor() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstLtS final : public AstNodeBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstLtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_LtS(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstLtS;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstLtS(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opLtS(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f< %r)"; }
|
|
|
|
|
string emitC() override { return "VL_LTS_%nq%lq%rq(%lw, %P, %li, %ri)"; }
|
|
|
|
|
string emitSimpleOperator() override { return ""; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
bool signedFlavor() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstLte final : public AstNodeBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstLte(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_Lte(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstLte;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstLte(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opLte(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f<= %r)"; }
|
|
|
|
|
string emitC() override { return "VL_LTE_%lq(%lW, %P, %li, %ri)"; }
|
|
|
|
|
string emitSimpleOperator() override { return "<="; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstLteD final : public AstNodeBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstLteD(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_LteD(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstLteD;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstLteD(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opLteD(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f<= %r)"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitSimpleOperator() override { return "<="; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool cleanRhs() const override { return false; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return INSTR_COUNT_DBL; }
|
|
|
|
|
bool doubleFlavor() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstLteN final : public AstNodeBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstLteN(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_LteN(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstLteN;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstLteN(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opLteN(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f<= %r)"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitSimpleOperator() override { return "<="; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool cleanRhs() const override { return false; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return INSTR_COUNT_STR; }
|
|
|
|
|
bool stringFlavor() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstLteS final : public AstNodeBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstLteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_LteS(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstLteS;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstLteS(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opLteS(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f<= %r)"; }
|
|
|
|
|
string emitC() override { return "VL_LTES_%nq%lq%rq(%lw, %P, %li, %ri)"; }
|
|
|
|
|
string emitSimpleOperator() override { return ""; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
bool signedFlavor() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstModDiv final : public AstNodeBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstModDiv(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_ModDiv(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeFrom(lhsp);
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstModDiv;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstModDiv(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opModDiv(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f%% %r)"; }
|
|
|
|
|
string emitC() override { return "VL_MODDIV_%nq%lq%rq(%lw, %P, %li, %ri)"; }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersRhs() const override { return true; }
|
|
|
|
|
int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_DIV; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstModDivS final : public AstNodeBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstModDivS(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_ModDivS(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeFrom(lhsp);
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstModDivS;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstModDivS(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opModDivS(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f%% %r)"; }
|
|
|
|
|
string emitC() override { return "VL_MODDIVS_%nq%lq%rq(%lw, %P, %li, %ri)"; }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersRhs() const override { return true; }
|
|
|
|
|
int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_DIV; }
|
|
|
|
|
bool signedFlavor() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstNeqWild final : public AstNodeBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstNeqWild(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_NeqWild(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstNeqWild;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstNeqWild(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opWildNeq(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f!=? %r)"; }
|
|
|
|
|
string emitC() override { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; }
|
|
|
|
|
string emitSimpleOperator() override { return "!="; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstPow final : public AstNodeBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstPow(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_Pow(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeFrom(lhsp);
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstPow;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstPow(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opPow(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f** %r)"; }
|
|
|
|
|
string emitC() override { return "VL_POW_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
|
|
|
|
bool emitCheckMaxWords() override { return true; }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL * 10; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstPowD final : public AstNodeBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstPowD(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_PowD(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetDouble();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstPowD;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstPowD(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opPowD(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f** %r)"; }
|
|
|
|
|
string emitC() override { return "pow(%li,%ri)"; }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool cleanRhs() const override { return false; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return INSTR_COUNT_DBL_DIV * 5; }
|
|
|
|
|
bool doubleFlavor() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstPowSS final : public AstNodeBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstPowSS(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_PowSS(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeFrom(lhsp);
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstPowSS;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstPowSS(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opPowSS(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f** %r)"; }
|
|
|
|
|
string emitC() override { return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 1,1)"; }
|
|
|
|
|
bool emitCheckMaxWords() override { return true; }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL * 10; }
|
|
|
|
|
bool signedFlavor() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstPowSU final : public AstNodeBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstPowSU(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_PowSU(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeFrom(lhsp);
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstPowSU;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstPowSU(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opPowSU(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f** %r)"; }
|
|
|
|
|
string emitC() override { return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 1,0)"; }
|
|
|
|
|
bool emitCheckMaxWords() override { return true; }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL * 10; }
|
|
|
|
|
bool signedFlavor() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstPowUS final : public AstNodeBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstPowUS(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_PowUS(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeFrom(lhsp);
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstPowUS;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstPowUS(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opPowUS(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f** %r)"; }
|
|
|
|
|
string emitC() override { return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 0,1)"; }
|
|
|
|
|
bool emitCheckMaxWords() override { return true; }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL * 10; }
|
|
|
|
|
bool signedFlavor() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstReplicate final : public AstNodeBiop {
|
|
|
|
|
// Also used as a "Uniop" flavor of Concat, e.g. "{a}"
|
|
|
|
|
// Verilog {rhs{lhs}} - Note rhsp() is the replicate value, not the lhsp()
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen alias op1 := srcp
|
|
|
|
|
// @astgen alias op2 := countp
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
AstReplicate(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_Replicate(fl, lhsp, rhsp) {
|
|
|
|
|
if (lhsp) {
|
|
|
|
|
if (const AstConst* const constp = VN_CAST(rhsp, Const)) {
|
|
|
|
|
dtypeSetLogicSized(lhsp->width() * constp->toUInt(), VSigning::UNSIGNED);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
AstReplicate(FileLine* fl, AstNode* lhsp, uint32_t repCount)
|
|
|
|
|
: AstReplicate(fl, lhsp, new AstConst(fl, repCount)) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstReplicate;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstReplicate(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opRepl(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%f{%r{%k%l}}"; }
|
|
|
|
|
string emitC() override { return "VL_REPLICATE_%nq%lq%rq(%lw, %P, %li, %ri)"; }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return widthInstrs() * 2; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstReplicateN final : public AstNodeBiop {
|
|
|
|
|
// String replicate
|
|
|
|
|
public:
|
|
|
|
|
AstReplicateN(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_ReplicateN(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetString();
|
|
|
|
|
}
|
|
|
|
|
AstReplicateN(FileLine* fl, AstNode* lhsp, uint32_t repCount)
|
|
|
|
|
: AstReplicateN(fl, lhsp, new AstConst(fl, repCount)) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstReplicateN;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstReplicateN(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opReplN(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%f{%r{%k%l}}"; }
|
|
|
|
|
string emitC() override { return "VL_REPLICATEN_NN%rq(%li, %ri)"; }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return widthInstrs() * 2; }
|
|
|
|
|
bool stringFlavor() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstShiftL final : public AstNodeBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstShiftL(FileLine* fl, AstNode* lhsp, AstNode* rhsp, int setwidth = 0)
|
|
|
|
|
: ASTGEN_SUPER_ShiftL(fl, lhsp, rhsp) {
|
|
|
|
|
if (setwidth) dtypeSetLogicSized(setwidth, VSigning::UNSIGNED);
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstShiftL;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstShiftL(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opShiftL(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f<< %r)"; }
|
|
|
|
|
string emitC() override { return "VL_SHIFTL_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
|
|
|
|
string emitSimpleOperator() override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return (rhsp()->isWide() || rhsp()->isQuad()) ? "" : "<<";
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstShiftR final : public AstNodeBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstShiftR(FileLine* fl, AstNode* lhsp, AstNode* rhsp, int setwidth = 0)
|
|
|
|
|
: ASTGEN_SUPER_ShiftR(fl, lhsp, rhsp) {
|
|
|
|
|
if (setwidth) dtypeSetLogicSized(setwidth, VSigning::UNSIGNED);
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstShiftR;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstShiftR(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opShiftR(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f>> %r)"; }
|
|
|
|
|
string emitC() override { return "VL_SHIFTR_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
|
|
|
|
string emitSimpleOperator() override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return (rhsp()->isWide() || rhsp()->isQuad()) ? "" : ">>";
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
// LHS size might be > output size, so don't want to force size
|
2022-09-16 12:22:11 +02:00
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstShiftRS final : public AstNodeBiop {
|
|
|
|
|
// Shift right with sign extension, >>> operator
|
|
|
|
|
// Output data type's width determines which bit is used for sign extension
|
|
|
|
|
public:
|
|
|
|
|
AstShiftRS(FileLine* fl, AstNode* lhsp, AstNode* rhsp, int setwidth = 0)
|
|
|
|
|
: ASTGEN_SUPER_ShiftRS(fl, lhsp, rhsp) {
|
|
|
|
|
// Important that widthMin be correct, as opExtend requires it after V3Expand
|
|
|
|
|
if (setwidth) dtypeSetLogicSized(setwidth, VSigning::SIGNED);
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstShiftRS;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstShiftRS(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opShiftRS(lhs, rhs, lhsp()->widthMinV());
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f>>> %r)"; }
|
|
|
|
|
string emitC() override { return "VL_SHIFTRS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
|
|
|
|
string emitSimpleOperator() override { return ""; }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
bool signedFlavor() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstSub final : public AstNodeBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstSub(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_Sub(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeFrom(lhsp);
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstSub;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstSub(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opSub(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f- %r)"; }
|
|
|
|
|
string emitC() override { return "VL_SUB_%lq(%lW, %P, %li, %ri)"; }
|
|
|
|
|
string emitSimpleOperator() override { return "-"; }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool cleanRhs() const override { return false; }
|
|
|
|
|
bool sizeMattersLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersRhs() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstSubD final : public AstNodeBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstSubD(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_SubD(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetDouble();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstSubD;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstSubD(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opSubD(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f- %r)"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitSimpleOperator() override { return "-"; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool cleanRhs() const override { return false; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return INSTR_COUNT_DBL; }
|
|
|
|
|
bool doubleFlavor() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstURandomRange final : public AstNodeBiop {
|
|
|
|
|
// $urandom_range
|
|
|
|
|
public:
|
|
|
|
|
explicit AstURandomRange(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_URandomRange(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetUInt32(); // Says IEEE
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstURandomRange;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstURandomRange(fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
V3ERROR_NA;
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%f$urandom_range(%l, %r)"; }
|
|
|
|
|
string emitC() override { return "VL_URANDOM_RANGE_%nq(%li, %ri)"; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
bool isGateOptimizable() const override { return false; }
|
|
|
|
|
bool isPredictOptimizable() const override { return false; }
|
|
|
|
|
int instrCount() const override { return INSTR_COUNT_PLI; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// === AstNodeBiCom ===
|
|
|
|
|
class AstEq final : public AstNodeBiCom {
|
|
|
|
|
public:
|
|
|
|
|
AstEq(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_Eq(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstEq;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstEq(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
|
|
|
|
static AstNodeBiop* newTyped(FileLine* fl, AstNode* lhsp,
|
|
|
|
|
AstNode* rhsp); // Return AstEq/AstEqD
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opEq(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f== %r)"; }
|
|
|
|
|
string emitC() override { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; }
|
|
|
|
|
string emitSimpleOperator() override { return "=="; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstEqCase final : public AstNodeBiCom {
|
|
|
|
|
public:
|
|
|
|
|
AstEqCase(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_EqCase(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstEqCase;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstEqCase(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opCaseEq(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f=== %r)"; }
|
|
|
|
|
string emitC() override { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; }
|
|
|
|
|
string emitSimpleOperator() override { return "=="; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstEqD final : public AstNodeBiCom {
|
|
|
|
|
public:
|
|
|
|
|
AstEqD(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_EqD(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstEqD;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstEqD(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opEqD(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f== %r)"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitSimpleOperator() override { return "=="; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool cleanRhs() const override { return false; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return INSTR_COUNT_DBL; }
|
|
|
|
|
bool doubleFlavor() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstEqN final : public AstNodeBiCom {
|
|
|
|
|
public:
|
|
|
|
|
AstEqN(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_EqN(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstEqN;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstEqN(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opEqN(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f== %r)"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitSimpleOperator() override { return "=="; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool cleanRhs() const override { return false; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return INSTR_COUNT_STR; }
|
|
|
|
|
bool stringFlavor() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstLogEq final : public AstNodeBiCom {
|
|
|
|
|
public:
|
|
|
|
|
AstLogEq(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_LogEq(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstLogEq;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstLogEq(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opLogEq(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f<-> %r)"; }
|
|
|
|
|
string emitC() override { return "VL_LOGEQ_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
|
|
|
|
string emitSimpleOperator() override { return "<->"; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstNeq final : public AstNodeBiCom {
|
|
|
|
|
public:
|
|
|
|
|
AstNeq(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_Neq(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstNeq;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstNeq(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opNeq(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f!= %r)"; }
|
|
|
|
|
string emitC() override { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; }
|
|
|
|
|
string emitSimpleOperator() override { return "!="; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstNeqCase final : public AstNodeBiCom {
|
|
|
|
|
public:
|
|
|
|
|
AstNeqCase(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_NeqCase(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstNeqCase;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstNeqCase(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opCaseNeq(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f!== %r)"; }
|
|
|
|
|
string emitC() override { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; }
|
|
|
|
|
string emitSimpleOperator() override { return "!="; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstNeqD final : public AstNodeBiCom {
|
|
|
|
|
public:
|
|
|
|
|
AstNeqD(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_NeqD(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstNeqD;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstNeqD(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opNeqD(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f!= %r)"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitSimpleOperator() override { return "!="; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool cleanRhs() const override { return false; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return INSTR_COUNT_DBL; }
|
|
|
|
|
bool doubleFlavor() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstNeqN final : public AstNodeBiCom {
|
|
|
|
|
public:
|
|
|
|
|
AstNeqN(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_NeqN(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstNeqN;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstNeqN(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opNeqN(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f!= %r)"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitSimpleOperator() override { return "!="; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool cleanRhs() const override { return false; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return INSTR_COUNT_STR; }
|
|
|
|
|
bool stringFlavor() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// === AstNodeBiComAsv ===
|
|
|
|
|
class AstAdd final : public AstNodeBiComAsv {
|
|
|
|
|
public:
|
|
|
|
|
AstAdd(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_Add(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeFrom(lhsp);
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstAdd;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstAdd(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opAdd(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f+ %r)"; }
|
|
|
|
|
string emitC() override { return "VL_ADD_%lq(%lW, %P, %li, %ri)"; }
|
|
|
|
|
string emitSimpleOperator() override { return "+"; }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool cleanRhs() const override { return false; }
|
|
|
|
|
bool sizeMattersLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersRhs() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstAddD final : public AstNodeBiComAsv {
|
|
|
|
|
public:
|
|
|
|
|
AstAddD(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_AddD(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetDouble();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstAddD;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstAddD(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opAddD(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f+ %r)"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitSimpleOperator() override { return "+"; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool cleanRhs() const override { return false; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return INSTR_COUNT_DBL; }
|
|
|
|
|
bool doubleFlavor() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstAnd final : public AstNodeBiComAsv {
|
|
|
|
|
public:
|
|
|
|
|
AstAnd(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_And(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeFrom(lhsp);
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstAnd;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstAnd(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opAnd(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f& %r)"; }
|
|
|
|
|
string emitC() override { return "VL_AND_%lq(%lW, %P, %li, %ri)"; }
|
|
|
|
|
string emitSimpleOperator() override { return "&"; }
|
|
|
|
|
bool cleanOut() const override { V3ERROR_NA_RETURN(false); }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool cleanRhs() const override { return false; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstMul final : public AstNodeBiComAsv {
|
|
|
|
|
public:
|
|
|
|
|
AstMul(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_Mul(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeFrom(lhsp);
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstMul;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstMul(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opMul(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f* %r)"; }
|
|
|
|
|
string emitC() override { return "VL_MUL_%lq(%lW, %P, %li, %ri)"; }
|
|
|
|
|
string emitSimpleOperator() override { return "*"; }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersRhs() const override { return true; }
|
|
|
|
|
int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstMulD final : public AstNodeBiComAsv {
|
|
|
|
|
public:
|
|
|
|
|
AstMulD(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_MulD(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeSetDouble();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstMulD;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstMulD(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opMulD(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f* %r)"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitSimpleOperator() override { return "*"; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool cleanRhs() const override { return false; }
|
|
|
|
|
bool sizeMattersLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersRhs() const override { return true; }
|
|
|
|
|
int instrCount() const override { return INSTR_COUNT_DBL; }
|
|
|
|
|
bool doubleFlavor() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstMulS final : public AstNodeBiComAsv {
|
|
|
|
|
public:
|
|
|
|
|
AstMulS(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_MulS(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeFrom(lhsp);
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstMulS;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstMulS(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opMulS(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f* %r)"; }
|
|
|
|
|
string emitC() override { return "VL_MULS_%nq%lq%rq(%lw, %P, %li, %ri)"; }
|
|
|
|
|
string emitSimpleOperator() override { return ""; }
|
|
|
|
|
bool emitCheckMaxWords() override { return true; }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersRhs() const override { return true; }
|
|
|
|
|
int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL; }
|
|
|
|
|
bool signedFlavor() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstOr final : public AstNodeBiComAsv {
|
|
|
|
|
public:
|
|
|
|
|
AstOr(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_Or(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeFrom(lhsp);
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstOr;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstOr(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opOr(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f| %r)"; }
|
|
|
|
|
string emitC() override { return "VL_OR_%lq(%lW, %P, %li, %ri)"; }
|
|
|
|
|
string emitSimpleOperator() override { return "|"; }
|
|
|
|
|
bool cleanOut() const override { V3ERROR_NA_RETURN(false); }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool cleanRhs() const override { return false; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstXor final : public AstNodeBiComAsv {
|
|
|
|
|
public:
|
|
|
|
|
AstXor(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_Xor(fl, lhsp, rhsp) {
|
|
|
|
|
dtypeFrom(lhsp);
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstXor;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstXor(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opXor(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l %f^ %r)"; }
|
|
|
|
|
string emitC() override { return "VL_XOR_%lq(%lW, %P, %li, %ri)"; }
|
|
|
|
|
string emitSimpleOperator() override { return "^"; }
|
|
|
|
|
bool cleanOut() const override { return false; } // Lclean && Rclean
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool cleanRhs() const override { return false; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// === AstNodeSel ===
|
|
|
|
|
class AstArraySel final : public AstNodeSel {
|
|
|
|
|
// Parents: math|stmt
|
|
|
|
|
// Children: varref|arraysel, math
|
|
|
|
|
private:
|
|
|
|
|
void init(AstNode* fromp) {
|
|
|
|
|
if (fromp && VN_IS(fromp->dtypep()->skipRefp(), NodeArrayDType)) {
|
|
|
|
|
// Strip off array to find what array references
|
|
|
|
|
dtypeFrom(VN_AS(fromp->dtypep()->skipRefp(), NodeArrayDType)->subDTypep());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
AstArraySel(FileLine* fl, AstNode* fromp, AstNode* bitp)
|
|
|
|
|
: ASTGEN_SUPER_ArraySel(fl, fromp, bitp) {
|
|
|
|
|
init(fromp);
|
|
|
|
|
}
|
|
|
|
|
AstArraySel(FileLine* fl, AstNode* fromp, int bit)
|
|
|
|
|
: ASTGEN_SUPER_ArraySel(fl, fromp, new AstConst(fl, bit)) {
|
|
|
|
|
init(fromp);
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstArraySel;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstArraySel(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
V3ERROR_NA; /* How can from be a const? */
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l%f[%r])"; }
|
|
|
|
|
string emitC() override { return "%li%k[%ri]"; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
bool isGateOptimizable() const override { return true; } // esp for V3Const::ifSameAssign
|
|
|
|
|
bool isPredictOptimizable() const override { return true; }
|
|
|
|
|
bool same(const AstNode* /*samep*/) const override { return true; }
|
|
|
|
|
int instrCount() const override { return widthInstrs(); }
|
2022-09-15 14:10:39 +02:00
|
|
|
// Special operators
|
|
|
|
|
// Return base var (or const) nodep dereferences
|
|
|
|
|
static AstNode* baseFromp(AstNode* nodep, bool overMembers);
|
|
|
|
|
};
|
|
|
|
|
class AstAssocSel final : public AstNodeSel {
|
|
|
|
|
// Parents: math|stmt
|
|
|
|
|
// Children: varref|arraysel, math
|
|
|
|
|
private:
|
|
|
|
|
void init(AstNode* fromp) {
|
|
|
|
|
if (fromp && VN_IS(fromp->dtypep()->skipRefp(), AssocArrayDType)) {
|
|
|
|
|
// Strip off array to find what array references
|
|
|
|
|
dtypeFrom(VN_AS(fromp->dtypep()->skipRefp(), AssocArrayDType)->subDTypep());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
AstAssocSel(FileLine* fl, AstNode* fromp, AstNode* bitp)
|
|
|
|
|
: ASTGEN_SUPER_AssocSel(fl, fromp, bitp) {
|
|
|
|
|
init(fromp);
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstAssocSel;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstAssocSel(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
V3ERROR_NA;
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l%f[%r])"; }
|
|
|
|
|
string emitC() override { return "%li%k[%ri]"; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
bool isGateOptimizable() const override { return true; } // esp for V3Const::ifSameAssign
|
|
|
|
|
bool isPredictOptimizable() const override { return false; }
|
|
|
|
|
bool same(const AstNode* /*samep*/) const override { return true; }
|
|
|
|
|
int instrCount() const override { return widthInstrs(); }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstWildcardSel final : public AstNodeSel {
|
|
|
|
|
// Parents: math|stmt
|
|
|
|
|
// Children: varref|arraysel, math
|
|
|
|
|
private:
|
|
|
|
|
void init(AstNode* fromp) {
|
|
|
|
|
if (fromp && VN_IS(fromp->dtypep()->skipRefp(), WildcardArrayDType)) {
|
|
|
|
|
// Strip off array to find what array references
|
|
|
|
|
dtypeFrom(VN_AS(fromp->dtypep()->skipRefp(), WildcardArrayDType)->subDTypep());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
AstWildcardSel(FileLine* fl, AstNode* fromp, AstNode* bitp)
|
|
|
|
|
: ASTGEN_SUPER_WildcardSel(fl, fromp, bitp) {
|
|
|
|
|
init(fromp);
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstWildcardSel;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstWildcardSel{this->fileline(), lhsp, rhsp};
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
V3ERROR_NA;
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l%f[%r])"; }
|
|
|
|
|
string emitC() override { return "%li%k[%ri]"; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
bool isGateOptimizable() const override { return true; } // esp for V3Const::ifSameAssign
|
|
|
|
|
bool isPredictOptimizable() const override { return false; }
|
|
|
|
|
bool same(const AstNode* /*samep*/) const override { return true; }
|
|
|
|
|
int instrCount() const override { return widthInstrs(); }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstWordSel final : public AstNodeSel {
|
|
|
|
|
// Select a single word from a multi-word wide value
|
|
|
|
|
public:
|
|
|
|
|
AstWordSel(FileLine* fl, AstNode* fromp, AstNode* bitp)
|
|
|
|
|
: ASTGEN_SUPER_WordSel(fl, fromp, bitp) {
|
|
|
|
|
dtypeSetUInt32(); // Always used on WData arrays so returns edata size
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstWordSel;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstWordSel(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& from, const V3Number& bit) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
V3ERROR_NA;
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%l%f[%r])"; }
|
|
|
|
|
string emitC() override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return "%li[%ri]";
|
|
|
|
|
} // Not %k, as usually it's a small constant rhsp
|
2022-09-16 12:22:11 +02:00
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
bool same(const AstNode* /*samep*/) const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// === AstNodeStream ===
|
|
|
|
|
class AstStreamL final : public AstNodeStream {
|
|
|
|
|
// Verilog {rhs{lhs}} - Note rhsp() is the slice size, not the lhsp()
|
|
|
|
|
public:
|
|
|
|
|
AstStreamL(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_StreamL(fl, lhsp, rhsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstStreamL;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstStreamL(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%f{ << %r %k{%l} }"; }
|
|
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opStreamL(lhs, rhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitC() override { return "VL_STREAML_%nq%lq%rq(%lw, %P, %li, %ri)"; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return widthInstrs() * 2; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstStreamR final : public AstNodeStream {
|
|
|
|
|
// Verilog {rhs{lhs}} - Note rhsp() is the slice size, not the lhsp()
|
|
|
|
|
public:
|
|
|
|
|
AstStreamR(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_StreamR(fl, lhsp, rhsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstStreamR;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstStreamR(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%f{ >> %r %k{%l} }"; }
|
|
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opAssign(lhs);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitC() override { return isWide() ? "VL_ASSIGN_W(%nw, %P, %li)" : "%li"; }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool cleanRhs() const override { return false; }
|
|
|
|
|
bool sizeMattersLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return widthInstrs() * 2; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// === AstNodeSystemBiop ===
|
|
|
|
|
class AstAtan2D final : public AstNodeSystemBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstAtan2D(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_Atan2D(fl, lhsp, rhsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstAtan2D;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstAtan2D(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.setDouble(std::atan2(lhs.toDouble(), rhs.toDouble()));
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%f$atan2(%l,%r)"; }
|
|
|
|
|
string emitC() override { return "atan2(%li,%ri)"; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstHypotD final : public AstNodeSystemBiop {
|
|
|
|
|
public:
|
|
|
|
|
AstHypotD(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: ASTGEN_SUPER_HypotD(fl, lhsp, rhsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstHypotD;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return new AstHypotD(this->fileline(), lhsp, rhsp);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.setDouble(std::hypot(lhs.toDouble(), rhs.toDouble()));
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%f$hypot(%l,%r)"; }
|
|
|
|
|
string emitC() override { return "hypot(%li,%ri)"; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// === AstNodeQuadop ===
|
|
|
|
|
class AstCountBits final : public AstNodeQuadop {
|
|
|
|
|
// Number of bits set in vector
|
|
|
|
|
public:
|
|
|
|
|
AstCountBits(FileLine* fl, AstNode* exprp, AstNode* ctrl1p)
|
|
|
|
|
: ASTGEN_SUPER_CountBits(fl, exprp, ctrl1p, ctrl1p->cloneTree(false),
|
|
|
|
|
ctrl1p->cloneTree(false)) {}
|
|
|
|
|
AstCountBits(FileLine* fl, AstNode* exprp, AstNode* ctrl1p, AstNode* ctrl2p)
|
|
|
|
|
: ASTGEN_SUPER_CountBits(fl, exprp, ctrl1p, ctrl2p, ctrl2p->cloneTree(false)) {}
|
|
|
|
|
AstCountBits(FileLine* fl, AstNode* exprp, AstNode* ctrl1p, AstNode* ctrl2p, AstNode* ctrl3p)
|
|
|
|
|
: ASTGEN_SUPER_CountBits(fl, exprp, ctrl1p, ctrl2p, ctrl3p) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstCountBits;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& expr, const V3Number& ctrl1,
|
|
|
|
|
const V3Number& ctrl2, const V3Number& ctrl3) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opCountBits(expr, ctrl1, ctrl2, ctrl3);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%f$countbits(%l, %r, %f, %o)"; }
|
|
|
|
|
string emitC() override { return ""; }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool cleanThs() const override { return true; }
|
|
|
|
|
bool cleanFhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
bool sizeMattersThs() const override { return false; }
|
|
|
|
|
bool sizeMattersFhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return widthInstrs() * 16; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// === AstNodeTermop ===
|
|
|
|
|
class AstTime final : public AstNodeTermop {
|
|
|
|
|
VTimescale m_timeunit; // Parent module time unit
|
|
|
|
|
public:
|
|
|
|
|
AstTime(FileLine* fl, const VTimescale& timeunit)
|
|
|
|
|
: ASTGEN_SUPER_Time(fl)
|
|
|
|
|
, m_timeunit{timeunit} {
|
|
|
|
|
dtypeSetUInt64();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstTime;
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%f$time"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool isGateOptimizable() const override { return false; }
|
|
|
|
|
bool isPredictOptimizable() const override { return false; }
|
|
|
|
|
int instrCount() const override { return INSTR_COUNT_TIME; }
|
|
|
|
|
bool same(const AstNode* /*samep*/) const override { return true; }
|
|
|
|
|
void dump(std::ostream& str = std::cout) const override;
|
2022-09-15 14:10:39 +02:00
|
|
|
void timeunit(const VTimescale& flag) { m_timeunit = flag; }
|
|
|
|
|
VTimescale timeunit() const { return m_timeunit; }
|
|
|
|
|
};
|
|
|
|
|
class AstTimeD final : public AstNodeTermop {
|
|
|
|
|
VTimescale m_timeunit; // Parent module time unit
|
|
|
|
|
public:
|
|
|
|
|
AstTimeD(FileLine* fl, const VTimescale& timeunit)
|
|
|
|
|
: ASTGEN_SUPER_TimeD(fl)
|
|
|
|
|
, m_timeunit{timeunit} {
|
|
|
|
|
dtypeSetDouble();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstTimeD;
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%f$realtime"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool isGateOptimizable() const override { return false; }
|
|
|
|
|
bool isPredictOptimizable() const override { return false; }
|
|
|
|
|
int instrCount() const override { return INSTR_COUNT_TIME; }
|
|
|
|
|
bool same(const AstNode* /*samep*/) const override { return true; }
|
|
|
|
|
void dump(std::ostream& str = std::cout) const override;
|
2022-09-15 14:10:39 +02:00
|
|
|
void timeunit(const VTimescale& flag) { m_timeunit = flag; }
|
|
|
|
|
VTimescale timeunit() const { return m_timeunit; }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// === AstNodeTriop ===
|
|
|
|
|
class AstPostAdd final : public AstNodeTriop {
|
|
|
|
|
// Post-increment/add
|
|
|
|
|
// Parents: MATH
|
|
|
|
|
// Children: lhsp: AstConst (1) as currently support only ++ not +=
|
|
|
|
|
// Children: rhsp: tree with AstVarRef that is value to read before operation
|
|
|
|
|
// Children: thsp: tree with AstVarRef LValue that is stored after operation
|
|
|
|
|
public:
|
|
|
|
|
AstPostAdd(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* thsp)
|
|
|
|
|
: ASTGEN_SUPER_PostAdd(fl, lhsp, rhsp, thsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstPostAdd;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs,
|
|
|
|
|
const V3Number& ths) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
V3ERROR_NA; // Need to modify lhs
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%r++)"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool cleanRhs() const override { return false; }
|
|
|
|
|
bool cleanThs() const override { return false; }
|
|
|
|
|
bool sizeMattersLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersThs() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstPostSub final : public AstNodeTriop {
|
|
|
|
|
// Post-decrement/subtract
|
|
|
|
|
// Parents: MATH
|
|
|
|
|
// Children: lhsp: AstConst (1) as currently support only -- not -=
|
|
|
|
|
// Children: rhsp: tree with AstVarRef that is value to read before operation
|
|
|
|
|
// Children: thsp: tree with AstVarRef LValue that is stored after operation
|
|
|
|
|
public:
|
|
|
|
|
AstPostSub(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* thsp)
|
|
|
|
|
: ASTGEN_SUPER_PostSub(fl, lhsp, rhsp, thsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstPostSub;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs,
|
|
|
|
|
const V3Number& ths) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
V3ERROR_NA; // Need to modify lhs
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(%r--)"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool cleanRhs() const override { return false; }
|
|
|
|
|
bool cleanThs() const override { return false; }
|
|
|
|
|
bool sizeMattersLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersThs() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstPreAdd final : public AstNodeTriop {
|
|
|
|
|
// Pre-increment/add
|
|
|
|
|
// Parents: MATH
|
|
|
|
|
// Children: lhsp: AstConst (1) as currently support only ++ not +=
|
|
|
|
|
// Children: rhsp: tree with AstVarRef that is value to read before operation
|
|
|
|
|
// Children: thsp: tree with AstVarRef LValue that is stored after operation
|
|
|
|
|
public:
|
|
|
|
|
AstPreAdd(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* thsp)
|
|
|
|
|
: ASTGEN_SUPER_PreAdd(fl, lhsp, rhsp, thsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstPreAdd;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs,
|
|
|
|
|
const V3Number& ths) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
V3ERROR_NA; // Need to modify lhs
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(++%r)"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool cleanRhs() const override { return false; }
|
|
|
|
|
bool cleanThs() const override { return false; }
|
|
|
|
|
bool sizeMattersLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersThs() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstPreSub final : public AstNodeTriop {
|
|
|
|
|
// Pre-decrement/subtract
|
|
|
|
|
// Parents: MATH
|
|
|
|
|
// Children: lhsp: AstConst (1) as currently support only -- not -=
|
|
|
|
|
// Children: rhsp: tree with AstVarRef that is value to read before operation
|
|
|
|
|
// Children: thsp: tree with AstVarRef LValue that is stored after operation
|
|
|
|
|
public:
|
|
|
|
|
AstPreSub(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* thsp)
|
|
|
|
|
: ASTGEN_SUPER_PreSub(fl, lhsp, rhsp, thsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstPreSub;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs,
|
|
|
|
|
const V3Number& ths) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
V3ERROR_NA; // Need to modify lhs
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%k(--%r)"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool cleanRhs() const override { return false; }
|
|
|
|
|
bool cleanThs() const override { return false; }
|
|
|
|
|
bool sizeMattersLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersRhs() const override { return true; }
|
|
|
|
|
bool sizeMattersThs() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstPutcN final : public AstNodeTriop {
|
|
|
|
|
// Verilog string.putc()
|
|
|
|
|
public:
|
|
|
|
|
AstPutcN(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* ths)
|
|
|
|
|
: ASTGEN_SUPER_PutcN(fl, lhsp, rhsp, ths) {
|
|
|
|
|
dtypeSetString();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstPutcN;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs,
|
|
|
|
|
const V3Number& ths) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opPutcN(lhs, rhs, ths);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string name() const override { return "putc"; }
|
|
|
|
|
string emitVerilog() override { return "%k(%l.putc(%r,%t))"; }
|
|
|
|
|
string emitC() override { return "VL_PUTC_N(%li,%ri,%ti)"; }
|
|
|
|
|
string emitSimpleOperator() override { return ""; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool cleanThs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
bool sizeMattersThs() const override { return false; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstSel final : public AstNodeTriop {
|
|
|
|
|
// Multiple bit range extraction
|
|
|
|
|
// Parents: math|stmt
|
|
|
|
|
// Children: varref|arraysel, math, constant math
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen alias op1 := fromp
|
|
|
|
|
// @astgen alias op2 := lsbp
|
|
|
|
|
// @astgen alias op3 := widthp
|
2022-09-15 14:10:39 +02:00
|
|
|
private:
|
|
|
|
|
VNumRange m_declRange; // Range of the 'from' array if isRanged() is set, else invalid
|
|
|
|
|
int m_declElWidth; // If a packed array, the number of bits per element
|
|
|
|
|
public:
|
|
|
|
|
AstSel(FileLine* fl, AstNode* fromp, AstNode* lsbp, AstNode* widthp)
|
|
|
|
|
: ASTGEN_SUPER_Sel(fl, fromp, lsbp, widthp)
|
|
|
|
|
, m_declElWidth{1} {
|
|
|
|
|
if (VN_IS(widthp, Const)) {
|
|
|
|
|
dtypeSetLogicSized(VN_AS(widthp, Const)->toUInt(), VSigning::UNSIGNED);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
AstSel(FileLine* fl, AstNode* fromp, int lsb, int bitwidth)
|
|
|
|
|
: ASTGEN_SUPER_Sel(fl, fromp, new AstConst(fl, lsb), new AstConst(fl, bitwidth))
|
|
|
|
|
, m_declElWidth{1} {
|
|
|
|
|
dtypeSetLogicSized(bitwidth, VSigning::UNSIGNED);
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstSel;
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str) const override;
|
|
|
|
|
void numberOperate(V3Number& out, const V3Number& from, const V3Number& bit,
|
|
|
|
|
const V3Number& width) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opSel(from, bit.toUInt() + width.toUInt() - 1, bit.toUInt());
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitC() override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return widthp()->isOne() ? "VL_BITSEL_%nq%lq%rq%tq(%lw, %P, %li, %ri)"
|
|
|
|
|
: isWide() ? "VL_SEL_%nq%lq%rq%tq(%nw,%lw, %P, %li, %ri, %ti)"
|
|
|
|
|
: "VL_SEL_%nq%lq%rq%tq(%lw, %P, %li, %ri, %ti)";
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool cleanThs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
bool sizeMattersThs() const override { return false; }
|
|
|
|
|
bool same(const AstNode*) const override { return true; }
|
|
|
|
|
int instrCount() const override { return widthInstrs() * (VN_CAST(lsbp(), Const) ? 3 : 10); }
|
2022-09-15 14:10:39 +02:00
|
|
|
int widthConst() const { return VN_AS(widthp(), Const)->toSInt(); }
|
|
|
|
|
int lsbConst() const { return VN_AS(lsbp(), Const)->toSInt(); }
|
|
|
|
|
int msbConst() const { return lsbConst() + widthConst() - 1; }
|
|
|
|
|
VNumRange& declRange() { return m_declRange; }
|
|
|
|
|
const VNumRange& declRange() const { return m_declRange; }
|
|
|
|
|
void declRange(const VNumRange& flag) { m_declRange = flag; }
|
|
|
|
|
int declElWidth() const { return m_declElWidth; }
|
|
|
|
|
void declElWidth(int flag) { m_declElWidth = flag; }
|
|
|
|
|
};
|
|
|
|
|
class AstSliceSel final : public AstNodeTriop {
|
|
|
|
|
// Multiple array element extraction
|
|
|
|
|
// Parents: math|stmt
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen alias op1 := fromp
|
2022-09-15 14:10:39 +02:00
|
|
|
private:
|
|
|
|
|
VNumRange m_declRange; // Range of the 'from' array if isRanged() is set, else invalid
|
|
|
|
|
public:
|
|
|
|
|
AstSliceSel(FileLine* fl, AstNode* fromp, const VNumRange& declRange)
|
|
|
|
|
: ASTGEN_SUPER_SliceSel(fl, fromp, new AstConst(fl, declRange.lo()),
|
|
|
|
|
new AstConst(fl, declRange.elements()))
|
|
|
|
|
, m_declRange{declRange} {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstSliceSel;
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str) const override;
|
|
|
|
|
void numberOperate(V3Number& out, const V3Number& from, const V3Number& lo,
|
|
|
|
|
const V3Number& width) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
V3ERROR_NA;
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); } // Removed before EmitC
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool cleanThs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
bool sizeMattersThs() const override { return false; }
|
|
|
|
|
bool same(const AstNode*) const override { return true; }
|
|
|
|
|
int instrCount() const override { return 10; } // Removed before matters
|
2022-09-15 14:10:39 +02:00
|
|
|
// For widthConst()/loConst etc, see declRange().elements() and other VNumRange methods
|
|
|
|
|
VNumRange& declRange() { return m_declRange; }
|
|
|
|
|
const VNumRange& declRange() const { return m_declRange; }
|
|
|
|
|
void declRange(const VNumRange& flag) { m_declRange = flag; }
|
|
|
|
|
};
|
|
|
|
|
class AstSubstrN final : public AstNodeTriop {
|
|
|
|
|
// Verilog string.substr()
|
|
|
|
|
public:
|
|
|
|
|
AstSubstrN(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* ths)
|
|
|
|
|
: ASTGEN_SUPER_SubstrN(fl, lhsp, rhsp, ths) {
|
|
|
|
|
dtypeSetString();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstSubstrN;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs,
|
|
|
|
|
const V3Number& ths) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opSubstrN(lhs, rhs, ths);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string name() const override { return "substr"; }
|
|
|
|
|
string emitVerilog() override { return "%k(%l.substr(%r,%t))"; }
|
|
|
|
|
string emitC() override { return "VL_SUBSTR_N(%li,%ri,%ti)"; }
|
|
|
|
|
string emitSimpleOperator() override { return ""; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool cleanRhs() const override { return true; }
|
|
|
|
|
bool cleanThs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
bool sizeMattersThs() const override { return false; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// === AstNodeCond ===
|
|
|
|
|
class AstCond final : public AstNodeCond {
|
|
|
|
|
// Conditional ?: statement
|
|
|
|
|
// Parents: MATH
|
|
|
|
|
// Children: MATH
|
|
|
|
|
public:
|
2022-09-15 20:43:56 +02:00
|
|
|
AstCond(FileLine* fl, AstNode* condp, AstNode* thenp, AstNode* elsep)
|
|
|
|
|
: ASTGEN_SUPER_Cond(fl, condp, thenp, elsep) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstCond;
|
2022-09-15 20:43:56 +02:00
|
|
|
AstNode* cloneType(AstNode* condp, AstNode* thenp, AstNode* elsep) override {
|
|
|
|
|
return new AstCond(this->fileline(), condp, thenp, elsep);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
class AstCondBound final : public AstNodeCond {
|
|
|
|
|
// Conditional ?: statement, specially made for safety checking of array bounds
|
|
|
|
|
// Parents: MATH
|
|
|
|
|
// Children: MATH
|
|
|
|
|
public:
|
2022-09-15 20:43:56 +02:00
|
|
|
AstCondBound(FileLine* fl, AstNode* condp, AstNode* thenp, AstNode* elsep)
|
|
|
|
|
: ASTGEN_SUPER_CondBound(fl, condp, thenp, elsep) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstCondBound;
|
2022-09-15 20:43:56 +02:00
|
|
|
AstNode* cloneType(AstNode* condp, AstNode* thenp, AstNode* elsep) override {
|
|
|
|
|
return new AstCondBound(this->fileline(), condp, thenp, elsep);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// === AstNodeUniop ===
|
|
|
|
|
class AstAtoN final : public AstNodeUniop {
|
|
|
|
|
// string.atoi(), atobin(), atohex(), atooct(), atoireal()
|
|
|
|
|
public:
|
|
|
|
|
enum FmtType { ATOI = 10, ATOHEX = 16, ATOOCT = 8, ATOBIN = 2, ATOREAL = -1 };
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
const FmtType m_fmt; // Operation type
|
|
|
|
|
public:
|
|
|
|
|
AstAtoN(FileLine* fl, AstNode* lhsp, FmtType fmt)
|
|
|
|
|
: ASTGEN_SUPER_AtoN(fl, lhsp)
|
|
|
|
|
, m_fmt{fmt} {
|
|
|
|
|
fmt == ATOREAL ? dtypeSetDouble() : dtypeSetSigned32();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstAtoN;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opAtoN(lhs, m_fmt); }
|
|
|
|
|
string name() const override {
|
2022-09-15 14:10:39 +02:00
|
|
|
switch (m_fmt) {
|
|
|
|
|
case ATOI: return "atoi";
|
|
|
|
|
case ATOHEX: return "atohex";
|
|
|
|
|
case ATOOCT: return "atooct";
|
|
|
|
|
case ATOBIN: return "atobin";
|
|
|
|
|
case ATOREAL: return "atoreal";
|
|
|
|
|
default: V3ERROR_NA;
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%l." + name() + "()"; }
|
|
|
|
|
string emitC() override {
|
2022-09-15 14:10:39 +02:00
|
|
|
switch (m_fmt) {
|
|
|
|
|
case ATOI: return "VL_ATOI_N(%li, 10)";
|
|
|
|
|
case ATOHEX: return "VL_ATOI_N(%li, 16)";
|
|
|
|
|
case ATOOCT: return "VL_ATOI_N(%li, 8)";
|
|
|
|
|
case ATOBIN: return "VL_ATOI_N(%li, 2)";
|
|
|
|
|
case ATOREAL: return "std::atof(%li.c_str())";
|
|
|
|
|
default: V3ERROR_NA;
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
2022-09-15 14:10:39 +02:00
|
|
|
FmtType format() const { return m_fmt; }
|
|
|
|
|
};
|
|
|
|
|
class AstBitsToRealD final : public AstNodeUniop {
|
|
|
|
|
public:
|
|
|
|
|
AstBitsToRealD(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_BitsToRealD(fl, lhsp) {
|
|
|
|
|
dtypeSetDouble();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstBitsToRealD;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opBitsToRealD(lhs); }
|
|
|
|
|
string emitVerilog() override { return "%f$bitstoreal(%l)"; }
|
|
|
|
|
string emitC() override { return "VL_CVT_D_Q(%li)"; }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return false; } // Eliminated before matters
|
|
|
|
|
bool sizeMattersLhs() const override { return false; } // Eliminated before matters
|
|
|
|
|
int instrCount() const override { return INSTR_COUNT_DBL; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstCCast final : public AstNodeUniop {
|
|
|
|
|
// Cast to C-based data type
|
|
|
|
|
private:
|
|
|
|
|
int m_size;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
AstCCast(FileLine* fl, AstNode* lhsp, int setwidth, int minwidth = -1)
|
|
|
|
|
: ASTGEN_SUPER_CCast(fl, lhsp) {
|
|
|
|
|
m_size = setwidth;
|
|
|
|
|
if (setwidth) {
|
|
|
|
|
if (minwidth == -1) minwidth = setwidth;
|
|
|
|
|
dtypeSetLogicUnsized(setwidth, minwidth, VSigning::UNSIGNED);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
AstCCast(FileLine* fl, AstNode* lhsp, AstNode* typeFromp)
|
|
|
|
|
: ASTGEN_SUPER_CCast(fl, lhsp) {
|
|
|
|
|
dtypeFrom(typeFromp);
|
|
|
|
|
m_size = width();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstCCast;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opAssign(lhs); }
|
|
|
|
|
string emitVerilog() override { return "%f$_CAST(%l)"; }
|
|
|
|
|
string emitC() override { return "VL_CAST_%nq%lq(%nw,%lw, %P, %li)"; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; } // Special cased in V3Cast
|
|
|
|
|
bool same(const AstNode* samep) const override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return size() == static_cast<const AstCCast*>(samep)->size();
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str = std::cout) const override;
|
2022-09-15 14:10:39 +02:00
|
|
|
//
|
|
|
|
|
int size() const { return m_size; }
|
|
|
|
|
};
|
|
|
|
|
class AstCLog2 final : public AstNodeUniop {
|
|
|
|
|
public:
|
|
|
|
|
AstCLog2(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_CLog2(fl, lhsp) {
|
|
|
|
|
dtypeSetSigned32();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstCLog2;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opCLog2(lhs); }
|
|
|
|
|
string emitVerilog() override { return "%f$clog2(%l)"; }
|
|
|
|
|
string emitC() override { return "VL_CLOG2_%lq(%lW, %P, %li)"; }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return widthInstrs() * 16; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstCountOnes final : public AstNodeUniop {
|
|
|
|
|
// Number of bits set in vector
|
|
|
|
|
public:
|
|
|
|
|
AstCountOnes(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_CountOnes(fl, lhsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstCountOnes;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opCountOnes(lhs); }
|
|
|
|
|
string emitVerilog() override { return "%f$countones(%l)"; }
|
|
|
|
|
string emitC() override { return "VL_COUNTONES_%lq(%lW, %P, %li)"; }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return widthInstrs() * 16; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstCvtPackString final : public AstNodeUniop {
|
|
|
|
|
// Convert to Verilator Packed String (aka verilog "string")
|
|
|
|
|
public:
|
|
|
|
|
AstCvtPackString(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_CvtPackString(fl, lhsp) {
|
|
|
|
|
dtypeSetString();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstCvtPackString;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; }
|
|
|
|
|
string emitVerilog() override { return "%f$_CAST(%l)"; }
|
|
|
|
|
string emitC() override { return "VL_CVT_PACK_STR_N%lq(%lW, %li)"; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool same(const AstNode* /*samep*/) const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstExtend final : public AstNodeUniop {
|
|
|
|
|
// Expand a value into a wider entity by 0 extension. Width is implied from nodep->width()
|
|
|
|
|
public:
|
|
|
|
|
AstExtend(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_Extend(fl, lhsp) {}
|
|
|
|
|
AstExtend(FileLine* fl, AstNode* lhsp, int width)
|
|
|
|
|
: ASTGEN_SUPER_Extend(fl, lhsp) {
|
|
|
|
|
dtypeSetLogicSized(width, VSigning::UNSIGNED);
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstExtend;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opAssign(lhs); }
|
|
|
|
|
string emitVerilog() override { return "%l"; }
|
|
|
|
|
string emitC() override { return "VL_EXTEND_%nq%lq(%nw,%lw, %P, %li)"; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return false; // Because the EXTEND operator self-casts
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
int instrCount() const override { return 0; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstExtendS final : public AstNodeUniop {
|
|
|
|
|
// Expand a value into a wider entity by sign extension. Width is implied from nodep->width()
|
|
|
|
|
public:
|
|
|
|
|
AstExtendS(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_ExtendS(fl, lhsp) {}
|
|
|
|
|
AstExtendS(FileLine* fl, AstNode* lhsp, int width)
|
|
|
|
|
// Important that widthMin be correct, as opExtend requires it after V3Expand
|
|
|
|
|
: ASTGEN_SUPER_ExtendS(fl, lhsp) {
|
|
|
|
|
dtypeSetLogicSized(width, VSigning::UNSIGNED);
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstExtendS;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opExtendS(lhs, lhsp()->widthMinV());
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%l"; }
|
|
|
|
|
string emitC() override { return "VL_EXTENDS_%nq%lq(%nw,%lw, %P, %li)"; }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return false; // Because the EXTEND operator self-casts
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
int instrCount() const override { return 0; }
|
|
|
|
|
bool signedFlavor() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstFEof final : public AstNodeUniop {
|
|
|
|
|
public:
|
|
|
|
|
AstFEof(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_FEof(fl, lhsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstFEof;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; }
|
|
|
|
|
string emitVerilog() override { return "%f$feof(%l)"; }
|
|
|
|
|
string emitC() override { return "(%li ? feof(VL_CVT_I_FP(%li)) : true)"; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return widthInstrs() * 16; }
|
|
|
|
|
bool isPure() const override { return false; } // SPECIAL: $display has 'visual' ordering
|
2022-09-15 14:10:39 +02:00
|
|
|
AstNode* filep() const { return lhsp(); }
|
|
|
|
|
};
|
|
|
|
|
class AstFGetC final : public AstNodeUniop {
|
|
|
|
|
public:
|
|
|
|
|
AstFGetC(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_FGetC(fl, lhsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstFGetC;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; }
|
|
|
|
|
string emitVerilog() override { return "%f$fgetc(%l)"; }
|
2022-09-15 14:10:39 +02:00
|
|
|
// Non-existent filehandle returns EOF
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitC() override { return "(%li ? fgetc(VL_CVT_I_FP(%li)) : -1)"; }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return widthInstrs() * 64; }
|
|
|
|
|
bool isPure() const override { return false; } // SPECIAL: $display has 'visual' ordering
|
2022-09-15 14:10:39 +02:00
|
|
|
AstNode* filep() const { return lhsp(); }
|
|
|
|
|
};
|
|
|
|
|
class AstISToRD final : public AstNodeUniop {
|
|
|
|
|
// $itor where lhs is signed
|
|
|
|
|
public:
|
|
|
|
|
AstISToRD(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_ISToRD(fl, lhsp) {
|
|
|
|
|
dtypeSetDouble();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstISToRD;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opISToRD(lhs); }
|
|
|
|
|
string emitVerilog() override { return "%f$itor($signed(%l))"; }
|
|
|
|
|
string emitC() override { return "VL_ISTOR_D_%lq(%lw, %li)"; }
|
|
|
|
|
bool emitCheckMaxWords() override { return true; }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return INSTR_COUNT_DBL; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstIToRD final : public AstNodeUniop {
|
|
|
|
|
// $itor where lhs is unsigned
|
|
|
|
|
public:
|
|
|
|
|
AstIToRD(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_IToRD(fl, lhsp) {
|
|
|
|
|
dtypeSetDouble();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstIToRD;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opIToRD(lhs); }
|
|
|
|
|
string emitVerilog() override { return "%f$itor(%l)"; }
|
|
|
|
|
string emitC() override { return "VL_ITOR_D_%lq(%lw, %li)"; }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return INSTR_COUNT_DBL; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstIsUnbounded final : public AstNodeUniop {
|
|
|
|
|
// True if is unmbounded ($)
|
|
|
|
|
public:
|
|
|
|
|
AstIsUnbounded(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_IsUnbounded(fl, lhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstIsUnbounded;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number&) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
// Any constant isn't unbounded
|
|
|
|
|
out.setZero();
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%f$isunbounded(%l)"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstIsUnknown final : public AstNodeUniop {
|
|
|
|
|
// True if any unknown bits
|
|
|
|
|
public:
|
|
|
|
|
AstIsUnknown(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_IsUnknown(fl, lhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstIsUnknown;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opIsUnknown(lhs); }
|
|
|
|
|
string emitVerilog() override { return "%f$isunknown(%l)"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstLenN final : public AstNodeUniop {
|
|
|
|
|
// Length of a string
|
|
|
|
|
public:
|
|
|
|
|
AstLenN(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_LenN(fl, lhsp) {
|
|
|
|
|
dtypeSetSigned32();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstLenN;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opLenN(lhs); }
|
|
|
|
|
string emitVerilog() override { return "%f(%l)"; }
|
|
|
|
|
string emitC() override { return "VL_LEN_IN(%li)"; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstLogNot final : public AstNodeUniop {
|
|
|
|
|
public:
|
|
|
|
|
AstLogNot(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_LogNot(fl, lhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstLogNot;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opLogNot(lhs); }
|
|
|
|
|
string emitVerilog() override { return "%f(! %l)"; }
|
|
|
|
|
string emitC() override { return "VL_LOGNOT_%nq%lq(%nw,%lw, %P, %li)"; }
|
|
|
|
|
string emitSimpleOperator() override { return "!"; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstNegate final : public AstNodeUniop {
|
|
|
|
|
public:
|
|
|
|
|
AstNegate(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_Negate(fl, lhsp) {
|
|
|
|
|
dtypeFrom(lhsp);
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstNegate;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opNegate(lhs); }
|
|
|
|
|
string emitVerilog() override { return "%f(- %l)"; }
|
|
|
|
|
string emitC() override { return "VL_NEGATE_%lq(%lW, %P, %li)"; }
|
|
|
|
|
string emitSimpleOperator() override { return "-"; }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersLhs() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstNegateD final : public AstNodeUniop {
|
|
|
|
|
public:
|
|
|
|
|
AstNegateD(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_NegateD(fl, lhsp) {
|
|
|
|
|
dtypeSetDouble();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstNegateD;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opNegateD(lhs); }
|
|
|
|
|
string emitVerilog() override { return "%f(- %l)"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitSimpleOperator() override { return "-"; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return INSTR_COUNT_DBL; }
|
|
|
|
|
bool doubleFlavor() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstNot final : public AstNodeUniop {
|
|
|
|
|
public:
|
|
|
|
|
AstNot(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_Not(fl, lhsp) {
|
|
|
|
|
dtypeFrom(lhsp);
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstNot;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opNot(lhs); }
|
|
|
|
|
string emitVerilog() override { return "%f(~ %l)"; }
|
|
|
|
|
string emitC() override { return "VL_NOT_%lq(%lW, %P, %li)"; }
|
|
|
|
|
string emitSimpleOperator() override { return "~"; }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersLhs() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstNullCheck final : public AstNodeUniop {
|
|
|
|
|
// Return LHS after checking that LHS is non-null
|
|
|
|
|
// Children: VarRef or something returning pointer
|
|
|
|
|
public:
|
|
|
|
|
AstNullCheck(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_NullCheck(fl, lhsp) {
|
|
|
|
|
dtypeFrom(lhsp);
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstNullCheck;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; }
|
|
|
|
|
int instrCount() const override { return 1; } // Rarely executes
|
|
|
|
|
string emitVerilog() override { return "%l"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
bool same(const AstNode* samep) const override { return fileline() == samep->fileline(); }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstOneHot final : public AstNodeUniop {
|
|
|
|
|
// True if only single bit set in vector
|
|
|
|
|
public:
|
|
|
|
|
AstOneHot(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_OneHot(fl, lhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstOneHot;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opOneHot(lhs); }
|
|
|
|
|
string emitVerilog() override { return "%f$onehot(%l)"; }
|
|
|
|
|
string emitC() override { return "VL_ONEHOT_%lq(%lW, %P, %li)"; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return widthInstrs() * 4; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstOneHot0 final : public AstNodeUniop {
|
|
|
|
|
// True if only single bit, or no bits set in vector
|
|
|
|
|
public:
|
|
|
|
|
AstOneHot0(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_OneHot0(fl, lhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstOneHot0;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opOneHot0(lhs); }
|
|
|
|
|
string emitVerilog() override { return "%f$onehot0(%l)"; }
|
|
|
|
|
string emitC() override { return "VL_ONEHOT0_%lq(%lW, %P, %li)"; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return widthInstrs() * 3; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstRToIRoundS final : public AstNodeUniop {
|
|
|
|
|
// Convert real to integer, with arbitrary sized output (not just "integer" format)
|
|
|
|
|
public:
|
|
|
|
|
AstRToIRoundS(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_RToIRoundS(fl, lhsp) {
|
|
|
|
|
dtypeSetSigned32();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstRToIRoundS;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRToIRoundS(lhs); }
|
|
|
|
|
string emitVerilog() override { return "%f$rtoi_rounded(%l)"; }
|
|
|
|
|
string emitC() override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return isWide() ? "VL_RTOIROUND_%nq_D(%nw, %P, %li)" : "VL_RTOIROUND_%nq_D(%li)";
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return INSTR_COUNT_DBL; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstRToIS final : public AstNodeUniop {
|
|
|
|
|
// $rtoi(lhs)
|
|
|
|
|
public:
|
|
|
|
|
AstRToIS(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_RToIS(fl, lhsp) {
|
|
|
|
|
dtypeSetSigned32();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstRToIS;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRToIS(lhs); }
|
|
|
|
|
string emitVerilog() override { return "%f$rtoi(%l)"; }
|
|
|
|
|
string emitC() override { return "VL_RTOI_I_D(%li)"; }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return false; } // Eliminated before matters
|
|
|
|
|
bool sizeMattersLhs() const override { return false; } // Eliminated before matters
|
|
|
|
|
int instrCount() const override { return INSTR_COUNT_DBL; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstRealToBits final : public AstNodeUniop {
|
|
|
|
|
public:
|
|
|
|
|
AstRealToBits(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_RealToBits(fl, lhsp) {
|
|
|
|
|
dtypeSetUInt64();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstRealToBits;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRealToBits(lhs); }
|
|
|
|
|
string emitVerilog() override { return "%f$realtobits(%l)"; }
|
|
|
|
|
string emitC() override { return "VL_CVT_Q_D(%li)"; }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return false; } // Eliminated before matters
|
|
|
|
|
bool sizeMattersLhs() const override { return false; } // Eliminated before matters
|
|
|
|
|
int instrCount() const override { return INSTR_COUNT_DBL; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstRedAnd final : public AstNodeUniop {
|
|
|
|
|
public:
|
|
|
|
|
AstRedAnd(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_RedAnd(fl, lhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstRedAnd;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedAnd(lhs); }
|
|
|
|
|
string emitVerilog() override { return "%f(& %l)"; }
|
|
|
|
|
string emitC() override { return "VL_REDAND_%nq%lq(%lw, %P, %li)"; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstRedOr final : public AstNodeUniop {
|
|
|
|
|
public:
|
|
|
|
|
AstRedOr(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_RedOr(fl, lhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstRedOr;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedOr(lhs); }
|
|
|
|
|
string emitVerilog() override { return "%f(| %l)"; }
|
|
|
|
|
string emitC() override { return "VL_REDOR_%lq(%lW, %P, %li)"; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstRedXor final : public AstNodeUniop {
|
|
|
|
|
public:
|
|
|
|
|
AstRedXor(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_RedXor(fl, lhsp) {
|
|
|
|
|
dtypeSetBit();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstRedXor;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedXor(lhs); }
|
|
|
|
|
string emitVerilog() override { return "%f(^ %l)"; }
|
|
|
|
|
string emitC() override { return "VL_REDXOR_%lq(%lW, %P, %li)"; }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override {
|
2022-09-15 14:10:39 +02:00
|
|
|
const int w = lhsp()->width();
|
|
|
|
|
return (w != 1 && w != 2 && w != 4 && w != 8 && w != 16);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
int instrCount() const override { return 1 + V3Number::log2b(width()); }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstSigned final : public AstNodeUniop {
|
|
|
|
|
// $signed(lhs)
|
|
|
|
|
public:
|
|
|
|
|
AstSigned(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_Signed(fl, lhsp) {
|
|
|
|
|
UASSERT_OBJ(!v3Global.assertDTypesResolved(), this,
|
|
|
|
|
"not coded to create after dtypes resolved");
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstSigned;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opAssign(lhs);
|
|
|
|
|
out.isSigned(false);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%f$signed(%l)"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return false; } // Eliminated before matters
|
|
|
|
|
bool sizeMattersLhs() const override { return true; } // Eliminated before matters
|
|
|
|
|
int instrCount() const override { return 0; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstTimeImport final : public AstNodeUniop {
|
|
|
|
|
// Take a constant that represents a time and needs conversion based on time units
|
|
|
|
|
VTimescale m_timeunit; // Parent module time unit
|
|
|
|
|
public:
|
|
|
|
|
AstTimeImport(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_TimeImport(fl, lhsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstTimeImport;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; }
|
|
|
|
|
string emitVerilog() override { return "%l"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return false; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
void dump(std::ostream& str = std::cout) const override;
|
2022-09-15 14:10:39 +02:00
|
|
|
void timeunit(const VTimescale& flag) { m_timeunit = flag; }
|
|
|
|
|
VTimescale timeunit() const { return m_timeunit; }
|
|
|
|
|
};
|
|
|
|
|
class AstToLowerN final : public AstNodeUniop {
|
|
|
|
|
// string.tolower()
|
|
|
|
|
public:
|
|
|
|
|
AstToLowerN(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_ToLowerN(fl, lhsp) {
|
|
|
|
|
dtypeSetString();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstToLowerN;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opToLowerN(lhs); }
|
|
|
|
|
string emitVerilog() override { return "%l.tolower()"; }
|
|
|
|
|
string emitC() override { return "VL_TOLOWER_NN(%li)"; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstToUpperN final : public AstNodeUniop {
|
|
|
|
|
// string.toupper()
|
|
|
|
|
public:
|
|
|
|
|
AstToUpperN(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_ToUpperN(fl, lhsp) {
|
|
|
|
|
dtypeSetString();
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstToUpperN;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opToUpperN(lhs); }
|
|
|
|
|
string emitVerilog() override { return "%l.toupper()"; }
|
|
|
|
|
string emitC() override { return "VL_TOUPPER_NN(%li)"; }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
bool cleanLhs() const override { return true; }
|
|
|
|
|
bool sizeMattersLhs() const override { return false; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstUnsigned final : public AstNodeUniop {
|
|
|
|
|
// $unsigned(lhs)
|
|
|
|
|
public:
|
|
|
|
|
AstUnsigned(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_Unsigned(fl, lhsp) {
|
|
|
|
|
UASSERT_OBJ(!v3Global.assertDTypesResolved(), this,
|
|
|
|
|
"not coded to create after dtypes resolved");
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstUnsigned;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.opAssign(lhs);
|
|
|
|
|
out.isSigned(false);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%f$unsigned(%l)"; }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { return false; }
|
|
|
|
|
bool cleanLhs() const override { return false; } // Eliminated before matters
|
|
|
|
|
bool sizeMattersLhs() const override { return true; } // Eliminated before matters
|
|
|
|
|
int instrCount() const override { return 0; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// === AstNodeSystemUniop ===
|
|
|
|
|
class AstAcosD final : public AstNodeSystemUniop {
|
|
|
|
|
public:
|
|
|
|
|
AstAcosD(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_AcosD(fl, lhsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstAcosD;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.setDouble(std::acos(lhs.toDouble()));
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%f$acos(%l)"; }
|
|
|
|
|
string emitC() override { return "acos(%li)"; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstAcoshD final : public AstNodeSystemUniop {
|
|
|
|
|
public:
|
|
|
|
|
AstAcoshD(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_AcoshD(fl, lhsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstAcoshD;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.setDouble(std::acosh(lhs.toDouble()));
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%f$acosh(%l)"; }
|
|
|
|
|
string emitC() override { return "acosh(%li)"; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstAsinD final : public AstNodeSystemUniop {
|
|
|
|
|
public:
|
|
|
|
|
AstAsinD(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_AsinD(fl, lhsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstAsinD;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.setDouble(std::asin(lhs.toDouble()));
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%f$asin(%l)"; }
|
|
|
|
|
string emitC() override { return "asin(%li)"; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstAsinhD final : public AstNodeSystemUniop {
|
|
|
|
|
public:
|
|
|
|
|
AstAsinhD(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_AsinhD(fl, lhsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstAsinhD;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.setDouble(std::asinh(lhs.toDouble()));
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%f$asinh(%l)"; }
|
|
|
|
|
string emitC() override { return "asinh(%li)"; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstAtanD final : public AstNodeSystemUniop {
|
|
|
|
|
public:
|
|
|
|
|
AstAtanD(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_AtanD(fl, lhsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstAtanD;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.setDouble(std::atan(lhs.toDouble()));
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%f$atan(%l)"; }
|
|
|
|
|
string emitC() override { return "atan(%li)"; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstAtanhD final : public AstNodeSystemUniop {
|
|
|
|
|
public:
|
|
|
|
|
AstAtanhD(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_AtanhD(fl, lhsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstAtanhD;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.setDouble(std::atanh(lhs.toDouble()));
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%f$atanh(%l)"; }
|
|
|
|
|
string emitC() override { return "atanh(%li)"; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstCeilD final : public AstNodeSystemUniop {
|
|
|
|
|
public:
|
|
|
|
|
AstCeilD(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_CeilD(fl, lhsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstCeilD;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.setDouble(std::ceil(lhs.toDouble()));
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%f$ceil(%l)"; }
|
|
|
|
|
string emitC() override { return "ceil(%li)"; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstCosD final : public AstNodeSystemUniop {
|
|
|
|
|
public:
|
|
|
|
|
AstCosD(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_CosD(fl, lhsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstCosD;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.setDouble(std::cos(lhs.toDouble()));
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%f$cos(%l)"; }
|
|
|
|
|
string emitC() override { return "cos(%li)"; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstCoshD final : public AstNodeSystemUniop {
|
|
|
|
|
public:
|
|
|
|
|
AstCoshD(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_CoshD(fl, lhsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstCoshD;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.setDouble(std::cosh(lhs.toDouble()));
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%f$cosh(%l)"; }
|
|
|
|
|
string emitC() override { return "cosh(%li)"; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstExpD final : public AstNodeSystemUniop {
|
|
|
|
|
public:
|
|
|
|
|
AstExpD(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_ExpD(fl, lhsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstExpD;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.setDouble(std::exp(lhs.toDouble()));
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%f$exp(%l)"; }
|
|
|
|
|
string emitC() override { return "exp(%li)"; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstFloorD final : public AstNodeSystemUniop {
|
|
|
|
|
public:
|
|
|
|
|
AstFloorD(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_FloorD(fl, lhsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstFloorD;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.setDouble(std::floor(lhs.toDouble()));
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%f$floor(%l)"; }
|
|
|
|
|
string emitC() override { return "floor(%li)"; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstLog10D final : public AstNodeSystemUniop {
|
|
|
|
|
public:
|
|
|
|
|
AstLog10D(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_Log10D(fl, lhsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstLog10D;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.setDouble(std::log10(lhs.toDouble()));
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%f$log10(%l)"; }
|
|
|
|
|
string emitC() override { return "log10(%li)"; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstLogD final : public AstNodeSystemUniop {
|
|
|
|
|
public:
|
|
|
|
|
AstLogD(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_LogD(fl, lhsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstLogD;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.setDouble(std::log(lhs.toDouble()));
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%f$ln(%l)"; }
|
|
|
|
|
string emitC() override { return "log(%li)"; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstSinD final : public AstNodeSystemUniop {
|
|
|
|
|
public:
|
|
|
|
|
AstSinD(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_SinD(fl, lhsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstSinD;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.setDouble(std::sin(lhs.toDouble()));
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%f$sin(%l)"; }
|
|
|
|
|
string emitC() override { return "sin(%li)"; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstSinhD final : public AstNodeSystemUniop {
|
|
|
|
|
public:
|
|
|
|
|
AstSinhD(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_SinhD(fl, lhsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstSinhD;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.setDouble(std::sinh(lhs.toDouble()));
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%f$sinh(%l)"; }
|
|
|
|
|
string emitC() override { return "sinh(%li)"; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstSqrtD final : public AstNodeSystemUniop {
|
|
|
|
|
public:
|
|
|
|
|
AstSqrtD(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_SqrtD(fl, lhsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstSqrtD;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.setDouble(std::sqrt(lhs.toDouble()));
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%f$sqrt(%l)"; }
|
|
|
|
|
string emitC() override { return "sqrt(%li)"; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstTanD final : public AstNodeSystemUniop {
|
|
|
|
|
public:
|
|
|
|
|
AstTanD(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_TanD(fl, lhsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstTanD;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.setDouble(std::tan(lhs.toDouble()));
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%f$tan(%l)"; }
|
|
|
|
|
string emitC() override { return "tan(%li)"; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstTanhD final : public AstNodeSystemUniop {
|
|
|
|
|
public:
|
|
|
|
|
AstTanhD(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: ASTGEN_SUPER_TanhD(fl, lhsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstTanhD;
|
2022-09-16 12:22:11 +02:00
|
|
|
void numberOperate(V3Number& out, const V3Number& lhs) override {
|
2022-09-15 14:10:39 +02:00
|
|
|
out.setDouble(std::tanh(lhs.toDouble()));
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { return "%f$tanh(%l)"; }
|
|
|
|
|
string emitC() override { return "tanh(%li)"; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// === AstNodeVarRef ===
|
|
|
|
|
class AstVarRef final : public AstNodeVarRef {
|
|
|
|
|
// A reference to a variable (lvalue or rvalue)
|
|
|
|
|
public:
|
|
|
|
|
AstVarRef(FileLine* fl, const string& name, const VAccess& access)
|
|
|
|
|
: ASTGEN_SUPER_VarRef(fl, name, nullptr, access) {}
|
|
|
|
|
// This form only allowed post-link because output/wire compression may
|
|
|
|
|
// lead to deletion of AstVar's
|
|
|
|
|
inline AstVarRef(FileLine* fl, AstVar* varp, const VAccess& access);
|
|
|
|
|
// This form only allowed post-link (see above)
|
|
|
|
|
inline AstVarRef(FileLine* fl, AstVarScope* varscp, const VAccess& access);
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstVarRef;
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str) const override;
|
2022-09-15 14:10:39 +02:00
|
|
|
bool same(const AstNode* samep) const override;
|
|
|
|
|
inline bool same(const AstVarRef* samep) const;
|
|
|
|
|
inline bool sameNoLvalue(AstVarRef* samep) const;
|
2022-09-16 12:22:11 +02:00
|
|
|
int instrCount() const override {
|
2022-09-15 14:10:39 +02:00
|
|
|
return widthInstrs() * (access().isReadOrRW() ? INSTR_COUNT_LD : 1);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstVarXRef final : public AstNodeVarRef {
|
|
|
|
|
// A VarRef to something in another module before AstScope.
|
|
|
|
|
// Includes pin on a cell, as part of a ASSIGN statement to connect I/Os until AstScope
|
|
|
|
|
private:
|
|
|
|
|
string m_dotted; // Dotted part of scope the name()'ed reference is under or ""
|
|
|
|
|
string m_inlinedDots; // Dotted hierarchy flattened out
|
|
|
|
|
public:
|
|
|
|
|
AstVarXRef(FileLine* fl, const string& name, const string& dotted, const VAccess& access)
|
|
|
|
|
: ASTGEN_SUPER_VarXRef(fl, name, nullptr, access)
|
|
|
|
|
, m_dotted{dotted} {}
|
|
|
|
|
inline AstVarXRef(FileLine* fl, AstVar* varp, const string& dotted, const VAccess& access);
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstVarXRef;
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str) const override;
|
2022-09-15 14:10:39 +02:00
|
|
|
string dotted() const { return m_dotted; }
|
|
|
|
|
void dotted(const string& dotted) { m_dotted = dotted; }
|
|
|
|
|
string inlinedDots() const { return m_inlinedDots; }
|
|
|
|
|
void inlinedDots(const string& flag) { m_inlinedDots = flag; }
|
2022-09-16 12:22:11 +02:00
|
|
|
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
bool cleanOut() const override { return true; }
|
|
|
|
|
int instrCount() const override { return widthInstrs(); }
|
|
|
|
|
bool same(const AstNode* samep) const override {
|
2022-09-15 14:10:39 +02:00
|
|
|
const AstVarXRef* asamep = static_cast<const AstVarXRef*>(samep);
|
|
|
|
|
return (selfPointer() == asamep->selfPointer() && varp() == asamep->varp()
|
|
|
|
|
&& name() == asamep->name() && dotted() == asamep->dotted());
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#endif // Guard
|