Branch data Line data Source code
1 : : // -*- mode: C++; c-file-style: "cc-mode" -*-
2 : : //*************************************************************************
3 : : // DESCRIPTION: Verilator: AstNode sub-types representing expressions
4 : : //
5 : : // Code available from: https://verilator.org
6 : : //
7 : : //*************************************************************************
8 : : //
9 : : // This program is free software; you can redistribute it and/or modify it
10 : : // under the terms of either the GNU Lesser General Public License Version 3
11 : : // or the Perl Artistic License Version 2.0.
12 : : // SPDX-FileCopyrightText: 2003-2026 Wilson Snyder
13 : : // SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
14 : : //
15 : : //*************************************************************************
16 : : //
17 : : // This files contains all 'AstNode' sub-types that represent expressions,
18 : : // i.e.: those constructs that represent, or evaluate to [a possible void]
19 : : // value. The root of the hierarchy is 'AstNodeExpr'.
20 : : //
21 : : // Think of expressions in a very general sense as constructs that "name
22 : : // things". The "thing" can be considered the value, but can be highly
23 : : // structured. For example, an AstConst can name the value '1', which is
24 : : // hopefully familiar. On the opposite end of the spectrum of "things" named by
25 : : // expressions, consider AstClassOrPackageRef, that can name a collection of
26 : : // pairs (specifically the collection of ('member name', 'member thing')
27 : : // pairs). Nevertheless, that collection itself can be considered a value. The
28 : : // valid composition of expressions then defines the calculus of values in the
29 : : // language.
30 : : //
31 : : //*************************************************************************
32 : :
33 : : #ifndef VERILATOR_V3ASTNODEEXPR_H_
34 : : #define VERILATOR_V3ASTNODEEXPR_H_
35 : :
36 : : #ifndef VERILATOR_V3AST_H_
37 : : #error "Use V3Ast.h as the include"
38 : : #include "V3Ast.h" // This helps code analysis tools pick up symbols in V3Ast.h
39 : : #define VL_NOT_FINAL // This #define fixes broken code folding in the CLion IDE
40 : : #endif
41 : :
42 : : // === Abstract base node types (AstNode*) =====================================
43 : :
44 : : class AstNodeExpr VL_NOT_FINAL : public AstNode {
45 : : // An expression tree node
46 : : protected:
47 : : AstNodeExpr(VNType t, FileLine* fl)
48 : : : AstNode{t, fl} {}
49 : :
50 : : public:
51 : : ASTGEN_MEMBERS_AstNodeExpr;
52 : : // METHODS
53 : : void dump(std::ostream& str) const override;
54 : : void dumpJson(std::ostream& str) const override;
55 : : // Every expression must have a data type after V3Width
56 : : bool hasDType() const override final VL_MT_SAFE { return true; }
57 : : virtual string emitVerilog() = 0; /// Format string for verilog writing; see V3EmitV
58 : : // For documentation on emitC format see EmitCFunc::emitOpName
59 : : virtual string emitC() = 0;
60 : : virtual string emitSMT() const { return ""; };
61 : : virtual string emitSimpleOperator() { return ""; } // "" means not ok to use
62 : : virtual bool emitCheckMaxWords() { return false; } // Check VL_MULS_MAX_WORDS
63 : : virtual bool cleanOut() const = 0; // True if output has extra upper bits zero
64 : : // Someday we will generically support data types on every expr node
65 : : // Until then isOpaque indicates we shouldn't constant optimize this node type
66 : : bool isOpaque() const { return VN_IS(this, CvtPackString); }
67 : : // True for SVA multi-cycle sequence nodes (SExpr, SConsRep, etc.)
68 : : virtual bool isMultiCycleSva() const { return false; }
69 : : bool isLValue() const;
70 : :
71 : : // Wrap This expression into an AstStmtExpr to denote it occurs in statement position
72 : : inline AstStmtExpr* makeStmt();
73 : : // Returns an error message if widthMin() is not correct otherwise returns nullptr like
74 : : // broken()
75 : : virtual const char* widthMismatch() const VL_MT_STABLE { return nullptr; }
76 : : };
77 : : class AstNodeBiop VL_NOT_FINAL : public AstNodeExpr {
78 : : // Binary expression
79 : : // @astgen op1 := lhsp : AstNodeExpr
80 : : // @astgen op2 := rhsp : AstNodeExpr
81 : : VIsCached m_purity; // Pure state
82 : :
83 : : protected:
84 : : AstNodeBiop(VNType t, FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
85 : : : AstNodeExpr{t, fl} {
86 : : this->lhsp(lhsp);
87 : : this->rhsp(rhsp);
88 : : }
89 : :
90 : : public:
91 : : ASTGEN_MEMBERS_AstNodeBiop;
92 : : // METHODS
93 : : // Set out to evaluation of a AstConst'ed
94 : : virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) = 0;
95 : : virtual bool cleanLhs() const = 0; // True if LHS must have extra upper bits zero
96 : : virtual bool cleanRhs() const = 0; // True if RHS must have extra upper bits zero
97 : : virtual bool sizeMattersLhs() const = 0; // True if output result depends on lhs size
98 : : virtual bool sizeMattersRhs() const = 0; // True if output result depends on rhs size
99 : : virtual bool doubleFlavor() const { return false; } // D flavor of nodes with both flavors?
100 : : // Signed flavor of nodes with both flavors?
101 : : virtual bool signedFlavor() const { return false; }
102 : : virtual bool stringFlavor() const { return false; } // N flavor of nodes with both flavors?
103 : : int instrCount() const override { return widthInstrs(); }
104 : : bool sameNode(const AstNode*) const override { return true; }
105 : : bool isPure() override;
106 : : const char* broken() const override;
107 : :
108 : : private:
109 : : bool getPurityRecurse() const { return lhsp()->isPure() && rhsp()->isPure(); }
110 : : };
111 : : class AstNodeBiCom VL_NOT_FINAL : public AstNodeBiop {
112 : : // Binary expr with commutative properties
113 : : protected:
114 : : AstNodeBiCom(VNType t, FileLine* fl, AstNodeExpr* lhs, AstNodeExpr* rhs)
115 : : : AstNodeBiop{t, fl, lhs, rhs} {}
116 : :
117 : : public:
118 : : ASTGEN_MEMBERS_AstNodeBiCom;
119 : : };
120 : : class AstNodeBiComAsv VL_NOT_FINAL : public AstNodeBiCom {
121 : : // Binary expr with commutative & associative properties
122 : : protected:
123 : : AstNodeBiComAsv(VNType t, FileLine* fl, AstNodeExpr* lhs, AstNodeExpr* rhs)
124 : : : AstNodeBiCom{t, fl, lhs, rhs} {}
125 : :
126 : : public:
127 : : ASTGEN_MEMBERS_AstNodeBiComAsv;
128 : : };
129 : : class AstNodeDistBiop VL_NOT_FINAL : public AstNodeBiop {
130 : : public:
131 : : AstNodeDistBiop(VNType t, FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
132 : : : AstNodeBiop{t, fl, lhsp, rhsp} {
133 : : dtypeSetSigned32();
134 : : }
135 : : ASTGEN_MEMBERS_AstNodeDistBiop;
136 : : bool cleanOut() const override { return false; }
137 : : bool cleanLhs() const override { return false; }
138 : : bool cleanRhs() const override { return false; }
139 : : bool sizeMattersLhs() const override { return false; }
140 : : bool sizeMattersRhs() const override { return false; }
141 : : bool isSystemFunc() const override { return true; }
142 : : int instrCount() const override { return INSTR_COUNT_DBL_TRIG; }
143 : : void numberOperate(V3Number&, const V3Number&, const V3Number&) override { V3ERROR_NA; }
144 : : };
145 : : class AstNodeSel VL_NOT_FINAL : public AstNodeBiop {
146 : : // Single bit range extraction, perhaps with non-constant selection or array selection
147 : : // @astgen alias op1 := fromp // Expression we are indexing into
148 : : // @astgen alias op2 := bitp // The index // TODO: rename to idxp
149 : : protected:
150 : : AstNodeSel(VNType t, FileLine* fl, AstNodeExpr* fromp, AstNodeExpr* bitp)
151 : : : AstNodeBiop{t, fl, fromp, bitp} {}
152 : :
153 : : public:
154 : : ASTGEN_MEMBERS_AstNodeSel;
155 : : int bitConst() const;
156 : : };
157 : : class AstNodeStream VL_NOT_FINAL : public AstNodeBiop {
158 : : // Verilog {rhs{lhs}} - Note rhsp() is the slice size, not the lhsp()
159 : : protected:
160 : : AstNodeStream(VNType t, FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
161 : : : AstNodeBiop{t, fl, lhsp, rhsp} {
162 : : if (lhsp->dtypep()) dtypeSetLogicSized(lhsp->dtypep()->width(), VSigning::UNSIGNED);
163 : : }
164 : :
165 : : public:
166 : : ASTGEN_MEMBERS_AstNodeStream;
167 : : };
168 : : class AstNodeSystemBiopD VL_NOT_FINAL : public AstNodeBiop {
169 : : public:
170 : : AstNodeSystemBiopD(VNType t, FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
171 : : : AstNodeBiop{t, fl, lhsp, rhsp} {
172 : : dtypeSetDouble();
173 : : }
174 : : ASTGEN_MEMBERS_AstNodeSystemBiopD;
175 : : bool cleanOut() const override { return false; }
176 : : bool cleanLhs() const override { return false; }
177 : : bool cleanRhs() const override { return false; }
178 : : bool sizeMattersLhs() const override { return false; }
179 : : bool sizeMattersRhs() const override { return false; }
180 : : bool isSystemFunc() const override { return true; }
181 : : int instrCount() const override { return INSTR_COUNT_DBL_TRIG; }
182 : : bool doubleFlavor() const override { return true; }
183 : : };
184 : : class AstNodeCCall VL_NOT_FINAL : public AstNodeExpr {
185 : : // A call of a C++ function, perhaps a AstCFunc or perhaps globally named
186 : : // @astgen op2 := argsp : List[AstNodeExpr] // Note: op1 used by some sub-types only
187 : : //
188 : : // @astgen ptr := m_funcp : AstCFunc // Function being called
189 : : string m_argTypes;
190 : : bool m_superReference = false; // Called with super reference
191 : :
192 : : protected:
193 : : AstNodeCCall(VNType t, FileLine* fl, AstCFunc* funcp, AstNodeExpr* argsp = nullptr)
194 : : : AstNodeExpr{t, fl}
195 : : , m_funcp{funcp} {
196 : : addArgsp(argsp);
197 : : }
198 : :
199 : : public:
200 : : ASTGEN_MEMBERS_AstNodeCCall;
201 : : void dump(std::ostream& str = std::cout) const override;
202 : : void dumpJson(std::ostream& str = std::cout) const override;
203 : : int instrCount() const override { return INSTR_COUNT_CALL; }
204 : : bool sameNode(const AstNode* samep) const override {
205 : : const AstNodeCCall* const asamep = VN_DBG_AS(samep, NodeCCall);
206 : : return (funcp() == asamep->funcp() && argTypes() == asamep->argTypes());
207 : : }
208 : : bool isGateOptimizable() const override { return false; }
209 : : bool isPredictOptimizable() const override { return false; }
210 : : bool isPure() override;
211 : : bool isOutputter() override { return !isPure(); }
212 : : AstCFunc* funcp() const { return m_funcp; }
213 : : void funcp(AstCFunc* funcp) { m_funcp = funcp; }
214 : : string argTypes() const { return m_argTypes; }
215 : : void argTypes(const string& str) { m_argTypes = str; }
216 : :
217 : : string emitVerilog() final override { V3ERROR_NA_RETURN(""); }
218 : : string emitC() final override { V3ERROR_NA_RETURN(""); }
219 : : bool cleanOut() const final override { return true; }
220 : : bool superReference() const { return m_superReference; }
221 : : void superReference(bool flag) { m_superReference = flag; }
222 : : };
223 : : class AstNodeFTaskRef VL_NOT_FINAL : public AstNodeExpr {
224 : : // A reference to a task (or function)
225 : : // op1 used by some sub-types only
226 : : // @astgen op2 := argsp : List[AstArg]
227 : : // @astgen op3 := withp : Optional[AstWith]
228 : : // @astgen op4 := scopeNamep : Optional[AstScopeName]
229 : : //
230 : : // @astgen ptr := m_taskp : Optional[AstNodeFTask] // [AfterLink] Pointer to task referenced
231 : : // @astgen ptr := m_classOrPackagep : Optional[AstNodeModule] // Class/package of the task
232 : : ASTGEN_MEMBERS_AstNodeFTaskRef; // Gen pointers before other members for performance
233 : : private:
234 : : string m_name; // Name of variable
235 : : string m_dotted; // Dotted part of scope the name()ed task/func is under or ""
236 : : string m_inlinedDots; // Dotted hierarchy flattened out
237 : : bool m_pli = false; // Pli system call ($name)
238 : : bool m_containsGenBlock = false; // Contains gen block reference
239 : : VIsCached m_purity; // Pure state
240 : :
241 : : protected:
242 : : AstNodeFTaskRef(VNType t, FileLine* fl, const string& name, AstArg* argsp)
243 : : : AstNodeExpr{t, fl}
244 : : , m_name{name} {
245 : : addArgsp(argsp);
246 : : }
247 : :
248 : : public:
249 : : const char* broken() const override;
250 : : void dump(std::ostream& str = std::cout) const override;
251 : : void dumpJson(std::ostream& str = std::cout) const override;
252 : : string name() const override VL_MT_STABLE { return m_name; } // * = Var name
253 : : bool isGateOptimizable() const override;
254 : : string dotted() const { return m_dotted; } // * = Scope name or ""
255 : : string inlinedDots() const { return m_inlinedDots; }
256 : : void inlinedDots(const string& flag) { m_inlinedDots = flag; }
257 : : AstNodeFTask* taskp() const { return m_taskp; } // [After Link] Pointer to variable
258 : : void taskp(AstNodeFTask* taskp) { m_taskp = taskp; }
259 : : void name(const string& name) override { m_name = name; }
260 : : void dotted(const string& name) { m_dotted = name; }
261 : : AstNodeModule* classOrPackagep() const { return m_classOrPackagep; }
262 : : void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; }
263 : : bool pli() const { return m_pli; }
264 : : void pli(bool flag) { m_pli = flag; }
265 : : bool containsGenBlock() const { return m_containsGenBlock; }
266 : : void containsGenBlock(const bool flag) { m_containsGenBlock = flag; }
267 : : bool isPure() override;
268 : :
269 : : string emitVerilog() final override { V3ERROR_NA_RETURN(""); }
270 : : string emitC() final override { V3ERROR_NA_RETURN(""); }
271 : : bool cleanOut() const final override { V3ERROR_NA_RETURN(true); }
272 : :
273 : : private:
274 : : bool getPurityRecurse() const;
275 : : };
276 : : class AstNodePreSel VL_NOT_FINAL : public AstNodeExpr {
277 : : // Something that becomes an AstSel
278 : : // @astgen op1 := fromp : AstNodeExpr
279 : : // @astgen op2 := rhsp : AstNodeExpr
280 : : // @astgen op3 := thsp : Optional[AstNodeExpr]
281 : : // @astgen op4 := attrp : Optional[AstAttrOf]
282 : : VIsCached m_purity; // Pure state
283 : :
284 : : protected:
285 : : AstNodePreSel(VNType t, FileLine* fl, AstNodeExpr* fromp, AstNodeExpr* rhsp, AstNodeExpr* thsp)
286 : : : AstNodeExpr{t, fl} {
287 : : this->fromp(fromp);
288 : : this->rhsp(rhsp);
289 : : this->thsp(thsp);
290 : : }
291 : :
292 : : public:
293 : : ASTGEN_MEMBERS_AstNodePreSel;
294 : : // METHODS
295 : : bool sameNode(const AstNode*) const override { return true; }
296 : :
297 : : string emitVerilog() final override { V3ERROR_NA_RETURN(""); }
298 : : string emitC() final override { V3ERROR_NA_RETURN(""); }
299 : : bool cleanOut() const final override { V3ERROR_NA_RETURN(true); }
300 : : bool isPure() override;
301 : : const char* broken() const override;
302 : :
303 : : private:
304 : : bool getPurityRecurse() const {
305 : : return fromp()->isPure() && rhsp()->isPure() && (!thsp() || thsp()->isPure());
306 : : }
307 : : };
308 : : class AstNodeQuadop VL_NOT_FINAL : public AstNodeExpr {
309 : : // 4-ary expression
310 : : // @astgen op1 := lhsp : AstNodeExpr
311 : : // @astgen op2 := rhsp : AstNodeExpr
312 : : // @astgen op3 := thsp : AstNodeExpr
313 : : // @astgen op4 := fhsp : AstNodeExpr
314 : : VIsCached m_purity; // Pure state
315 : :
316 : : protected:
317 : : AstNodeQuadop(VNType t, FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp, AstNodeExpr* thsp,
318 : : AstNodeExpr* fhsp)
319 : : : AstNodeExpr{t, fl} {
320 : : this->lhsp(lhsp);
321 : : this->rhsp(rhsp);
322 : : this->thsp(thsp);
323 : : this->fhsp(fhsp);
324 : : }
325 : :
326 : : public:
327 : : ASTGEN_MEMBERS_AstNodeQuadop;
328 : : // METHODS
329 : : // Set out to evaluation of a AstConst'ed
330 : : virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs,
331 : : const V3Number& ths, const V3Number& fhs)
332 : : = 0;
333 : : virtual bool cleanLhs() const = 0; // True if LHS must have extra upper bits zero
334 : : virtual bool cleanRhs() const = 0; // True if RHS must have extra upper bits zero
335 : : virtual bool cleanThs() const = 0; // True if THS must have extra upper bits zero
336 : : virtual bool cleanFhs() const = 0; // True if THS must have extra upper bits zero
337 : : virtual bool sizeMattersLhs() const = 0; // True if output result depends on lhs size
338 : : virtual bool sizeMattersRhs() const = 0; // True if output result depends on rhs size
339 : : virtual bool sizeMattersThs() const = 0; // True if output result depends on ths size
340 : : virtual bool sizeMattersFhs() const = 0; // True if output result depends on ths size
341 : : int instrCount() const override { return widthInstrs(); }
342 : : bool sameNode(const AstNode*) const override { return true; }
343 : : bool isPure() override;
344 : : const char* broken() const override;
345 : :
346 : : private:
347 : : bool getPurityRecurse() const {
348 : : return lhsp()->isPure() && rhsp()->isPure() && thsp()->isPure() && fhsp()->isPure();
349 : : }
350 : : };
351 : : class AstNodeTermop VL_NOT_FINAL : public AstNodeExpr {
352 : : // Terminal operator -- an operator with no "inputs"
353 : : protected:
354 : : AstNodeTermop(VNType t, FileLine* fl)
355 : : : AstNodeExpr{t, fl} {}
356 : :
357 : : public:
358 : : ASTGEN_MEMBERS_AstNodeTermop;
359 : : bool isSystemFunc() const override { return true; }
360 : : };
361 : : class AstNodeTriop VL_NOT_FINAL : public AstNodeExpr {
362 : : // Ternary expression
363 : : // @astgen op1 := lhsp : AstNodeExpr
364 : : // @astgen op2 := rhsp : AstNodeExpr
365 : : // @astgen op3 := thsp : AstNodeExpr
366 : : VIsCached m_purity; // Pure state
367 : :
368 : : protected:
369 : : AstNodeTriop(VNType t, FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp, AstNodeExpr* thsp)
370 : : : AstNodeExpr{t, fl} {
371 : : this->lhsp(lhsp);
372 : : this->rhsp(rhsp);
373 : : this->thsp(thsp);
374 : : }
375 : :
376 : : public:
377 : : ASTGEN_MEMBERS_AstNodeTriop;
378 : : // METHODS
379 : : void dump(std::ostream& str) const override;
380 : : void dumpJson(std::ostream& str) const override;
381 : : // Set out to evaluation of a AstConst'ed
382 : : virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs,
383 : : const V3Number& ths)
384 : : = 0;
385 : : virtual bool cleanLhs() const = 0; // True if LHS must have extra upper bits zero
386 : : virtual bool cleanRhs() const = 0; // True if RHS must have extra upper bits zero
387 : : virtual bool cleanThs() const = 0; // True if THS must have extra upper bits zero
388 : : virtual bool sizeMattersLhs() const = 0; // True if output result depends on lhs size
389 : : virtual bool sizeMattersRhs() const = 0; // True if output result depends on rhs size
390 : : virtual bool sizeMattersThs() const = 0; // True if output result depends on ths size
391 : : int instrCount() const override { return widthInstrs(); }
392 : : bool sameNode(const AstNode*) const override { return true; }
393 : : bool isPure() override;
394 : : const char* broken() const override;
395 : :
396 : : private:
397 : : bool getPurityRecurse() const {
398 : : return lhsp()->isPure() && rhsp()->isPure() && thsp()->isPure();
399 : : }
400 : : };
401 : : class AstNodeDistTriop VL_NOT_FINAL : public AstNodeTriop {
402 : : public:
403 : : AstNodeDistTriop(VNType t, FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp,
404 : : AstNodeExpr* thsp)
405 : : : AstNodeTriop{t, fl, lhsp, rhsp, thsp} {
406 : : dtypeSetSigned32();
407 : : }
408 : : ASTGEN_MEMBERS_AstNodeDistTriop;
409 : : bool cleanOut() const override { return false; }
410 : : bool cleanLhs() const override { return false; }
411 : : bool cleanRhs() const override { return false; }
412 : : bool cleanThs() const override { return false; }
413 : : bool sizeMattersLhs() const override { return false; }
414 : : bool sizeMattersRhs() const override { return false; }
415 : : bool sizeMattersThs() const override { return false; }
416 : : bool isSystemFunc() const override { return true; }
417 : : int instrCount() const override { return INSTR_COUNT_DBL_TRIG; }
418 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs,
419 : : const V3Number& ths) override {
420 : : V3ERROR_NA;
421 : : }
422 : : };
423 : : class AstNodeUniop VL_NOT_FINAL : public AstNodeExpr {
424 : : // Unary expression
425 : : // @astgen op1 := lhsp : AstNodeExpr
426 : : VIsCached m_purity; // Pure state
427 : :
428 : : protected:
429 : : AstNodeUniop(VNType t, FileLine* fl, AstNodeExpr* lhsp)
430 : : : AstNodeExpr{t, fl} {
431 : : dtypeFrom(lhsp);
432 : : this->lhsp(lhsp);
433 : : }
434 : :
435 : : public:
436 : : ASTGEN_MEMBERS_AstNodeUniop;
437 : : // METHODS
438 : : void dump(std::ostream& str) const override;
439 : : void dumpJson(std::ostream& str) const override;
440 : : // Set out to evaluation of a AstConst'ed lhs
441 : : virtual void numberOperate(V3Number& out, const V3Number& lhs) = 0;
442 : : virtual bool cleanLhs() const = 0;
443 : : virtual bool sizeMattersLhs() const = 0; // True if output result depends on lhs size
444 : : virtual bool doubleFlavor() const { return false; } // D flavor of nodes with both flavors?
445 : : // Signed flavor of nodes with both flavors?
446 : : virtual bool signedFlavor() const { return false; }
447 : : virtual bool stringFlavor() const { return false; } // N flavor of nodes with both flavors?
448 : : int instrCount() const override { return widthInstrs(); }
449 : : bool sameNode(const AstNode*) const override { return true; }
450 : : bool isPure() override;
451 : : const char* broken() const override;
452 : : };
453 : : class AstNodeSystemUniopD VL_NOT_FINAL : public AstNodeUniop {
454 : : public:
455 : : AstNodeSystemUniopD(VNType t, FileLine* fl, AstNodeExpr* lhsp)
456 : : : AstNodeUniop{t, fl, lhsp} {
457 : : dtypeSetDouble();
458 : : }
459 : : ASTGEN_MEMBERS_AstNodeSystemUniopD;
460 : : bool cleanOut() const override { return true; }
461 : : bool cleanLhs() const override { return false; }
462 : : bool sizeMattersLhs() const override { return false; }
463 : : bool isSystemFunc() const override { return true; }
464 : : int instrCount() const override { return INSTR_COUNT_DBL_TRIG; }
465 : : bool doubleFlavor() const override { return true; }
466 : : };
467 : : class AstNodeVarRef VL_NOT_FINAL : public AstNodeExpr {
468 : : // An AstVarRef or AstVarXRef
469 : : // @astgen ptr := m_varp : Optional[AstVar] // [AfterLink] Pointer to variable itself
470 : : // @astgen ptr := m_varScopep : Optional[AstVarScope] // Varscope for hierarchy
471 : : // @astgen ptr := m_classOrPackagep : Optional[AstNodeModule] // Class/package of the variable
472 : : ASTGEN_MEMBERS_AstNodeVarRef; // Gen pointers before other members for performance
473 : : private:
474 : : VAccess m_access; // Left hand side assignment
475 : : VSelfPointerText m_selfPointer
476 : : = VSelfPointerText{VSelfPointerText::Empty()}; // Output code object
477 : : // pointer (e.g.: 'this')
478 : : protected:
479 : : AstNodeVarRef(VNType t, FileLine* fl, AstVar* varp, const VAccess& access)
480 : : : AstNodeExpr{t, fl}
481 : : , m_access{access} {
482 : : // May have varp==nullptr
483 : : this->varp(varp);
484 : : }
485 : :
486 : : public:
487 : : void dump(std::ostream& str) const override;
488 : : void dumpJson(std::ostream& str) const override;
489 : : int instrCount() const override { return widthInstrs(); }
490 : : VAccess access() const { return m_access; }
491 : : void access(const VAccess& flag) { m_access = flag; } // Avoid using this; Set in constructor
492 : : AstVar* varp() const VL_MT_STABLE { return m_varp; } // [After Link] Pointer to variable
493 : : void varp(AstVar* varp) {
494 : : m_varp = varp;
495 : : dtypeFrom(reinterpret_cast<AstNode*>(varp));
496 : : }
497 : : AstVarScope* varScopep() const { return m_varScopep; }
498 : : void varScopep(AstVarScope* varscp) { m_varScopep = varscp; }
499 : : const VSelfPointerText& selfPointer() const { return m_selfPointer; }
500 : : void selfPointer(const VSelfPointerText& selfPointer) { m_selfPointer = selfPointer; }
501 : : string selfPointerProtect(bool useSelfForThis) const {
502 : : return selfPointer().protect(useSelfForThis, protect());
503 : : }
504 : : AstNodeModule* classOrPackagep() const { return m_classOrPackagep; }
505 : : void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; }
506 : : static AstNodeVarRef* varRefLValueRecurse(AstNode* nodep);
507 : : };
508 : :
509 : : // === Concrete node types =====================================================
510 : :
511 : : // === AstNode ===
512 : : class AstArg final : public AstNode {
513 : : // An argument to a function/task, which is either an expression, or is a placeholder for an
514 : : // omitted argument.
515 : : // @astgen op1 := exprp : Optional[AstNodeExpr] // nullptr if omitted
516 : : std::string m_name; // Argument name, or "" for number based interconnect
517 : : public:
518 : : AstArg(FileLine* fl, const std::string& name, AstNodeExpr* exprp)
519 : : : ASTGEN_SUPER_Arg(fl)
520 : : , m_name{name} {
521 : : this->exprp(exprp);
522 : : }
523 : : ASTGEN_MEMBERS_AstArg;
524 : : std::string name() const override VL_MT_STABLE { return m_name; }
525 : : void name(const std::string& name) override { m_name = name; }
526 : : bool emptyConnectNoNext() const { return !exprp() && name() == "" && !nextp(); }
527 : : };
528 : : class AstWith final : public AstNode {
529 : : // Similar to AstArg, but this is essentially a lambda passed to a call.
530 : : // Not an AstNodeExpr as there is no concept of function values in Verilator
531 : : // The dtypep() contains the with lambda's return dtype, not a function type.
532 : : // Parents: NodeFTaskRef, CMethodHard
533 : : // Children: LambdaArgRef that declares the item variable
534 : : // Children: LambdaArgRef that declares the item.index variable
535 : : // Children: expression (equation establishing the with)
536 : : // @astgen op1 := indexArgRefp : AstLambdaArgRef
537 : : // @astgen op2 := valueArgRefp : AstLambdaArgRef
538 : : // @astgen op3 := exprp : List[AstNode] // Pins, expression and constraints
539 : : // TODO: Separate expression and constraints
540 : : public:
541 : : AstWith(FileLine* fl, AstLambdaArgRef* indexArgRefp, AstLambdaArgRef* valueArgRefp,
542 : : AstNode* exprp)
543 : : : ASTGEN_SUPER_With(fl) {
544 : : this->indexArgRefp(indexArgRefp);
545 : : this->valueArgRefp(valueArgRefp);
546 : : addExprp(exprp);
547 : : }
548 : : ASTGEN_MEMBERS_AstWith;
549 : : bool hasDType() const override { return true; }
550 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
551 : : const char* broken() const override {
552 : : BROKEN_RTN(!indexArgRefp()); // varp needed to know lambda's arg dtype
553 : : BROKEN_RTN(!valueArgRefp()); // varp needed to know lambda's arg dtype
554 : : return nullptr;
555 : : }
556 : : };
557 : :
558 : : // === AstNodeExpr ===
559 : : class AstAddrOfCFunc final : public AstNodeExpr {
560 : : // Get address of CFunc
561 : : // @astgen ptr := m_funcp : AstCFunc // Pointer to function itself
562 : :
563 : : public:
564 : : AstAddrOfCFunc(FileLine* fl, AstCFunc* funcp)
565 : : : ASTGEN_SUPER_AddrOfCFunc(fl)
566 : : , m_funcp{funcp} {
567 : : dtypep(findCHandleDType());
568 : : }
569 : :
570 : : ASTGEN_MEMBERS_AstAddrOfCFunc;
571 : : void dump(std::ostream& str) const override;
572 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
573 : : string emitC() override { V3ERROR_NA_RETURN(""); }
574 : : bool cleanOut() const override { return true; }
575 : : AstCFunc* funcp() const { return m_funcp; }
576 : : };
577 : : class AstAttrOf final : public AstNodeExpr {
578 : : // Return a value of a attribute, for example a LSB or array LSB of a signal
579 : : // @astgen op1 := fromp : Optional[AstNode<AstNodeExpr|AstNodeDType>]
580 : : // @astgen op2 := dimp : Optional[AstNodeExpr]
581 : : VAttrType m_attrType; // What sort of extraction
582 : : string m_name; // Name for some attributes
583 : : public:
584 : : AstAttrOf(FileLine* fl, VAttrType attrtype, AstNode* fromp = nullptr,
585 : : AstNodeExpr* dimp = nullptr)
586 : : : ASTGEN_SUPER_AttrOf(fl) {
587 : : this->fromp(fromp);
588 : : this->dimp(dimp);
589 : : m_attrType = attrtype;
590 : : }
591 : : ASTGEN_MEMBERS_AstAttrOf;
592 : : string name() const override VL_MT_STABLE { return m_name; } // * = Var name
593 : : void name(const string& name) override { m_name = name; }
594 : : VAttrType attrType() const { return m_attrType; }
595 : : void dump(std::ostream& str = std::cout) const override;
596 : : void dumpJson(std::ostream& str = std::cout) const override;
597 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
598 : : string emitC() override { V3ERROR_NA_RETURN(""); }
599 : : bool cleanOut() const override { V3ERROR_NA_RETURN(true); }
600 : : };
601 : : class AstCExpr final : public AstNodeExpr {
602 : : // C expression emitted into output, with some arbitrary nodes interspersed
603 : : // @astgen op1 := nodesp : List[AstNode<AstNodeExpr|AstText>]
604 : : const bool m_pure; // Pure optimizable
605 : :
606 : : void init(const string& text, int setwidth) {
607 : : if (!text.empty()) add(text);
608 : : if (setwidth) {
609 : : dtypeSetBitSized(setwidth, VSigning::UNSIGNED);
610 : : } else {
611 : : dtypeSetVoid(); // Caller to override if necessary
612 : : }
613 : : }
614 : :
615 : : public:
616 : : class Pure {};
617 : : explicit AstCExpr(FileLine* fl, const string& text = "", int setwidth = 0)
618 : : : ASTGEN_SUPER_CExpr(fl)
619 : : , m_pure{false} {
620 : : init(text, setwidth);
621 : : }
622 : : AstCExpr(FileLine* fl, Pure, const string& text = "", int setwidth = 0)
623 : : : ASTGEN_SUPER_CExpr(fl)
624 : : , m_pure{true} {
625 : : init(text, setwidth);
626 : : }
627 : : ASTGEN_MEMBERS_AstCExpr;
628 : : void dump(std::ostream& str = std::cout) const override;
629 : : void dumpJson(std::ostream& str = std::cout) const override;
630 : : // METHODS
631 : : bool cleanOut() const override { return true; }
632 : : std::string emitC() override { V3ERROR_NA_RETURN(""); }
633 : : std::string emitVerilog() override { V3ERROR_NA_RETURN(""); }
634 : : bool isGateOptimizable() const override { return m_pure; }
635 : : bool isOutputter() override { return true; }
636 : : bool isPredictOptimizable() const override { return m_pure; }
637 : : bool isPure() override { return m_pure; }
638 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
639 : : // Add some text, or a node to this expression
640 : : void add(const std::string& text) { addNodesp(new AstText{fileline(), text}); }
641 : : void add(AstNode* nodep) { addNodesp(nodep); }
642 : : };
643 : : class AstCExprUser final : public AstNodeExpr {
644 : : // User '$c' or '$cpure' expression - Like AstCStmt, with text tracking and optimizations
645 : : // disabled.
646 : : //
647 : : // Use AstCExpr instead, unless the text is from user input.
648 : : //
649 : : // @astgen op1 := nodesp : List[AstNode<AstNodeExpr|AstText>]
650 : : const bool m_pure; // Whether the function is pure
651 : : public:
652 : : class Pure {};
653 : : explicit AstCExprUser(FileLine* fl)
654 : : : ASTGEN_SUPER_CExprUser(fl)
655 : : , m_pure{false} {}
656 : : AstCExprUser(FileLine* fl, Pure)
657 : : : ASTGEN_SUPER_CExprUser(fl)
658 : : , m_pure{true} {}
659 : : ASTGEN_MEMBERS_AstCExprUser;
660 : : // METHODS
661 : : bool cleanOut() const override { return false; }
662 : : std::string emitC() override { V3ERROR_NA_RETURN(""); }
663 : : std::string emitVerilog() override { V3ERROR_NA_RETURN(""); }
664 : : bool isGateOptimizable() const override { return m_pure; }
665 : : bool isOutputter() override { return true; }
666 : : bool isPredictOptimizable() const override { return m_pure; }
667 : : bool isPure() override { return m_pure; }
668 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
669 : : // Add some text, or a node to this expression
670 : : void add(const std::string& text) { addNodesp(new AstText{fileline(), text}); }
671 : : void add(AstNode* nodep) { addNodesp(nodep); }
672 : : };
673 : : class AstCMethodHard final : public AstNodeExpr {
674 : : // A reference to a "C" hardcoded member task (or function)
675 : : // PARENTS: stmt/expr
676 : : // @astgen op1 := fromp : AstNodeExpr // Subject of method call
677 : : // @astgen op2 := pinsp : List[AstNodeExpr] // Arguments
678 : : // @astgen op3 := withp : Optional[AstWith] // With clause
679 : : VCMethod m_method; // Which method to call
680 : : bool m_pure = false; // Pure optimizable
681 : : bool m_usePtr = false; // Use '->' not '.'
682 : : public:
683 : : AstCMethodHard(FileLine* fl, AstNodeExpr* fromp, VCMethod method, AstNodeExpr* pinsp = nullptr)
684 : : : ASTGEN_SUPER_CMethodHard(fl)
685 : : , m_method{method} {
686 : : this->fromp(fromp);
687 : : addPinsp(pinsp);
688 : : setPurity();
689 : : }
690 : : ASTGEN_MEMBERS_AstCMethodHard;
691 : : string name() const override VL_MT_STABLE { return method().ascii(); }
692 : : bool sameNode(const AstNode* samep) const override {
693 : : const AstCMethodHard* const asamep = VN_DBG_AS(samep, CMethodHard);
694 : : return (m_method == asamep->m_method);
695 : : }
696 : : bool isPure() override { return m_pure; }
697 : : int instrCount() const override;
698 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
699 : : string emitC() override { V3ERROR_NA_RETURN(""); }
700 : : bool cleanOut() const override { return true; }
701 : : bool usePtr() const { return m_usePtr; }
702 : : void usePtr(bool flag) { m_usePtr = flag; }
703 : : VCMethod method() const VL_MT_STABLE { return m_method; }
704 : : void method(VCMethod value) { m_method = value; }
705 : :
706 : : private:
707 : : void setPurity();
708 : : };
709 : : class AstCReset final : public AstNodeExpr {
710 : : // Reset variable at startup
711 : : const bool m_constructing; // Previously cleared by constructor
712 : : public:
713 : : AstCReset(FileLine* fl, AstVar* varp, bool constructing)
714 : : : ASTGEN_SUPER_CReset(fl)
715 : : , m_constructing{constructing} {
716 : : dtypeFrom(varp);
717 : : }
718 : : ASTGEN_MEMBERS_AstCReset;
719 : : void dump(std::ostream& str) const override;
720 : : void dumpJson(std::ostream& str) const override;
721 : : bool isPure() override { return true; }
722 : : int instrCount() const override { return widthInstrs(); }
723 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
724 : : string emitC() override { V3ERROR_NA_RETURN(""); }
725 : : bool cleanOut() const override { return true; }
726 : : const char* broken() const override {
727 : : BROKEN_RTN(!VN_IS(backp(), NodeAssign)); // V3Emit* assumption
728 : : return nullptr;
729 : : }
730 : : bool sameNode(const AstNode* samep) const override {
731 : : return constructing() == VN_DBG_AS(samep, CReset)->constructing();
732 : : }
733 : : bool constructing() const { return m_constructing; }
734 : : };
735 : : class AstCast final : public AstNodeExpr {
736 : : // Cast to appropriate data type
737 : : // @astgen op1 := fromp : AstNodeExpr
738 : : // @astgen op2 := childDTypep : Optional[AstNodeDType]
739 : : public:
740 : : AstCast(FileLine* fl, AstNodeExpr* fromp, VFlagChildDType, AstNodeDType* dtp)
741 : : : ASTGEN_SUPER_Cast(fl) {
742 : : this->fromp(fromp);
743 : : childDTypep(dtp);
744 : : dtypeFrom(dtp);
745 : : }
746 : : // cppcheck-suppress constParameterPointer
747 : : // cppcheck-suppress constParameterCallback
748 : : AstCast(FileLine* fl, AstNodeExpr* fromp, AstNodeDType* dtp)
749 : : : ASTGEN_SUPER_Cast(fl) {
750 : : this->fromp(fromp);
751 : : dtypeFrom(dtp);
752 : : }
753 : : ASTGEN_MEMBERS_AstCast;
754 : : string emitVerilog() override { return "((%d)'(%l))"; }
755 : : string emitC() override { V3ERROR_NA_RETURN(""); }
756 : : bool cleanOut() const override { V3ERROR_NA_RETURN(true); }
757 : : AstNodeDType* getChildDTypep() const override { return childDTypep(); }
758 : : AstNodeDType* subDTypep() const VL_MT_STABLE { return dtypep() ? dtypep() : childDTypep(); }
759 : : };
760 : : class AstCastParse final : public AstNodeExpr {
761 : : // Cast to appropriate type, where we haven't determined yet what the data type is
762 : : // @astgen op1 := lhsp : AstNodeExpr
763 : : // @astgen op2 := dtp : AstNode
764 : : public:
765 : : AstCastParse(FileLine* fl, AstNodeExpr* lhsp, AstNode* dtp)
766 : : : ASTGEN_SUPER_CastParse(fl) {
767 : : this->lhsp(lhsp);
768 : : this->dtp(dtp);
769 : : }
770 : : ASTGEN_MEMBERS_AstCastParse;
771 : : string emitVerilog() override { return "((%d)'(%l))"; }
772 : : string emitC() override { V3ERROR_NA_RETURN(""); }
773 : : bool cleanOut() const override { V3ERROR_NA_RETURN(true); }
774 : : };
775 : : class AstCastSize final : public AstNodeExpr {
776 : : // Cast to specific size; signed/twostate inherited from lower element per IEEE
777 : : // @astgen op1 := lhsp : AstNodeExpr
778 : : // @astgen op2 := rhsp : AstConst
779 : : public:
780 : : AstCastSize(FileLine* fl, AstNodeExpr* lhsp, AstConst* rhsp)
781 : : : ASTGEN_SUPER_CastSize(fl) {
782 : : this->lhsp(lhsp);
783 : : this->rhsp(rhsp);
784 : : }
785 : : ASTGEN_MEMBERS_AstCastSize;
786 : : string emitVerilog() override { return "((%r)'(%l))"; }
787 : : string emitC() override { V3ERROR_NA_RETURN(""); }
788 : : bool cleanOut() const override { V3ERROR_NA_RETURN(true); }
789 : : };
790 : : class AstCellArrayRef final : public AstNodeExpr {
791 : : // As-of-yet unlinkable reference into an array of cells
792 : : // @astgen op1 := selp : List[AstNodeExpr] // Select expression
793 : : string m_name; // Array name
794 : : public:
795 : : AstCellArrayRef(FileLine* fl, const string& name, AstNodeExpr* selp)
796 : : : ASTGEN_SUPER_CellArrayRef(fl)
797 : : , m_name{name} {
798 : : addSelp(selp);
799 : : }
800 : : ASTGEN_MEMBERS_AstCellArrayRef;
801 : : // ACCESSORS
802 : : string name() const override VL_MT_STABLE { return m_name; } // * = Array name
803 : :
804 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
805 : : string emitC() override { V3ERROR_NA_RETURN(""); }
806 : : bool cleanOut() const override { V3ERROR_NA_RETURN(true); }
807 : : };
808 : : class AstCellRef final : public AstNodeExpr {
809 : : // As-of-yet unlinkable reference into a cell
810 : : // @astgen op1 := cellp : AstNode
811 : : // @astgen op2 := exprp : AstNode<AstNodeExpr|AstNodeDType>
812 : : string m_name; // Cell name
813 : : public:
814 : : AstCellRef(FileLine* fl, const string& name, AstNode* cellp, AstNode* exprp)
815 : : : ASTGEN_SUPER_CellRef(fl)
816 : : , m_name{name} {
817 : : this->cellp(cellp);
818 : : this->exprp(exprp);
819 : : }
820 : : ASTGEN_MEMBERS_AstCellRef;
821 : : // ACCESSORS
822 : : string name() const override VL_MT_STABLE { return m_name; } // * = Array name
823 : :
824 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
825 : : string emitC() override { V3ERROR_NA_RETURN(""); }
826 : : bool cleanOut() const override { V3ERROR_NA_RETURN(true); }
827 : : };
828 : : class AstClassOrPackageRef final : public AstNodeExpr {
829 : : // @astgen op1 := paramsp : List[AstPin]
830 : : string m_name;
831 : : // Node not NodeModule to appease some early parser usage
832 : : // @astgen ptr := m_classOrPackageNodep : Optional[AstNode] // Class/package referenced
833 : : public:
834 : : AstClassOrPackageRef(FileLine* fl, const string& name, AstNode* classOrPackageNodep,
835 : : AstPin* paramsp)
836 : : : ASTGEN_SUPER_ClassOrPackageRef(fl)
837 : : , m_name{name}
838 : : , m_classOrPackageNodep{classOrPackageNodep} {
839 : : addParamsp(paramsp);
840 : : }
841 : : ASTGEN_MEMBERS_AstClassOrPackageRef;
842 : : // METHODS
843 : : bool sameNode(const AstNode* samep) const override {
844 : : return (m_classOrPackageNodep
845 : : == VN_DBG_AS(samep, ClassOrPackageRef)->m_classOrPackageNodep);
846 : : }
847 : : void dump(std::ostream& str = std::cout) const override;
848 : : void dumpJson(std::ostream& str = std::cout) const override;
849 : : string name() const override VL_MT_STABLE { return m_name; } // * = Var name
850 : : // There's no classOrPackagep(); use classOrPackageNodep() to get Node,
851 : : // or iterating to package with classOrPackageSkipp()
852 : : AstNodeModule* classOrPackageSkipp() const;
853 : : AstNode* classOrPackageNodep() const { return m_classOrPackageNodep; }
854 : : void classOrPackageNodep(AstNode* nodep) { m_classOrPackageNodep = nodep; }
855 : : void classOrPackagep(AstNodeModule* nodep) {
856 : : m_classOrPackageNodep = reinterpret_cast<AstNode*>(nodep);
857 : : }
858 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
859 : : string emitC() override { V3ERROR_NA_RETURN(""); }
860 : : bool cleanOut() const override { V3ERROR_NA_RETURN(true); }
861 : : };
862 : : class AstConsAssoc final : public AstNodeExpr {
863 : : // Construct an assoc array and return object, '{}
864 : : // @astgen op1 := defaultp : Optional[AstNodeExpr]
865 : : public:
866 : : AstConsAssoc(FileLine* fl, AstNodeExpr* defaultp)
867 : : : ASTGEN_SUPER_ConsAssoc(fl) {
868 : : this->defaultp(defaultp);
869 : : }
870 : : ASTGEN_MEMBERS_AstConsAssoc;
871 : : string emitVerilog() override { return "'{}"; }
872 : : string emitC() override { V3ERROR_NA_RETURN(""); }
873 : : string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
874 : : bool cleanOut() const override { return true; }
875 : : int instrCount() const override { return widthInstrs(); }
876 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
877 : : };
878 : : class AstConsDynArray final : public AstNodeExpr {
879 : : // Construct a queue and return object, '{}. '{lhs}, '{lhs. rhs}
880 : : // @astgen op1 := lhsp : Optional[AstNodeExpr]
881 : : // @astgen op2 := rhsp : Optional[AstNodeExpr]
882 : : const bool m_lhsIsValue; // LHS constructs value inside the queue, not concat
883 : : const bool m_rhsIsValue; // RHS constructs value inside the queue, not concat
884 : : public:
885 : : explicit AstConsDynArray(FileLine* fl)
886 : : : ASTGEN_SUPER_ConsDynArray(fl)
887 : : , m_lhsIsValue{false}
888 : : , m_rhsIsValue{false} {}
889 : : explicit AstConsDynArray(FileLine* fl, bool lhsIsValue, AstNodeExpr* lhsp, bool rhsIsValue,
890 : : AstNodeExpr* rhsp)
891 : : : ASTGEN_SUPER_ConsDynArray(fl)
892 : : , m_lhsIsValue{lhsIsValue}
893 : : , m_rhsIsValue{rhsIsValue} {
894 : : this->lhsp(lhsp);
895 : : this->rhsp(rhsp);
896 : : }
897 : : ASTGEN_MEMBERS_AstConsDynArray;
898 : : void dump(std::ostream& str) const override;
899 : : void dumpJson(std::ostream& str) const override;
900 : : string emitVerilog() override { return "'{%l, %r}"; }
901 : : string emitC() override { V3ERROR_NA_RETURN(""); }
902 : : string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
903 : : bool cleanOut() const override { return true; }
904 : : int instrCount() const override { return widthInstrs(); }
905 : : bool sameNode(const AstNode* samep) const override {
906 : : const AstConsDynArray* const sp = VN_DBG_AS(samep, ConsDynArray);
907 : : return m_lhsIsValue == sp->m_lhsIsValue && m_rhsIsValue == sp->m_rhsIsValue;
908 : : }
909 : : bool lhsIsValue() const { return m_lhsIsValue; }
910 : : bool rhsIsValue() const { return m_rhsIsValue; }
911 : : };
912 : : class AstConsPackMember final : public AstNodeExpr {
913 : : // Construct a packed array single element [member1: value1]
914 : : // Don't need the member we are constructing, as the dtypep can get us to it
915 : : // @astgen op2 := rhsp : AstNodeExpr
916 : : public:
917 : : explicit AstConsPackMember(FileLine* fl, AstMemberDType* dtypep, AstNodeExpr* rhsp)
918 : : : ASTGEN_SUPER_ConsPackMember(fl) {
919 : : this->dtypep(dtypep);
920 : : this->rhsp(rhsp);
921 : : }
922 : : ASTGEN_MEMBERS_AstConsPackMember;
923 : : const char* broken() const override {
924 : : BROKEN_RTN(dtypep() && !VN_IS(dtypep(), MemberDType));
925 : : return nullptr;
926 : : }
927 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
928 : : string emitC() override { V3ERROR_NA_RETURN(""); }
929 : : string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
930 : : bool cleanOut() const override { return true; }
931 : : int instrCount() const override { return widthInstrs(); }
932 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
933 : : };
934 : : class AstConsPackUOrStruct final : public AstNodeExpr {
935 : : // Construct a packed struct and return object, '{member1: value1, member2: value2}
936 : : // Don't need the class we are constructing, as the dtypep can get us to it
937 : : // @astgen op1 := membersp : List[AstConsPackMember]
938 : : public:
939 : : explicit AstConsPackUOrStruct(FileLine* fl, AstNodeUOrStructDType* dtypep,
940 : : AstConsPackMember* membersp = nullptr)
941 : : : ASTGEN_SUPER_ConsPackUOrStruct(fl) {
942 : : this->dtypep(dtypep);
943 : : addMembersp(membersp);
944 : : }
945 : : ASTGEN_MEMBERS_AstConsPackUOrStruct;
946 : : const char* broken() const override { return nullptr; }
947 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
948 : : string emitC() override { V3ERROR_NA_RETURN(""); }
949 : : string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
950 : : bool cleanOut() const override { return true; }
951 : : int instrCount() const override { return widthInstrs(); }
952 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
953 : : };
954 : : class AstConsQueue final : public AstNodeExpr {
955 : : // Construct a queue and return object, '{}. '{lhs}, '{lhs. rhs}
956 : : // @astgen op1 := lhsp : Optional[AstNodeExpr]
957 : : // @astgen op2 := rhsp : Optional[AstNodeExpr]
958 : : const bool m_lhsIsValue; // LHS constructs value inside the queue, not concat
959 : : const bool m_rhsIsValue; // RHS constructs value inside the queue, not concat
960 : : public:
961 : : explicit AstConsQueue(FileLine* fl)
962 : : : ASTGEN_SUPER_ConsQueue(fl)
963 : : , m_lhsIsValue{false}
964 : : , m_rhsIsValue{false} {}
965 : : explicit AstConsQueue(FileLine* fl, bool lhsIsValue, AstNodeExpr* lhsp, bool rhsIsValue,
966 : : AstNodeExpr* rhsp)
967 : : : ASTGEN_SUPER_ConsQueue(fl)
968 : : , m_lhsIsValue{lhsIsValue}
969 : : , m_rhsIsValue{rhsIsValue} {
970 : : this->lhsp(lhsp);
971 : : this->rhsp(rhsp);
972 : : }
973 : : ASTGEN_MEMBERS_AstConsQueue;
974 : : void dump(std::ostream& str) const override;
975 : : void dumpJson(std::ostream& str) const override;
976 : : string emitVerilog() override { return "'{%l, %r}"; }
977 : : string emitC() override { V3ERROR_NA_RETURN(""); }
978 : : string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
979 : : bool cleanOut() const override { return true; }
980 : : int instrCount() const override { return widthInstrs(); }
981 : : bool sameNode(const AstNode* samep) const override {
982 : : const AstConsQueue* const sp = VN_DBG_AS(samep, ConsQueue);
983 : : return m_lhsIsValue == sp->m_lhsIsValue && m_rhsIsValue == sp->m_rhsIsValue;
984 : : }
985 : : bool lhsIsValue() const { return m_lhsIsValue; }
986 : : bool rhsIsValue() const { return m_rhsIsValue; }
987 : : };
988 : : class AstConsWildcard final : public AstNodeExpr {
989 : : // Construct a wildcard assoc array and return object, '{}
990 : : // @astgen op1 := defaultp : Optional[AstNodeExpr]
991 : : public:
992 : : AstConsWildcard(FileLine* fl, AstNodeExpr* defaultp)
993 : : : ASTGEN_SUPER_ConsWildcard(fl) {
994 : : this->defaultp(defaultp);
995 : : }
996 : : ASTGEN_MEMBERS_AstConsWildcard;
997 : : string emitVerilog() override { return "'{}"; }
998 : : string emitC() override { V3ERROR_NA_RETURN(""); }
999 : : string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
1000 : : bool cleanOut() const override { return true; }
1001 : : int instrCount() const override { return widthInstrs(); }
1002 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
1003 : : };
1004 : : class AstConst final : public AstNodeExpr {
1005 : : // A constant
1006 : : V3Number m_num; // Constant value
1007 : : void initWithNumber() {
1008 : : if (m_num.isDouble()) {
1009 : : dtypeSetDouble();
1010 : : } else if (m_num.isString()) {
1011 : : dtypeSetString();
1012 : : } else if (m_num.isAnyXZ()) {
1013 : : dtypeSetLogicUnsized(m_num.width(), (m_num.sized() ? 0 : m_num.widthToFit()),
1014 : : VSigning::fromBool(m_num.isSigned()));
1015 : : } else {
1016 : : dtypeSetBitUnsized(m_num.width(), (m_num.sized() ? 0 : m_num.widthToFit()),
1017 : : VSigning::fromBool(m_num.isSigned()));
1018 : : }
1019 : : m_num.nodep(this);
1020 : : }
1021 : :
1022 : : public:
1023 : : AstConst(FileLine* fl, const V3Number& num)
1024 : : : ASTGEN_SUPER_Const(fl)
1025 : : , m_num{num} {
1026 : : initWithNumber();
1027 : : }
1028 : : class WidthedValue {}; // for creator type-overload selection
1029 : : AstConst(FileLine* fl, WidthedValue, int width, uint32_t value)
1030 : : : ASTGEN_SUPER_Const(fl)
1031 : : , m_num(this, width, value) { // Need () constructor
1032 : : initWithNumber();
1033 : : }
1034 : : class DTyped {}; // for creator type-overload selection
1035 : : // Zero/empty constant with a type matching nodetypep
1036 : : AstConst(FileLine* fl, DTyped, const AstNodeDType* nodedtypep)
1037 : : : ASTGEN_SUPER_Const(fl)
1038 : : , m_num{this, nodedtypep} {
1039 : : initWithNumber();
1040 : : }
1041 : : class StringToParse {}; // for creator type-overload selection
1042 : : AstConst(FileLine* fl, StringToParse, const char* sourcep)
1043 : : : ASTGEN_SUPER_Const(fl)
1044 : : , m_num{this, V3Number::VerilogNumberLiteral{}, sourcep} {
1045 : : initWithNumber();
1046 : : }
1047 : : class VerilogStringLiteral {}; // for creator type-overload selection
1048 : : AstConst(FileLine* fl, VerilogStringLiteral, const string& str)
1049 : : : ASTGEN_SUPER_Const(fl)
1050 : : , m_num{this, V3Number::VerilogStringLiteral{}, str} {
1051 : : initWithNumber();
1052 : : }
1053 : : AstConst(FileLine* fl, uint32_t num)
1054 : : : ASTGEN_SUPER_Const(fl)
1055 : : , m_num(this, 32, num) { // Need () constructor
1056 : : dtypeSetBitUnsized(m_num.width(), 0, VSigning::UNSIGNED);
1057 : : }
1058 : : class Unsized32 {}; // for creator type-overload selection
1059 : : AstConst(FileLine* fl, Unsized32, uint32_t num) // Unsized 32-bit integer of specified value
1060 : : : ASTGEN_SUPER_Const(fl)
1061 : : , m_num(this, 32, num) { // Need () constructor
1062 : : m_num.width(32, false);
1063 : : dtypeSetBitUnsized(32, m_num.widthToFit(), VSigning::UNSIGNED);
1064 : : }
1065 : : class Signed32 {}; // for creator type-overload selection
1066 : : AstConst(FileLine* fl, Signed32, int32_t num) // Signed 32-bit integer of specified value
1067 : : : ASTGEN_SUPER_Const(fl)
1068 : : , m_num(this, 32, num) { // Need () constructor
1069 : : m_num.width(32, true);
1070 : : dtypeSetBitUnsized(32, m_num.widthToFit(), VSigning::SIGNED);
1071 : : }
1072 : : class Unsized64 {}; // for creator type-overload selection
1073 : : AstConst(FileLine* fl, Unsized64, uint64_t num)
1074 : : : ASTGEN_SUPER_Const(fl)
1075 : : , m_num(this, 64, 0) { // Need () constructor
1076 : : m_num.setQuad(num);
1077 : : dtypeSetBitSized(64, VSigning::UNSIGNED);
1078 : : }
1079 : : class SizedEData {}; // for creator type-overload selection
1080 : : AstConst(FileLine* fl, SizedEData, uint64_t num)
1081 : : : ASTGEN_SUPER_Const(fl)
1082 : : , m_num(this, VL_EDATASIZE, 0) { // Need () constructor
1083 : : m_num.setQuad(num);
1084 : : dtypeSetBitSized(VL_EDATASIZE, VSigning::UNSIGNED);
1085 : : }
1086 : : class RealDouble {}; // for creator type-overload selection
1087 : : AstConst(FileLine* fl, RealDouble, double num)
1088 : : : ASTGEN_SUPER_Const(fl)
1089 : : , m_num(this, 64) { // Need () constructor
1090 : : m_num.setDouble(num);
1091 : : dtypeSetDouble();
1092 : : }
1093 : : class String {}; // for creator type-overload selection
1094 : : AstConst(FileLine* fl, String, const string& num)
1095 : : : ASTGEN_SUPER_Const(fl)
1096 : : , m_num{this, V3Number::String{}, num} {
1097 : : dtypeSetString();
1098 : : }
1099 : : class BitFalse {};
1100 : : AstConst(FileLine* fl, BitFalse) // Shorthand const 0, dtype should be a bit of size 1
1101 : : : ASTGEN_SUPER_Const(fl)
1102 : : , m_num(this, 1, 0) { // Need () constructor
1103 : : dtypeSetBit();
1104 : : }
1105 : : // Shorthand const 1 (or with argument 0/1), dtype should be a bit of size 1
1106 : : class BitTrue {};
1107 : : AstConst(FileLine* fl, BitTrue, bool on = true)
1108 : : : ASTGEN_SUPER_Const(fl)
1109 : : , m_num(this, 1, on) { // Need () constructor
1110 : : dtypeSetBit();
1111 : : }
1112 : : class All0 {};
1113 : : AstConst(FileLine* fl, All0)
1114 : : : ASTGEN_SUPER_Const(fl)
1115 : : , m_num{this, V3Number::VerilogNumberLiteral{}, "'0"} {
1116 : : initWithNumber();
1117 : : fl->warnOff(V3ErrorCode::NEWERSTD, true);
1118 : : }
1119 : : class All1 {};
1120 : : AstConst(FileLine* fl, All1)
1121 : : : ASTGEN_SUPER_Const(fl)
1122 : : , m_num{this, V3Number::VerilogNumberLiteral{}, "'1"} {
1123 : : initWithNumber();
1124 : : fl->warnOff(V3ErrorCode::NEWERSTD, true);
1125 : : }
1126 : : class Null {};
1127 : : AstConst(FileLine* fl, Null)
1128 : : : ASTGEN_SUPER_Const(fl)
1129 : : , m_num{this, V3Number::Null{}} {
1130 : : dtypeSetBit(); // Events 1 bit, objects 64 bits, so autoExtend=1 and use bit here
1131 : : initWithNumber();
1132 : : }
1133 : : class OneStep {};
1134 : : AstConst(FileLine* fl, OneStep)
1135 : : : ASTGEN_SUPER_Const(fl)
1136 : : , m_num{this, V3Number::OneStep{}} {
1137 : : dtypeSetBitSized(64, VSigning::UNSIGNED);
1138 : : initWithNumber();
1139 : : }
1140 : : ASTGEN_MEMBERS_AstConst;
1141 : : string name() const override VL_MT_STABLE { return num().ascii(); } // * = Value
1142 : : const V3Number& num() const VL_MT_SAFE { return m_num; } // * = Value
1143 : : V3Number& num() { return m_num; } // * = Value
1144 : : uint32_t toUInt() const { return num().toUInt(); }
1145 : : int32_t toSInt() const VL_MT_SAFE { return num().toSInt(); }
1146 : : uint64_t toUQuad() const { return num().toUQuad(); }
1147 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
1148 : : string emitC() override { V3ERROR_NA_RETURN(""); }
1149 : : bool cleanOut() const override { return true; }
1150 : : bool sameNode(const AstNode* samep) const override {
1151 : : const AstConst* const sp = VN_DBG_AS(samep, Const);
1152 : : return num().isCaseEq(sp->num());
1153 : : }
1154 : : void cloneRelink() override { m_num.nodep(this); }
1155 : : const char* broken() const override {
1156 : : BROKEN_RTN(m_num.nodep() && m_num.nodep() != this);
1157 : : return nullptr;
1158 : : }
1159 : : int instrCount() const override { return widthInstrs(); }
1160 : : bool isEqAllOnes() const { return num().isEqAllOnes(width()); }
1161 : : bool isEqAllOnesV() const { return num().isEqAllOnes(widthMinV()); }
1162 : : // Parse string and create appropriate type of AstConst.
1163 : : // May return nullptr on parse failure.
1164 : : static AstConst* parseParamLiteral(FileLine* fl, const string& literal);
1165 : : };
1166 : : class AstConstraintRef final : public AstNodeExpr {
1167 : : // A reference to a constraint identifier
1168 : : // @astgen op1 := fromp : Optional[AstNodeExpr]
1169 : : //
1170 : : // @astgen ptr := m_constrp : AstConstraint // The constraint pointed to
1171 : : // @astgen ptr := m_classOrPackagep : Optional[AstNodeModule] // Class/package of constraint
1172 : :
1173 : : public:
1174 : : AstConstraintRef(FileLine* fl, AstNodeExpr* fromp, AstConstraint* constrp)
1175 : : : ASTGEN_SUPER_ConstraintRef(fl) {
1176 : : this->fromp(fromp);
1177 : : this->constrp(constrp);
1178 : : dtypep(findConstraintRefDType());
1179 : : }
1180 : : ASTGEN_MEMBERS_AstConstraintRef;
1181 : : string name() const override VL_MT_STABLE;
1182 : : AstConstraint* constrp() const VL_MT_STABLE { return m_constrp; }
1183 : : void constrp(AstConstraint* nodep) { m_constrp = nodep; }
1184 : : AstNodeModule* classOrPackagep() const VL_MT_STABLE { return m_classOrPackagep; }
1185 : : // TODO: this setter is unused
1186 : : void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; }
1187 : :
1188 : : string emitVerilog() final override { V3ERROR_NA_RETURN(""); }
1189 : : string emitC() final override { V3ERROR_NA_RETURN(""); }
1190 : : bool cleanOut() const final override { V3ERROR_NA_RETURN(true); }
1191 : : };
1192 : : class AstCvtArrayToArray final : public AstNodeExpr {
1193 : : // Copy/Cast from dynamic/unpacked types to dynamic/unpacked types
1194 : : // @astgen op1 := fromp : AstNodeExpr
1195 : : private:
1196 : : const bool m_reverse; // whether ordering gets reversed in this operation (ex: {<<{expr}})
1197 : : const int m_blockSize; // num bits per block in a streaming operation (ex: 4 in {<<4{expr}}))
1198 : : const int m_dstElementBits; // num bits in lhs (ex: 8 if to byte-queue, 1 if to bit-queue)
1199 : : const int m_srcElementBits; // num bits in rhs (ex 8 if from byte-queue, 1 if from bit-queue)
1200 : :
1201 : : public:
1202 : : // cppcheck-suppress constParameterPointer
1203 : : // cppcheck-suppress constParameterCallback
1204 : : AstCvtArrayToArray(FileLine* fl, AstNodeExpr* fromp, AstNodeDType* dtp, bool reverse,
1205 : : int blockSize, int dstElementBits, int srcElementBits)
1206 : : : ASTGEN_SUPER_CvtArrayToArray(fl)
1207 : : , m_reverse{reverse}
1208 : : , m_blockSize{blockSize}
1209 : : , m_dstElementBits{dstElementBits}
1210 : : , m_srcElementBits{srcElementBits} {
1211 : : this->fromp(fromp);
1212 : : dtypeFrom(dtp);
1213 : : }
1214 : : ASTGEN_MEMBERS_AstCvtArrayToArray;
1215 : : void dump(std::ostream& str) const override;
1216 : : void dumpJson(std::ostream& str) const override;
1217 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
1218 : : string emitC() override { V3ERROR_NA_RETURN(""); }
1219 : : bool cleanOut() const override { return true; }
1220 : : bool reverse() const { return m_reverse; }
1221 : : int blockSize() const { return m_blockSize; }
1222 : : int dstElementBits() const { return m_dstElementBits; }
1223 : : int srcElementBits() const { return m_srcElementBits; }
1224 : : };
1225 : : class AstCvtArrayToPacked final : public AstNodeExpr {
1226 : : // Cast from dynamic queue data type to packed array
1227 : : // @astgen op1 := fromp : AstNodeExpr
1228 : : public:
1229 : : // cppcheck-suppress constParameterPointer
1230 : : // cppcheck-suppress constParameterCallback
1231 : : AstCvtArrayToPacked(FileLine* fl, AstNodeExpr* fromp, AstNodeDType* dtp)
1232 : : : ASTGEN_SUPER_CvtArrayToPacked(fl) {
1233 : : this->fromp(fromp);
1234 : : dtypeFrom(dtp);
1235 : : }
1236 : : ASTGEN_MEMBERS_AstCvtArrayToPacked;
1237 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
1238 : : string emitC() override { V3ERROR_NA_RETURN(""); }
1239 : : bool cleanOut() const override { return true; }
1240 : : };
1241 : : class AstCvtPackedToArray final : public AstNodeExpr {
1242 : : // Cast from packed array to dynamic/unpacked queue data type
1243 : : // @astgen op1 := fromp : AstNodeExpr
1244 : : public:
1245 : : // cppcheck-suppress constParameterPointer
1246 : : // cppcheck-suppress constParameterCallback
1247 : : AstCvtPackedToArray(FileLine* fl, AstNodeExpr* fromp, AstNodeDType* dtp)
1248 : : : ASTGEN_SUPER_CvtPackedToArray(fl) {
1249 : : this->fromp(fromp);
1250 : : dtypeFrom(dtp);
1251 : : }
1252 : : ASTGEN_MEMBERS_AstCvtPackedToArray;
1253 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
1254 : : string emitC() override { V3ERROR_NA_RETURN(""); }
1255 : : bool cleanOut() const override { return true; }
1256 : : };
1257 : : class AstCvtUnpackedToQueue final : public AstNodeExpr {
1258 : : // Cast from unpacked array to dynamic/unpacked queue data type
1259 : : // @astgen op1 := fromp : AstNodeExpr
1260 : : public:
1261 : : // cppcheck-suppress constParameterPointer
1262 : : // cppcheck-suppress constParameterCallback
1263 : : AstCvtUnpackedToQueue(FileLine* fl, AstNodeExpr* fromp, AstNodeDType* dtp)
1264 : : : ASTGEN_SUPER_CvtUnpackedToQueue(fl) {
1265 : : this->fromp(fromp);
1266 : : dtypeFrom(dtp);
1267 : : }
1268 : : ASTGEN_MEMBERS_AstCvtUnpackedToQueue;
1269 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
1270 : : string emitC() override { return "VL_CVT_UNPACK_TO_Q(%P, %li)"; }
1271 : : bool cleanOut() const override { return true; }
1272 : : };
1273 : : class AstDist final : public AstNodeExpr {
1274 : : // @astgen op1 := exprp : AstNodeExpr
1275 : : // @astgen op2 := itemsp : List[AstDistItem]
1276 : : public:
1277 : : AstDist(FileLine* fl, AstNodeExpr* exprp, AstDistItem* itemsp)
1278 : : : ASTGEN_SUPER_Dist(fl) {
1279 : : this->exprp(exprp);
1280 : : addItemsp(itemsp);
1281 : : dtypeSetBit();
1282 : : }
1283 : : ASTGEN_MEMBERS_AstDist;
1284 : : string emitVerilog() override { return "%l dist { %r }"; }
1285 : : string emitC() override { V3ERROR_NA_RETURN(""); }
1286 : : bool cleanOut() const override { return false; } // NA
1287 : : };
1288 : : class AstDistItem final : public AstNodeExpr {
1289 : : // Constraint distribution item
1290 : : // @astgen op1 := rangep : AstNodeExpr
1291 : : // @astgen op2 := weightp : AstNodeExpr
1292 : : bool m_isWhole = false; // True for weight ':/', false for ':='
1293 : : public:
1294 : : AstDistItem(FileLine* fl, AstNodeExpr* rangep, AstNodeExpr* weightp)
1295 : : : ASTGEN_SUPER_DistItem(fl) {
1296 : : this->rangep(rangep);
1297 : : this->weightp(weightp);
1298 : : }
1299 : : ASTGEN_MEMBERS_AstDistItem;
1300 : : string emitVerilog() override { return "%l "s + (m_isWhole ? ":/" : ":=") + " %r"; }
1301 : : string emitC() override { V3ERROR_NA_RETURN(""); }
1302 : : bool cleanOut() const override { return false; } // NA
1303 : : void isWhole(bool flag) { m_isWhole = flag; }
1304 : : bool isWhole() const { return m_isWhole; }
1305 : : };
1306 : : class AstDot final : public AstNodeExpr {
1307 : : // A dot separating paths in an AstVarXRef, AstFuncRef or AstTaskRef
1308 : : // These are eliminated in the link stage
1309 : : // @astgen op1 := lhsp : AstNode<AstNodeExpr|AstNodeDType>
1310 : : // @astgen op2 := rhsp : AstNode<AstNodeExpr|AstNodeDType>
1311 : : //
1312 : : // We don't have a list of elements as it's probably legal to do '(foo.bar).(baz.bap)'
1313 : : const bool m_colon; // Is a "::" instead of a "." (lhs must be package/class)
1314 : : public:
1315 : : AstDot(FileLine* fl, bool colon, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
1316 : : : ASTGEN_SUPER_Dot(fl)
1317 : : , m_colon{colon} {
1318 : : this->lhsp(lhsp);
1319 : : this->rhsp(rhsp);
1320 : : }
1321 : : ASTGEN_MEMBERS_AstDot;
1322 : : // For parser, make only if non-null package
1323 : : static AstNodeExpr* newIfPkg(FileLine* fl, AstNodeExpr* packageOrClassp, AstNodeExpr* rhsp) {
1324 : : if (!packageOrClassp) return rhsp;
1325 : : return new AstDot{fl, true, packageOrClassp, rhsp};
1326 : : }
1327 : : void dump(std::ostream& str) const override;
1328 : : void dumpJson(std::ostream& str) const override;
1329 : : bool colon() const { return m_colon; }
1330 : :
1331 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
1332 : : string emitC() override { V3ERROR_NA_RETURN(""); }
1333 : : bool cleanOut() const override { V3ERROR_NA_RETURN(true); }
1334 : : };
1335 : : class AstEmptyQueue final : public AstNodeExpr {
1336 : : public:
1337 : : explicit AstEmptyQueue(FileLine* fl)
1338 : : : ASTGEN_SUPER_EmptyQueue(fl) {}
1339 : : ASTGEN_MEMBERS_AstEmptyQueue;
1340 : : string emitC() override { V3ERROR_NA_RETURN(""); }
1341 : : string emitVerilog() override { return "{}"; }
1342 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
1343 : : bool cleanOut() const override { return true; }
1344 : : };
1345 : : class AstEnumItemRef final : public AstNodeExpr {
1346 : : // @astgen ptr := m_itemp : Optional[AstEnumItem] // [AfterLink] Pointer to item
1347 : : // @astgen ptr := m_classOrPackagep : Optional[AstNodeModule] // Class/package defined in
1348 : : string m_name; // Name of enum (for param relink)
1349 : : public:
1350 : : AstEnumItemRef(FileLine* fl, AstEnumItem* itemp, AstNodeModule* classOrPackagep)
1351 : : : ASTGEN_SUPER_EnumItemRef(fl)
1352 : : , m_name{itemp->name()}
1353 : : , m_itemp{itemp}
1354 : : , m_classOrPackagep{classOrPackagep} {
1355 : : dtypeFrom(m_itemp);
1356 : : }
1357 : : ASTGEN_MEMBERS_AstEnumItemRef;
1358 : : void dump(std::ostream& str) const override;
1359 : : void dumpJson(std::ostream& str) const override;
1360 : : const char* broken() const override;
1361 : : string name() const override VL_MT_STABLE { return itemp() ? itemp()->name() : m_name; }
1362 : : int instrCount() const override { return 0; }
1363 : : bool sameNode(const AstNode* samep) const override {
1364 : : const AstEnumItemRef* const sp = VN_DBG_AS(samep, EnumItemRef);
1365 : : return itemp() == sp->itemp();
1366 : : }
1367 : : AstEnumItem* itemp() const VL_MT_STABLE { return m_itemp; }
1368 : : void itemp(AstEnumItem* nodep) { m_itemp = nodep; }
1369 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
1370 : : string emitC() override { V3ERROR_NA_RETURN(""); }
1371 : : bool cleanOut() const override { return true; }
1372 : : AstNodeModule* classOrPackagep() const { return m_classOrPackagep; }
1373 : : void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; }
1374 : : };
1375 : : class AstExprStmt final : public AstNodeExpr {
1376 : : // Perform a statement, often assignment inside an expression node,
1377 : : // the parent gets passed the 'resultp()'.
1378 : : // resultp is evaluated AFTER the statement(s).
1379 : : // @astgen op1 := stmtsp : List[AstNode]
1380 : : // @astgen op2 := resultp : AstNodeExpr
1381 : : private:
1382 : : bool m_hasResult = true;
1383 : :
1384 : : public:
1385 : : AstExprStmt(FileLine* fl, AstNode* stmtsp, AstNodeExpr* resultp)
1386 : : : ASTGEN_SUPER_ExprStmt(fl) {
1387 : : addStmtsp(stmtsp);
1388 : : this->resultp(resultp);
1389 : : dtypeFrom(resultp);
1390 : : }
1391 : : ASTGEN_MEMBERS_AstExprStmt;
1392 : : // METHODS
1393 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
1394 : : string emitC() override { V3ERROR_NA_RETURN(""); }
1395 : : bool cleanOut() const override { return true; }
1396 : : bool isPure() override {
1397 : : if (AstNode::afterCommentp(stmtsp())) return false;
1398 : : return resultp()->isPure();
1399 : : }
1400 : : bool sameNode(const AstNode*) const override { return true; }
1401 : : bool hasResult() const { return m_hasResult; }
1402 : : void hasResult(bool flag) { m_hasResult = flag; }
1403 : : };
1404 : : class AstFError final : public AstNodeExpr {
1405 : : // @astgen op1 := filep : AstNodeExpr
1406 : : // @astgen op2 := strp : AstNodeExpr
1407 : : public:
1408 : : AstFError(FileLine* fl, AstNodeExpr* filep, AstNodeExpr* strp)
1409 : : : ASTGEN_SUPER_FError(fl) {
1410 : : this->filep(filep);
1411 : : this->strp(strp);
1412 : : }
1413 : : ASTGEN_MEMBERS_AstFError;
1414 : : string emitVerilog() override { return "%f$ferror(%l, %r)"; }
1415 : : string emitC() override { V3ERROR_NA_RETURN(""); }
1416 : : bool cleanOut() const override { return true; }
1417 : : int instrCount() const override { return widthInstrs() * 64; }
1418 : : bool isPredictOptimizable() const override { return false; }
1419 : : bool isPure() override { return false; } // SPECIAL: $display has 'visual' ordering
1420 : : bool isSystemFunc() const override { return true; }
1421 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
1422 : : };
1423 : : class AstFOpen final : public AstNodeExpr {
1424 : : // @astgen op2 := filenamep : AstNodeExpr
1425 : : // @astgen op3 := modep : AstNodeExpr
1426 : : public:
1427 : : AstFOpen(FileLine* fl, AstNodeExpr* filenamep, AstNodeExpr* modep)
1428 : : : ASTGEN_SUPER_FOpen(fl) {
1429 : : this->filenamep(filenamep);
1430 : : this->modep(modep);
1431 : : }
1432 : : ASTGEN_MEMBERS_AstFOpen;
1433 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
1434 : : string emitC() override { V3ERROR_NA_RETURN(""); }
1435 : : bool cleanOut() const override { return true; }
1436 : : string verilogKwd() const override { return "$fopen"; }
1437 : : bool isGateOptimizable() const override { return false; }
1438 : : bool isPredictOptimizable() const override { return false; }
1439 : : bool isPure() override { return false; }
1440 : : bool isOutputter() override { return true; }
1441 : : bool isUnlikely() const override { return true; }
1442 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
1443 : : bool isSystemFunc() const override { return true; }
1444 : : };
1445 : : class AstFOpenMcd final : public AstNodeExpr {
1446 : : // @astgen op2 := filenamep : AstNodeExpr
1447 : : public:
1448 : : AstFOpenMcd(FileLine* fl, AstNodeExpr* filenamep)
1449 : : : ASTGEN_SUPER_FOpenMcd(fl) {
1450 : : this->filenamep(filenamep);
1451 : : }
1452 : : ASTGEN_MEMBERS_AstFOpenMcd;
1453 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
1454 : : string emitC() override { V3ERROR_NA_RETURN(""); }
1455 : : bool cleanOut() const override { return true; }
1456 : : string verilogKwd() const override { return "$fopen"; }
1457 : : bool isGateOptimizable() const override { return false; }
1458 : : bool isPredictOptimizable() const override { return false; }
1459 : : bool isPure() override { return false; }
1460 : : bool isOutputter() override { return true; }
1461 : : bool isUnlikely() const override { return true; }
1462 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
1463 : : };
1464 : : class AstFRead final : public AstNodeExpr {
1465 : : // @astgen op1 := memp : AstNodeExpr // VarRef for result
1466 : : // @astgen op2 := filep : AstNodeExpr // file (must be a VarRef)
1467 : : // @astgen op3 := startp : Optional[AstNodeExpr] // Offset
1468 : : // @astgen op4 := countp : Optional[AstNodeExpr] // Size
1469 : : public:
1470 : : AstFRead(FileLine* fl, AstNodeExpr* memp, AstNodeExpr* filep, AstNodeExpr* startp,
1471 : : AstNodeExpr* countp)
1472 : : : ASTGEN_SUPER_FRead(fl) {
1473 : : this->memp(memp);
1474 : : this->filep(filep);
1475 : : this->startp(startp);
1476 : : this->countp(countp);
1477 : : }
1478 : : ASTGEN_MEMBERS_AstFRead;
1479 : : string verilogKwd() const override { return "$fread"; }
1480 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
1481 : : string emitC() override { V3ERROR_NA_RETURN(""); }
1482 : : bool isGateOptimizable() const override { return false; }
1483 : : bool isPredictOptimizable() const override { return false; }
1484 : : bool isPure() override { return false; } // SPECIAL: has 'visual' ordering
1485 : : bool isOutputter() override { return true; } // SPECIAL: makes output
1486 : : bool cleanOut() const override { return false; }
1487 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
1488 : : bool isSystemFunc() const override { return true; }
1489 : : };
1490 : : class AstFRewind final : public AstNodeExpr {
1491 : : // @astgen op1 := filep : Optional[AstNodeExpr]
1492 : : public:
1493 : : AstFRewind(FileLine* fl, AstNodeExpr* filep)
1494 : : : ASTGEN_SUPER_FRewind(fl) {
1495 : : this->filep(filep);
1496 : : }
1497 : : ASTGEN_MEMBERS_AstFRewind;
1498 : : string verilogKwd() const override { return "$frewind"; }
1499 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
1500 : : string emitC() override { V3ERROR_NA_RETURN(""); }
1501 : : bool isGateOptimizable() const override { return false; }
1502 : : bool isPredictOptimizable() const override { return false; }
1503 : : bool isPure() override { return false; }
1504 : : bool isOutputter() override { return true; }
1505 : : bool isUnlikely() const override { return true; }
1506 : : bool cleanOut() const override { return false; }
1507 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
1508 : : };
1509 : : class AstFScanF final : public AstNodeExpr {
1510 : : // @astgen op1 := exprsp : List[AstNodeExpr] // VarRefs for results
1511 : : // @astgen op2 := filep : Optional[AstNodeExpr] // file (must be a VarRef)
1512 : : string m_text;
1513 : :
1514 : : public:
1515 : : AstFScanF(FileLine* fl, const string& text, AstNodeExpr* filep, AstNodeExpr* exprsp)
1516 : : : ASTGEN_SUPER_FScanF(fl)
1517 : : , m_text{text} {
1518 : : addExprsp(exprsp);
1519 : : this->filep(filep);
1520 : : }
1521 : : ASTGEN_MEMBERS_AstFScanF;
1522 : : string name() const override VL_MT_STABLE { return m_text; }
1523 : : string verilogKwd() const override { return "$fscanf"; }
1524 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
1525 : : string emitC() override { V3ERROR_NA_RETURN(""); }
1526 : : bool isGateOptimizable() const override { return false; }
1527 : : bool isPredictOptimizable() const override { return false; }
1528 : : bool isPure() override { return false; } // SPECIAL: has 'visual' ordering
1529 : : bool isOutputter() override { return true; } // SPECIAL: makes output
1530 : : bool cleanOut() const override { return false; }
1531 : : bool sameNode(const AstNode* samep) const override {
1532 : : return text() == VN_DBG_AS(samep, FScanF)->text();
1533 : : }
1534 : : string text() const { return m_text; } // * = Text to display
1535 : : void text(const string& text) { m_text = text; }
1536 : : bool isSystemFunc() const override { return true; }
1537 : : };
1538 : : class AstFSeek final : public AstNodeExpr {
1539 : : // @astgen op1 := filep : AstNodeExpr // file (must be a VarRef)
1540 : : // @astgen op2 := offset : Optional[AstNodeExpr]
1541 : : // @astgen op3 := operation : Optional[AstNodeExpr]
1542 : : public:
1543 : : AstFSeek(FileLine* fl, AstNodeExpr* filep, AstNodeExpr* offset, AstNodeExpr* operation)
1544 : : : ASTGEN_SUPER_FSeek(fl) {
1545 : : this->filep(filep);
1546 : : this->offset(offset);
1547 : : this->operation(operation);
1548 : : }
1549 : : ASTGEN_MEMBERS_AstFSeek;
1550 : : string verilogKwd() const override { return "$fseek"; }
1551 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
1552 : : string emitC() override { V3ERROR_NA_RETURN(""); }
1553 : : bool isGateOptimizable() const override { return false; }
1554 : : bool isPredictOptimizable() const override { return false; }
1555 : : bool isPure() override { return false; } // SPECIAL: has 'visual' ordering
1556 : : bool isOutputter() override { return true; } // SPECIAL: makes output
1557 : : bool cleanOut() const override { return false; }
1558 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
1559 : : bool isSystemFunc() const override { return true; }
1560 : : };
1561 : : class AstFTell final : public AstNodeExpr {
1562 : : // @astgen op1 := filep : AstNodeExpr // file (must be a VarRef)
1563 : : public:
1564 : : AstFTell(FileLine* fl, AstNodeExpr* filep)
1565 : : : ASTGEN_SUPER_FTell(fl) {
1566 : : this->filep(filep);
1567 : : }
1568 : : ASTGEN_MEMBERS_AstFTell;
1569 : : string verilogKwd() const override { return "$ftell"; }
1570 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
1571 : : string emitC() override { V3ERROR_NA_RETURN(""); }
1572 : : bool isGateOptimizable() const override { return false; }
1573 : : bool isPredictOptimizable() const override { return false; }
1574 : : bool isPure() override { return false; }
1575 : : bool isOutputter() override { return true; }
1576 : : bool isUnlikely() const override { return true; }
1577 : : bool cleanOut() const override { return false; }
1578 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
1579 : : bool isSystemFunc() const override { return true; }
1580 : : };
1581 : : class AstFalling final : public AstNodeExpr {
1582 : : // Verilog $falling_gclk
1583 : : // @astgen op1 := exprp : AstNodeExpr
1584 : : public:
1585 : : AstFalling(FileLine* fl, AstNodeExpr* exprp)
1586 : : : ASTGEN_SUPER_Falling(fl) {
1587 : : this->exprp(exprp);
1588 : : }
1589 : : ASTGEN_MEMBERS_AstFalling;
1590 : : string emitVerilog() override { return "$falling_gclk(%l)"; }
1591 : : string emitC() override { V3ERROR_NA_RETURN(""); }
1592 : : string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
1593 : : bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
1594 : : int instrCount() const override { return widthInstrs(); }
1595 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
1596 : : bool isSystemFunc() const override { return true; }
1597 : : };
1598 : : class AstFell final : public AstNodeExpr {
1599 : : // Verilog $fell
1600 : : // @astgen op1 := exprp : AstNodeExpr
1601 : : // @astgen op2 := sentreep : Optional[AstSenTree]
1602 : : public:
1603 : : AstFell(FileLine* fl, AstNodeExpr* exprp, AstSenTree* sentreep)
1604 : : : ASTGEN_SUPER_Fell(fl) {
1605 : : this->exprp(exprp);
1606 : : this->sentreep(sentreep);
1607 : : }
1608 : : ASTGEN_MEMBERS_AstFell;
1609 : : string emitVerilog() override { return "$fell(%l)"; }
1610 : : string emitC() override { V3ERROR_NA_RETURN(""); }
1611 : : string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
1612 : : bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
1613 : : int instrCount() const override { return widthInstrs(); }
1614 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
1615 : : bool isSystemFunc() const override { return true; }
1616 : : };
1617 : : class AstFuture final : public AstNodeExpr {
1618 : : // Verilog $future_gclk
1619 : : // @astgen op1 := exprp : AstNodeExpr
1620 : : // @astgen op2 := sentreep : Optional[AstSenTree]
1621 : : public:
1622 : : AstFuture(FileLine* fl, AstNodeExpr* exprp, AstSenTree* sentreep)
1623 : : : ASTGEN_SUPER_Future(fl) {
1624 : : this->exprp(exprp);
1625 : : this->sentreep(sentreep);
1626 : : }
1627 : : ASTGEN_MEMBERS_AstFuture;
1628 : : string emitVerilog() override { return "$future_gclk(%l)"; }
1629 : : string emitC() override { V3ERROR_NA_RETURN(""); }
1630 : : string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
1631 : : bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
1632 : : int instrCount() const override { return widthInstrs(); }
1633 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
1634 : : bool isSystemFunc() const override { return true; }
1635 : : };
1636 : : class AstGatePin final : public AstNodeExpr {
1637 : : // Possibly expand a gate primitive input pin value to match the range of the gate primitive
1638 : : // @astgen op1 := exprp : AstNodeExpr // Pin expression
1639 : : // @astgen op2 := rangep : AstRange // Range of pin
1640 : : public:
1641 : : AstGatePin(FileLine* fl, AstNodeExpr* exprp, AstRange* rangep)
1642 : : : ASTGEN_SUPER_GatePin(fl) {
1643 : : this->exprp(exprp);
1644 : : this->rangep(rangep);
1645 : : }
1646 : : ASTGEN_MEMBERS_AstGatePin;
1647 : : string emitVerilog() override { return "%l"; }
1648 : : string emitC() override { V3ERROR_NA_RETURN(""); }
1649 : : bool cleanOut() const override { return true; }
1650 : : };
1651 : : class AstGetInitialRandomSeed final : public AstNodeExpr {
1652 : : // Verilog $get_initial_random_seed()
1653 : : public:
1654 : : explicit AstGetInitialRandomSeed(FileLine* fl)
1655 : : : ASTGEN_SUPER_GetInitialRandomSeed(fl) {
1656 : : dtypeSetSigned32();
1657 : : }
1658 : : ASTGEN_MEMBERS_AstGetInitialRandomSeed;
1659 : : string emitVerilog() override { return "$get_initial_random_seed()"; }
1660 : : string emitC() final override { V3ERROR_NA_RETURN(""); }
1661 : : bool cleanOut() const override { return true; }
1662 : : bool isGateOptimizable() const override { return false; }
1663 : : bool isPredictOptimizable() const override { return true; }
1664 : : bool isPure() override { return true; }
1665 : : bool isSystemFunc() const override { return true; }
1666 : : int instrCount() const override { return INSTR_COUNT_PLI; }
1667 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
1668 : : };
1669 : : class AstImplication final : public AstNodeExpr {
1670 : : // Verilog Implication Operator
1671 : : // Nonoverlapped "|=>"
1672 : : // Overlapped "|->"
1673 : : // @astgen op1 := lhsp : AstNodeExpr
1674 : : // @astgen op2 := rhsp : AstNodeExpr
1675 : : // @astgen op3 := sentreep : Optional[AstSenTree]
1676 : :
1677 : : private:
1678 : : const bool m_isOverlapped; // True if overlapped
1679 : :
1680 : : public:
1681 : : AstImplication(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp, bool isOverlapped)
1682 : : : ASTGEN_SUPER_Implication(fl)
1683 : : , m_isOverlapped{isOverlapped} {
1684 : : this->lhsp(lhsp);
1685 : : this->rhsp(rhsp);
1686 : : }
1687 : : ASTGEN_MEMBERS_AstImplication;
1688 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
1689 : : string emitC() override { V3ERROR_NA_RETURN(""); }
1690 : : string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
1691 : : bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
1692 : : int instrCount() const override { return widthInstrs(); }
1693 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
1694 : : bool isOverlapped() const { return m_isOverlapped; }
1695 : : };
1696 : : class AstInitArray final : public AstNodeExpr {
1697 : : // This is also used as an array value in V3Simulate/const prop.
1698 : : // Would be better called as 'AstConstArray'
1699 : : // Set a var to a map of values
1700 : : // The list of initsp() is not relevant
1701 : : // If default is specified, the vector may be sparse, and not provide each value.
1702 : : // Key values are C++ array style, with lo() at index 0
1703 : : // Parents: ASTVAR::init()
1704 : : // @astgen op1 := defaultp : Optional[AstNodeExpr] // Default, if sparse
1705 : : // @astgen op2 := initsp : List[AstInitItem] // Initial value expressions
1706 : : //
1707 : : public:
1708 : : using KeyItemMap = std::map<uint64_t, AstInitItem*>;
1709 : :
1710 : : private:
1711 : : KeyItemMap m_map; // Node value for each array index
1712 : : // METHODS
1713 : : void dumpInitList(std::ostream& str) const;
1714 : :
1715 : : public:
1716 : : AstInitArray(FileLine* fl, AstNodeDType* newDTypep, AstNodeExpr* defaultp)
1717 : : : ASTGEN_SUPER_InitArray(fl) {
1718 : : dtypep(newDTypep);
1719 : : this->defaultp(defaultp);
1720 : : }
1721 : : ASTGEN_MEMBERS_AstInitArray;
1722 : : void dump(std::ostream& str) const override;
1723 : : void dumpJson(std::ostream& str) const override;
1724 : : const char* broken() const override;
1725 : : void cloneRelink() override;
1726 : : bool sameNode(const AstNode* samep) const override {
1727 : : // Only works if exact same children, instead should override comparison
1728 : : // of children list, and instead use map-vs-map key/value compare
1729 : : return m_map == VN_DBG_AS(samep, InitArray)->m_map;
1730 : : }
1731 : : void addValuep(AstNodeExpr* newp) { addIndexValuep(m_map.size(), newp); }
1732 : : const KeyItemMap& map() const { return m_map; }
1733 : : void addIndexValuep(uint64_t index, AstNodeExpr* newp);
1734 : : AstNodeExpr* getIndexValuep(uint64_t index) const;
1735 : : AstNodeExpr* getIndexDefaultedValuep(uint64_t index) const;
1736 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
1737 : : string emitC() override { V3ERROR_NA_RETURN(""); }
1738 : : bool cleanOut() const override { return true; }
1739 : : };
1740 : : class AstInside final : public AstNodeExpr {
1741 : : // @astgen op1 := exprp : AstNodeExpr
1742 : : // @astgen op2 := itemsp : List[AstNodeExpr]
1743 : : public:
1744 : : AstInside(FileLine* fl, AstNodeExpr* exprp, AstNodeExpr* itemsp)
1745 : : : ASTGEN_SUPER_Inside(fl) {
1746 : : this->exprp(exprp);
1747 : : addItemsp(itemsp);
1748 : : dtypeSetBit();
1749 : : }
1750 : : ASTGEN_MEMBERS_AstInside;
1751 : : string emitVerilog() override { return "%l inside { %r }"; }
1752 : : string emitC() override { V3ERROR_NA_RETURN(""); }
1753 : : bool cleanOut() const override { return false; } // NA
1754 : : };
1755 : : class AstInsideRange final : public AstNodeExpr {
1756 : : // @astgen op1 := lhsp : AstNodeExpr
1757 : : // @astgen op2 := rhsp : AstNodeExpr
1758 : : public:
1759 : : AstInsideRange(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
1760 : : : ASTGEN_SUPER_InsideRange(fl) {
1761 : : this->lhsp(lhsp);
1762 : : this->rhsp(rhsp);
1763 : : }
1764 : : ASTGEN_MEMBERS_AstInsideRange;
1765 : : string emitVerilog() override { return "[%l:%r]"; }
1766 : : string emitC() override { V3ERROR_NA_RETURN(""); }
1767 : : bool cleanOut() const override { return false; } // NA
1768 : : // Create AstAnd(AstGte(...), AstLte(...))
1769 : : AstNodeExpr* newAndFromInside(AstNodeExpr* exprp, AstNodeExpr* lhsp, AstNodeExpr* rhsp);
1770 : : };
1771 : : class AstLambdaArgRef final : public AstNodeExpr {
1772 : : // Lambda argument usage
1773 : : // These are not AstVarRefs because we need to be able to delete/clone lambdas during
1774 : : // optimizations and AstVar's are painful to remove.
1775 : : string m_name; // Name of variable
1776 : : bool m_index; // Index, not value
1777 : :
1778 : : public:
1779 : : AstLambdaArgRef(FileLine* fl, const string& name, bool index)
1780 : : : ASTGEN_SUPER_LambdaArgRef(fl)
1781 : : , m_name{name}
1782 : : , m_index{index} {}
1783 : : ASTGEN_MEMBERS_AstLambdaArgRef;
1784 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
1785 : : string emitVerilog() override { return name(); }
1786 : : string emitC() override { V3ERROR_NA_RETURN(""); }
1787 : : bool cleanOut() const override { return true; }
1788 : : int instrCount() const override { return widthInstrs(); }
1789 : : string name() const override VL_MT_STABLE { return m_name; } // * = Var name
1790 : : void name(const string& name) override { m_name = name; }
1791 : : bool index() const { return m_index; }
1792 : : bool isExprCoverageEligible() const override { return false; }
1793 : : };
1794 : : class AstMatches final : public AstNodeExpr {
1795 : : // "matches" operator: "expr matches pattern"
1796 : : // @astgen op1 := lhsp : AstNodeExpr // Expression to match
1797 : : // @astgen op2 := patternp : AstNode // Pattern to match against
1798 : : public:
1799 : : AstMatches(FileLine* fl, AstNodeExpr* lhsp, AstNode* patternp)
1800 : : : ASTGEN_SUPER_Matches(fl) {
1801 : : this->lhsp(lhsp);
1802 : : this->patternp(patternp);
1803 : : }
1804 : : ASTGEN_MEMBERS_AstMatches;
1805 : : string emitVerilog() override { return "%l matches %r"; }
1806 : : string emitC() override { V3ERROR_NA_RETURN(""); }
1807 : : bool cleanOut() const override { return false; }
1808 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
1809 : : };
1810 : : class AstMemberSel final : public AstNodeExpr {
1811 : : // @astgen op1 := fromp : AstNodeExpr
1812 : : //
1813 : : // @astgen ptr := m_varp : Optional[AstVar] // Post link, variable in class that is selecting
1814 : : // Don't need the class we are extracting from, as the "fromp()"'s datatype can get us to it
1815 : : string m_name;
1816 : : VAccess m_access; // Read or write, as in AstNodeVarRef
1817 : : public:
1818 : : AstMemberSel(FileLine* fl, AstNodeExpr* fromp, VFlagChildDType, const string& name)
1819 : : : ASTGEN_SUPER_MemberSel(fl)
1820 : : , m_name{name} {
1821 : : this->fromp(fromp);
1822 : : dtypep(nullptr); // V3Width will resolve
1823 : : }
1824 : : AstMemberSel(FileLine* fl, AstNodeExpr* fromp, AstVar* varp);
1825 : : ASTGEN_MEMBERS_AstMemberSel;
1826 : : void dump(std::ostream& str) const override;
1827 : : void dumpJson(std::ostream& str) const override;
1828 : : string name() const override VL_MT_STABLE { return m_name; }
1829 : : void name(const string& name) override { m_name = name; }
1830 : : VAccess access() const { return m_access; }
1831 : : void access(const VAccess& flag) { m_access = flag; }
1832 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
1833 : : string emitC() override { V3ERROR_NA_RETURN(""); }
1834 : : bool cleanOut() const override { return true; }
1835 : : bool sameNode(const AstNode* samep) const override;
1836 : : int instrCount() const override { return widthInstrs(); }
1837 : : AstVar* varp() const { return m_varp; }
1838 : : void varp(AstVar* nodep) { m_varp = nodep; }
1839 : : };
1840 : : class AstNewCopy final : public AstNodeExpr {
1841 : : // New as shallow copy
1842 : : // @astgen op1 := rhsp : AstNodeExpr
1843 : : public:
1844 : : AstNewCopy(FileLine* fl, AstNodeExpr* rhsp)
1845 : : : ASTGEN_SUPER_NewCopy(fl) {
1846 : : dtypeFrom(rhsp); // otherwise V3Width will resolve
1847 : : this->rhsp(rhsp);
1848 : : }
1849 : : ASTGEN_MEMBERS_AstNewCopy;
1850 : : string emitVerilog() override { return "new"; }
1851 : : string emitC() override { V3ERROR_NA_RETURN(""); }
1852 : : bool cleanOut() const override { return true; }
1853 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
1854 : : int instrCount() const override { return widthInstrs(); }
1855 : : };
1856 : : class AstNewDynamic final : public AstNodeExpr {
1857 : : // New for dynamic array
1858 : : // @astgen op1 := sizep : AstNodeExpr
1859 : : // @astgen op2 := rhsp : Optional[AstNodeExpr]
1860 : : public:
1861 : : AstNewDynamic(FileLine* fl, AstNodeExpr* sizep, AstNodeExpr* rhsp)
1862 : : : ASTGEN_SUPER_NewDynamic(fl) {
1863 : : dtypeFrom(rhsp); // otherwise V3Width will resolve
1864 : : this->sizep(sizep);
1865 : : this->rhsp(rhsp);
1866 : : }
1867 : : ASTGEN_MEMBERS_AstNewDynamic;
1868 : : string emitVerilog() override { return "new"; }
1869 : : string emitC() override { V3ERROR_NA_RETURN(""); }
1870 : : bool cleanOut() const override { return true; }
1871 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
1872 : : int instrCount() const override { return widthInstrs(); }
1873 : : };
1874 : : class AstPExpr final : public AstNodeExpr {
1875 : : // Property expression
1876 : : // @astgen op1 := bodyp : AstBegin
1877 : : // @astgen op2 := finalp : Optional[AstNodeStmt]
1878 : : public:
1879 : : explicit AstPExpr(FileLine* fl, AstBegin* bodyp, AstNodeDType* dtypep)
1880 : : : ASTGEN_SUPER_PExpr(fl) {
1881 : : this->bodyp(bodyp);
1882 : 28 : this->finalp(nullptr);
1883 : 28 : this->dtypep(dtypep);
1884 : : }
1885 : 7 : explicit AstPExpr(FileLine* fl, AstBegin* bodyp, AstNodeStmt* finalp, AstNodeDType* dtypep)
1886 : 7 : : ASTGEN_SUPER_PExpr(fl) {
1887 : 7 : this->bodyp(bodyp);
1888 : 7 : this->finalp(finalp);
1889 : : this->dtypep(dtypep);
1890 : : }
1891 : : ASTGEN_MEMBERS_AstPExpr;
1892 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
1893 : : string emitC() override { V3ERROR_NA_RETURN(""); }
1894 : : bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
1895 : : int instrCount() const override { return widthInstrs(); }
1896 : : };
1897 : : class AstParseHolder final : public AstNodeExpr {
1898 : : // A reference to something soon to replace, used in a select at parse time
1899 : : // that needs conversion to pull the upper lvalue later
1900 : : public:
1901 : : explicit AstParseHolder(FileLine* fl)
1902 : : : ASTGEN_SUPER_ParseHolder(fl) {}
1903 : : ASTGEN_MEMBERS_AstParseHolder;
1904 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
1905 : : string emitC() override { V3ERROR_NA_RETURN(""); }
1906 : : bool cleanOut() const override { V3ERROR_NA_RETURN(true); }
1907 : : };
1908 : : class AstParseRef final : public AstNodeExpr {
1909 : : // A reference to a variable, function or task
1910 : : // We don't know which at parse time due to bison constraints
1911 : : // The link stages will replace this with AstVarRef, or AstTaskRef, etc.
1912 : : // @astgen op1 := lhsp : Optional[AstNodeExpr]
1913 : : // @astgen op2 := ftaskrefp : Optional[AstNodeFTaskRef]
1914 : :
1915 : : string m_name;
1916 : :
1917 : : public:
1918 : : AstParseRef(FileLine* fl, const string& name, AstNodeExpr* lhsp = nullptr,
1919 : : AstNodeFTaskRef* ftaskrefp = nullptr)
1920 : : : ASTGEN_SUPER_ParseRef(fl)
1921 : : , m_name{name} {
1922 : : this->lhsp(lhsp);
1923 : : this->ftaskrefp(ftaskrefp);
1924 : : }
1925 : : ASTGEN_MEMBERS_AstParseRef;
1926 : : string name() const override VL_MT_STABLE { return m_name; } // * = Var name
1927 : : void name(const string& name) override { m_name = name; }
1928 : : bool sameNode(const AstNode* samep) const override {
1929 : : const AstParseRef* const asamep = VN_DBG_AS(samep, ParseRef);
1930 : : return m_name == asamep->m_name;
1931 : : }
1932 : :
1933 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
1934 : : string emitC() override { V3ERROR_NA_RETURN(""); }
1935 : : bool cleanOut() const override { V3ERROR_NA_RETURN(true); }
1936 : : };
1937 : : class AstPast final : public AstNodeExpr {
1938 : : // Verilog $past
1939 : : // @astgen op1 := exprp : AstNodeExpr
1940 : : // @astgen op2 := ticksp : Optional[AstNodeExpr]
1941 : : // @astgen op3 := sentreep : Optional[AstSenTree]
1942 : : public:
1943 : : AstPast(FileLine* fl, AstNodeExpr* exprp, AstNodeExpr* ticksp = nullptr,
1944 : : AstSenTree* sentreep = nullptr)
1945 : : : ASTGEN_SUPER_Past(fl) {
1946 : : this->exprp(exprp);
1947 : : this->ticksp(ticksp);
1948 : : this->sentreep(sentreep);
1949 : : }
1950 : : ASTGEN_MEMBERS_AstPast;
1951 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
1952 : : string emitC() override { V3ERROR_NA_RETURN(""); }
1953 : : string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
1954 : : bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
1955 : : int instrCount() const override { return widthInstrs(); }
1956 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
1957 : : bool isSystemFunc() const override { return true; }
1958 : : };
1959 : : class AstPatMember final : public AstNodeExpr {
1960 : : // Verilog '{a} or '{a{b}}
1961 : : // Parents: AstPattern
1962 : : // Children: expression, AstPattern, replication count, decoded nodep if TEXT
1963 : : // Expression to assign or another AstPattern (list if replicated)
1964 : : // @astgen op1 := lhssp : List[AstNodeExpr]
1965 : : // @astgen op2 := keyp : Optional[AstNode]
1966 : : // @astgen op3 := repp : Optional[AstNodeExpr] // replication count, or nullptr for count 1
1967 : : // @astgen op4 := varrefp : Optional[AstNodeExpr] // Decoded variable if TEXT
1968 : : bool m_isDefault = false; // Has default
1969 : : bool m_isConcat = false; // From concatenate
1970 : :
1971 : : public:
1972 : : AstPatMember(FileLine* fl, AstNodeExpr* lhssp, AstNode* keyp, AstNodeExpr* repp)
1973 : : : ASTGEN_SUPER_PatMember(fl) {
1974 : : addLhssp(lhssp);
1975 : : this->keyp(keyp);
1976 : : this->repp(repp);
1977 : : }
1978 : : ASTGEN_MEMBERS_AstPatMember;
1979 : : string emitVerilog() override { return lhssp() ? "%f{%r{%k%l}}" : "%l"; }
1980 : : string emitC() override { V3ERROR_NA_RETURN(""); }
1981 : : string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
1982 : : bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
1983 : : int instrCount() const override { return widthInstrs() * 2; }
1984 : : void dump(std::ostream& str = std::cout) const override;
1985 : : void dumpJson(std::ostream& str = std::cout) const override;
1986 : : bool isConcat() const { return m_isConcat; }
1987 : : void isConcat(bool flag) { m_isConcat = flag; }
1988 : : bool isDefault() const { return m_isDefault; }
1989 : : void isDefault(bool flag) { m_isDefault = flag; }
1990 : : };
1991 : : class AstPattern final : public AstNodeExpr {
1992 : : // Verilog '{a,b,c,d...}
1993 : : // Parents: AstNodeAssign, AstPattern, ...
1994 : : // Children: expression, AstPattern, AstPatReplicate
1995 : : // @astgen op1 := childDTypep : Optional[AstNodeDType]
1996 : : // @astgen op2 := itemsp : List[AstNode] // AstPatReplicate, AstPatMember, etc
1997 : : public:
1998 : : AstPattern(FileLine* fl, AstNode* itemsp)
1999 : : : ASTGEN_SUPER_Pattern(fl) {
2000 : : addItemsp(itemsp);
2001 : : }
2002 : : ASTGEN_MEMBERS_AstPattern;
2003 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
2004 : : string emitC() override { V3ERROR_NA_RETURN(""); }
2005 : : string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
2006 : : bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
2007 : : int instrCount() const override { return widthInstrs(); }
2008 : : AstNodeDType* getChildDTypep() const override { return childDTypep(); }
2009 : : AstNodeDType* subDTypep() const VL_MT_STABLE { return dtypep() ? dtypep() : childDTypep(); }
2010 : : };
2011 : : class AstPatternStar final : public AstNodeExpr {
2012 : : // Pattern wildcard: ".*"
2013 : : public:
2014 : : explicit AstPatternStar(FileLine* fl)
2015 : : : ASTGEN_SUPER_PatternStar(fl) {}
2016 : : ASTGEN_MEMBERS_AstPatternStar;
2017 : : string emitVerilog() override { return ".*"; }
2018 : : string emitC() override { V3ERROR_NA_RETURN(""); }
2019 : : bool cleanOut() const override { return false; }
2020 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
2021 : : };
2022 : : class AstPatternVar final : public AstNodeExpr {
2023 : : // Pattern variable binding: ".variable"
2024 : : string m_name; // Variable name
2025 : : public:
2026 : : AstPatternVar(FileLine* fl, const string& name)
2027 : : : ASTGEN_SUPER_PatternVar(fl)
2028 : : , m_name{name} {}
2029 : : ASTGEN_MEMBERS_AstPatternVar;
2030 : : string emitVerilog() override { return ".%k"; }
2031 : : string emitC() override { V3ERROR_NA_RETURN(""); }
2032 : : bool cleanOut() const override { return false; }
2033 : : bool sameNode(const AstNode* samep) const override {
2034 : : return m_name == VN_DBG_AS(samep, PatternVar)->m_name;
2035 : : }
2036 : : string name() const override VL_MT_STABLE { return m_name; }
2037 : : };
2038 : : class AstPropAlways final : public AstNodeExpr {
2039 : : // always[m:n] / s_always[m:n] (IEEE 1800-2023 16.12.11)
2040 : : // @astgen op1 := propp : AstNodeExpr
2041 : : // @astgen op2 := loBoundp : AstNodeExpr
2042 : : // @astgen op3 := hiBoundp : AstNodeExpr
2043 : : const bool m_isStrong = false; // s_always
2044 : : public:
2045 : : AstPropAlways(FileLine* fl, AstNodeExpr* propp, AstNodeExpr* loBoundp, AstNodeExpr* hiBoundp,
2046 : : bool isStrong)
2047 : : : ASTGEN_SUPER_PropAlways(fl)
2048 : : , m_isStrong{isStrong} {
2049 : : this->propp(propp);
2050 : : this->loBoundp(loBoundp);
2051 : : this->hiBoundp(hiBoundp);
2052 : : }
2053 : : ASTGEN_MEMBERS_AstPropAlways;
2054 : : void dump(std::ostream& str) const override;
2055 : : void dumpJson(std::ostream& str) const override;
2056 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
2057 : : string emitC() override { V3ERROR_NA_RETURN(""); }
2058 : : string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
2059 : : bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
2060 : : int instrCount() const override { V3ERROR_NA_RETURN(0); }
2061 : : bool isStrong() const { return m_isStrong; }
2062 : : bool isMultiCycleSva() const override { return true; }
2063 : : };
2064 : : class AstRand final : public AstNodeExpr {
2065 : : // $random/$random(seed) or $urandom/$urandom(seed)
2066 : : // Return a random number, based upon width()
2067 : : // @astgen op1 := seedp : Optional[AstNodeExpr]
2068 : : const bool m_urandom; // $urandom vs $random
2069 : : public:
2070 : : class Reset {};
2071 : : AstRand(FileLine* fl, AstNodeExpr* seedp, bool urandom)
2072 : : : ASTGEN_SUPER_Rand(fl)
2073 : : , m_urandom{urandom} {
2074 : : this->seedp(seedp);
2075 : : }
2076 : : class SRandomU32 {};
2077 : : AstRand(FileLine* fl, SRandomU32)
2078 : : : ASTGEN_SUPER_Rand(fl)
2079 : : , m_urandom{true} {
2080 : : dtypeSetUInt32();
2081 : : }
2082 : : ASTGEN_MEMBERS_AstRand;
2083 : : string emitVerilog() override {
2084 : : return seedp() ? (m_urandom ? "%f$urandom(%l)" : "%f$random(%l)")
2085 : : : (m_urandom ? "%f$urandom()" : "%f$random()");
2086 : : }
2087 : : string emitC() override {
2088 : : if (seedp()) {
2089 : : if (urandom()) return "VL_URANDOM_SEEDED_%nq%lq(%li)";
2090 : : return "VL_RANDOM_SEEDED_%nq%lq(%li)";
2091 : : }
2092 : : if (isWide()) return "VL_RANDOM_%nq(%nw, %P)";
2093 : : return "VL_RANDOM_%nq()";
2094 : : }
2095 : : bool cleanOut() const override { return false; }
2096 : : bool isGateOptimizable() const override { return false; }
2097 : : bool isPredictOptimizable() const override { return false; }
2098 : : bool isPure() override { return !seedp(); }
2099 : : bool isSystemFunc() const override { return true; }
2100 : : int instrCount() const override { return INSTR_COUNT_PLI; }
2101 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
2102 : : bool combinable(const AstRand* samep) const {
2103 : : return !seedp() && !samep->seedp() && urandom() == samep->urandom();
2104 : : }
2105 : : bool urandom() const { return m_urandom; }
2106 : : };
2107 : : class AstRandRNG final : public AstNodeExpr {
2108 : : // Random used in a class using VlRNG
2109 : : // Return a random number, based upon width()
2110 : : public:
2111 : : AstRandRNG(FileLine* fl, AstNodeDType* dtp)
2112 : : : ASTGEN_SUPER_RandRNG(fl) {
2113 : : dtypep(dtp);
2114 : : }
2115 : : ASTGEN_MEMBERS_AstRandRNG;
2116 : : string emitVerilog() override { return "%f$rngrandom()"; }
2117 : : string emitC() override {
2118 : : return isWide() ? "VL_RANDOM_RNG_%nq(__Vm_rng, %nw, %P)" //
2119 : : : "VL_RANDOM_RNG_%nq(__Vm_rng)";
2120 : : }
2121 : : bool cleanOut() const override { return false; }
2122 : : bool isGateOptimizable() const override { return false; }
2123 : : bool isPredictOptimizable() const override { return false; }
2124 : : bool isSystemFunc() const override { return true; }
2125 : : int instrCount() const override { return INSTR_COUNT_PLI; }
2126 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
2127 : : };
2128 : : class AstRising final : public AstNodeExpr {
2129 : : // Verilog $rising_gclk
2130 : : // @astgen op1 := exprp : AstNodeExpr
2131 : : public:
2132 : : AstRising(FileLine* fl, AstNodeExpr* exprp)
2133 : : : ASTGEN_SUPER_Rising(fl) {
2134 : : this->exprp(exprp);
2135 : : }
2136 : : ASTGEN_MEMBERS_AstRising;
2137 : : string emitVerilog() override { return "$rising_gclk(%l)"; }
2138 : : string emitC() override { V3ERROR_NA_RETURN(""); }
2139 : : string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
2140 : : bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
2141 : : int instrCount() const override { return widthInstrs(); }
2142 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
2143 : : bool isSystemFunc() const override { return true; }
2144 : : };
2145 : : class AstRose final : public AstNodeExpr {
2146 : : // Verilog $rose
2147 : : // @astgen op1 := exprp : AstNodeExpr
2148 : : // @astgen op2 := sentreep : Optional[AstSenTree]
2149 : : public:
2150 : : AstRose(FileLine* fl, AstNodeExpr* exprp, AstSenTree* sentreep)
2151 : : : ASTGEN_SUPER_Rose(fl) {
2152 : : this->exprp(exprp);
2153 : : this->sentreep(sentreep);
2154 : : }
2155 : : ASTGEN_MEMBERS_AstRose;
2156 : : string emitVerilog() override { return "$rose(%l)"; }
2157 : : string emitC() override { V3ERROR_NA_RETURN(""); }
2158 : : string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
2159 : : bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
2160 : : int instrCount() const override { return widthInstrs(); }
2161 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
2162 : : bool isSystemFunc() const override { return true; }
2163 : : };
2164 : : class AstSConsRep final : public AstNodeExpr {
2165 : : // Consecutive repetition [*N], [*N:M], [+], [*] (IEEE 1800-2023 16.9.2)
2166 : : // op1 := exprp -- the repeated expression
2167 : : // op2 := countp -- min repetition count (N); always a positive constant after V3Width
2168 : : // op3 := maxCountp -- max repetition count (M); nullptr when exact or unbounded
2169 : : //
2170 : : // Encoding:
2171 : : // [*N]: countp=N, maxCountp=nullptr, unbounded=false
2172 : : // [*N:M]: countp=N, maxCountp=M, unbounded=false
2173 : : // [+]: countp=1, maxCountp=nullptr, unbounded=true (= [*1:$])
2174 : : // [*]: countp=0, maxCountp=nullptr, unbounded=true (= [*0:$])
2175 : : //
2176 : : // Lowering:
2177 : : // Exact [*N] standalone: V3AssertPre saturating counter
2178 : : // All other forms and all SExpr-contained forms: V3AssertProp PExpr loop
2179 : : // @astgen op1 := exprp : AstNodeExpr
2180 : : // @astgen op2 := countp : AstNodeExpr
2181 : : // @astgen op3 := maxCountp : Optional[AstNodeExpr]
2182 : : const bool m_unbounded = false; // True for [+] and [*] (upper bound is $)
2183 : : public:
2184 : : // Exact [*N]
2185 : : AstSConsRep(FileLine* fl, AstNodeExpr* exprp, AstNodeExpr* countp)
2186 : : : ASTGEN_SUPER_SConsRep(fl) {
2187 : : this->exprp(exprp);
2188 : : this->countp(countp);
2189 : : }
2190 : : // Range [*N:M] or unbounded [+]/[*]
2191 : : AstSConsRep(FileLine* fl, AstNodeExpr* exprp, AstNodeExpr* countp, AstNodeExpr* maxCountp,
2192 : : bool unbounded)
2193 : : : ASTGEN_SUPER_SConsRep(fl)
2194 : : , m_unbounded{unbounded} {
2195 : : this->exprp(exprp);
2196 : : this->countp(countp);
2197 : : this->maxCountp(maxCountp);
2198 : : }
2199 : : ASTGEN_MEMBERS_AstSConsRep;
2200 : : void dump(std::ostream& str) const override;
2201 : : void dumpJson(std::ostream& str) const override;
2202 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
2203 : : string emitC() override { V3ERROR_NA_RETURN(""); }
2204 : : string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
2205 : : bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
2206 : : int instrCount() const override { V3ERROR_NA_RETURN(0); }
2207 : : bool sameNode(const AstNode* samep) const override { // LCOV_EXCL_LINE
2208 : : return m_unbounded == VN_DBG_AS(samep, SConsRep)->m_unbounded; // LCOV_EXCL_LINE
2209 : : }
2210 : : bool unbounded() const { return m_unbounded; }
2211 : : bool isMultiCycleSva() const override { return true; }
2212 : : };
2213 : : class AstSEventually final : public AstNodeExpr {
2214 : : // s_eventually
2215 : : // @astgen op1 := exprp : AstNodeExpr
2216 : : public:
2217 : 28 : explicit AstSEventually(FileLine* fl, AstNodeExpr* exprp)
2218 : 28 : : ASTGEN_SUPER_SEventually(fl) {
2219 : 28 : this->exprp(exprp);
2220 : : }
2221 : : ASTGEN_MEMBERS_AstSEventually;
2222 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
2223 : : string emitC() override { V3ERROR_NA_RETURN(""); }
2224 : : bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
2225 : 0 : int instrCount() const override { return widthInstrs(); }
2226 : : };
2227 : : class AstSExpr final : public AstNodeExpr {
2228 : : // Sequence expression
2229 : : // @astgen op1 := preExprp: Optional[AstNodeExpr]
2230 : : // @astgen op2 := delayp : AstNodeStmt<AstDelay|AstBegin>
2231 : : // @astgen op3 := exprp : AstNodeExpr
2232 : : public:
2233 : : explicit AstSExpr(FileLine* fl, AstNodeExpr* preExprp, AstNodeStmt* delayp, AstNodeExpr* exprp)
2234 : : : ASTGEN_SUPER_SExpr(fl) {
2235 : : this->preExprp(preExprp);
2236 : : this->delayp(delayp);
2237 : : this->exprp(exprp);
2238 : : }
2239 : : explicit AstSExpr(FileLine* fl, AstNodeStmt* delayp, AstNodeExpr* exprp)
2240 : : : ASTGEN_SUPER_SExpr(fl) {
2241 : : this->preExprp(nullptr);
2242 : : this->delayp(delayp);
2243 : : this->exprp(exprp);
2244 : : }
2245 : : ASTGEN_MEMBERS_AstSExpr;
2246 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
2247 : : string emitC() override { V3ERROR_NA_RETURN(""); }
2248 : : bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
2249 : : int instrCount() const override { return widthInstrs(); }
2250 : : bool isMultiCycleSva() const override { return true; }
2251 : : };
2252 : : class AstSFormatArg final : public AstNodeExpr {
2253 : : // Information for formatting each argument to AstSFormat,
2254 : : // used to pass to (potentially) runtime decoding of format arguments
2255 : : // PARENT: SFormatF (or next list of expressions)
2256 : : // @astgen op1 := exprp : AstNodeExpr
2257 : : VFormatAttr m_formatAttr; // How to format expression
2258 : :
2259 : : public:
2260 : : AstSFormatArg(FileLine* fl, VFormatAttr formatAttr, AstNodeExpr* exprp)
2261 : : : ASTGEN_SUPER_SFormatArg(fl)
2262 : : , m_formatAttr{formatAttr} {
2263 : : dtypeFrom(exprp);
2264 : : this->exprp(exprp);
2265 : : }
2266 : : ASTGEN_MEMBERS_AstSFormatArg;
2267 : : void dump(std::ostream& str = std::cout) const override;
2268 : : void dumpJson(std::ostream& str = std::cout) const override;
2269 : : int instrCount() const override { return 0; }
2270 : : bool sameNode(const AstNode* samep) const override {
2271 : : return formatAttr() == VN_DBG_AS(samep, SFormatArg)->formatAttr();
2272 : : }
2273 : : string verilogKwd() const override { return "$sformatarg"; }
2274 : : string emitVerilog() override { return "%l"; }
2275 : : string emitC() override { V3ERROR_NA_RETURN(""); }
2276 : : bool cleanOut() const override { return true; }
2277 : : const char* broken() const override {
2278 : : BROKEN_RTN(!VN_IS(backp(), SFormatF) && firstAbovep()); // In list under SFormatF
2279 : : return nullptr;
2280 : : }
2281 : : VFormatAttr formatAttr() const { return m_formatAttr; }
2282 : : void formatAttr(const VFormatAttr& formatAttr) { m_formatAttr = formatAttr; }
2283 : : static VFormatAttr formatAttrDefauled(const AstSFormatArg* nodep, const AstNodeDType* dtypep);
2284 : : };
2285 : : class AstSFormatF final : public AstNodeExpr {
2286 : : // Convert format to string, generally under an AstDisplay or AstSFormat
2287 : : // Also used as "real" function for /*verilator sformat*/ functions
2288 : : // exprsp() once past parsing may be AstSFormatArgs
2289 : : // @astgen op1 := exprsp : List[AstNodeExpr]
2290 : : // @astgen op2 := scopeNamep : Optional[AstScopeName]
2291 : : string m_text;
2292 : : const bool m_hidden; // Under display, etc
2293 : : bool m_exprFormat
2294 : : = false; // Runtime Node* format, false = text() format code, false = possibly r
2295 : : bool m_optionalFormat
2296 : : = false; // With exprFormat, first argument is either format or format-implied
2297 : : const char m_missingArgChar; // Format code when argument without format, 'h'/'o'/'b'
2298 : : VTimescale m_timeunit; // Parent module time unit
2299 : : public:
2300 : : class ExprFormat {};
2301 : : AstSFormatF(FileLine* fl, const string& text, bool hidden, AstNodeExpr* exprsp,
2302 : : char missingArgChar = 'd')
2303 : : : ASTGEN_SUPER_SFormatF(fl)
2304 : : , m_text{text}
2305 : : , m_hidden{hidden}
2306 : : , m_missingArgChar{missingArgChar} {
2307 : : dtypeSetString();
2308 : : addExprsp(exprsp);
2309 : : }
2310 : : AstSFormatF(FileLine* fl, ExprFormat, AstNodeExpr* exprsp, char missingArgChar = 'd',
2311 : : bool hidden = true)
2312 : : : ASTGEN_SUPER_SFormatF(fl)
2313 : : , m_text{""}
2314 : : , m_hidden{hidden}
2315 : : , m_exprFormat{true}
2316 : : , m_missingArgChar{missingArgChar} {
2317 : : dtypeSetString();
2318 : : addExprsp(exprsp);
2319 : : }
2320 : : ASTGEN_MEMBERS_AstSFormatF;
2321 : : void dump(std::ostream& str = std::cout) const override;
2322 : : void dumpJson(std::ostream& str = std::cout) const override;
2323 : : string name() const override VL_MT_STABLE { return m_text; }
2324 : : void name(const string& name) override { m_text = name; }
2325 : : int instrCount() const override { return INSTR_COUNT_PLI; }
2326 : : bool sameNode(const AstNode* samep) const override {
2327 : : return text() == VN_DBG_AS(samep, SFormatF)->text();
2328 : : }
2329 : : string verilogKwd() const override { return "$sformatf"; }
2330 : : string text() const { return m_text; } // * = Text to display
2331 : : void text(const string& text) { m_text = text; }
2332 : : const char* broken() const override {
2333 : : BROKEN_RTN(text() != "" && exprFormat()); // Expr format means no literal format
2334 : : return nullptr;
2335 : : }
2336 : : bool formatScopeTracking() const { // Track scopeNamep(); Ok if false positive
2337 : : return exprFormat() || name().find("%m") != string::npos
2338 : : || name().find("%M") != string::npos;
2339 : : }
2340 : : bool hidden() const { return m_hidden; }
2341 : : bool exprFormat() const { return m_exprFormat; }
2342 : : void exprFormat(bool flag) { m_exprFormat = flag; }
2343 : : bool optionalFormat() const { return m_optionalFormat; }
2344 : : void optionalFormat(bool flag) { m_optionalFormat = flag; }
2345 : : char missingArgChar() const { return m_missingArgChar; }
2346 : : VTimescale timeunit() const { return m_timeunit; }
2347 : : void timeunit(const VTimescale& flag) { m_timeunit = flag; }
2348 : :
2349 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
2350 : : string emitC() override { V3ERROR_NA_RETURN(""); }
2351 : : bool cleanOut() const override { V3ERROR_NA_RETURN(true); }
2352 : : bool isSystemFunc() const override { return true; }
2353 : : };
2354 : : class AstSGotoRep final : public AstNodeExpr {
2355 : : // Goto repetition: expr [-> count]
2356 : : // IEEE 1800-2023 16.9.2
2357 : : // @astgen op1 := exprp : AstNodeExpr
2358 : : // @astgen op2 := countp : AstNodeExpr
2359 : : public:
2360 : : explicit AstSGotoRep(FileLine* fl, AstNodeExpr* exprp, AstNodeExpr* countp)
2361 : : : ASTGEN_SUPER_SGotoRep(fl) {
2362 : : this->exprp(exprp);
2363 : : this->countp(countp);
2364 : : }
2365 : : ASTGEN_MEMBERS_AstSGotoRep;
2366 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
2367 : : string emitC() override { V3ERROR_NA_RETURN(""); }
2368 : : bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
2369 : : bool isMultiCycleSva() const override { return true; }
2370 : : };
2371 : : class AstSNonConsRep final : public AstNodeExpr {
2372 : : // Nonconsecutive repetition: expr [= count]
2373 : : // IEEE 1800-2023 16.9.2
2374 : : // @astgen op1 := exprp : AstNodeExpr
2375 : : // @astgen op2 := countp : AstNodeExpr
2376 : : public:
2377 : : explicit AstSNonConsRep(FileLine* fl, AstNodeExpr* exprp, AstNodeExpr* countp)
2378 : : : ASTGEN_SUPER_SNonConsRep(fl) {
2379 : : this->exprp(exprp);
2380 : : this->countp(countp);
2381 : : }
2382 : : ASTGEN_MEMBERS_AstSNonConsRep;
2383 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
2384 : : string emitC() override { V3ERROR_NA_RETURN(""); }
2385 : : bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
2386 : : bool isMultiCycleSva() const override { return true; }
2387 : : };
2388 : : class AstSScanF final : public AstNodeExpr {
2389 : : // @astgen op1 := exprsp : List[AstNodeExpr] // VarRefs for results
2390 : : // @astgen op2 := fromp : AstNodeExpr
2391 : : string m_text;
2392 : : VTimescale m_timeunit; // Parent module time unit
2393 : :
2394 : : public:
2395 : : AstSScanF(FileLine* fl, const string& text, AstNodeExpr* fromp, AstNodeExpr* exprsp)
2396 : : : ASTGEN_SUPER_SScanF(fl)
2397 : : , m_text{text} {
2398 : : addExprsp(exprsp);
2399 : : this->fromp(fromp);
2400 : : }
2401 : : ASTGEN_MEMBERS_AstSScanF;
2402 : : string name() const override VL_MT_STABLE { return m_text; }
2403 : : string verilogKwd() const override { return "$sscanf"; }
2404 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
2405 : : string emitC() override { V3ERROR_NA_RETURN(""); }
2406 : : bool isGateOptimizable() const override { return false; }
2407 : : bool isPredictOptimizable() const override { return false; }
2408 : : bool isPure() override { return false; } // SPECIAL: has 'visual' ordering
2409 : : bool isOutputter() override { return true; } // SPECIAL: makes output
2410 : : bool cleanOut() const override { return false; }
2411 : : bool sameNode(const AstNode* samep) const override {
2412 : : const AstSScanF* const asamep = VN_DBG_AS(samep, SScanF);
2413 : : return text() == asamep->text() && timeunit() == asamep->timeunit();
2414 : : }
2415 : : string text() const { return m_text; } // * = Text to display
2416 : : VTimescale timeunit() const { return m_timeunit; }
2417 : : void timeunit(const VTimescale& flag) { m_timeunit = flag; }
2418 : : bool isSystemFunc() const override { return true; }
2419 : : };
2420 : : class AstSampled final : public AstNodeExpr {
2421 : : // Verilog $sampled
2422 : : // @astgen op1 := exprp : AstNode<AstNodeExpr|AstPropSpec>
2423 : : public:
2424 : : AstSampled(FileLine* fl, AstNode* exprp)
2425 : : : ASTGEN_SUPER_Sampled(fl) {
2426 : : this->exprp(exprp);
2427 : : }
2428 : : ASTGEN_MEMBERS_AstSampled;
2429 : : string emitVerilog() override { return "$sampled(%l)"; }
2430 : : string emitC() override { V3ERROR_NA_RETURN(""); }
2431 : : string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
2432 : : bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
2433 : : int instrCount() const override { return 0; }
2434 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
2435 : : bool isSystemFunc() const override { return true; }
2436 : : };
2437 : : class AstScopeName final : public AstNodeExpr {
2438 : : // For display %m and DPI context imports
2439 : : // Parents: AstSFormatF, AstNodeFTaskRef, AstNodeFTask
2440 : : std::string m_scopeAttr;
2441 : : std::string m_scopeEntr;
2442 : : bool m_dpiExport = false; // Is for dpiExport
2443 : : const bool m_forFormat; // Is for a format %m
2444 : : static std::string scopeNameFormatter(const std::string& text);
2445 : : static std::string scopePrettyNameFormatter(const std::string& text);
2446 : :
2447 : : public:
2448 : : class ForFormat {};
2449 : : AstScopeName(FileLine* fl, bool forFormat)
2450 : : : ASTGEN_SUPER_ScopeName(fl)
2451 : : , m_forFormat{forFormat} {
2452 : : dtypeSetUInt64();
2453 : : }
2454 : : ASTGEN_MEMBERS_AstScopeName;
2455 : : bool sameNode(const AstNode* samep) const override {
2456 : : const AstScopeName* const sp = VN_DBG_AS(samep, ScopeName);
2457 : : return m_scopeAttr == sp->m_scopeAttr //
2458 : : && m_scopeEntr == sp->m_scopeEntr //
2459 : : && m_dpiExport == sp->m_dpiExport //
2460 : : && m_forFormat == sp->m_forFormat;
2461 : : }
2462 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
2463 : : string emitC() override { V3ERROR_NA_RETURN(""); }
2464 : : bool cleanOut() const override { return true; }
2465 : : void dump(std::ostream& str = std::cout) const override;
2466 : : void dumpJson(std::ostream& str = std::cout) const override;
2467 : : // ACCESSORS
2468 : : const std::string& scopeAttr() const { return m_scopeAttr; }
2469 : : void scopeAttr(const std::string& val) { m_scopeAttr = val; }
2470 : : const std::string& scopeEntr() const { return m_scopeEntr; }
2471 : : void scopeEntr(const std::string& val) { m_scopeEntr = val; }
2472 : : bool dpiExport() const { return m_dpiExport; }
2473 : : void dpiExport(bool flag) { m_dpiExport = flag; }
2474 : : bool forFormat() const { return m_forFormat; }
2475 : : // Name for __Vscopep variable including children
2476 : : string scopeSymName() const { return scopeNameFormatter(m_scopeAttr); }
2477 : : // Name for DPI import scope
2478 : : string scopeDpiName() const { return scopeNameFormatter(m_scopeEntr); }
2479 : : // Name for __Vscopep variable including children
2480 : : string scopePrettySymName() const { return scopePrettyNameFormatter(m_scopeAttr); }
2481 : : // Name for __Vscopep variable including children
2482 : : string scopePrettyDpiName() const { return scopePrettyNameFormatter(m_scopeEntr); }
2483 : : };
2484 : : class AstSetAssoc final : public AstNodeExpr {
2485 : : // Set an assoc array element and return object, '{}
2486 : : // @astgen op1 := lhsp : AstNodeExpr
2487 : : // @astgen op2 := keyp : Optional[AstNode]
2488 : : // @astgen op3 := valuep : AstNodeExpr
2489 : : public:
2490 : : AstSetAssoc(FileLine* fl, AstNodeExpr* lhsp, AstNode* keyp, AstNodeExpr* valuep)
2491 : : : ASTGEN_SUPER_SetAssoc(fl) {
2492 : : this->lhsp(lhsp);
2493 : : this->keyp(keyp);
2494 : : this->valuep(valuep);
2495 : : }
2496 : : ASTGEN_MEMBERS_AstSetAssoc;
2497 : : string emitVerilog() override { return "'{}"; }
2498 : : string emitC() override { V3ERROR_NA_RETURN(""); }
2499 : : string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
2500 : : bool cleanOut() const override { return true; }
2501 : : int instrCount() const override { return widthInstrs(); }
2502 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
2503 : : };
2504 : : class AstSetWildcard final : public AstNodeExpr {
2505 : : // Set a wildcard assoc array element and return object, '{}
2506 : : // @astgen op1 := lhsp : AstNodeExpr
2507 : : // @astgen op2 := keyp : Optional[AstNode]
2508 : : // @astgen op3 := valuep : AstNodeExpr
2509 : : public:
2510 : : AstSetWildcard(FileLine* fl, AstNodeExpr* lhsp, AstNode* keyp, AstNodeExpr* valuep)
2511 : : : ASTGEN_SUPER_SetWildcard(fl) {
2512 : : this->lhsp(lhsp);
2513 : : this->keyp(keyp);
2514 : : this->valuep(valuep);
2515 : : }
2516 : : ASTGEN_MEMBERS_AstSetWildcard;
2517 : : string emitVerilog() override { return "'{}"; }
2518 : : string emitC() override { V3ERROR_NA_RETURN(""); }
2519 : : string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
2520 : : bool cleanOut() const override { return true; }
2521 : : int instrCount() const override { return widthInstrs(); }
2522 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
2523 : : };
2524 : : class AstStable final : public AstNodeExpr {
2525 : : // Verilog $stable
2526 : : // @astgen op1 := exprp : AstNodeExpr
2527 : : // @astgen op2 := sentreep : Optional[AstSenTree]
2528 : : public:
2529 : : AstStable(FileLine* fl, AstNodeExpr* exprp, AstSenTree* sentreep)
2530 : : : ASTGEN_SUPER_Stable(fl) {
2531 : : this->exprp(exprp);
2532 : : this->sentreep(sentreep);
2533 : : }
2534 : : ASTGEN_MEMBERS_AstStable;
2535 : : string emitVerilog() override { return "$stable(%l)"; }
2536 : : string emitC() override { V3ERROR_NA_RETURN(""); }
2537 : : string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
2538 : : bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
2539 : : int instrCount() const override { return widthInstrs(); }
2540 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
2541 : : bool isSystemFunc() const override { return true; }
2542 : : };
2543 : : class AstStackTraceF final : public AstNodeExpr {
2544 : : // $stacktrace used as function
2545 : : public:
2546 : : explicit AstStackTraceF(FileLine* fl)
2547 : : : ASTGEN_SUPER_StackTraceF(fl) {
2548 : : dtypeSetString();
2549 : : }
2550 : : ASTGEN_MEMBERS_AstStackTraceF;
2551 : : string verilogKwd() const override { return "$stacktrace"; }
2552 : : string emitVerilog() override { return verilogKwd(); }
2553 : : string emitC() override { return "VL_STACKTRACE_N()"; }
2554 : : bool isGateOptimizable() const override { return false; }
2555 : : bool isPredictOptimizable() const override { return false; }
2556 : : bool isPure() override { return false; }
2557 : : bool isOutputter() override { return true; }
2558 : : bool isUnlikely() const override { return true; }
2559 : : bool cleanOut() const override { return true; }
2560 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
2561 : : };
2562 : : class AstSteady final : public AstNodeExpr {
2563 : : // Verilog $steady_gclk
2564 : : // @astgen op1 := exprp : AstNodeExpr
2565 : : public:
2566 : : AstSteady(FileLine* fl, AstNodeExpr* exprp)
2567 : : : ASTGEN_SUPER_Steady(fl) {
2568 : : this->exprp(exprp);
2569 : : }
2570 : : ASTGEN_MEMBERS_AstSteady;
2571 : : string emitVerilog() override { return "$steady_gclk(%l)"; }
2572 : : string emitC() override { V3ERROR_NA_RETURN(""); }
2573 : : string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
2574 : : bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
2575 : : int instrCount() const override { return widthInstrs(); }
2576 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
2577 : : bool isSystemFunc() const override { return true; }
2578 : : };
2579 : : class AstStructSel final : public AstNodeExpr {
2580 : : // Unpacked struct/union member access
2581 : : // Parents: math|stmt
2582 : : // Children: varref, math
2583 : : // @astgen op1 := fromp : AstNodeExpr
2584 : : string m_name; // Name of the member
2585 : : public:
2586 : : AstStructSel(FileLine* fl, AstNodeExpr* fromp, const string& name)
2587 : : : ASTGEN_SUPER_StructSel(fl)
2588 : : , m_name{name} {
2589 : : this->fromp(fromp);
2590 : : dtypep(nullptr); // V3Width will resolve
2591 : : }
2592 : : ASTGEN_MEMBERS_AstStructSel;
2593 : : string name() const override VL_MT_STABLE { return m_name; }
2594 : : void name(const string& name) override { m_name = name; }
2595 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
2596 : : string emitC() override { V3ERROR_NA_RETURN(""); }
2597 : : bool cleanOut() const override {
2598 : : // Not a union
2599 : : return VN_IS(fromp()->dtypep()->skipRefp(), StructDType);
2600 : : }
2601 : : bool sameNode(const AstNode* samep) const override {
2602 : : const AstStructSel* const sp = VN_DBG_AS(samep, StructSel);
2603 : : return m_name == sp->m_name;
2604 : : }
2605 : : int instrCount() const override { return widthInstrs(); }
2606 : : };
2607 : : class AstSysIgnore final : public AstNodeExpr {
2608 : : // @astgen op1 := exprsp : List[AstNodeExpr] // Expressions to output (???)
2609 : : public:
2610 : : AstSysIgnore(FileLine* fl, AstNodeExpr* exprsp)
2611 : : : ASTGEN_SUPER_SysIgnore(fl) {
2612 : : addExprsp(exprsp);
2613 : : }
2614 : : ASTGEN_MEMBERS_AstSysIgnore;
2615 : : string verilogKwd() const override { return "$ignored"; }
2616 : : bool isGateOptimizable() const override { return false; } // Though deleted before opt
2617 : : bool isPredictOptimizable() const override { return false; } // Though deleted before opt
2618 : : bool isPure() override { return false; } // Though deleted before opt
2619 : : bool isOutputter() override { return true; } // Though deleted before opt
2620 : : int instrCount() const override { return INSTR_COUNT_PLI; }
2621 : :
2622 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
2623 : : string emitC() override { V3ERROR_NA_RETURN(""); }
2624 : : bool cleanOut() const override { V3ERROR_NA_RETURN(true); }
2625 : : };
2626 : : class AstSystemF final : public AstNodeExpr {
2627 : : // $system used as function
2628 : : // @astgen op1 := lhsp : AstNodeExpr
2629 : : public:
2630 : : AstSystemF(FileLine* fl, AstNodeExpr* lhsp)
2631 : : : ASTGEN_SUPER_SystemF(fl) {
2632 : : this->lhsp(lhsp);
2633 : : }
2634 : : ASTGEN_MEMBERS_AstSystemF;
2635 : : string verilogKwd() const override { return "$system"; }
2636 : : string emitVerilog() override { return verilogKwd(); }
2637 : : string emitC() override { return "VL_SYSTEM_%nq(%lw, %P)"; }
2638 : : bool isGateOptimizable() const override { return false; }
2639 : : bool isPredictOptimizable() const override { return false; }
2640 : : bool isPure() override { return false; }
2641 : : bool isOutputter() override { return true; }
2642 : : bool isUnlikely() const override { return true; }
2643 : : bool cleanOut() const override { return true; }
2644 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
2645 : : bool isSystemFunc() const override { return true; }
2646 : : };
2647 : : class AstTaggedExpr final : public AstNodeExpr {
2648 : : // Tagged union expression: "tagged MemberName [expr]"
2649 : : // @astgen op1 := exprp : Optional[AstNodeExpr] // Optional value expression
2650 : : string m_name; // Member identifier name
2651 : : public:
2652 : : AstTaggedExpr(FileLine* fl, const string& name, AstNodeExpr* exprp)
2653 : : : ASTGEN_SUPER_TaggedExpr(fl)
2654 : : , m_name{name} {
2655 : : this->exprp(exprp);
2656 : : }
2657 : : ASTGEN_MEMBERS_AstTaggedExpr;
2658 : : string emitVerilog() override { return "tagged %k"; }
2659 : : string emitC() override { V3ERROR_NA_RETURN(""); }
2660 : : bool cleanOut() const override { return false; }
2661 : : bool sameNode(const AstNode* samep) const override {
2662 : : return m_name == VN_DBG_AS(samep, TaggedExpr)->m_name;
2663 : : }
2664 : : string name() const override VL_MT_STABLE { return m_name; }
2665 : : };
2666 : : class AstTaggedPattern final : public AstNodeExpr {
2667 : : // Tagged pattern for matches: "tagged MemberName [pattern]"
2668 : : // @astgen op1 := patternp : Optional[AstNode] // Optional nested pattern
2669 : : string m_name; // Member identifier name
2670 : : public:
2671 : : AstTaggedPattern(FileLine* fl, const string& name, AstNode* patternp)
2672 : : : ASTGEN_SUPER_TaggedPattern(fl)
2673 : : , m_name{name} {
2674 : : this->patternp(patternp);
2675 : : }
2676 : : ASTGEN_MEMBERS_AstTaggedPattern;
2677 : : string emitVerilog() override { return "tagged %k"; }
2678 : : string emitC() override { V3ERROR_NA_RETURN(""); }
2679 : : bool cleanOut() const override { return false; }
2680 : : bool sameNode(const AstNode* samep) const override {
2681 : : return m_name == VN_DBG_AS(samep, TaggedPattern)->m_name;
2682 : : }
2683 : : string name() const override VL_MT_STABLE { return m_name; }
2684 : : };
2685 : : class AstTestPlusArgs final : public AstNodeExpr {
2686 : : // Search expression. If nullptr then this is a $test$plusargs instead of $value$plusargs.
2687 : : // @astgen op1 := searchp : Optional[AstNodeExpr]
2688 : : public:
2689 : : AstTestPlusArgs(FileLine* fl, AstNodeExpr* searchp)
2690 : : : ASTGEN_SUPER_TestPlusArgs(fl) {
2691 : : this->searchp(searchp);
2692 : : }
2693 : : ASTGEN_MEMBERS_AstTestPlusArgs;
2694 : : string verilogKwd() const override { return "$test$plusargs"; }
2695 : : string emitVerilog() override { return verilogKwd(); }
2696 : : string emitC() override { return "VL_VALUEPLUSARGS_%nq(%lw, %P, nullptr)"; }
2697 : : bool isGateOptimizable() const override { return false; }
2698 : : bool isPredictOptimizable() const override { return false; }
2699 : : // but isPure() true
2700 : : bool isSystemFunc() const override { return true; }
2701 : : bool cleanOut() const override { return true; }
2702 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
2703 : : };
2704 : : class AstThisRef final : public AstNodeExpr {
2705 : : // Reference to 'this'.
2706 : : // @astgen op1 := childDTypep : Optional[AstClassRefDType] // dtype of the node
2707 : : public:
2708 : : AstThisRef(FileLine* fl, VFlagChildDType, AstClassRefDType* dtypep)
2709 : : : ASTGEN_SUPER_ThisRef(fl) {
2710 : : childDTypep(dtypep);
2711 : : }
2712 : : AstThisRef(FileLine* fl, AstClassRefDType* dtypep)
2713 : : : ASTGEN_SUPER_ThisRef(fl) {
2714 : : this->dtypep(dtypep);
2715 : : }
2716 : : ASTGEN_MEMBERS_AstThisRef;
2717 : : string emitC() override { return "this"; }
2718 : : string emitVerilog() override { return "this"; }
2719 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
2720 : : bool cleanOut() const override { return true; }
2721 : : AstNodeDType* getChildDTypep() const override { return childDTypep(); }
2722 : : };
2723 : : class AstTimePrecision final : public AstNodeExpr {
2724 : : // Verilog $timeprecision
2725 : : public:
2726 : : explicit AstTimePrecision(FileLine* fl)
2727 : : : ASTGEN_SUPER_TimePrecision(fl) {
2728 : : dtypeSetSigned32();
2729 : : }
2730 : : ASTGEN_MEMBERS_AstTimePrecision;
2731 : : string emitVerilog() override { return "$timeprecision"; }
2732 : : string emitC() override { V3ERROR_NA_RETURN(""); }
2733 : : string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
2734 : : bool cleanOut() const override { return true; }
2735 : : bool isSystemFunc() const override { return true; }
2736 : : int instrCount() const override { return widthInstrs(); }
2737 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
2738 : : };
2739 : : class AstTimeUnit final : public AstNodeExpr {
2740 : : VTimescale m_timeunit; // Parent module time unit
2741 : : // Verilog $timeunit
2742 : : public:
2743 : : explicit AstTimeUnit(FileLine* fl)
2744 : : : ASTGEN_SUPER_TimeUnit(fl) {
2745 : : dtypeSetSigned32();
2746 : : }
2747 : : ASTGEN_MEMBERS_AstTimeUnit;
2748 : : string emitVerilog() override { return "$timeunit"; }
2749 : : string emitC() override { V3ERROR_NA_RETURN(""); }
2750 : : string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
2751 : : bool cleanOut() const override { return true; }
2752 : : bool isSystemFunc() const override { return true; }
2753 : : int instrCount() const override { return widthInstrs(); }
2754 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
2755 : : VTimescale timeunit() const { return m_timeunit; }
2756 : : void timeunit(const VTimescale& flag) { m_timeunit = flag; }
2757 : : };
2758 : : class AstUnbounded final : public AstNodeExpr {
2759 : : // A $ in the parser, used for unbounded and queues
2760 : : // Due to where is used, treated as Signed32
2761 : : public:
2762 : : explicit AstUnbounded(FileLine* fl)
2763 : : : ASTGEN_SUPER_Unbounded(fl) {
2764 : : dtypeSetSigned32();
2765 : : }
2766 : : ASTGEN_MEMBERS_AstUnbounded;
2767 : : string emitVerilog() override { return "$"; }
2768 : : string emitC() override { V3ERROR_NA_RETURN(""); }
2769 : : bool cleanOut() const override { return true; }
2770 : : };
2771 : : class AstUnlinkedRef final : public AstNodeExpr {
2772 : : // As-of-yet unlinkable Ref
2773 : : // @astgen op1 := refp : AstNode
2774 : : // @astgen op2 := cellrefp : AstNode
2775 : :
2776 : : string m_name; // Var name // TODO: There is no way to access this, fix or remove
2777 : : public:
2778 : : AstUnlinkedRef(FileLine* fl, AstNode* refp, const string& name, AstNode* cellrefp)
2779 : : : ASTGEN_SUPER_UnlinkedRef(fl)
2780 : : , m_name{name} {
2781 : : this->refp(refp);
2782 : : this->cellrefp(cellrefp);
2783 : : }
2784 : : ASTGEN_MEMBERS_AstUnlinkedRef;
2785 : :
2786 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
2787 : : string emitC() override { V3ERROR_NA_RETURN(""); }
2788 : : bool cleanOut() const override { V3ERROR_NA_RETURN(true); }
2789 : : };
2790 : : class AstUntil final : public AstNodeExpr {
2791 : : // The until property expression
2792 : : // @astgen op1 := lhsp : AstNodeExpr
2793 : : // @astgen op2 := rhsp : AstNodeExpr
2794 : :
2795 : : const bool m_strong; // 's_' preffix
2796 : : const bool m_overlapping; // '_with` suffix
2797 : : public:
2798 : : AstUntil(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp, bool strong, bool overlapping)
2799 : : : ASTGEN_SUPER_Until(fl)
2800 : : , m_strong{strong}
2801 : : , m_overlapping{overlapping} {
2802 : : this->lhsp(lhsp);
2803 : : this->rhsp(rhsp);
2804 : : }
2805 : : ASTGEN_MEMBERS_AstUntil;
2806 : : void dump(std::ostream& str) const override;
2807 : : void dumpJson(std::ostream& str) const override;
2808 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
2809 : : string emitC() override { V3ERROR_NA_RETURN(""); }
2810 : : string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
2811 : : bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
2812 : : int instrCount() const override { return widthInstrs(); }
2813 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
2814 : : bool isStrong() const { return m_strong; }
2815 : : bool isOverlapping() const { return m_overlapping; }
2816 : : };
2817 : : class AstValuePlusArgs final : public AstNodeExpr {
2818 : : // Search expression. If nullptr then this is a $test$plusargs instead of $value$plusargs.
2819 : : // @astgen op1 := searchp : Optional[AstNodeExpr]
2820 : : // @astgen op2 := outp : AstNodeExpr // VarRef for result
2821 : : public:
2822 : : AstValuePlusArgs(FileLine* fl, AstNodeExpr* searchp, AstNodeExpr* outp)
2823 : : : ASTGEN_SUPER_ValuePlusArgs(fl) {
2824 : : this->searchp(searchp);
2825 : : this->outp(outp);
2826 : : }
2827 : : ASTGEN_MEMBERS_AstValuePlusArgs;
2828 : : string verilogKwd() const override { return "$value$plusargs"; }
2829 : : string emitVerilog() override { return "%f$value$plusargs(%l, %k%r)"; }
2830 : : string emitC() override { V3ERROR_NA_RETURN(""); }
2831 : : bool isGateOptimizable() const override { return false; }
2832 : : bool isPredictOptimizable() const override { return false; }
2833 : : bool isPure() override { return !outp(); }
2834 : : bool isSystemFunc() const override { return true; }
2835 : : bool cleanOut() const override { return true; }
2836 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
2837 : : };
2838 : : class AstWithParse final : public AstNodeExpr {
2839 : : // In early parse, FUNC(index) WITH equation-using-index
2840 : : // Replaced with AstWith
2841 : : // Parents: expr|stmt
2842 : : // Children: funcref, expr
2843 : : // @astgen op1 := funcrefp : AstNodeExpr
2844 : : // @astgen op3 := exprsp : List[AstNodeExpr] // With's parenthesis part
2845 : : // @astgen op4 := constraintsp : List[AstNode] // With's braces part
2846 : : public:
2847 : : AstWithParse(FileLine* fl, AstNodeExpr* funcrefp, AstNodeExpr* exprsp,
2848 : : AstNode* constraintsp = nullptr)
2849 : : : ASTGEN_SUPER_WithParse(fl) {
2850 : : this->funcrefp(funcrefp);
2851 : : addExprsp(exprsp);
2852 : : addConstraintsp(constraintsp);
2853 : : }
2854 : : ASTGEN_MEMBERS_AstWithParse;
2855 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
2856 : :
2857 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
2858 : : string emitC() override { V3ERROR_NA_RETURN(""); }
2859 : : bool cleanOut() const override { V3ERROR_NA_RETURN(true); }
2860 : : };
2861 : :
2862 : : // === AstNodeBiop ===
2863 : : class AstBufIf1 final : public AstNodeBiop {
2864 : : // lhs is enable, rhs is data to drive
2865 : : // Note unlike the Verilog bufif1() UDP, this allows any width; each lhsp
2866 : : // bit enables respective rhsp bit
2867 : : public:
2868 : : AstBufIf1(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
2869 : : : ASTGEN_SUPER_BufIf1(fl, lhsp, rhsp) {
2870 : : dtypeFrom(lhsp);
2871 : : }
2872 : : ASTGEN_MEMBERS_AstBufIf1;
2873 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
2874 : : out.opBufIf1(lhs, rhs);
2875 : : }
2876 : : string emitVerilog() override { return "bufif(%r,%l)"; }
2877 : : string emitC() override { V3ERROR_NA_RETURN(""); } // Lclean || Rclean
2878 : : string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } // Lclean || Rclean
2879 : : bool cleanOut() const override { V3ERROR_NA_RETURN(""); } // Lclean || Rclean
2880 : : bool cleanLhs() const override { return false; }
2881 : : bool cleanRhs() const override { return false; }
2882 : : bool sizeMattersLhs() const override { return false; }
2883 : : bool sizeMattersRhs() const override { return false; }
2884 : : };
2885 : : class AstCastDynamic final : public AstNodeBiop {
2886 : : // Verilog $cast used as a function
2887 : : // Task usage of $cast is converted during parse to assert($cast(...))
2888 : : // lhsp() is value (we are converting FROM) to match AstCCast etc, this
2889 : : // is opposite of $cast's order, because the first access is to the
2890 : : // value reading from. Suggest use fromp()/top() instead of lhsp/rhsp().
2891 : : // @astgen alias op1 := fromp
2892 : : // @astgen alias op2 := top
2893 : : public:
2894 : : AstCastDynamic(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
2895 : : : ASTGEN_SUPER_CastDynamic(fl, lhsp, rhsp) {}
2896 : : ASTGEN_MEMBERS_AstCastDynamic;
2897 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
2898 : : V3ERROR_NA;
2899 : : }
2900 : : string emitVerilog() override { return "%f$cast(%r, %l)"; }
2901 : : string emitC() override { return "VL_DYNAMIC_CAST(%r, %l)"; }
2902 : : bool cleanOut() const override { return true; }
2903 : : bool cleanLhs() const override { return true; }
2904 : : bool cleanRhs() const override { return true; }
2905 : : bool sizeMattersLhs() const override { return false; }
2906 : : bool sizeMattersRhs() const override { return false; }
2907 : : bool isSystemFunc() const override { return true; }
2908 : : int instrCount() const override { return widthInstrs() * 20; }
2909 : : bool isPure() override { return false; }
2910 : : };
2911 : : class AstCompareNN final : public AstNodeBiop {
2912 : : // Verilog str.compare() and str.icompare()
2913 : : const bool m_ignoreCase; // True for str.icompare()
2914 : : public:
2915 : : AstCompareNN(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp, bool ignoreCase)
2916 : : : ASTGEN_SUPER_CompareNN(fl, lhsp, rhsp)
2917 : : , m_ignoreCase{ignoreCase} {
2918 : : dtypeSetUInt32();
2919 : : }
2920 : : ASTGEN_MEMBERS_AstCompareNN;
2921 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
2922 : : out.opCompareNN(lhs, rhs, m_ignoreCase);
2923 : : }
2924 : : string name() const override VL_MT_STABLE { return m_ignoreCase ? "icompare" : "compare"; }
2925 : : string emitVerilog() override {
2926 : : return m_ignoreCase ? "%k(%l.icompare(%r))" : "%k(%l.compare(%r))";
2927 : : }
2928 : : string emitC() override {
2929 : : return m_ignoreCase ? "VL_CMP_NN(%li,%ri,true)" : "VL_CMP_NN(%li,%ri,false)";
2930 : : }
2931 : : string emitSimpleOperator() override { return ""; }
2932 : : bool cleanOut() const override { return true; }
2933 : : bool cleanLhs() const override { return true; }
2934 : : bool cleanRhs() const override { return true; }
2935 : : bool sizeMattersLhs() const override { return false; }
2936 : : bool sizeMattersRhs() const override { return false; }
2937 : : };
2938 : : class AstConcat final : public AstNodeBiop {
2939 : : // If you're looking for {#{}}, see AstReplicate
2940 : : // @astgen makeDfgVertex
2941 : : public:
2942 : : AstConcat(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
2943 : : : ASTGEN_SUPER_Concat(fl, lhsp, rhsp) {
2944 : : if (lhsp->dtypep() && rhsp->dtypep()) {
2945 : : if (lhsp->dtypep()->isFourstate() || rhsp->dtypep()->isFourstate()) {
2946 : : dtypeSetLogicSized(lhsp->dtypep()->width() + rhsp->dtypep()->width(),
2947 : : VSigning::UNSIGNED);
2948 : : } else {
2949 : : dtypeSetBitSized(lhsp->dtypep()->width() + rhsp->dtypep()->width(),
2950 : : VSigning::UNSIGNED);
2951 : : }
2952 : : }
2953 : : }
2954 : : ASTGEN_MEMBERS_AstConcat;
2955 : : string emitVerilog() override { return "%f{%l, %k%r}"; }
2956 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
2957 : : out.opConcat(lhs, rhs);
2958 : : }
2959 : : string emitC() override { return "VL_CONCAT_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
2960 : : string emitSMT() const override { return "(concat %l %r)"; }
2961 : : bool cleanOut() const override { return true; }
2962 : : bool cleanLhs() const override { return true; }
2963 : : bool cleanRhs() const override { return true; }
2964 : : bool sizeMattersLhs() const override { return false; }
2965 : : bool sizeMattersRhs() const override { return false; }
2966 : : int instrCount() const override { return widthInstrs() * 2; }
2967 : : };
2968 : : class AstConcatN final : public AstNodeBiop {
2969 : : // String concatenate
2970 : : public:
2971 : : AstConcatN(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
2972 : : : ASTGEN_SUPER_ConcatN(fl, lhsp, rhsp) {
2973 : : dtypeSetString();
2974 : : }
2975 : : ASTGEN_MEMBERS_AstConcatN;
2976 : : string emitVerilog() override { return "%f{%l, %k%r}"; }
2977 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
2978 : : out.opConcatN(lhs, rhs);
2979 : : }
2980 : : string emitC() override { return "VL_CONCATN_NNN(%li, %ri)"; }
2981 : : bool cleanOut() const override { return true; }
2982 : : bool cleanLhs() const override { return true; }
2983 : : bool cleanRhs() const override { return true; }
2984 : : bool sizeMattersLhs() const override { return false; }
2985 : : bool sizeMattersRhs() const override { return false; }
2986 : : int instrCount() const override { return INSTR_COUNT_STR; }
2987 : : bool stringFlavor() const override { return true; }
2988 : : };
2989 : : class AstDiv final : public AstNodeBiop {
2990 : : // @astgen makeDfgVertex
2991 : : public:
2992 : : AstDiv(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
2993 : : : ASTGEN_SUPER_Div(fl, lhsp, rhsp) {
2994 : : dtypeFrom(lhsp);
2995 : : }
2996 : : ASTGEN_MEMBERS_AstDiv;
2997 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
2998 : : out.opDiv(lhs, rhs);
2999 : : }
3000 : : string emitVerilog() override { return "%k(%l %f/ %r)"; }
3001 : : string emitC() override { return "VL_DIV_%nq%lq%rq(%lw, %P, %li, %ri)"; }
3002 : : string emitSMT() const override { return "(bvudiv %l %r)"; }
3003 : : bool emitCheckMaxWords() override { return true; }
3004 : : bool cleanOut() const override { return false; }
3005 : : bool cleanLhs() const override { return true; }
3006 : : bool cleanRhs() const override { return true; }
3007 : : bool sizeMattersLhs() const override { return true; }
3008 : : bool sizeMattersRhs() const override { return true; }
3009 : : int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_DIV; }
3010 : : };
3011 : : class AstDivD final : public AstNodeBiop {
3012 : : public:
3013 : : AstDivD(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3014 : : : ASTGEN_SUPER_DivD(fl, lhsp, rhsp) {
3015 : : dtypeSetDouble();
3016 : : }
3017 : : ASTGEN_MEMBERS_AstDivD;
3018 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3019 : : out.opDivD(lhs, rhs);
3020 : : }
3021 : : string emitVerilog() override { return "%k(%l %f/ %r)"; }
3022 : : string emitC() override { V3ERROR_NA_RETURN(""); }
3023 : : string emitSimpleOperator() override { return "/"; }
3024 : : bool cleanOut() const override { return true; }
3025 : : bool cleanLhs() const override { return false; }
3026 : : bool cleanRhs() const override { return false; }
3027 : : bool sizeMattersLhs() const override { return false; }
3028 : : bool sizeMattersRhs() const override { return false; }
3029 : : int instrCount() const override { return INSTR_COUNT_DBL_DIV; }
3030 : : bool doubleFlavor() const override { return true; }
3031 : : };
3032 : : class AstDivS final : public AstNodeBiop {
3033 : : // @astgen makeDfgVertex
3034 : : public:
3035 : : AstDivS(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3036 : : : ASTGEN_SUPER_DivS(fl, lhsp, rhsp) {
3037 : : dtypeFrom(lhsp);
3038 : : }
3039 : : ASTGEN_MEMBERS_AstDivS;
3040 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3041 : : out.opDivS(lhs, rhs);
3042 : : }
3043 : : string emitVerilog() override { return "%k(%l %f/ %r)"; }
3044 : : string emitC() override { return "VL_DIVS_%nq%lq%rq(%lw, %P, %li, %ri)"; }
3045 : : string emitSMT() const override { return "(bvsdiv %l %r)"; }
3046 : : bool emitCheckMaxWords() override { return true; }
3047 : : bool cleanOut() const override { return false; }
3048 : : bool cleanLhs() const override { return true; }
3049 : : bool cleanRhs() const override { return true; }
3050 : : bool sizeMattersLhs() const override { return true; }
3051 : : bool sizeMattersRhs() const override { return true; }
3052 : : int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_DIV; }
3053 : : bool signedFlavor() const override { return true; }
3054 : : };
3055 : : class AstEqWild final : public AstNodeBiop {
3056 : : // Note wildcard operator rhs differs from lhs
3057 : : // @astgen makeDfgVertex
3058 : : public:
3059 : : AstEqWild(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3060 : : : ASTGEN_SUPER_EqWild(fl, lhsp, rhsp) {
3061 : : dtypeSetBit();
3062 : : }
3063 : : ASTGEN_MEMBERS_AstEqWild;
3064 : : // Return AstEqWild/AstEqD
3065 : : static AstNodeBiop* newTyped(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp);
3066 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3067 : : out.opWildEq(lhs, rhs);
3068 : : }
3069 : : string emitVerilog() override { return "%k(%l %f==? %r)"; }
3070 : : string emitC() override { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; }
3071 : : string emitSMT() const override { return "(__Vbv (= %l %r))"; }
3072 : : string emitSimpleOperator() override { return "=="; }
3073 : : bool cleanOut() const override { return true; }
3074 : : bool cleanLhs() const override { return true; }
3075 : : bool cleanRhs() const override { return true; }
3076 : : bool sizeMattersLhs() const override { return false; }
3077 : : bool sizeMattersRhs() const override { return false; }
3078 : : };
3079 : : class AstFGetS final : public AstNodeBiop {
3080 : : // @astgen alias op1 := strgp
3081 : : // @astgen alias op2 := filep
3082 : : public:
3083 : : AstFGetS(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3084 : : : ASTGEN_SUPER_FGetS(fl, lhsp, rhsp) {}
3085 : : ASTGEN_MEMBERS_AstFGetS;
3086 : : void numberOperate(V3Number&, const V3Number&, const V3Number&) override { V3ERROR_NA; }
3087 : : string emitVerilog() override { return "%f$fgets(%l,%r)"; }
3088 : : string emitC() override {
3089 : : return strgp()->dtypep()->basicp()->isString() ? "VL_FGETS_NI(%li, %ri)"
3090 : : : "VL_FGETS_%nqX%rq(%lw, %P, &(%li), %ri)";
3091 : : }
3092 : : bool cleanOut() const override { return false; }
3093 : : bool cleanLhs() const override { return true; }
3094 : : bool cleanRhs() const override { return true; }
3095 : : bool sizeMattersLhs() const override { return false; }
3096 : : bool sizeMattersRhs() const override { return false; }
3097 : : bool isSystemFunc() const override { return true; }
3098 : : int instrCount() const override { return widthInstrs() * 64; }
3099 : : };
3100 : : class AstFUngetC final : public AstNodeBiop {
3101 : : public:
3102 : : AstFUngetC(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3103 : : : ASTGEN_SUPER_FUngetC(fl, lhsp, rhsp) {}
3104 : : ASTGEN_MEMBERS_AstFUngetC;
3105 : : void numberOperate(V3Number&, const V3Number&, const V3Number&) override { V3ERROR_NA; }
3106 : : string emitVerilog() override { return "%f$ungetc(%r, %l)"; }
3107 : : // Non-existent filehandle returns EOF
3108 : : string emitC() override {
3109 : : return "(%li ? (ungetc(%ri, VL_CVT_I_FP(%li)) >= 0 ? 0 : -1) : -1)";
3110 : : }
3111 : : bool cleanOut() const override { return false; }
3112 : : bool cleanLhs() const override { return true; }
3113 : : bool cleanRhs() const override { return true; }
3114 : : bool sizeMattersLhs() const override { return false; }
3115 : : bool sizeMattersRhs() const override { return false; }
3116 : : bool isSystemFunc() const override { return true; }
3117 : : int instrCount() const override { return widthInstrs() * 64; }
3118 : : bool isPredictOptimizable() const override { return false; }
3119 : : bool isPure() override { return false; } // SPECIAL: $display has 'visual' ordering
3120 : : AstNode* filep() const { return lhsp(); }
3121 : : AstNode* charp() const { return rhsp(); }
3122 : : };
3123 : : class AstGetcN final : public AstNodeBiop {
3124 : : // Verilog string.getc()
3125 : : public:
3126 : : AstGetcN(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3127 : : : ASTGEN_SUPER_GetcN(fl, lhsp, rhsp) {
3128 : : dtypeSetBitSized(8, VSigning::UNSIGNED);
3129 : : }
3130 : : ASTGEN_MEMBERS_AstGetcN;
3131 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3132 : : out.opGetcN(lhs, rhs);
3133 : : }
3134 : : string name() const override VL_MT_STABLE { return "getc"; }
3135 : : string emitVerilog() override { return "%k(%l.getc(%r))"; }
3136 : : string emitC() override { return "VL_GETC_N(%li,%ri)"; }
3137 : : string emitSimpleOperator() override { return ""; }
3138 : : bool cleanOut() const override { return true; }
3139 : : bool cleanLhs() const override { return true; }
3140 : : bool cleanRhs() const override { return true; }
3141 : : bool sizeMattersLhs() const override { return false; }
3142 : : bool sizeMattersRhs() const override { return false; }
3143 : : };
3144 : : class AstGetcRefN final : public AstNodeBiop {
3145 : : // Verilog string[#] on the left-hand-side of assignment
3146 : : // Spec says is of type byte (not string of single character)
3147 : : public:
3148 : : AstGetcRefN(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3149 : : : ASTGEN_SUPER_GetcRefN(fl, lhsp, rhsp) {
3150 : : dtypeSetBitSized(8, VSigning::UNSIGNED);
3151 : : }
3152 : : ASTGEN_MEMBERS_AstGetcRefN;
3153 : : void numberOperate(V3Number&, const V3Number&, const V3Number&) override { V3ERROR_NA; }
3154 : : string emitVerilog() override { return "%k%l[%r]"; }
3155 : : string emitC() override { V3ERROR_NA_RETURN(""); }
3156 : : string emitSimpleOperator() override { return ""; }
3157 : : bool cleanOut() const override { return true; }
3158 : : bool cleanLhs() const override { return true; }
3159 : : bool cleanRhs() const override { return true; }
3160 : : bool sizeMattersLhs() const override { return false; }
3161 : : bool sizeMattersRhs() const override { return false; }
3162 : : };
3163 : : class AstGt final : public AstNodeBiop {
3164 : : // @astgen makeDfgVertex
3165 : : public:
3166 : : AstGt(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3167 : : : ASTGEN_SUPER_Gt(fl, lhsp, rhsp) {
3168 : : dtypeSetBit();
3169 : : }
3170 : : ASTGEN_MEMBERS_AstGt;
3171 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3172 : : out.opGt(lhs, rhs);
3173 : : }
3174 : : string emitVerilog() override { return "%k(%l %f> %r)"; }
3175 : : string emitC() override { return "VL_GT_%lq(%lW, %P, %li, %ri)"; }
3176 : : string emitSMT() const override { return "(__Vbv (bvugt %l %r))"; }
3177 : : string emitSimpleOperator() override { return ">"; }
3178 : : bool cleanOut() const override { return true; }
3179 : : bool cleanLhs() const override { return true; }
3180 : : bool cleanRhs() const override { return true; }
3181 : : bool sizeMattersLhs() const override { return false; }
3182 : : bool sizeMattersRhs() const override { return false; }
3183 : : };
3184 : : class AstGtD final : public AstNodeBiop {
3185 : : public:
3186 : : AstGtD(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3187 : : : ASTGEN_SUPER_GtD(fl, lhsp, rhsp) {
3188 : : dtypeSetBit();
3189 : : }
3190 : : ASTGEN_MEMBERS_AstGtD;
3191 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3192 : : out.opGtD(lhs, rhs);
3193 : : }
3194 : : string emitVerilog() override { return "%k(%l %f> %r)"; }
3195 : : string emitC() override { V3ERROR_NA_RETURN(""); }
3196 : : string emitSimpleOperator() override { return ">"; }
3197 : : bool cleanOut() const override { return true; }
3198 : : bool cleanLhs() const override { return false; }
3199 : : bool cleanRhs() const override { return false; }
3200 : : bool sizeMattersLhs() const override { return false; }
3201 : : bool sizeMattersRhs() const override { return false; }
3202 : : int instrCount() const override { return INSTR_COUNT_DBL; }
3203 : : bool doubleFlavor() const override { return true; }
3204 : : };
3205 : : class AstGtN final : public AstNodeBiop {
3206 : : public:
3207 : : AstGtN(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3208 : : : ASTGEN_SUPER_GtN(fl, lhsp, rhsp) {
3209 : : dtypeSetBit();
3210 : : }
3211 : : ASTGEN_MEMBERS_AstGtN;
3212 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3213 : : out.opGtN(lhs, rhs);
3214 : : }
3215 : : string emitVerilog() override { return "%k(%l %f> %r)"; }
3216 : : string emitC() override { V3ERROR_NA_RETURN(""); }
3217 : : string emitSimpleOperator() override { return ">"; }
3218 : : bool cleanOut() const override { return true; }
3219 : : bool cleanLhs() const override { return false; }
3220 : : bool cleanRhs() const override { return false; }
3221 : : bool sizeMattersLhs() const override { return false; }
3222 : : bool sizeMattersRhs() const override { return false; }
3223 : : int instrCount() const override { return INSTR_COUNT_STR; }
3224 : : bool stringFlavor() const override { return true; }
3225 : : };
3226 : : class AstGtS final : public AstNodeBiop {
3227 : : // @astgen makeDfgVertex
3228 : : public:
3229 : : AstGtS(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3230 : : : ASTGEN_SUPER_GtS(fl, lhsp, rhsp) {
3231 : : dtypeSetBit();
3232 : : }
3233 : : ASTGEN_MEMBERS_AstGtS;
3234 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3235 : : out.opGtS(lhs, rhs);
3236 : : }
3237 : : string emitVerilog() override { return "%k(%l %f> %r)"; }
3238 : : string emitC() override { return "VL_GTS_%nq%lq%rq(%lw, %P, %li, %ri)"; }
3239 : : string emitSMT() const override { return "(__Vbv (bvsgt %l %r))"; }
3240 : : string emitSimpleOperator() override { return ""; }
3241 : : bool cleanOut() const override { return true; }
3242 : : bool cleanLhs() const override { return true; }
3243 : : bool cleanRhs() const override { return true; }
3244 : : bool sizeMattersLhs() const override { return false; }
3245 : : bool sizeMattersRhs() const override { return false; }
3246 : : bool signedFlavor() const override { return true; }
3247 : : };
3248 : : class AstGte final : public AstNodeBiop {
3249 : : // @astgen makeDfgVertex
3250 : : public:
3251 : : AstGte(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3252 : : : ASTGEN_SUPER_Gte(fl, lhsp, rhsp) {
3253 : : dtypeSetBit();
3254 : : }
3255 : : ASTGEN_MEMBERS_AstGte;
3256 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3257 : : out.opGte(lhs, rhs);
3258 : : }
3259 : : string emitVerilog() override { return "%k(%l %f>= %r)"; }
3260 : : string emitC() override { return "VL_GTE_%lq(%lW, %P, %li, %ri)"; }
3261 : : string emitSMT() const override { return "(__Vbv (bvuge %l %r))"; }
3262 : : string emitSimpleOperator() override { return ">="; }
3263 : : bool cleanOut() const override { return true; }
3264 : : bool cleanLhs() const override { return true; }
3265 : : bool cleanRhs() const override { return true; }
3266 : : bool sizeMattersLhs() const override { return false; }
3267 : : bool sizeMattersRhs() const override { return false; }
3268 : : };
3269 : : class AstGteD final : public AstNodeBiop {
3270 : : public:
3271 : : AstGteD(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3272 : : : ASTGEN_SUPER_GteD(fl, lhsp, rhsp) {
3273 : : dtypeSetBit();
3274 : : }
3275 : : ASTGEN_MEMBERS_AstGteD;
3276 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3277 : : out.opGteD(lhs, rhs);
3278 : : }
3279 : : string emitVerilog() override { return "%k(%l %f>= %r)"; }
3280 : : string emitC() override { V3ERROR_NA_RETURN(""); }
3281 : : string emitSimpleOperator() override { return ">="; }
3282 : : bool cleanOut() const override { return true; }
3283 : : bool cleanLhs() const override { return false; }
3284 : : bool cleanRhs() const override { return false; }
3285 : : bool sizeMattersLhs() const override { return false; }
3286 : : bool sizeMattersRhs() const override { return false; }
3287 : : int instrCount() const override { return INSTR_COUNT_DBL; }
3288 : : bool doubleFlavor() const override { return true; }
3289 : : };
3290 : : class AstGteN final : public AstNodeBiop {
3291 : : public:
3292 : : AstGteN(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3293 : : : ASTGEN_SUPER_GteN(fl, lhsp, rhsp) {
3294 : : dtypeSetBit();
3295 : : }
3296 : : ASTGEN_MEMBERS_AstGteN;
3297 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3298 : : out.opGteN(lhs, rhs);
3299 : : }
3300 : : string emitVerilog() override { return "%k(%l %f>= %r)"; }
3301 : : string emitC() override { V3ERROR_NA_RETURN(""); }
3302 : : string emitSimpleOperator() override { return ">="; }
3303 : : bool cleanOut() const override { return true; }
3304 : : bool cleanLhs() const override { return false; }
3305 : : bool cleanRhs() const override { return false; }
3306 : : bool sizeMattersLhs() const override { return false; }
3307 : : bool sizeMattersRhs() const override { return false; }
3308 : : int instrCount() const override { return INSTR_COUNT_STR; }
3309 : : bool stringFlavor() const override { return true; }
3310 : : };
3311 : : class AstGteS final : public AstNodeBiop {
3312 : : // @astgen makeDfgVertex
3313 : : public:
3314 : : AstGteS(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3315 : : : ASTGEN_SUPER_GteS(fl, lhsp, rhsp) {
3316 : : dtypeSetBit();
3317 : : }
3318 : : ASTGEN_MEMBERS_AstGteS;
3319 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3320 : : out.opGteS(lhs, rhs);
3321 : : }
3322 : : string emitVerilog() override { return "%k(%l %f>= %r)"; }
3323 : : string emitC() override { return "VL_GTES_%nq%lq%rq(%lw, %P, %li, %ri)"; }
3324 : : string emitSMT() const override { return "(__Vbv (bvsge %l %r))"; }
3325 : : string emitSimpleOperator() override { return ""; }
3326 : : bool cleanOut() const override { return true; }
3327 : : bool cleanLhs() const override { return true; }
3328 : : bool cleanRhs() const override { return true; }
3329 : : bool sizeMattersLhs() const override { return false; }
3330 : : bool sizeMattersRhs() const override { return false; }
3331 : : bool signedFlavor() const override { return true; }
3332 : : };
3333 : : class AstLogAnd final : public AstNodeBiop {
3334 : : // @astgen makeDfgVertex
3335 : : public:
3336 : : AstLogAnd(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3337 : : : ASTGEN_SUPER_LogAnd(fl, lhsp, rhsp) {
3338 : : dtypeSetBit();
3339 : : }
3340 : : ASTGEN_MEMBERS_AstLogAnd;
3341 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3342 : : out.opLogAnd(lhs, rhs);
3343 : : }
3344 : : string emitVerilog() override { return "%k(%l %f&& %r)"; }
3345 : : string emitC() override { return "VL_LOGAND_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
3346 : : string emitSMT() const override { return "(bvand %l %r)"; }
3347 : : string emitSimpleOperator() override { return "&&"; }
3348 : : bool cleanOut() const override { return true; }
3349 : : bool cleanLhs() const override { return true; }
3350 : : bool cleanRhs() const override { return true; }
3351 : : bool sizeMattersLhs() const override { return false; }
3352 : : bool sizeMattersRhs() const override { return false; }
3353 : : int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; }
3354 : : };
3355 : : class AstLogIf final : public AstNodeBiop {
3356 : : // @astgen makeDfgVertex
3357 : : public:
3358 : : AstLogIf(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3359 : : : ASTGEN_SUPER_LogIf(fl, lhsp, rhsp) {
3360 : : dtypeSetBit();
3361 : : }
3362 : : ASTGEN_MEMBERS_AstLogIf;
3363 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3364 : : out.opLogIf(lhs, rhs);
3365 : : }
3366 : : string emitVerilog() override { return "%k(%l %f-> %r)"; }
3367 : : string emitC() override { return "VL_LOGIF_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
3368 : : string emitSMT() const override { return "(__Vbv (=> (__Vbool %l) (__Vbool %r)))"; }
3369 : : string emitSimpleOperator() override { return "->"; }
3370 : : bool cleanOut() const override { return true; }
3371 : : bool cleanLhs() const override { return true; }
3372 : : bool cleanRhs() const override { return true; }
3373 : : bool sizeMattersLhs() const override { return false; }
3374 : : bool sizeMattersRhs() const override { return false; }
3375 : : int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; }
3376 : : };
3377 : : class AstLogOr final : public AstNodeBiop {
3378 : : // @astgen makeDfgVertex
3379 : : public:
3380 : : AstLogOr(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3381 : : : ASTGEN_SUPER_LogOr(fl, lhsp, rhsp) {
3382 : : dtypeSetBit();
3383 : : }
3384 : : ASTGEN_MEMBERS_AstLogOr;
3385 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3386 : : out.opLogOr(lhs, rhs);
3387 : : }
3388 : : string emitVerilog() override { return "%k(%l %f|| %r)"; }
3389 : : string emitC() override { return "VL_LOGOR_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
3390 : : string emitSMT() const override { return "(bvor %l %r)"; }
3391 : : string emitSimpleOperator() override { return "||"; }
3392 : : bool cleanOut() const override { return true; }
3393 : : bool cleanLhs() const override { return true; }
3394 : : bool cleanRhs() const override { return true; }
3395 : : bool sizeMattersLhs() const override { return false; }
3396 : : bool sizeMattersRhs() const override { return false; }
3397 : : int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; }
3398 : : };
3399 : : class AstLt final : public AstNodeBiop {
3400 : : // @astgen makeDfgVertex
3401 : : public:
3402 : : AstLt(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3403 : : : ASTGEN_SUPER_Lt(fl, lhsp, rhsp) {
3404 : : dtypeSetBit();
3405 : : }
3406 : : ASTGEN_MEMBERS_AstLt;
3407 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3408 : : out.opLt(lhs, rhs);
3409 : : }
3410 : : string emitVerilog() override { return "%k(%l %f< %r)"; }
3411 : : string emitC() override { return "VL_LT_%lq(%lW, %P, %li, %ri)"; }
3412 : : string emitSMT() const override { return "(__Vbv (bvult %l %r))"; }
3413 : : string emitSimpleOperator() override { return "<"; }
3414 : : bool cleanOut() const override { return true; }
3415 : : bool cleanLhs() const override { return true; }
3416 : : bool cleanRhs() const override { return true; }
3417 : : bool sizeMattersLhs() const override { return false; }
3418 : : bool sizeMattersRhs() const override { return false; }
3419 : : };
3420 : : class AstLtD final : public AstNodeBiop {
3421 : : public:
3422 : : AstLtD(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3423 : : : ASTGEN_SUPER_LtD(fl, lhsp, rhsp) {
3424 : : dtypeSetBit();
3425 : : }
3426 : : ASTGEN_MEMBERS_AstLtD;
3427 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3428 : : out.opLtD(lhs, rhs);
3429 : : }
3430 : : string emitVerilog() override { return "%k(%l %f< %r)"; }
3431 : : string emitC() override { V3ERROR_NA_RETURN(""); }
3432 : : string emitSimpleOperator() override { return "<"; }
3433 : : bool cleanOut() const override { return true; }
3434 : : bool cleanLhs() const override { return false; }
3435 : : bool cleanRhs() const override { return false; }
3436 : : bool sizeMattersLhs() const override { return false; }
3437 : : bool sizeMattersRhs() const override { return false; }
3438 : : int instrCount() const override { return INSTR_COUNT_DBL; }
3439 : : bool doubleFlavor() const override { return true; }
3440 : : };
3441 : : class AstLtN final : public AstNodeBiop {
3442 : : public:
3443 : : AstLtN(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3444 : : : ASTGEN_SUPER_LtN(fl, lhsp, rhsp) {
3445 : : dtypeSetBit();
3446 : : }
3447 : : ASTGEN_MEMBERS_AstLtN;
3448 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3449 : : out.opLtN(lhs, rhs);
3450 : : }
3451 : : string emitVerilog() override { return "%k(%l %f< %r)"; }
3452 : : string emitC() override { V3ERROR_NA_RETURN(""); }
3453 : : string emitSimpleOperator() override { return "<"; }
3454 : : bool cleanOut() const override { return true; }
3455 : : bool cleanLhs() const override { return false; }
3456 : : bool cleanRhs() const override { return false; }
3457 : : bool sizeMattersLhs() const override { return false; }
3458 : : bool sizeMattersRhs() const override { return false; }
3459 : : int instrCount() const override { return INSTR_COUNT_STR; }
3460 : : bool stringFlavor() const override { return true; }
3461 : : };
3462 : : class AstLtS final : public AstNodeBiop {
3463 : : // @astgen makeDfgVertex
3464 : : public:
3465 : : AstLtS(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3466 : : : ASTGEN_SUPER_LtS(fl, lhsp, rhsp) {
3467 : : dtypeSetBit();
3468 : : }
3469 : : ASTGEN_MEMBERS_AstLtS;
3470 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3471 : : out.opLtS(lhs, rhs);
3472 : : }
3473 : : string emitVerilog() override { return "%k(%l %f< %r)"; }
3474 : : string emitC() override { return "VL_LTS_%nq%lq%rq(%lw, %P, %li, %ri)"; }
3475 : : string emitSMT() const override { return "(__Vbv (bvslt %l %r))"; }
3476 : : string emitSimpleOperator() override { return ""; }
3477 : : bool cleanOut() const override { return true; }
3478 : : bool cleanLhs() const override { return true; }
3479 : : bool cleanRhs() const override { return true; }
3480 : : bool sizeMattersLhs() const override { return false; }
3481 : : bool sizeMattersRhs() const override { return false; }
3482 : : bool signedFlavor() const override { return true; }
3483 : : };
3484 : : class AstLte final : public AstNodeBiop {
3485 : : // @astgen makeDfgVertex
3486 : : public:
3487 : : AstLte(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3488 : : : ASTGEN_SUPER_Lte(fl, lhsp, rhsp) {
3489 : : dtypeSetBit();
3490 : : }
3491 : : ASTGEN_MEMBERS_AstLte;
3492 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3493 : : out.opLte(lhs, rhs);
3494 : : }
3495 : : string emitVerilog() override { return "%k(%l %f<= %r)"; }
3496 : : string emitC() override { return "VL_LTE_%lq(%lW, %P, %li, %ri)"; }
3497 : : string emitSMT() const override { return "(__Vbv (bvule %l %r))"; }
3498 : : string emitSimpleOperator() override { return "<="; }
3499 : : bool cleanOut() const override { return true; }
3500 : : bool cleanLhs() const override { return true; }
3501 : : bool cleanRhs() const override { return true; }
3502 : : bool sizeMattersLhs() const override { return false; }
3503 : : bool sizeMattersRhs() const override { return false; }
3504 : : };
3505 : : class AstLteD final : public AstNodeBiop {
3506 : : public:
3507 : : AstLteD(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3508 : : : ASTGEN_SUPER_LteD(fl, lhsp, rhsp) {
3509 : : dtypeSetBit();
3510 : : }
3511 : : ASTGEN_MEMBERS_AstLteD;
3512 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3513 : : out.opLteD(lhs, rhs);
3514 : : }
3515 : : string emitVerilog() override { return "%k(%l %f<= %r)"; }
3516 : : string emitC() override { V3ERROR_NA_RETURN(""); }
3517 : : string emitSimpleOperator() override { return "<="; }
3518 : : bool cleanOut() const override { return true; }
3519 : : bool cleanLhs() const override { return false; }
3520 : : bool cleanRhs() const override { return false; }
3521 : : bool sizeMattersLhs() const override { return false; }
3522 : : bool sizeMattersRhs() const override { return false; }
3523 : : int instrCount() const override { return INSTR_COUNT_DBL; }
3524 : : bool doubleFlavor() const override { return true; }
3525 : : };
3526 : : class AstLteN final : public AstNodeBiop {
3527 : : public:
3528 : : AstLteN(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3529 : : : ASTGEN_SUPER_LteN(fl, lhsp, rhsp) {
3530 : : dtypeSetBit();
3531 : : }
3532 : : ASTGEN_MEMBERS_AstLteN;
3533 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3534 : : out.opLteN(lhs, rhs);
3535 : : }
3536 : : string emitVerilog() override { return "%k(%l %f<= %r)"; }
3537 : : string emitC() override { V3ERROR_NA_RETURN(""); }
3538 : : string emitSimpleOperator() override { return "<="; }
3539 : : bool cleanOut() const override { return true; }
3540 : : bool cleanLhs() const override { return false; }
3541 : : bool cleanRhs() const override { return false; }
3542 : : bool sizeMattersLhs() const override { return false; }
3543 : : bool sizeMattersRhs() const override { return false; }
3544 : : int instrCount() const override { return INSTR_COUNT_STR; }
3545 : : bool stringFlavor() const override { return true; }
3546 : : };
3547 : : class AstLteS final : public AstNodeBiop {
3548 : : // @astgen makeDfgVertex
3549 : : public:
3550 : : AstLteS(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3551 : : : ASTGEN_SUPER_LteS(fl, lhsp, rhsp) {
3552 : : dtypeSetBit();
3553 : : }
3554 : : ASTGEN_MEMBERS_AstLteS;
3555 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3556 : : out.opLteS(lhs, rhs);
3557 : : }
3558 : : string emitVerilog() override { return "%k(%l %f<= %r)"; }
3559 : : string emitC() override { return "VL_LTES_%nq%lq%rq(%lw, %P, %li, %ri)"; }
3560 : : string emitSMT() const override { return "(__Vbv (bvsle %l %r))"; }
3561 : : string emitSimpleOperator() override { return ""; }
3562 : : bool cleanOut() const override { return true; }
3563 : : bool cleanLhs() const override { return true; }
3564 : : bool cleanRhs() const override { return true; }
3565 : : bool sizeMattersLhs() const override { return false; }
3566 : : bool sizeMattersRhs() const override { return false; }
3567 : : bool signedFlavor() const override { return true; }
3568 : : };
3569 : : class AstModDiv final : public AstNodeBiop {
3570 : : // @astgen makeDfgVertex
3571 : : public:
3572 : : AstModDiv(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3573 : : : ASTGEN_SUPER_ModDiv(fl, lhsp, rhsp) {
3574 : : dtypeFrom(lhsp);
3575 : : }
3576 : : ASTGEN_MEMBERS_AstModDiv;
3577 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3578 : : out.opModDiv(lhs, rhs);
3579 : : }
3580 : : string emitVerilog() override { return "%k(%l %f%% %r)"; }
3581 : : string emitC() override { return "VL_MODDIV_%nq%lq%rq(%lw, %P, %li, %ri)"; }
3582 : : string emitSMT() const override { return "(bvurem %l %r)"; }
3583 : : bool emitCheckMaxWords() override { return true; }
3584 : : bool cleanOut() const override { return false; }
3585 : : bool cleanLhs() const override { return true; }
3586 : : bool cleanRhs() const override { return true; }
3587 : : bool sizeMattersLhs() const override { return true; }
3588 : : bool sizeMattersRhs() const override { return true; }
3589 : : int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_DIV; }
3590 : : };
3591 : : class AstModDivS final : public AstNodeBiop {
3592 : : // @astgen makeDfgVertex
3593 : : public:
3594 : : AstModDivS(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3595 : : : ASTGEN_SUPER_ModDivS(fl, lhsp, rhsp) {
3596 : : dtypeFrom(lhsp);
3597 : : }
3598 : : ASTGEN_MEMBERS_AstModDivS;
3599 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3600 : : out.opModDivS(lhs, rhs);
3601 : : }
3602 : : string emitVerilog() override { return "%k(%l %f%% %r)"; }
3603 : : string emitC() override { return "VL_MODDIVS_%nq%lq%rq(%lw, %P, %li, %ri)"; }
3604 : : string emitSMT() const override { return "(bvsmod %l %r)"; }
3605 : : bool emitCheckMaxWords() override { return true; }
3606 : : bool cleanOut() const override { return false; }
3607 : : bool cleanLhs() const override { return true; }
3608 : : bool cleanRhs() const override { return true; }
3609 : : bool sizeMattersLhs() const override { return true; }
3610 : : bool sizeMattersRhs() const override { return true; }
3611 : : int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_DIV; }
3612 : : bool signedFlavor() const override { return true; }
3613 : : };
3614 : : class AstNeqWild final : public AstNodeBiop {
3615 : : // @astgen makeDfgVertex
3616 : : public:
3617 : : AstNeqWild(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3618 : : : ASTGEN_SUPER_NeqWild(fl, lhsp, rhsp) {
3619 : : dtypeSetBit();
3620 : : }
3621 : : ASTGEN_MEMBERS_AstNeqWild;
3622 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3623 : : out.opWildNeq(lhs, rhs);
3624 : : }
3625 : : string emitVerilog() override { return "%k(%l %f!=? %r)"; }
3626 : : string emitC() override { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; }
3627 : : string emitSimpleOperator() override { return "!="; }
3628 : : bool cleanOut() const override { return true; }
3629 : : bool cleanLhs() const override { return true; }
3630 : : bool cleanRhs() const override { return true; }
3631 : : bool sizeMattersLhs() const override { return false; }
3632 : : bool sizeMattersRhs() const override { return false; }
3633 : : };
3634 : : class AstPow final : public AstNodeBiop {
3635 : : // @astgen makeDfgVertex
3636 : : public:
3637 : : AstPow(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3638 : : : ASTGEN_SUPER_Pow(fl, lhsp, rhsp) {
3639 : : dtypeFrom(lhsp);
3640 : : }
3641 : : ASTGEN_MEMBERS_AstPow;
3642 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3643 : : out.opPow(lhs, rhs);
3644 : : }
3645 : : string emitVerilog() override { return "%k(%l %f** %r)"; }
3646 : : string emitC() override { return "VL_POW_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
3647 : : bool emitCheckMaxWords() override { return true; }
3648 : : bool cleanOut() const override { return false; }
3649 : : bool cleanLhs() const override { return true; }
3650 : : bool cleanRhs() const override { return true; }
3651 : : bool sizeMattersLhs() const override { return true; }
3652 : : bool sizeMattersRhs() const override { return false; }
3653 : : int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL * 10; }
3654 : : };
3655 : : class AstPowD final : public AstNodeBiop {
3656 : : public:
3657 : : AstPowD(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3658 : : : ASTGEN_SUPER_PowD(fl, lhsp, rhsp) {
3659 : : dtypeSetDouble();
3660 : : }
3661 : : ASTGEN_MEMBERS_AstPowD;
3662 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3663 : : out.opPowD(lhs, rhs);
3664 : : }
3665 : : string emitVerilog() override { return "%k(%l %f** %r)"; }
3666 : : string emitC() override { return "pow(%li,%ri)"; }
3667 : : bool cleanOut() const override { return false; }
3668 : : bool cleanLhs() const override { return false; }
3669 : : bool cleanRhs() const override { return false; }
3670 : : bool sizeMattersLhs() const override { return false; }
3671 : : bool sizeMattersRhs() const override { return false; }
3672 : : int instrCount() const override { return INSTR_COUNT_DBL_DIV * 5; }
3673 : : bool doubleFlavor() const override { return true; }
3674 : : };
3675 : : class AstPowSS final : public AstNodeBiop {
3676 : : // @astgen makeDfgVertex
3677 : : public:
3678 : : AstPowSS(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3679 : : : ASTGEN_SUPER_PowSS(fl, lhsp, rhsp) {
3680 : : dtypeFrom(lhsp);
3681 : : }
3682 : : ASTGEN_MEMBERS_AstPowSS;
3683 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3684 : : out.opPowSS(lhs, rhs);
3685 : : }
3686 : : string emitVerilog() override { return "%k(%l %f** %r)"; }
3687 : : string emitC() override { return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 1,1)"; }
3688 : : bool emitCheckMaxWords() override { return true; }
3689 : : bool cleanOut() const override { return false; }
3690 : : bool cleanLhs() const override { return true; }
3691 : : bool cleanRhs() const override { return true; }
3692 : : bool sizeMattersLhs() const override { return true; }
3693 : : bool sizeMattersRhs() const override { return false; }
3694 : : int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL * 10; }
3695 : : bool signedFlavor() const override { return true; }
3696 : : };
3697 : : class AstPowSU final : public AstNodeBiop {
3698 : : // @astgen makeDfgVertex
3699 : : public:
3700 : : AstPowSU(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3701 : : : ASTGEN_SUPER_PowSU(fl, lhsp, rhsp) {
3702 : : dtypeFrom(lhsp);
3703 : : }
3704 : : ASTGEN_MEMBERS_AstPowSU;
3705 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3706 : : out.opPowSU(lhs, rhs);
3707 : : }
3708 : : string emitVerilog() override { return "%k(%l %f** %r)"; }
3709 : : string emitC() override { return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 1,0)"; }
3710 : : bool emitCheckMaxWords() override { return true; }
3711 : : bool cleanOut() const override { return false; }
3712 : : bool cleanLhs() const override { return true; }
3713 : : bool cleanRhs() const override { return true; }
3714 : : bool sizeMattersLhs() const override { return true; }
3715 : : bool sizeMattersRhs() const override { return false; }
3716 : : int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL * 10; }
3717 : : bool signedFlavor() const override { return true; }
3718 : : };
3719 : : class AstPowUS final : public AstNodeBiop {
3720 : : // @astgen makeDfgVertex
3721 : : public:
3722 : : AstPowUS(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3723 : : : ASTGEN_SUPER_PowUS(fl, lhsp, rhsp) {
3724 : : dtypeFrom(lhsp);
3725 : : }
3726 : : ASTGEN_MEMBERS_AstPowUS;
3727 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3728 : : out.opPowUS(lhs, rhs);
3729 : : }
3730 : : string emitVerilog() override { return "%k(%l %f** %r)"; }
3731 : : string emitC() override { return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 0,1)"; }
3732 : : bool emitCheckMaxWords() override { return true; }
3733 : : bool cleanOut() const override { return false; }
3734 : : bool cleanLhs() const override { return true; }
3735 : : bool cleanRhs() const override { return true; }
3736 : : bool sizeMattersLhs() const override { return true; }
3737 : : bool sizeMattersRhs() const override { return false; }
3738 : : int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL * 10; }
3739 : : bool signedFlavor() const override { return true; }
3740 : : };
3741 : : class AstReplicate final : public AstNodeBiop {
3742 : : // Also used as a "Uniop" flavor of Concat, e.g. "{a}"
3743 : : // Verilog {rhs{lhs}} - Note rhsp() is the replicate value, not the lhsp()
3744 : : // @astgen alias op1 := srcp
3745 : : // @astgen alias op2 := countp
3746 : : public:
3747 : : AstReplicate(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3748 : : : ASTGEN_SUPER_Replicate(fl, lhsp, rhsp) {
3749 : : if (lhsp) {
3750 : : if (const AstConst* const constp = VN_CAST(rhsp, Const)) {
3751 : : if (constp->num().isFourState()
3752 : : || (constp->dtypep()->isSigned() && constp->num().isNegative())) {
3753 : : dtypeSetLogicSized(lhsp->width(), VSigning::UNSIGNED); // V3Width warns
3754 : : } else {
3755 : : dtypeSetLogicSized(lhsp->width() * constp->toSInt(), VSigning::UNSIGNED);
3756 : : }
3757 : : }
3758 : : }
3759 : : }
3760 : : AstReplicate(FileLine* fl, AstNodeExpr* lhsp, uint32_t repCount)
3761 : : : AstReplicate{fl, lhsp, new AstConst{fl, repCount}} {}
3762 : : ASTGEN_MEMBERS_AstReplicate;
3763 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3764 : : out.opRepl(lhs, rhs);
3765 : : }
3766 : : string emitVerilog() override { return "%f{%r{%k%l}}"; }
3767 : : string emitC() override { return "VL_REPLICATE_%nq%lq%rq(%lw, %P, %li, %ri)"; }
3768 : : string emitSMT() const override {
3769 : : return "((_ repeat " + cvtToStr(width() / lhsp()->width()) + ") %l)";
3770 : : }
3771 : : bool cleanOut() const override { return false; }
3772 : : bool cleanLhs() const override { return true; }
3773 : : bool cleanRhs() const override { return true; }
3774 : : bool sizeMattersLhs() const override { return false; }
3775 : : bool sizeMattersRhs() const override { return false; }
3776 : : int instrCount() const override { return widthInstrs() * 2; }
3777 : : };
3778 : : class AstReplicateN final : public AstNodeBiop {
3779 : : // String replicate
3780 : : public:
3781 : : AstReplicateN(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3782 : : : ASTGEN_SUPER_ReplicateN(fl, lhsp, rhsp) {
3783 : : dtypeSetString();
3784 : : }
3785 : : ASTGEN_MEMBERS_AstReplicateN;
3786 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3787 : : out.opReplN(lhs, rhs);
3788 : : }
3789 : : string emitVerilog() override { return "%f{%r{%k%l}}"; }
3790 : : string emitC() override { return "VL_REPLICATEN_NN%rq(%li, %ri)"; }
3791 : : bool cleanOut() const override { return false; }
3792 : : bool cleanLhs() const override { return true; }
3793 : : bool cleanRhs() const override { return true; }
3794 : : bool sizeMattersLhs() const override { return false; }
3795 : : bool sizeMattersRhs() const override { return false; }
3796 : : int instrCount() const override { return widthInstrs() * 2; }
3797 : : bool stringFlavor() const override { return true; }
3798 : : };
3799 : : class AstSAnd final : public AstNodeBiop {
3800 : : // Sequence 'and' (IEEE 1800-2023 16.9.5): both operand sequences must match.
3801 : : // Operates on match sets, not values. For boolean operands, lowered to AstLogAnd.
3802 : : public:
3803 : : AstSAnd(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3804 : : : ASTGEN_SUPER_SAnd(fl, lhsp, rhsp) {
3805 : : dtypeSetBit();
3806 : : }
3807 : : ASTGEN_MEMBERS_AstSAnd;
3808 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3809 : : out.opLogAnd(lhs, rhs);
3810 : : }
3811 : : string emitVerilog() override { return "%k(%l %fand %r)"; }
3812 : : string emitC() override { V3ERROR_NA_RETURN(""); }
3813 : : string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
3814 : : bool cleanOut() const override { return true; }
3815 : : bool cleanLhs() const override { return true; }
3816 : : bool cleanRhs() const override { return true; }
3817 : : bool sizeMattersLhs() const override { return false; }
3818 : : bool sizeMattersRhs() const override { return false; }
3819 : : int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; }
3820 : : bool isMultiCycleSva() const override { return true; }
3821 : : };
3822 : : class AstSIntersect final : public AstNodeBiop {
3823 : : // Sequence 'intersect' (IEEE 1800-2023 16.9.6): both operands match with equal length.
3824 : : // AND with a length restriction. For boolean operands, lowered to AstLogAnd.
3825 : : public:
3826 : : AstSIntersect(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3827 : : : ASTGEN_SUPER_SIntersect(fl, lhsp, rhsp) {
3828 : : dtypeSetBit();
3829 : : }
3830 : : ASTGEN_MEMBERS_AstSIntersect;
3831 : : // LCOV_EXCL_START // Lowered before these are ever called
3832 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3833 : : out.opLogAnd(lhs, rhs);
3834 : : }
3835 : : string emitVerilog() override { return "%k(%l %fintersect %r)"; }
3836 : : string emitC() override { V3ERROR_NA_RETURN(""); }
3837 : : string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
3838 : : bool cleanOut() const override { return true; }
3839 : : bool cleanLhs() const override { return true; }
3840 : : bool cleanRhs() const override { return true; }
3841 : : bool sizeMattersLhs() const override { return false; }
3842 : : bool sizeMattersRhs() const override { return false; }
3843 : : int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; }
3844 : : // LCOV_EXCL_STOP
3845 : : bool isMultiCycleSva() const override { return true; }
3846 : : };
3847 : : class AstSOr final : public AstNodeBiop {
3848 : : // Sequence 'or' (IEEE 1800-2023 16.9.7): at least one operand sequence must match.
3849 : : // Operates on match sets, not values. For boolean operands, lowered to AstLogOr.
3850 : : public:
3851 : : AstSOr(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3852 : : : ASTGEN_SUPER_SOr(fl, lhsp, rhsp) {
3853 : : dtypeSetBit();
3854 : : }
3855 : : ASTGEN_MEMBERS_AstSOr;
3856 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3857 : : out.opLogOr(lhs, rhs);
3858 : : }
3859 : : string emitVerilog() override { return "%k(%l %for %r)"; }
3860 : : string emitC() override { V3ERROR_NA_RETURN(""); }
3861 : : string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
3862 : : bool cleanOut() const override { return true; }
3863 : : bool cleanLhs() const override { return true; }
3864 : : bool cleanRhs() const override { return true; }
3865 : : bool sizeMattersLhs() const override { return false; }
3866 : : bool sizeMattersRhs() const override { return false; }
3867 : : int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; }
3868 : : bool isMultiCycleSva() const override { return true; }
3869 : : };
3870 : : class AstSThroughout final : public AstNodeBiop {
3871 : : // expr throughout seq (IEEE 1800-2023 16.9.9)
3872 : : public:
3873 : : AstSThroughout(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3874 : : : ASTGEN_SUPER_SThroughout(fl, lhsp, rhsp) {
3875 : : dtypeSetBit();
3876 : : }
3877 : : ASTGEN_MEMBERS_AstSThroughout;
3878 : : // LCOV_EXCL_START // Lowered in V3AssertProp before these are called
3879 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3880 : : out.opLogAnd(lhs, rhs);
3881 : : }
3882 : : string emitVerilog() override { return "%k(%l %fthroughout %r)"; }
3883 : : string emitC() override { V3ERROR_NA_RETURN(""); }
3884 : : string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
3885 : : bool cleanOut() const override { return true; }
3886 : : bool cleanLhs() const override { return true; }
3887 : : bool cleanRhs() const override { return true; }
3888 : : bool sizeMattersLhs() const override { return false; }
3889 : : bool sizeMattersRhs() const override { return false; }
3890 : : // LCOV_EXCL_STOP
3891 : : bool isMultiCycleSva() const override { return true; }
3892 : : };
3893 : : class AstSWithin final : public AstNodeBiop {
3894 : : // seq1 within seq2 (IEEE 1800-2023 16.9.10)
3895 : : public:
3896 : : AstSWithin(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
3897 : : : ASTGEN_SUPER_SWithin(fl, lhsp, rhsp) {
3898 : : dtypeSetBit();
3899 : : }
3900 : : ASTGEN_MEMBERS_AstSWithin;
3901 : : // LCOV_EXCL_START // Lowered in V3AssertNfa before these are called
3902 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3903 : : out.opLogAnd(lhs, rhs);
3904 : : }
3905 : : string emitVerilog() override { return "%k(%l %fwithin %r)"; }
3906 : : string emitC() override { V3ERROR_NA_RETURN(""); }
3907 : : string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
3908 : : bool cleanOut() const override { return true; }
3909 : : bool cleanLhs() const override { return true; }
3910 : : bool cleanRhs() const override { return true; }
3911 : : bool sizeMattersLhs() const override { return false; }
3912 : : bool sizeMattersRhs() const override { return false; }
3913 : : // LCOV_EXCL_STOP
3914 : : bool isMultiCycleSva() const override { return true; }
3915 : : };
3916 : : class AstSel final : public AstNodeBiop {
3917 : : // *Resolved* (tyep checked) multiple bit range extraction. Always const width
3918 : : // @astgen alias op1 := fromp
3919 : : // @astgen alias op2 := lsbp
3920 : : VNumRange m_declRange; // Range of the 'from' array if isRanged() is set, else invalid
3921 : : int m_declElWidth; // If a packed array, the number of bits per element
3922 : : // Selection width (!= this->width() from V3Clean onwards, != this->widthMin() in V3Width)
3923 : : int m_widthConst;
3924 : :
3925 : : public:
3926 : : AstSel(FileLine* fl, AstNodeExpr* fromp, AstNodeExpr* lsbp, int bitwidth)
3927 : : : ASTGEN_SUPER_Sel(fl, fromp, lsbp)
3928 : : , m_declElWidth{1}
3929 : : , m_widthConst{bitwidth} {
3930 : : dtypeSetLogicSized(bitwidth, VSigning::UNSIGNED);
3931 : : }
3932 : : AstSel(FileLine* fl, AstNodeExpr* fromp, int lsb, int bitwidth)
3933 : : : ASTGEN_SUPER_Sel(fl, fromp, new AstConst(fl, lsb)) // Need () constructor
3934 : : , m_declElWidth{1}
3935 : : , m_widthConst{bitwidth} {
3936 : : dtypeSetLogicSized(bitwidth, VSigning::UNSIGNED);
3937 : : }
3938 : : ASTGEN_MEMBERS_AstSel;
3939 : : void dump(std::ostream& str) const override;
3940 : : void dumpJson(std::ostream& str) const override;
3941 : : void numberOperate(V3Number& out, const V3Number& from, const V3Number& bit) override {
3942 : : out.opSel(from, bit.toUInt() + widthConst() - 1, bit.toUInt());
3943 : : }
3944 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
3945 : : string emitC() override {
3946 : : return widthConst() == 1 ? "VL_BITSEL_%nq%lq%rqI(%lw, %P, %li, %ri)"
3947 : : : isWide() ? "VL_SEL_%nq%lq%rqI(%nw, %lw, %P, %li, %ri, %nw)"
3948 : : : "VL_SEL_%nq%lq%rqI(%lw, %P, %li, %ri, %nw)";
3949 : : }
3950 : : string emitSMT() const override { return "((_ extract %t %r) %l)"; }
3951 : : bool cleanOut() const override { return false; }
3952 : : bool cleanLhs() const override { return true; }
3953 : : bool cleanRhs() const override { return true; }
3954 : : bool sizeMattersLhs() const override { return false; }
3955 : : bool sizeMattersRhs() const override { return false; }
3956 : : bool sameNode(const AstNode* otherp) const override {
3957 : : return widthConst() == VN_DBG_AS(otherp, Sel)->widthConst();
3958 : : }
3959 : : int instrCount() const override {
3960 : : return widthInstrs() * (VN_CAST(lsbp(), Const) ? 3 : 10) + 1;
3961 : : }
3962 : : int widthConst() const { return m_widthConst; }
3963 : : void widthConst(int value) { m_widthConst = value; }
3964 : : int lsbConst() const { return VN_AS(lsbp(), Const)->toSInt(); }
3965 : : int msbConst() const { return lsbConst() + widthConst() - 1; }
3966 : : VNumRange& declRange() VL_MT_STABLE { return m_declRange; }
3967 : : const VNumRange& declRange() const VL_MT_STABLE { return m_declRange; }
3968 : : void declRange(const VNumRange& flag) { m_declRange = flag; }
3969 : : int declElWidth() const { return m_declElWidth; }
3970 : : void declElWidth(int flag) { m_declElWidth = flag; }
3971 : : };
3972 : : class AstShiftL final : public AstNodeBiop {
3973 : : // @astgen makeDfgVertex
3974 : : public:
3975 : : AstShiftL(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp, int setwidth = 0)
3976 : : : ASTGEN_SUPER_ShiftL(fl, lhsp, rhsp) {
3977 : : if (setwidth) dtypeSetLogicSized(setwidth, VSigning::UNSIGNED);
3978 : : }
3979 : : ASTGEN_MEMBERS_AstShiftL;
3980 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
3981 : : out.opShiftL(lhs, rhs);
3982 : : }
3983 : : string emitVerilog() override { return "%k(%l %f<< %r)"; }
3984 : : string emitC() override { return "VL_SHIFTL_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
3985 : : string emitSMT() const override { return "(bvshl %l %r)"; }
3986 : : string emitSimpleOperator() override {
3987 : : return (rhsp()->isWide() || rhsp()->isQuad()) ? "" : "<<";
3988 : : }
3989 : : bool cleanOut() const override { return false; }
3990 : : bool cleanLhs() const override { return false; }
3991 : : bool cleanRhs() const override { return true; }
3992 : : bool sizeMattersLhs() const override { return true; }
3993 : : bool sizeMattersRhs() const override { return false; }
3994 : : };
3995 : : class AstShiftLOvr final : public AstNodeBiop {
3996 : : // Like ShiftL but checks for an over shift and returns zeros
3997 : : // TODO: All Verilog shifts should start as these and later get demoted to AstShiftL
3998 : : public:
3999 : : AstShiftLOvr(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp, int setwidth = 0)
4000 : : : ASTGEN_SUPER_ShiftLOvr(fl, lhsp, rhsp) {
4001 : : if (setwidth) dtypeSetLogicSized(setwidth, VSigning::UNSIGNED);
4002 : : }
4003 : : ASTGEN_MEMBERS_AstShiftLOvr;
4004 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
4005 : : out.opShiftL(lhs, rhs);
4006 : : }
4007 : : string emitVerilog() override { return "%k(%l %f<< %r)"; }
4008 : : string emitC() override { return "VL_SHIFTL_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
4009 : : string emitSimpleOperator() override { return ""; }
4010 : : bool cleanOut() const override { return false; }
4011 : : bool cleanLhs() const override { return false; }
4012 : : bool cleanRhs() const override { return true; }
4013 : : bool sizeMattersLhs() const override { return true; }
4014 : : bool sizeMattersRhs() const override { return false; }
4015 : : };
4016 : : class AstShiftR final : public AstNodeBiop {
4017 : : // @astgen makeDfgVertex
4018 : : public:
4019 : : AstShiftR(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp, int setwidth = 0)
4020 : : : ASTGEN_SUPER_ShiftR(fl, lhsp, rhsp) {
4021 : : if (setwidth) dtypeSetLogicSized(setwidth, VSigning::UNSIGNED);
4022 : : }
4023 : : ASTGEN_MEMBERS_AstShiftR;
4024 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
4025 : : out.opShiftR(lhs, rhs);
4026 : : }
4027 : : string emitVerilog() override { return "%k(%l %f>> %r)"; }
4028 : : string emitC() override { return "VL_SHIFTR_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
4029 : : string emitSMT() const override { return "(bvlshr %l %r)"; }
4030 : : string emitSimpleOperator() override {
4031 : : return (rhsp()->isWide() || rhsp()->isQuad()) ? "" : ">>";
4032 : : }
4033 : : bool cleanOut() const override { return true; }
4034 : : bool cleanLhs() const override { return true; }
4035 : : bool cleanRhs() const override { return true; }
4036 : : // LHS size might be > output size, so don't want to force size
4037 : : bool sizeMattersLhs() const override { return false; }
4038 : : bool sizeMattersRhs() const override { return false; }
4039 : : };
4040 : : class AstShiftROvr final : public AstNodeBiop {
4041 : : // Like ShiftR but checks for an over shift and returns zeros
4042 : : // TODO: All Verilog shifts should start as these and later get demoted to AstShiftR
4043 : : public:
4044 : : AstShiftROvr(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp, int setwidth = 0)
4045 : : : ASTGEN_SUPER_ShiftROvr(fl, lhsp, rhsp) {
4046 : : if (setwidth) dtypeSetLogicSized(setwidth, VSigning::UNSIGNED);
4047 : : }
4048 : : ASTGEN_MEMBERS_AstShiftROvr;
4049 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
4050 : : out.opShiftR(lhs, rhs);
4051 : : }
4052 : : string emitVerilog() override { return "%k(%l %f>> %r)"; }
4053 : : string emitC() override { return "VL_SHIFTR_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
4054 : : string emitSimpleOperator() override { return ""; }
4055 : : bool cleanOut() const override { return true; }
4056 : : bool cleanLhs() const override { return true; }
4057 : : bool cleanRhs() const override { return true; }
4058 : : // LHS size might be > output size, so don't want to force size
4059 : : bool sizeMattersLhs() const override { return false; }
4060 : : bool sizeMattersRhs() const override { return false; }
4061 : : };
4062 : : class AstShiftRS final : public AstNodeBiop {
4063 : : // Shift right with sign extension, >>> operator
4064 : : // Output data type's width determines which bit is used for sign extension
4065 : : // @astgen makeDfgVertex
4066 : : public:
4067 : : AstShiftRS(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp, int setwidth = 0)
4068 : : : ASTGEN_SUPER_ShiftRS(fl, lhsp, rhsp) {
4069 : : // Important that widthMin be correct, as opExtend requires it after V3Expand
4070 : : if (setwidth) dtypeSetLogicSized(setwidth, VSigning::SIGNED);
4071 : : }
4072 : : ASTGEN_MEMBERS_AstShiftRS;
4073 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
4074 : : out.opShiftRS(lhs, rhs, lhsp()->widthMinV());
4075 : : }
4076 : : string emitVerilog() override { return "%k(%l %f>>> %r)"; }
4077 : : string emitSMT() const override { return "(bvashr %l %r)"; }
4078 : : string emitC() override { return "VL_SHIFTRS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
4079 : : string emitSimpleOperator() override { return ""; }
4080 : : bool cleanOut() const override { return false; }
4081 : : bool cleanLhs() const override { return true; }
4082 : : bool cleanRhs() const override { return true; }
4083 : : bool sizeMattersLhs() const override { return false; }
4084 : : bool sizeMattersRhs() const override { return false; }
4085 : : bool signedFlavor() const override { return true; }
4086 : : };
4087 : : class AstShiftRSOvr final : public AstNodeBiop {
4088 : : // Shift right with sign extension, >>> operator, checks for an over shift and returns zeros
4089 : : // Output data type's width determines which bit is used for sign extension
4090 : : // TODO: All Verilog shifts should start as these and later get demoted to AstShiftRSOvr
4091 : : public:
4092 : : AstShiftRSOvr(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp, int setwidth = 0)
4093 : : : ASTGEN_SUPER_ShiftRSOvr(fl, lhsp, rhsp) {
4094 : : // Important that widthMin be correct, as opExtend requires it after V3Expand
4095 : : if (setwidth) dtypeSetLogicSized(setwidth, VSigning::SIGNED);
4096 : : }
4097 : : ASTGEN_MEMBERS_AstShiftRSOvr;
4098 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
4099 : : out.opShiftRS(lhs, rhs, lhsp()->widthMinV());
4100 : : }
4101 : : string emitVerilog() override { return "%k(%l %f>>> %r)"; }
4102 : : string emitC() override { return "VL_SHIFTRS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
4103 : : string emitSimpleOperator() override { return ""; }
4104 : : bool cleanOut() const override { return false; }
4105 : : bool cleanLhs() const override { return true; }
4106 : : bool cleanRhs() const override { return true; }
4107 : : bool sizeMattersLhs() const override { return false; }
4108 : : bool sizeMattersRhs() const override { return false; }
4109 : : bool signedFlavor() const override { return true; }
4110 : : };
4111 : : class AstSub final : public AstNodeBiop {
4112 : : // @astgen makeDfgVertex
4113 : : public:
4114 : : AstSub(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
4115 : : : ASTGEN_SUPER_Sub(fl, lhsp, rhsp) {
4116 : : dtypeFrom(lhsp);
4117 : : }
4118 : : ASTGEN_MEMBERS_AstSub;
4119 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
4120 : : out.opSub(lhs, rhs);
4121 : : }
4122 : : string emitVerilog() override { return "%k(%l %f- %r)"; }
4123 : : string emitC() override { return "VL_SUB_%lq(%lW, %P, %li, %ri)"; }
4124 : : string emitSMT() const override { return "(bvsub %l %r)"; }
4125 : : string emitSimpleOperator() override { return "-"; }
4126 : : bool cleanOut() const override { return false; }
4127 : : bool cleanLhs() const override { return false; }
4128 : : bool cleanRhs() const override { return false; }
4129 : : bool sizeMattersLhs() const override { return true; }
4130 : : bool sizeMattersRhs() const override { return true; }
4131 : : };
4132 : : class AstSubD final : public AstNodeBiop {
4133 : : public:
4134 : : AstSubD(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
4135 : : : ASTGEN_SUPER_SubD(fl, lhsp, rhsp) {
4136 : : dtypeSetDouble();
4137 : : }
4138 : : ASTGEN_MEMBERS_AstSubD;
4139 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
4140 : : out.opSubD(lhs, rhs);
4141 : : }
4142 : : string emitVerilog() override { return "%k(%l %f- %r)"; }
4143 : : string emitC() override { V3ERROR_NA_RETURN(""); }
4144 : : string emitSimpleOperator() override { return "-"; }
4145 : : bool cleanOut() const override { return true; }
4146 : : bool cleanLhs() const override { return false; }
4147 : : bool cleanRhs() const override { return false; }
4148 : : bool sizeMattersLhs() const override { return false; }
4149 : : bool sizeMattersRhs() const override { return false; }
4150 : : int instrCount() const override { return INSTR_COUNT_DBL; }
4151 : : bool doubleFlavor() const override { return true; }
4152 : : };
4153 : : class AstURandomRange final : public AstNodeBiop {
4154 : : // $urandom_range
4155 : : public:
4156 : : AstURandomRange(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
4157 : : : ASTGEN_SUPER_URandomRange(fl, lhsp, rhsp) {
4158 : : dtypeSetUInt32(); // Says IEEE
4159 : : }
4160 : : ASTGEN_MEMBERS_AstURandomRange;
4161 : : void numberOperate(V3Number&, const V3Number&, const V3Number&) override { V3ERROR_NA; }
4162 : : string emitVerilog() override { return "%f$urandom_range(%l, %r)"; }
4163 : : string emitC() override { return "VL_URANDOM_RANGE_%nq(%li, %ri)"; }
4164 : : bool cleanOut() const override { return true; }
4165 : : bool cleanLhs() const override { return true; }
4166 : : bool cleanRhs() const override { return true; }
4167 : : bool sizeMattersLhs() const override { return false; }
4168 : : bool sizeMattersRhs() const override { return false; }
4169 : : bool isGateOptimizable() const override { return false; }
4170 : : bool isPredictOptimizable() const override { return false; }
4171 : : bool isPure() override { return false; }
4172 : : bool isSystemFunc() const override { return true; }
4173 : : int instrCount() const override { return INSTR_COUNT_PLI; }
4174 : : };
4175 : :
4176 : : // === AstNodeBiCom ===
4177 : : class AstEq final : public AstNodeBiCom {
4178 : : // @astgen makeDfgVertex
4179 : : public:
4180 : : AstEq(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
4181 : : : ASTGEN_SUPER_Eq(fl, lhsp, rhsp) {
4182 : : dtypeSetBit();
4183 : : }
4184 : : ASTGEN_MEMBERS_AstEq;
4185 : : // Return AstEq/AstEqD
4186 : : static AstNodeBiop* newTyped(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp);
4187 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
4188 : : out.opEq(lhs, rhs);
4189 : : }
4190 : : string emitVerilog() override { return "%k(%l %f== %r)"; }
4191 : : string emitC() override { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; }
4192 : : string emitSMT() const override { return "(__Vbv (= %l %r))"; }
4193 : : string emitSimpleOperator() override { return "=="; }
4194 : : bool cleanOut() const override { return true; }
4195 : : bool cleanLhs() const override { return true; }
4196 : : bool cleanRhs() const override { return true; }
4197 : : bool sizeMattersLhs() const override { return false; }
4198 : : bool sizeMattersRhs() const override { return false; }
4199 : : };
4200 : : class AstEqCase final : public AstNodeBiCom {
4201 : : // @astgen makeDfgVertex
4202 : : public:
4203 : : AstEqCase(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
4204 : : : ASTGEN_SUPER_EqCase(fl, lhsp, rhsp) {
4205 : : dtypeSetBit();
4206 : : }
4207 : : ASTGEN_MEMBERS_AstEqCase;
4208 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
4209 : : out.opCaseEq(lhs, rhs);
4210 : : }
4211 : : string emitVerilog() override { return "%k(%l %f=== %r)"; }
4212 : : string emitC() override { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; }
4213 : : string emitSimpleOperator() override { return "=="; }
4214 : : bool cleanOut() const override { return true; }
4215 : : bool cleanLhs() const override { return true; }
4216 : : bool cleanRhs() const override { return true; }
4217 : : bool sizeMattersLhs() const override { return false; }
4218 : : bool sizeMattersRhs() const override { return false; }
4219 : : };
4220 : : class AstEqD final : public AstNodeBiCom {
4221 : : public:
4222 : : AstEqD(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
4223 : : : ASTGEN_SUPER_EqD(fl, lhsp, rhsp) {
4224 : : dtypeSetBit();
4225 : : }
4226 : : ASTGEN_MEMBERS_AstEqD;
4227 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
4228 : : out.opEqD(lhs, rhs);
4229 : : }
4230 : : string emitVerilog() override { return "%k(%l %f== %r)"; }
4231 : : string emitC() override { V3ERROR_NA_RETURN(""); }
4232 : : string emitSimpleOperator() override { return "=="; }
4233 : : bool cleanOut() const override { return true; }
4234 : : bool cleanLhs() const override { return false; }
4235 : : bool cleanRhs() const override { return false; }
4236 : : bool sizeMattersLhs() const override { return false; }
4237 : : bool sizeMattersRhs() const override { return false; }
4238 : : int instrCount() const override { return INSTR_COUNT_DBL; }
4239 : : bool doubleFlavor() const override { return true; }
4240 : : };
4241 : : class AstEqN final : public AstNodeBiCom {
4242 : : public:
4243 : : AstEqN(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
4244 : : : ASTGEN_SUPER_EqN(fl, lhsp, rhsp) {
4245 : : dtypeSetBit();
4246 : : }
4247 : : ASTGEN_MEMBERS_AstEqN;
4248 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
4249 : : out.opEqN(lhs, rhs);
4250 : : }
4251 : : string emitVerilog() override { return "%k(%l %f== %r)"; }
4252 : : string emitC() override { V3ERROR_NA_RETURN(""); }
4253 : : string emitSimpleOperator() override { return "=="; }
4254 : : bool cleanOut() const override { return true; }
4255 : : bool cleanLhs() const override { return false; }
4256 : : bool cleanRhs() const override { return false; }
4257 : : bool sizeMattersLhs() const override { return false; }
4258 : : bool sizeMattersRhs() const override { return false; }
4259 : : int instrCount() const override { return INSTR_COUNT_STR; }
4260 : : bool stringFlavor() const override { return true; }
4261 : : };
4262 : : class AstEqT final : public AstNodeBiCom {
4263 : : // Equal (==) for data types
4264 : : public:
4265 : : AstEqT(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
4266 : : : ASTGEN_SUPER_EqT(fl, lhsp, rhsp) {
4267 : : dtypeSetBit();
4268 : : }
4269 : : ASTGEN_MEMBERS_AstEqT;
4270 : : void numberOperate(V3Number&, const V3Number&, const V3Number&) override { V3ERROR_NA; }
4271 : : string emitVerilog() override { return "%k(%l %f== %r)"; }
4272 : : string emitC() override { V3ERROR_NA_RETURN(""); }
4273 : : string emitSimpleOperator() override { return "=="; }
4274 : : bool cleanOut() const override { return true; }
4275 : : bool cleanLhs() const override { return false; }
4276 : : bool cleanRhs() const override { return false; }
4277 : : bool sizeMattersLhs() const override { return false; }
4278 : : bool sizeMattersRhs() const override { return false; }
4279 : : int instrCount() const override { return INSTR_COUNT_STR; }
4280 : : };
4281 : : class AstLogEq final : public AstNodeBiCom {
4282 : : // @astgen makeDfgVertex
4283 : : public:
4284 : : AstLogEq(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
4285 : : : ASTGEN_SUPER_LogEq(fl, lhsp, rhsp) {
4286 : : dtypeSetBit();
4287 : : }
4288 : : ASTGEN_MEMBERS_AstLogEq;
4289 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
4290 : : out.opLogEq(lhs, rhs);
4291 : : }
4292 : : string emitVerilog() override { return "%k(%l %f<-> %r)"; }
4293 : : string emitC() override { return "VL_LOGEQ_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
4294 : : string emitSMT() const override { return "(bvxnor %l %r)"; }
4295 : : string emitSimpleOperator() override { return "<->"; }
4296 : : bool cleanOut() const override { return true; }
4297 : : bool cleanLhs() const override { return true; }
4298 : : bool cleanRhs() const override { return true; }
4299 : : bool sizeMattersLhs() const override { return false; }
4300 : : bool sizeMattersRhs() const override { return false; }
4301 : : int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; }
4302 : : };
4303 : : class AstNeq final : public AstNodeBiCom {
4304 : : // @astgen makeDfgVertex
4305 : : public:
4306 : : AstNeq(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
4307 : : : ASTGEN_SUPER_Neq(fl, lhsp, rhsp) {
4308 : : dtypeSetBit();
4309 : : }
4310 : : ASTGEN_MEMBERS_AstNeq;
4311 : : static AstNodeBiop* newTyped(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp);
4312 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
4313 : : out.opNeq(lhs, rhs);
4314 : : }
4315 : : string emitVerilog() override { return "%k(%l %f!= %r)"; }
4316 : : string emitC() override { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; }
4317 : : string emitSimpleOperator() override { return "!="; }
4318 : : string emitSMT() const override { return "(__Vbv (not (= %l %r)))"; }
4319 : : bool cleanOut() const override { return true; }
4320 : : bool cleanLhs() const override { return true; }
4321 : : bool cleanRhs() const override { return true; }
4322 : : bool sizeMattersLhs() const override { return false; }
4323 : : bool sizeMattersRhs() const override { return false; }
4324 : : };
4325 : : class AstNeqCase final : public AstNodeBiCom {
4326 : : // @astgen makeDfgVertex
4327 : : public:
4328 : : AstNeqCase(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
4329 : : : ASTGEN_SUPER_NeqCase(fl, lhsp, rhsp) {
4330 : : dtypeSetBit();
4331 : : }
4332 : : ASTGEN_MEMBERS_AstNeqCase;
4333 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
4334 : : out.opCaseNeq(lhs, rhs);
4335 : : }
4336 : : string emitVerilog() override { return "%k(%l %f!== %r)"; }
4337 : : string emitC() override { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; }
4338 : : string emitSimpleOperator() override { return "!="; }
4339 : : bool cleanOut() const override { return true; }
4340 : : bool cleanLhs() const override { return true; }
4341 : : bool cleanRhs() const override { return true; }
4342 : : bool sizeMattersLhs() const override { return false; }
4343 : : bool sizeMattersRhs() const override { return false; }
4344 : : };
4345 : : class AstNeqD final : public AstNodeBiCom {
4346 : : public:
4347 : : AstNeqD(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
4348 : : : ASTGEN_SUPER_NeqD(fl, lhsp, rhsp) {
4349 : : dtypeSetBit();
4350 : : }
4351 : : ASTGEN_MEMBERS_AstNeqD;
4352 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
4353 : : out.opNeqD(lhs, rhs);
4354 : : }
4355 : : string emitVerilog() override { return "%k(%l %f!= %r)"; }
4356 : : string emitC() override { V3ERROR_NA_RETURN(""); }
4357 : : string emitSimpleOperator() override { return "!="; }
4358 : : bool cleanOut() const override { return true; }
4359 : : bool cleanLhs() const override { return false; }
4360 : : bool cleanRhs() const override { return false; }
4361 : : bool sizeMattersLhs() const override { return false; }
4362 : : bool sizeMattersRhs() const override { return false; }
4363 : : int instrCount() const override { return INSTR_COUNT_DBL; }
4364 : : bool doubleFlavor() const override { return true; }
4365 : : };
4366 : : class AstNeqN final : public AstNodeBiCom {
4367 : : public:
4368 : : AstNeqN(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
4369 : : : ASTGEN_SUPER_NeqN(fl, lhsp, rhsp) {
4370 : : dtypeSetBit();
4371 : : }
4372 : : ASTGEN_MEMBERS_AstNeqN;
4373 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
4374 : : out.opNeqN(lhs, rhs);
4375 : : }
4376 : : string emitVerilog() override { return "%k(%l %f!= %r)"; }
4377 : : string emitC() override { V3ERROR_NA_RETURN(""); }
4378 : : string emitSimpleOperator() override { return "!="; }
4379 : : bool cleanOut() const override { return true; }
4380 : : bool cleanLhs() const override { return false; }
4381 : : bool cleanRhs() const override { return false; }
4382 : : bool sizeMattersLhs() const override { return false; }
4383 : : bool sizeMattersRhs() const override { return false; }
4384 : : int instrCount() const override { return INSTR_COUNT_STR; }
4385 : : bool stringFlavor() const override { return true; }
4386 : : };
4387 : : class AstNeqT final : public AstNodeBiCom {
4388 : : // Not-equal (!=) for data types
4389 : : public:
4390 : : AstNeqT(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
4391 : : : ASTGEN_SUPER_NeqT(fl, lhsp, rhsp) {
4392 : : dtypeSetBit();
4393 : : }
4394 : : ASTGEN_MEMBERS_AstNeqT;
4395 : : void numberOperate(V3Number&, const V3Number&, const V3Number&) override { V3ERROR_NA; }
4396 : : string emitVerilog() override { return "%k(%l %f!= %r)"; }
4397 : : string emitC() override { V3ERROR_NA_RETURN(""); }
4398 : : string emitSimpleOperator() override { return "!="; }
4399 : : bool cleanOut() const override { return true; }
4400 : : bool cleanLhs() const override { return false; }
4401 : : bool cleanRhs() const override { return false; }
4402 : : bool sizeMattersLhs() const override { return false; }
4403 : : bool sizeMattersRhs() const override { return false; }
4404 : : int instrCount() const override { return INSTR_COUNT_STR; }
4405 : : };
4406 : :
4407 : : // === AstNodeBiComAsv ===
4408 : : class AstAdd final : public AstNodeBiComAsv {
4409 : : // @astgen makeDfgVertex
4410 : : public:
4411 : : AstAdd(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
4412 : : : ASTGEN_SUPER_Add(fl, lhsp, rhsp) {
4413 : : dtypeFrom(lhsp);
4414 : : }
4415 : : ASTGEN_MEMBERS_AstAdd;
4416 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
4417 : : out.opAdd(lhs, rhs);
4418 : : }
4419 : : string emitVerilog() override { return "%k(%l %f+ %r)"; }
4420 : : string emitC() override { return "VL_ADD_%lq(%lW, %P, %li, %ri)"; }
4421 : : string emitSMT() const override { return "(bvadd %l %r)"; }
4422 : : string emitSimpleOperator() override { return "+"; }
4423 : : bool cleanOut() const override { return false; }
4424 : : bool cleanLhs() const override { return false; }
4425 : : bool cleanRhs() const override { return false; }
4426 : : bool sizeMattersLhs() const override { return true; }
4427 : : bool sizeMattersRhs() const override { return true; }
4428 : : };
4429 : : class AstAddD final : public AstNodeBiComAsv {
4430 : : public:
4431 : : AstAddD(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
4432 : : : ASTGEN_SUPER_AddD(fl, lhsp, rhsp) {
4433 : : dtypeSetDouble();
4434 : : }
4435 : : ASTGEN_MEMBERS_AstAddD;
4436 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
4437 : : out.opAddD(lhs, rhs);
4438 : : }
4439 : : string emitVerilog() override { return "%k(%l %f+ %r)"; }
4440 : : string emitC() override { V3ERROR_NA_RETURN(""); }
4441 : : string emitSimpleOperator() override { return "+"; }
4442 : : bool cleanOut() const override { return true; }
4443 : : bool cleanLhs() const override { return false; }
4444 : : bool cleanRhs() const override { return false; }
4445 : : bool sizeMattersLhs() const override { return false; }
4446 : : bool sizeMattersRhs() const override { return false; }
4447 : : int instrCount() const override { return INSTR_COUNT_DBL; }
4448 : : bool doubleFlavor() const override { return true; }
4449 : : };
4450 : : class AstAnd final : public AstNodeBiComAsv {
4451 : : // @astgen makeDfgVertex
4452 : : public:
4453 : : AstAnd(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
4454 : : : ASTGEN_SUPER_And(fl, lhsp, rhsp) {
4455 : : dtypeFrom(lhsp);
4456 : : }
4457 : : ASTGEN_MEMBERS_AstAnd;
4458 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
4459 : : out.opAnd(lhs, rhs);
4460 : : }
4461 : : string emitVerilog() override { return "%k(%l %f& %r)"; }
4462 : : string emitC() override { return "VL_AND_%lq(%lW, %P, %li, %ri)"; }
4463 : : string emitSMT() const override { return "(bvand %l %r)"; }
4464 : : string emitSimpleOperator() override { return "&"; }
4465 : : bool cleanOut() const override { V3ERROR_NA_RETURN(false); }
4466 : : bool cleanLhs() const override { return false; }
4467 : : bool cleanRhs() const override { return false; }
4468 : : bool sizeMattersLhs() const override { return false; }
4469 : : bool sizeMattersRhs() const override { return false; }
4470 : : const char* widthMismatch() const override VL_MT_STABLE;
4471 : : };
4472 : : class AstMul final : public AstNodeBiComAsv {
4473 : : // @astgen makeDfgVertex
4474 : : public:
4475 : : AstMul(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
4476 : : : ASTGEN_SUPER_Mul(fl, lhsp, rhsp) {
4477 : : dtypeFrom(lhsp);
4478 : : }
4479 : : ASTGEN_MEMBERS_AstMul;
4480 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
4481 : : out.opMul(lhs, rhs);
4482 : : }
4483 : : string emitVerilog() override { return "%k(%l %f* %r)"; }
4484 : : string emitC() override { return "VL_MUL_%lq(%lW, %P, %li, %ri)"; }
4485 : : string emitSMT() const override { return "(bvmul %l %r)"; }
4486 : : string emitSimpleOperator() override { return "*"; }
4487 : : bool cleanOut() const override { return false; }
4488 : : bool cleanLhs() const override { return true; }
4489 : : bool cleanRhs() const override { return true; }
4490 : : bool sizeMattersLhs() const override { return true; }
4491 : : bool sizeMattersRhs() const override { return true; }
4492 : : int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL; }
4493 : : };
4494 : : class AstMulD final : public AstNodeBiComAsv {
4495 : : public:
4496 : : AstMulD(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
4497 : : : ASTGEN_SUPER_MulD(fl, lhsp, rhsp) {
4498 : : dtypeSetDouble();
4499 : : }
4500 : : ASTGEN_MEMBERS_AstMulD;
4501 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
4502 : : out.opMulD(lhs, rhs);
4503 : : }
4504 : : string emitVerilog() override { return "%k(%l %f* %r)"; }
4505 : : string emitC() override { V3ERROR_NA_RETURN(""); }
4506 : : string emitSimpleOperator() override { return "*"; }
4507 : : bool cleanOut() const override { return true; }
4508 : : bool cleanLhs() const override { return false; }
4509 : : bool cleanRhs() const override { return false; }
4510 : : bool sizeMattersLhs() const override { return true; }
4511 : : bool sizeMattersRhs() const override { return true; }
4512 : : int instrCount() const override { return INSTR_COUNT_DBL; }
4513 : : bool doubleFlavor() const override { return true; }
4514 : : };
4515 : : class AstMulS final : public AstNodeBiComAsv {
4516 : : // @astgen makeDfgVertex
4517 : : public:
4518 : : AstMulS(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
4519 : : : ASTGEN_SUPER_MulS(fl, lhsp, rhsp) {
4520 : : dtypeFrom(lhsp);
4521 : : }
4522 : : ASTGEN_MEMBERS_AstMulS;
4523 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
4524 : : out.opMulS(lhs, rhs);
4525 : : }
4526 : : string emitVerilog() override { return "%k(%l %f* %r)"; }
4527 : : string emitC() override { return "VL_MULS_%nq%lq%rq(%lw, %P, %li, %ri)"; }
4528 : : string emitSMT() const override { return "(bvmul %l %r)"; }
4529 : : string emitSimpleOperator() override { return ""; }
4530 : : bool emitCheckMaxWords() override { return true; }
4531 : : bool cleanOut() const override { return false; }
4532 : : bool cleanLhs() const override { return true; }
4533 : : bool cleanRhs() const override { return true; }
4534 : : bool sizeMattersLhs() const override { return true; }
4535 : : bool sizeMattersRhs() const override { return true; }
4536 : : int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL; }
4537 : : bool signedFlavor() const override { return true; }
4538 : : };
4539 : : class AstOr final : public AstNodeBiComAsv {
4540 : : // @astgen makeDfgVertex
4541 : : public:
4542 : : AstOr(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
4543 : : : ASTGEN_SUPER_Or(fl, lhsp, rhsp) {
4544 : : dtypeFrom(lhsp);
4545 : : }
4546 : : ASTGEN_MEMBERS_AstOr;
4547 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
4548 : : out.opOr(lhs, rhs);
4549 : : }
4550 : : string emitVerilog() override { return "%k(%l %f| %r)"; }
4551 : : string emitC() override { return "VL_OR_%lq(%lW, %P, %li, %ri)"; }
4552 : : string emitSMT() const override { return "(bvor %l %r)"; }
4553 : : string emitSimpleOperator() override { return "|"; }
4554 : : bool cleanOut() const override { V3ERROR_NA_RETURN(false); }
4555 : : bool cleanLhs() const override { return false; }
4556 : : bool cleanRhs() const override { return false; }
4557 : : bool sizeMattersLhs() const override { return false; }
4558 : : bool sizeMattersRhs() const override { return false; }
4559 : : const char* widthMismatch() const override VL_MT_STABLE;
4560 : : };
4561 : : class AstXor final : public AstNodeBiComAsv {
4562 : : // @astgen makeDfgVertex
4563 : : public:
4564 : : AstXor(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
4565 : : : ASTGEN_SUPER_Xor(fl, lhsp, rhsp) {
4566 : : dtypeFrom(lhsp);
4567 : : }
4568 : : ASTGEN_MEMBERS_AstXor;
4569 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
4570 : : out.opXor(lhs, rhs);
4571 : : }
4572 : : string emitVerilog() override { return "%k(%l %f^ %r)"; }
4573 : : string emitC() override { return "VL_XOR_%lq(%lW, %P, %li, %ri)"; }
4574 : : string emitSMT() const override { return "(bvxor %l %r)"; }
4575 : : string emitSimpleOperator() override { return "^"; }
4576 : : bool cleanOut() const override { return false; } // Lclean && Rclean
4577 : : bool cleanLhs() const override { return false; }
4578 : : bool cleanRhs() const override { return false; }
4579 : : bool sizeMattersLhs() const override { return false; }
4580 : : bool sizeMattersRhs() const override { return false; }
4581 : : const char* widthMismatch() const override VL_MT_STABLE;
4582 : : };
4583 : :
4584 : : // === AstNodeDistBiop ===
4585 : : class AstDistChiSquare final : public AstNodeDistBiop {
4586 : : public:
4587 : : AstDistChiSquare(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
4588 : : : ASTGEN_SUPER_DistChiSquare(fl, lhsp, rhsp) {}
4589 : : ASTGEN_MEMBERS_AstDistChiSquare;
4590 : : string emitVerilog() override { return "%f$dist_chi_square(%l, %r)"; }
4591 : : string emitC() override { return "VL_DIST_CHI_SQUARE(%li, %ri)"; }
4592 : : };
4593 : : class AstDistExponential final : public AstNodeDistBiop {
4594 : : public:
4595 : : AstDistExponential(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
4596 : : : ASTGEN_SUPER_DistExponential(fl, lhsp, rhsp) {}
4597 : : ASTGEN_MEMBERS_AstDistExponential;
4598 : : string emitVerilog() override { return "%f$dist_exponential(%l, %r)"; }
4599 : : string emitC() override { return "VL_DIST_EXPONENTIAL(%li, %ri)"; }
4600 : : };
4601 : : class AstDistPoisson final : public AstNodeDistBiop {
4602 : : public:
4603 : : AstDistPoisson(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
4604 : : : ASTGEN_SUPER_DistPoisson(fl, lhsp, rhsp) {}
4605 : : ASTGEN_MEMBERS_AstDistPoisson;
4606 : : string emitVerilog() override { return "%f$dist_poisson(%l, %r)"; }
4607 : : string emitC() override { return "VL_DIST_POISSON(%li, %ri)"; }
4608 : : };
4609 : : class AstDistT final : public AstNodeDistBiop {
4610 : : public:
4611 : : AstDistT(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
4612 : : : ASTGEN_SUPER_DistT(fl, lhsp, rhsp) {}
4613 : : ASTGEN_MEMBERS_AstDistT;
4614 : : string emitVerilog() override { return "%f$dist_t(%l, %r)"; }
4615 : : string emitC() override { return "VL_DIST_T(%li, %ri)"; }
4616 : : };
4617 : :
4618 : : // === AstNodeSel ===
4619 : : class AstArraySel final : public AstNodeSel {
4620 : : // @astgen makeDfgVertex
4621 : : void init(const AstNode* fromp) {
4622 : : if (fromp && VN_IS(fromp->dtypep()->skipRefp(), NodeArrayDType)) {
4623 : : // Strip off array to find what array references
4624 : : dtypeFrom(VN_AS(fromp->dtypep()->skipRefp(), NodeArrayDType)->subDTypep());
4625 : : }
4626 : : }
4627 : :
4628 : : public:
4629 : : AstArraySel(FileLine* fl, AstNodeExpr* fromp, AstNodeExpr* bitp)
4630 : : : ASTGEN_SUPER_ArraySel(fl, fromp, bitp) {
4631 : : init(fromp);
4632 : : }
4633 : : AstArraySel(FileLine* fl, AstNodeExpr* fromp, int bit)
4634 : : : ASTGEN_SUPER_ArraySel(fl, fromp, new AstConst(fl, bit)) { // Need () constructor
4635 : : init(fromp);
4636 : : }
4637 : : ASTGEN_MEMBERS_AstArraySel;
4638 : : void numberOperate(V3Number&, const V3Number&, const V3Number&) override { V3ERROR_NA; }
4639 : : string emitVerilog() override { return "%k(%l%f[%r])"; }
4640 : : string emitC() override { V3ERROR_NA_RETURN(""); } // Special cased
4641 : : string emitSMT() const override { return "(select %l %r)"; }
4642 : : bool cleanOut() const override { return true; }
4643 : : bool cleanLhs() const override { return false; }
4644 : : bool cleanRhs() const override { return true; }
4645 : : bool sizeMattersLhs() const override { return false; }
4646 : : bool sizeMattersRhs() const override { return false; }
4647 : : bool isGateOptimizable() const override { return true; } // esp for V3Const::ifSameAssign
4648 : : bool isPredictOptimizable() const override { return true; }
4649 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
4650 : : int instrCount() const override { return widthInstrs(); }
4651 : : // Special operators
4652 : : // Return base var (or const) nodep dereferences
4653 : : static AstNode* baseFromp(AstNode* nodep, bool overMembers);
4654 : : };
4655 : : class AstAssocSel final : public AstNodeSel {
4656 : : void init(const AstNode* fromp) {
4657 : : if (fromp && VN_IS(fromp->dtypep()->skipRefp(), AssocArrayDType)) {
4658 : : // Strip off array to find what array references
4659 : : dtypeFrom(VN_AS(fromp->dtypep()->skipRefp(), AssocArrayDType)->subDTypep());
4660 : : }
4661 : : }
4662 : :
4663 : : public:
4664 : : AstAssocSel(FileLine* fl, AstNodeExpr* fromp, AstNodeExpr* bitp)
4665 : : : ASTGEN_SUPER_AssocSel(fl, fromp, bitp) {
4666 : : init(fromp);
4667 : : }
4668 : : ASTGEN_MEMBERS_AstAssocSel;
4669 : : void numberOperate(V3Number&, const V3Number&, const V3Number&) override { V3ERROR_NA; }
4670 : : string emitVerilog() override { return "%k(%l%f[%r])"; }
4671 : : string emitC() override { return "%li%k[%ri]"; }
4672 : : string emitSMT() const override { return "(select %l %r)"; }
4673 : : bool cleanOut() const override { return true; }
4674 : : bool cleanLhs() const override { return false; }
4675 : : bool cleanRhs() const override { return true; }
4676 : : bool sizeMattersLhs() const override { return false; }
4677 : : bool sizeMattersRhs() const override { return false; }
4678 : : bool isGateOptimizable() const override { return false; } // AssocSel creates on miss
4679 : : bool isPredictOptimizable() const override { return false; }
4680 : : bool isPure() override { return false; } // AssocSel creates on miss
4681 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
4682 : : int instrCount() const override { return widthInstrs(); }
4683 : : };
4684 : : class AstWildcardSel final : public AstNodeSel {
4685 : : void init(const AstNode* fromp) {
4686 : : if (fromp && VN_IS(fromp->dtypep()->skipRefp(), WildcardArrayDType)) {
4687 : : // Strip off array to find what array references
4688 : : dtypeFrom(VN_AS(fromp->dtypep()->skipRefp(), WildcardArrayDType)->subDTypep());
4689 : : }
4690 : : }
4691 : :
4692 : : public:
4693 : : AstWildcardSel(FileLine* fl, AstNodeExpr* fromp, AstNodeExpr* bitp)
4694 : : : ASTGEN_SUPER_WildcardSel(fl, fromp, bitp) {
4695 : : init(fromp);
4696 : : }
4697 : : ASTGEN_MEMBERS_AstWildcardSel;
4698 : : void numberOperate(V3Number&, const V3Number&, const V3Number&) override { V3ERROR_NA; }
4699 : : string emitVerilog() override { return "%k(%l%f[%r])"; }
4700 : : string emitC() override { return "%li%k[%ri]"; }
4701 : : bool cleanOut() const override { return true; }
4702 : : bool cleanLhs() const override { return false; }
4703 : : bool cleanRhs() const override { return true; }
4704 : : bool sizeMattersLhs() const override { return false; }
4705 : : bool sizeMattersRhs() const override { return false; }
4706 : : bool isGateOptimizable() const override { return true; } // esp for V3Const::ifSameAssign
4707 : : bool isPredictOptimizable() const override { return false; }
4708 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
4709 : : int instrCount() const override { return widthInstrs(); }
4710 : : };
4711 : : class AstWordSel final : public AstNodeSel {
4712 : : // Select a single word from a multi-word wide value
4713 : : public:
4714 : : AstWordSel(FileLine* fl, AstNodeExpr* fromp, AstNodeExpr* bitp)
4715 : : : ASTGEN_SUPER_WordSel(fl, fromp, bitp) {
4716 : : dtypeSetUInt32(); // Always used on WData arrays so returns edata size
4717 : : }
4718 : : ASTGEN_MEMBERS_AstWordSel;
4719 : : void numberOperate(V3Number&, const V3Number&, const V3Number&) override { V3ERROR_NA; }
4720 : : string emitVerilog() override { return "%k(%l%f[%r])"; }
4721 : : string emitC() override { V3ERROR_NA_RETURN(""); } // Special cased
4722 : : bool cleanOut() const override { return true; }
4723 : : bool cleanLhs() const override { return true; }
4724 : : bool cleanRhs() const override { return true; }
4725 : : bool sizeMattersLhs() const override { return false; }
4726 : : bool sizeMattersRhs() const override { return false; }
4727 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
4728 : : };
4729 : :
4730 : : // === AstNodeStream ===
4731 : : class AstStreamL final : public AstNodeStream {
4732 : : // Verilog {rhs{lhs}} - Note rhsp() is the slice size, not the lhsp()
4733 : : // @astgen makeDfgVertex
4734 : : public:
4735 : : AstStreamL(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
4736 : : : ASTGEN_SUPER_StreamL(fl, lhsp, rhsp) {}
4737 : : ASTGEN_MEMBERS_AstStreamL;
4738 : : string emitVerilog() override { return "%f{ << %r %k{%l} }"; }
4739 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
4740 : : out.opStreamL(lhs, rhs);
4741 : : }
4742 : : string emitC() override { return "VL_STREAML_%nq%lq%rq(%lw, %P, %li, %ri)"; }
4743 : : bool cleanOut() const override { return true; }
4744 : : bool cleanLhs() const override { return true; }
4745 : : bool cleanRhs() const override { return true; }
4746 : : bool sizeMattersLhs() const override { return false; }
4747 : : bool sizeMattersRhs() const override { return false; }
4748 : : int instrCount() const override { return widthInstrs() * 2; }
4749 : : };
4750 : : class AstStreamR final : public AstNodeStream {
4751 : : // Verilog {rhs{lhs}} - Note rhsp() is the slice size, not the lhsp()
4752 : : // @astgen makeDfgVertex
4753 : : public:
4754 : : AstStreamR(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
4755 : : : ASTGEN_SUPER_StreamR(fl, lhsp, rhsp) {}
4756 : : ASTGEN_MEMBERS_AstStreamR;
4757 : : string emitVerilog() override { return "%f{ >> %r %k{%l} }"; }
4758 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
4759 : : out.opAssign(lhs);
4760 : : }
4761 : : string emitC() override { return isWide() ? "VL_ASSIGN_W(%nw, %P, %li)" : "%li"; }
4762 : : bool cleanOut() const override { return false; }
4763 : : bool cleanLhs() const override { return false; }
4764 : : bool cleanRhs() const override { return false; }
4765 : : bool sizeMattersLhs() const override { return false; }
4766 : : bool sizeMattersRhs() const override { return false; }
4767 : : int instrCount() const override { return widthInstrs() * 2; }
4768 : : };
4769 : :
4770 : : // === AstNodeSystemBiopD ===
4771 : : class AstAtan2D final : public AstNodeSystemBiopD {
4772 : : public:
4773 : : AstAtan2D(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
4774 : : : ASTGEN_SUPER_Atan2D(fl, lhsp, rhsp) {}
4775 : : ASTGEN_MEMBERS_AstAtan2D;
4776 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
4777 : : out.setDouble(std::atan2(lhs.toDouble(), rhs.toDouble()));
4778 : : }
4779 : : string emitVerilog() override { return "%f$atan2(%l,%r)"; }
4780 : : string emitC() override { return "atan2(%li,%ri)"; }
4781 : : };
4782 : : class AstHypotD final : public AstNodeSystemBiopD {
4783 : : public:
4784 : : AstHypotD(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp)
4785 : : : ASTGEN_SUPER_HypotD(fl, lhsp, rhsp) {}
4786 : : ASTGEN_MEMBERS_AstHypotD;
4787 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
4788 : : out.setDouble(std::hypot(lhs.toDouble(), rhs.toDouble()));
4789 : : }
4790 : : string emitVerilog() override { return "%f$hypot(%l,%r)"; }
4791 : : string emitC() override { return "hypot(%li,%ri)"; }
4792 : : };
4793 : :
4794 : : // === AstNodeCCall ===
4795 : : class AstCCall final : public AstNodeCCall {
4796 : : // C++ function call
4797 : : VSelfPointerText m_selfPointer
4798 : : = VSelfPointerText{VSelfPointerText::Empty()}; // Output code object
4799 : : // pointer (e.g.: 'this')
4800 : : public:
4801 : : AstCCall(FileLine* fl, AstCFunc* funcp, AstNodeExpr* argsp = nullptr)
4802 : : : ASTGEN_SUPER_CCall(fl, funcp, argsp) {
4803 : : UASSERT_OBJ(funcp, this, "CCall created calling null function");
4804 : : }
4805 : : ASTGEN_MEMBERS_AstCCall;
4806 : :
4807 : : const VSelfPointerText& selfPointer() const { return m_selfPointer; }
4808 : : void selfPointer(const VSelfPointerText& selfPointer) { m_selfPointer = selfPointer; }
4809 : : string selfPointerProtect(bool useSelfForThis) const {
4810 : : return selfPointer().protect(useSelfForThis, protect());
4811 : : }
4812 : : bool maybePointedTo() const override VL_MT_SAFE { return true; }
4813 : : };
4814 : : class AstCMethodCall final : public AstNodeCCall {
4815 : : // C++ method call
4816 : : // @astgen op1 := fromp : AstNodeExpr
4817 : : public:
4818 : : AstCMethodCall(FileLine* fl, AstNodeExpr* fromp, AstCFunc* funcp, AstNodeExpr* argsp = nullptr)
4819 : : : ASTGEN_SUPER_CMethodCall(fl, funcp, argsp) {
4820 : : this->fromp(fromp);
4821 : : UASSERT_OBJ(funcp, this, "CMethodCall created calling null function");
4822 : : }
4823 : : ASTGEN_MEMBERS_AstCMethodCall;
4824 : : };
4825 : : class AstCNew final : public AstNodeCCall {
4826 : : // C++ new() call
4827 : : public:
4828 : : AstCNew(FileLine* fl, AstCFunc* funcp, AstNodeExpr* argsp = nullptr)
4829 : : : ASTGEN_SUPER_CNew(fl, funcp, argsp) {}
4830 : : ASTGEN_MEMBERS_AstCNew;
4831 : : };
4832 : :
4833 : : // === AstNodeFTaskRef ===
4834 : : class AstFuncRef final : public AstNodeFTaskRef {
4835 : : // A reference to a function
4836 : : bool m_superReference = false; // Called with super reference
4837 : : public:
4838 : : inline AstFuncRef(FileLine* fl, AstFunc* taskp, AstArg* argsp = nullptr);
4839 : : AstFuncRef(FileLine* fl, const string& name, AstArg* argsp = nullptr)
4840 : : : ASTGEN_SUPER_FuncRef(fl, name, argsp) {}
4841 : : ASTGEN_MEMBERS_AstFuncRef;
4842 : : bool superReference() const { return m_superReference; }
4843 : : void superReference(bool flag) { m_superReference = flag; }
4844 : : };
4845 : : class AstMethodCall final : public AstNodeFTaskRef {
4846 : : // A reference to a member task (or function)
4847 : : // Don't need the class we are extracting from, as the "fromp()"'s datatype can get us to it
4848 : : // @astgen op1 := fromp : AstNodeExpr
4849 : : //
4850 : : public:
4851 : : AstMethodCall(FileLine* fl, AstNodeExpr* fromp, VFlagChildDType, const string& name,
4852 : : AstArg* argsp = nullptr)
4853 : : : ASTGEN_SUPER_MethodCall(fl, name, argsp) {
4854 : : this->fromp(fromp);
4855 : : dtypep(nullptr); // V3Width will resolve
4856 : : }
4857 : : AstMethodCall(FileLine* fl, AstNodeExpr* fromp, const string& name, AstArg* argsp = nullptr)
4858 : : : ASTGEN_SUPER_MethodCall(fl, name, argsp) {
4859 : : this->fromp(fromp);
4860 : : }
4861 : : ASTGEN_MEMBERS_AstMethodCall;
4862 : : };
4863 : : class AstNew final : public AstNodeFTaskRef {
4864 : : // New as constructor
4865 : : // Don't need the class we are extracting from, as the "fromp()"'s datatype can get us to it
4866 : : bool m_isImplicit = false; // Implicitly generated from extends args
4867 : : bool m_isScoped = false; // Had :: scope when parsed
4868 : : public:
4869 : : AstNew(FileLine* fl, AstArg* argsp = nullptr, bool isScoped = false)
4870 : : : ASTGEN_SUPER_New(fl, "new", argsp)
4871 : : , m_isScoped{isScoped} {}
4872 : : ASTGEN_MEMBERS_AstNew;
4873 : : void dump(std::ostream& str = std::cout) const override;
4874 : : void dumpJson(std::ostream& str = std::cout) const override;
4875 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
4876 : : int instrCount() const override { return widthInstrs(); }
4877 : : bool isImplicit() const { return m_isImplicit; }
4878 : : void isImplicit(bool flag) { m_isImplicit = flag; }
4879 : : bool isScoped() const { return m_isScoped; }
4880 : : void isScoped(bool flag) { m_isScoped = flag; }
4881 : : bool isPure() override { return false; }
4882 : : };
4883 : : class AstTaskRef final : public AstNodeFTaskRef {
4884 : : // A reference to a task
4885 : : bool m_superReference = false; // Called with super reference
4886 : : public:
4887 : : inline AstTaskRef(FileLine* fl, AstTask* taskp, AstArg* argsp = nullptr);
4888 : : AstTaskRef(FileLine* fl, const string& name, AstArg* argsp = nullptr)
4889 : : : ASTGEN_SUPER_TaskRef(fl, name, argsp) {
4890 : : dtypeSetVoid();
4891 : : }
4892 : : ASTGEN_MEMBERS_AstTaskRef;
4893 : : bool superReference() const { return m_superReference; }
4894 : : void superReference(bool flag) { m_superReference = flag; }
4895 : : };
4896 : :
4897 : : // === AstNodePreSel ===
4898 : : class AstSelBit final : public AstNodePreSel {
4899 : : // Single bit range extraction, perhaps with non-constant selection or array selection
4900 : : // Gets replaced during link with AstArraySel or AstSel
4901 : : // @astgen alias op2 := bitp
4902 : : private:
4903 : : VAccess m_access; // Left hand side assignment
4904 : : public:
4905 : : AstSelBit(FileLine* fl, AstNodeExpr* fromp, AstNodeExpr* bitp)
4906 : : : ASTGEN_SUPER_SelBit(fl, fromp, bitp, nullptr) {
4907 : : UASSERT_OBJ(!v3Global.assertDTypesResolved(), this,
4908 : : "not coded to create after dtypes resolved");
4909 : : }
4910 : : ASTGEN_MEMBERS_AstSelBit;
4911 : : VAccess access() const { return m_access; }
4912 : : void access(const VAccess& flag) { m_access = flag; }
4913 : : };
4914 : : class AstSelExtract final : public AstNodePreSel {
4915 : : // Range extraction, gets replaced with AstSel
4916 : : // @astgen alias op2 := leftp
4917 : : // @astgen alias op3 := rightp
4918 : : public:
4919 : : AstSelExtract(FileLine* fl, AstNodeExpr* fromp, AstNodeExpr* msbp, AstNodeExpr* lsbp)
4920 : : : ASTGEN_SUPER_SelExtract(fl, fromp, msbp, lsbp) {}
4921 : : ASTGEN_MEMBERS_AstSelExtract;
4922 : : };
4923 : : class AstSelMinus final : public AstNodePreSel {
4924 : : // -: range extraction, perhaps with non-constant selection
4925 : : // Gets replaced during link with AstSel
4926 : : // @astgen alias op2 := bitp
4927 : : // @astgen alias op3 := widthp
4928 : : public:
4929 : : AstSelMinus(FileLine* fl, AstNodeExpr* fromp, AstNodeExpr* bitp, AstNodeExpr* widthp)
4930 : : : ASTGEN_SUPER_SelMinus(fl, fromp, bitp, widthp) {}
4931 : : ASTGEN_MEMBERS_AstSelMinus;
4932 : : };
4933 : : class AstSelPlus final : public AstNodePreSel {
4934 : : // +: range extraction, perhaps with non-constant selection
4935 : : // Gets replaced during link with AstSel
4936 : : // @astgen alias op2 := bitp
4937 : : // @astgen alias op3 := widthp
4938 : : public:
4939 : : AstSelPlus(FileLine* fl, AstNodeExpr* fromp, AstNodeExpr* bitp, AstNodeExpr* widthp)
4940 : : : ASTGEN_SUPER_SelPlus(fl, fromp, bitp, widthp) {}
4941 : : ASTGEN_MEMBERS_AstSelPlus;
4942 : : };
4943 : :
4944 : : // === AstNodeQuadop ===
4945 : : class AstCountBits final : public AstNodeQuadop {
4946 : : // Number of bits set in vector
4947 : : public:
4948 : : AstCountBits(FileLine* fl, AstNodeExpr* exprp, AstNodeExpr* ctrl1p)
4949 : : : ASTGEN_SUPER_CountBits(fl, exprp, ctrl1p, ctrl1p->cloneTreePure(false),
4950 : : ctrl1p->cloneTreePure(false)) {}
4951 : : AstCountBits(FileLine* fl, AstNodeExpr* exprp, AstNodeExpr* ctrl1p, AstNodeExpr* ctrl2p)
4952 : : : ASTGEN_SUPER_CountBits(fl, exprp, ctrl1p, ctrl2p, ctrl2p->cloneTreePure(false)) {}
4953 : : AstCountBits(FileLine* fl, AstNodeExpr* exprp, AstNodeExpr* ctrl1p, AstNodeExpr* ctrl2p,
4954 : : AstNodeExpr* ctrl3p)
4955 : : : ASTGEN_SUPER_CountBits(fl, exprp, ctrl1p, ctrl2p, ctrl3p) {}
4956 : : ASTGEN_MEMBERS_AstCountBits;
4957 : : void numberOperate(V3Number& out, const V3Number& expr, const V3Number& ctrl1,
4958 : : const V3Number& ctrl2, const V3Number& ctrl3) override {
4959 : : out.opCountBits(expr, ctrl1, ctrl2, ctrl3);
4960 : : }
4961 : : string emitVerilog() override { return "%f$countbits(%l, %r, %f, %o)"; }
4962 : : string emitC() override { return ""; }
4963 : : bool cleanOut() const override { return false; }
4964 : : bool cleanLhs() const override { return true; }
4965 : : bool cleanRhs() const override { return true; }
4966 : : bool cleanThs() const override { return true; }
4967 : : bool cleanFhs() const override { return true; }
4968 : : bool sizeMattersLhs() const override { return false; }
4969 : : bool sizeMattersRhs() const override { return false; }
4970 : : bool sizeMattersThs() const override { return false; }
4971 : : bool sizeMattersFhs() const override { return false; }
4972 : : bool isSystemFunc() const override { return true; }
4973 : : int instrCount() const override { return widthInstrs() * 16; }
4974 : : };
4975 : :
4976 : : // === AstNodeTermop ===
4977 : : class AstInferredDisable final : public AstNodeTermop {
4978 : : public:
4979 : : explicit AstInferredDisable(FileLine* fl)
4980 : : : ASTGEN_SUPER_InferredDisable(fl) {
4981 : : dtypeSetLogicSized(1, VSigning::UNSIGNED);
4982 : : }
4983 : : ASTGEN_MEMBERS_AstInferredDisable;
4984 : : string emitVerilog() override { return "%f$inferred_disable"; }
4985 : : string emitC() override { V3ERROR_NA_RETURN(""); }
4986 : : bool cleanOut() const override { return true; }
4987 : : bool isSystemFunc() const override { return true; }
4988 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
4989 : : };
4990 : : class AstTime final : public AstNodeTermop {
4991 : : VTimescale m_timeunit; // Parent module time unit
4992 : : public:
4993 : : AstTime(FileLine* fl, const VTimescale& timeunit)
4994 : : : ASTGEN_SUPER_Time(fl)
4995 : : , m_timeunit{timeunit} {
4996 : : dtypeSetUInt64();
4997 : : }
4998 : : ASTGEN_MEMBERS_AstTime;
4999 : : string emitVerilog() override { return "%f$time"; }
5000 : : string emitC() override { V3ERROR_NA_RETURN(""); }
5001 : : bool cleanOut() const override { return true; }
5002 : : bool isGateOptimizable() const override { return false; }
5003 : : bool isPredictOptimizable() const override { return false; }
5004 : : bool isSystemFunc() const override { return true; }
5005 : : int instrCount() const override { return INSTR_COUNT_TIME; }
5006 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
5007 : : void dump(std::ostream& str = std::cout) const override;
5008 : : void dumpJson(std::ostream& str = std::cout) const override;
5009 : : VTimescale timeunit() const { return m_timeunit; }
5010 : : void timeunit(const VTimescale& flag) { m_timeunit = flag; }
5011 : : };
5012 : : class AstTimeD final : public AstNodeTermop {
5013 : : VTimescale m_timeunit; // Parent module time unit
5014 : : public:
5015 : : AstTimeD(FileLine* fl, const VTimescale& timeunit)
5016 : : : ASTGEN_SUPER_TimeD(fl)
5017 : : , m_timeunit{timeunit} {
5018 : : dtypeSetDouble();
5019 : : }
5020 : : ASTGEN_MEMBERS_AstTimeD;
5021 : : string emitVerilog() override { return "%f$realtime"; }
5022 : : string emitC() override { V3ERROR_NA_RETURN(""); }
5023 : : bool cleanOut() const override { return true; }
5024 : : bool isGateOptimizable() const override { return false; }
5025 : : bool isPredictOptimizable() const override { return false; }
5026 : : bool isSystemFunc() const override { return true; }
5027 : : int instrCount() const override { return INSTR_COUNT_TIME; }
5028 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
5029 : : void dump(std::ostream& str = std::cout) const override;
5030 : : void dumpJson(std::ostream& str = std::cout) const override;
5031 : : VTimescale timeunit() const { return m_timeunit; }
5032 : : void timeunit(const VTimescale& flag) { m_timeunit = flag; }
5033 : : };
5034 : :
5035 : : // === AstNodeTriop ===
5036 : :
5037 : : class AstCond final : public AstNodeTriop {
5038 : : // @astgen alias op1 := condp
5039 : : // @astgen alias op2 := thenp
5040 : : // @astgen alias op3 := elsep
5041 : : // @astgen makeDfgVertex
5042 : : public:
5043 : : AstCond(FileLine* fl, AstNodeExpr* condp, AstNodeExpr* thenp, AstNodeExpr* elsep);
5044 : : ASTGEN_MEMBERS_AstCond;
5045 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs,
5046 : : const V3Number& ths) override {
5047 : : out.opAssign(lhs.isNeqZero() ? rhs : ths);
5048 : : }
5049 : : string emitVerilog() override { return "%k(%l %f? %r %k: %t)"; }
5050 : : string emitC() override { return "VL_COND_%nq%lq%rq%tq(%nw, %P, %li, %ri, %ti)"; }
5051 : : string emitSMT() const override { return "(ite (__Vbool %l) %r %t)"; }
5052 : : bool cleanOut() const override { return false; } // clean if e1 & e2 clean
5053 : : bool cleanLhs() const override { return true; }
5054 : : bool cleanRhs() const override { return false; }
5055 : : bool cleanThs() const override { return false; } // Propagates up
5056 : : bool sizeMattersLhs() const override { return false; }
5057 : : bool sizeMattersRhs() const override { return false; }
5058 : : bool sizeMattersThs() const override { return false; }
5059 : : int instrCount() const override { return INSTR_COUNT_BRANCH; }
5060 : : };
5061 : : class AstPostAdd final : public AstNodeTriop {
5062 : : // Post-increment/add
5063 : : // Children: lhsp: AstConst (1) as currently support only ++ not +=
5064 : : // Children: rhsp: tree with AstVarRef that is value to read before operation
5065 : : // Children: thsp: tree with AstVarRef LValue that is stored after operation
5066 : : public:
5067 : : AstPostAdd(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp, AstNodeExpr* thsp)
5068 : : : ASTGEN_SUPER_PostAdd(fl, lhsp, rhsp, thsp) {}
5069 : : ASTGEN_MEMBERS_AstPostAdd;
5070 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs,
5071 : : const V3Number& ths) override {
5072 : : V3ERROR_NA; // Need to modify lhs
5073 : : }
5074 : : string emitVerilog() override { return "%k(%r++)"; }
5075 : : string emitC() override { V3ERROR_NA_RETURN(""); }
5076 : : string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
5077 : : bool cleanOut() const override { V3ERROR_NA_RETURN(false); }
5078 : : bool cleanLhs() const override { V3ERROR_NA_RETURN(false); }
5079 : : bool cleanRhs() const override { V3ERROR_NA_RETURN(false); }
5080 : : bool cleanThs() const override { V3ERROR_NA_RETURN(false); }
5081 : : bool sizeMattersLhs() const override { V3ERROR_NA_RETURN(true); }
5082 : : bool sizeMattersRhs() const override { V3ERROR_NA_RETURN(true); }
5083 : : bool sizeMattersThs() const override { V3ERROR_NA_RETURN(true); }
5084 : : };
5085 : : class AstPostSub final : public AstNodeTriop {
5086 : : // Post-decrement/subtract
5087 : : // Children: lhsp: AstConst (1) as currently support only -- not -=
5088 : : // Children: rhsp: tree with AstVarRef that is value to read before operation
5089 : : // Children: thsp: tree with AstVarRef LValue that is stored after operation
5090 : : public:
5091 : : AstPostSub(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp, AstNodeExpr* thsp)
5092 : : : ASTGEN_SUPER_PostSub(fl, lhsp, rhsp, thsp) {}
5093 : : ASTGEN_MEMBERS_AstPostSub;
5094 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs,
5095 : : const V3Number& ths) override {
5096 : : V3ERROR_NA; // Need to modify lhs
5097 : : }
5098 : : string emitVerilog() override { return "%k(%r--)"; }
5099 : : string emitC() override { V3ERROR_NA_RETURN(""); }
5100 : : string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
5101 : : bool cleanOut() const override { V3ERROR_NA_RETURN(false); }
5102 : : bool cleanLhs() const override { V3ERROR_NA_RETURN(false); }
5103 : : bool cleanRhs() const override { V3ERROR_NA_RETURN(false); }
5104 : : bool cleanThs() const override { V3ERROR_NA_RETURN(false); }
5105 : : bool sizeMattersLhs() const override { V3ERROR_NA_RETURN(true); }
5106 : : bool sizeMattersRhs() const override { V3ERROR_NA_RETURN(true); }
5107 : : bool sizeMattersThs() const override { V3ERROR_NA_RETURN(true); }
5108 : : };
5109 : : class AstPreAdd final : public AstNodeTriop {
5110 : : // Pre-increment/add
5111 : : // Children: lhsp: AstConst (1) as currently support only ++ not +=
5112 : : // Children: rhsp: tree with AstVarRef that is value to read before operation
5113 : : // Children: thsp: tree with AstVarRef LValue that is stored after operation
5114 : : public:
5115 : : AstPreAdd(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp, AstNodeExpr* thsp)
5116 : : : ASTGEN_SUPER_PreAdd(fl, lhsp, rhsp, thsp) {}
5117 : : ASTGEN_MEMBERS_AstPreAdd;
5118 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs,
5119 : : const V3Number& ths) override {
5120 : : V3ERROR_NA; // Need to modify lhs
5121 : : }
5122 : : string emitVerilog() override { return "%k(++%r)"; }
5123 : : string emitC() override { V3ERROR_NA_RETURN(""); }
5124 : : string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
5125 : : bool cleanOut() const override { V3ERROR_NA_RETURN(false); }
5126 : : bool cleanLhs() const override { V3ERROR_NA_RETURN(false); }
5127 : : bool cleanRhs() const override { V3ERROR_NA_RETURN(false); }
5128 : : bool cleanThs() const override { V3ERROR_NA_RETURN(false); }
5129 : : bool sizeMattersLhs() const override { V3ERROR_NA_RETURN(true); }
5130 : : bool sizeMattersRhs() const override { V3ERROR_NA_RETURN(true); }
5131 : : bool sizeMattersThs() const override { V3ERROR_NA_RETURN(true); }
5132 : : };
5133 : : class AstPreSub final : public AstNodeTriop {
5134 : : // Pre-decrement/subtract
5135 : : // Children: lhsp: AstConst (1) as currently support only -- not -=
5136 : : // Children: rhsp: tree with AstVarRef that is value to read before operation
5137 : : // Children: thsp: tree with AstVarRef LValue that is stored after operation
5138 : : public:
5139 : : AstPreSub(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp, AstNodeExpr* thsp)
5140 : : : ASTGEN_SUPER_PreSub(fl, lhsp, rhsp, thsp) {}
5141 : : ASTGEN_MEMBERS_AstPreSub;
5142 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs,
5143 : : const V3Number& ths) override {
5144 : : V3ERROR_NA; // Need to modify lhs
5145 : : }
5146 : : string emitVerilog() override { return "%k(--%r)"; }
5147 : : string emitC() override { V3ERROR_NA_RETURN(""); }
5148 : : string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
5149 : : bool cleanOut() const override { V3ERROR_NA_RETURN(false); }
5150 : : bool cleanLhs() const override { V3ERROR_NA_RETURN(false); }
5151 : : bool cleanRhs() const override { V3ERROR_NA_RETURN(false); }
5152 : : bool cleanThs() const override { V3ERROR_NA_RETURN(false); }
5153 : : bool sizeMattersLhs() const override { V3ERROR_NA_RETURN(true); }
5154 : : bool sizeMattersRhs() const override { V3ERROR_NA_RETURN(true); }
5155 : : bool sizeMattersThs() const override { V3ERROR_NA_RETURN(true); }
5156 : : };
5157 : : class AstPutcN final : public AstNodeTriop {
5158 : : // Verilog string.putc()
5159 : : public:
5160 : : AstPutcN(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp, AstNodeExpr* ths)
5161 : : : ASTGEN_SUPER_PutcN(fl, lhsp, rhsp, ths) {
5162 : : dtypeSetString();
5163 : : }
5164 : : ASTGEN_MEMBERS_AstPutcN;
5165 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs,
5166 : : const V3Number& ths) override {
5167 : : out.opPutcN(lhs, rhs, ths);
5168 : : }
5169 : : string name() const override VL_MT_STABLE { return "putc"; }
5170 : : string emitVerilog() override { return "%k(%l.putc(%r,%t))"; }
5171 : : string emitC() override { return "VL_PUTC_N(%li,%ri,%ti)"; }
5172 : : string emitSimpleOperator() override { return ""; }
5173 : : bool cleanOut() const override { return true; }
5174 : : bool cleanLhs() const override { return true; }
5175 : : bool cleanRhs() const override { return true; }
5176 : : bool cleanThs() const override { return true; }
5177 : : bool sizeMattersLhs() const override { return false; }
5178 : : bool sizeMattersRhs() const override { return false; }
5179 : : bool sizeMattersThs() const override { return false; }
5180 : : };
5181 : : class AstSliceSel final : public AstNodeTriop {
5182 : : // Multiple array element extraction
5183 : : // @astgen alias op1 := fromp
5184 : : VNumRange m_declRange; // Range of the 'from' array if isRanged() is set, else invalid
5185 : : public:
5186 : : AstSliceSel(FileLine* fl, AstNodeExpr* fromp, const VNumRange& declRange)
5187 : : : ASTGEN_SUPER_SliceSel(fl, fromp,
5188 : : new AstConst(fl, declRange.lo()), // Need () constructor
5189 : : new AstConst(fl, declRange.elements())) // Need () constructor
5190 : : , m_declRange{declRange} {}
5191 : : ASTGEN_MEMBERS_AstSliceSel;
5192 : : void dump(std::ostream& str) const override;
5193 : : void dumpJson(std::ostream& str) const override;
5194 : : void numberOperate(V3Number& out, const V3Number& from, const V3Number& lo,
5195 : : const V3Number& width) override {
5196 : : V3ERROR_NA;
5197 : : }
5198 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
5199 : : string emitC() override { V3ERROR_NA_RETURN(""); } // Removed before EmitC
5200 : : bool cleanOut() const override { return false; }
5201 : : bool cleanLhs() const override { return false; }
5202 : : bool cleanRhs() const override { return true; }
5203 : : bool cleanThs() const override { return true; }
5204 : : bool sizeMattersLhs() const override { return false; }
5205 : : bool sizeMattersRhs() const override { return false; }
5206 : : bool sizeMattersThs() const override { return false; }
5207 : : bool sameNode(const AstNode*) const override { return true; }
5208 : : int instrCount() const override { return 10; } // Removed before matters
5209 : : // For widthConst()/loConst etc, see declRange().elements() and other VNumRange methods
5210 : : VNumRange& declRange() VL_MT_STABLE { return m_declRange; }
5211 : : const VNumRange& declRange() const VL_MT_STABLE { return m_declRange; }
5212 : : };
5213 : : class AstSubstrN final : public AstNodeTriop {
5214 : : // Verilog string.substr()
5215 : : public:
5216 : : AstSubstrN(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp, AstNodeExpr* ths)
5217 : : : ASTGEN_SUPER_SubstrN(fl, lhsp, rhsp, ths) {
5218 : : dtypeSetString();
5219 : : }
5220 : : ASTGEN_MEMBERS_AstSubstrN;
5221 : : void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs,
5222 : : const V3Number& ths) override {
5223 : : out.opSubstrN(lhs, rhs, ths);
5224 : : }
5225 : : string name() const override VL_MT_STABLE { return "substr"; }
5226 : : string emitVerilog() override { return "%k(%l.substr(%r,%t))"; }
5227 : : string emitC() override { return "VL_SUBSTR_N(%li,%ri,%ti)"; }
5228 : : string emitSimpleOperator() override { return ""; }
5229 : : bool cleanOut() const override { return true; }
5230 : : bool cleanLhs() const override { return true; }
5231 : : bool cleanRhs() const override { return true; }
5232 : : bool cleanThs() const override { return true; }
5233 : : bool sizeMattersLhs() const override { return false; }
5234 : : bool sizeMattersRhs() const override { return false; }
5235 : : bool sizeMattersThs() const override { return false; }
5236 : : };
5237 : :
5238 : : // === AstNodeDistTriop ===
5239 : : class AstDistErlang final : public AstNodeDistTriop {
5240 : : public:
5241 : : AstDistErlang(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp, AstNodeExpr* thsp)
5242 : : : ASTGEN_SUPER_DistErlang(fl, lhsp, rhsp, thsp) {}
5243 : : ASTGEN_MEMBERS_AstDistErlang;
5244 : : string emitVerilog() override { return "%f$dist_erlang(%l, %r, %t)"; }
5245 : : string emitC() override { return "VL_DIST_ERLANG(%li, %ri, %ti)"; }
5246 : : };
5247 : : class AstDistNormal final : public AstNodeDistTriop {
5248 : : public:
5249 : : AstDistNormal(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp, AstNodeExpr* thsp)
5250 : : : ASTGEN_SUPER_DistNormal(fl, lhsp, rhsp, thsp) {}
5251 : : ASTGEN_MEMBERS_AstDistNormal;
5252 : : string emitVerilog() override { return "%f$dist_normal(%l, %r, %t)"; }
5253 : : string emitC() override { return "VL_DIST_NORMAL(%li, %ri, %ti)"; }
5254 : : };
5255 : : class AstDistUniform final : public AstNodeDistTriop {
5256 : : public:
5257 : : AstDistUniform(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp, AstNodeExpr* thsp)
5258 : : : ASTGEN_SUPER_DistUniform(fl, lhsp, rhsp, thsp) {}
5259 : : ASTGEN_MEMBERS_AstDistUniform;
5260 : : string emitVerilog() override { return "%f$dist_uniform(%l, %r, %t)"; }
5261 : : string emitC() override { return "VL_DIST_UNIFORM(%li, %ri, %ti)"; }
5262 : : };
5263 : :
5264 : : // === AstNodeUniop ===
5265 : : class AstAtoN final : public AstNodeUniop {
5266 : : // string.atoi(), atobin(), atohex(), atooct(), atoireal()
5267 : : public:
5268 : : enum FmtType { ATOI = 10, ATOHEX = 16, ATOOCT = 8, ATOBIN = 2, ATOREAL = -1 };
5269 : :
5270 : : private:
5271 : : const FmtType m_fmt; // Operation type
5272 : : public:
5273 : : AstAtoN(FileLine* fl, AstNodeExpr* lhsp, FmtType fmt)
5274 : : : ASTGEN_SUPER_AtoN(fl, lhsp)
5275 : : , m_fmt{fmt} {
5276 : : fmt == ATOREAL ? dtypeSetDouble() : dtypeSetSigned32();
5277 : : }
5278 : : ASTGEN_MEMBERS_AstAtoN;
5279 : : void numberOperate(V3Number& out, const V3Number& lhs) override { out.opAtoN(lhs, m_fmt); }
5280 : : string name() const override VL_MT_STABLE {
5281 : : switch (m_fmt) {
5282 : : case ATOI: return "atoi";
5283 : : case ATOHEX: return "atohex";
5284 : : case ATOOCT: return "atooct";
5285 : : case ATOBIN: return "atobin";
5286 : : case ATOREAL: return "atoreal";
5287 : : }
5288 : : V3ERROR_NA_RETURN("");
5289 : : }
5290 : : string emitVerilog() override { return "%l." + name() + "()"; }
5291 : : string emitC() override {
5292 : : switch (m_fmt) {
5293 : : case ATOI: return "VL_ATOI_N(%li, 10)";
5294 : : case ATOHEX: return "VL_ATOI_N(%li, 16)";
5295 : : case ATOOCT: return "VL_ATOI_N(%li, 8)";
5296 : : case ATOBIN: return "VL_ATOI_N(%li, 2)";
5297 : : case ATOREAL: return "std::atof(%li.c_str())";
5298 : : }
5299 : : V3ERROR_NA_RETURN("");
5300 : : }
5301 : : bool cleanOut() const override { return true; }
5302 : : bool cleanLhs() const override { return true; }
5303 : : bool sizeMattersLhs() const override { return false; }
5304 : : FmtType format() const { return m_fmt; }
5305 : : };
5306 : : class AstBitsToRealD final : public AstNodeUniop {
5307 : : public:
5308 : : AstBitsToRealD(FileLine* fl, AstNodeExpr* lhsp)
5309 : : : ASTGEN_SUPER_BitsToRealD(fl, lhsp) {
5310 : : dtypeSetDouble();
5311 : : }
5312 : : ASTGEN_MEMBERS_AstBitsToRealD;
5313 : : void numberOperate(V3Number& out, const V3Number& lhs) override { out.opBitsToRealD(lhs); }
5314 : : string emitVerilog() override { return "%f$bitstoreal(%l)"; }
5315 : : string emitC() override { return "VL_CVT_D_Q(%li)"; }
5316 : : bool cleanOut() const override { return false; }
5317 : : bool cleanLhs() const override { return false; } // Eliminated before matters
5318 : : bool sizeMattersLhs() const override { return false; } // Eliminated before matters
5319 : : int instrCount() const override { return INSTR_COUNT_DBL; }
5320 : : bool isSystemFunc() const override { return true; }
5321 : : };
5322 : : class AstCCast final : public AstNodeUniop {
5323 : : // Cast to C-based data type
5324 : : int m_size;
5325 : :
5326 : : public:
5327 : : AstCCast(FileLine* fl, AstNodeExpr* lhsp, int setwidth, int minwidth = -1)
5328 : : : ASTGEN_SUPER_CCast(fl, lhsp) {
5329 : : m_size = setwidth;
5330 : : if (setwidth) {
5331 : : if (minwidth == -1) minwidth = setwidth;
5332 : : dtypeSetBitUnsized(setwidth, minwidth, VSigning::UNSIGNED);
5333 : : }
5334 : : }
5335 : : // cppcheck-suppress constParameterPointer
5336 : : // cppcheck-suppress constParameterCallback
5337 : : AstCCast(FileLine* fl, AstNodeExpr* lhsp, AstNode* typeFromp)
5338 : : : ASTGEN_SUPER_CCast(fl, lhsp) {
5339 : : dtypeFrom(typeFromp);
5340 : : m_size = width();
5341 : : }
5342 : : ASTGEN_MEMBERS_AstCCast;
5343 : : void numberOperate(V3Number& out, const V3Number& lhs) override { out.opAssign(lhs); }
5344 : : string emitVerilog() override { return "%f$_CAST(%l)"; }
5345 : : string emitC() override { return "VL_CAST_%nq%lq(%nw,%lw, %P, %li)"; }
5346 : : bool cleanOut() const override { return true; }
5347 : : bool cleanLhs() const override { return true; }
5348 : : bool sizeMattersLhs() const override { return false; } // Special cased in V3Cast
5349 : : bool sameNode(const AstNode* samep) const override {
5350 : : return size() == VN_DBG_AS(samep, CCast)->size();
5351 : : }
5352 : : void dump(std::ostream& str = std::cout) const override;
5353 : : void dumpJson(std::ostream& str = std::cout) const override;
5354 : : //
5355 : : int size() const { return m_size; }
5356 : : };
5357 : : class AstCLog2 final : public AstNodeUniop {
5358 : : public:
5359 : : AstCLog2(FileLine* fl, AstNodeExpr* lhsp)
5360 : : : ASTGEN_SUPER_CLog2(fl, lhsp) {
5361 : : dtypeSetSigned32();
5362 : : }
5363 : : ASTGEN_MEMBERS_AstCLog2;
5364 : : void numberOperate(V3Number& out, const V3Number& lhs) override { out.opCLog2(lhs); }
5365 : : string emitVerilog() override { return "%f$clog2(%l)"; }
5366 : : string emitC() override { return "VL_CLOG2_%lq(%lW, %P, %li)"; }
5367 : : bool cleanOut() const override { return false; }
5368 : : bool cleanLhs() const override { return true; }
5369 : : bool sizeMattersLhs() const override { return false; }
5370 : : int instrCount() const override { return widthInstrs() * 16; }
5371 : : bool isSystemFunc() const override { return true; }
5372 : : };
5373 : : class AstCastWrap final : public AstNodeUniop {
5374 : : // A cast which has been expanded and the LHSP does all the lifting
5375 : : // This remains until V3Width final commit pass to suppress ENUMVALUE warnings
5376 : : public:
5377 : : AstCastWrap(FileLine* fl, AstNodeExpr* lhsp)
5378 : : : ASTGEN_SUPER_CastWrap(fl, lhsp) {}
5379 : : ASTGEN_MEMBERS_AstCastWrap;
5380 : : void numberOperate(V3Number& out, const V3Number& lhs) override { out.opAssign(lhs); }
5381 : : string emitVerilog() override { return "(%l)"; }
5382 : : string emitC() override { V3ERROR_NA_RETURN(""); }
5383 : : bool cleanOut() const override { return false; }
5384 : : bool cleanLhs() const override { return false; }
5385 : : bool sizeMattersLhs() const override { return false; }
5386 : : int instrCount() const override { return 0; }
5387 : : };
5388 : : class AstCountOnes final : public AstNodeUniop {
5389 : : // Number of bits set in vector
5390 : : // @astgen makeDfgVertex
5391 : : public:
5392 : : AstCountOnes(FileLine* fl, AstNodeExpr* lhsp)
5393 : : : ASTGEN_SUPER_CountOnes(fl, lhsp) {}
5394 : : ASTGEN_MEMBERS_AstCountOnes;
5395 : : void numberOperate(V3Number& out, const V3Number& lhs) override { out.opCountOnes(lhs); }
5396 : : string emitVerilog() override { return "%f$countones(%l)"; }
5397 : : string emitC() override { return "VL_COUNTONES_%lq(%lW, %P, %li)"; }
5398 : : bool cleanOut() const override { return false; }
5399 : : bool cleanLhs() const override { return true; }
5400 : : bool sizeMattersLhs() const override { return false; }
5401 : : int instrCount() const override { return widthInstrs() * 16; }
5402 : : bool isSystemFunc() const override { return true; }
5403 : : };
5404 : : class AstCvtPackString final : public AstNodeUniop {
5405 : : // Convert to Verilator Packed String (aka verilog "string")
5406 : : public:
5407 : : AstCvtPackString(FileLine* fl, AstNodeExpr* lhsp)
5408 : : : ASTGEN_SUPER_CvtPackString(fl, lhsp) {
5409 : : dtypeSetString();
5410 : : }
5411 : : ASTGEN_MEMBERS_AstCvtPackString;
5412 : : void numberOperate(V3Number& out, const V3Number& lhs) override { out.opAssign(lhs); }
5413 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
5414 : : string emitC() override { V3ERROR_NA_RETURN(""); }
5415 : : bool cleanOut() const override { return true; }
5416 : : bool cleanLhs() const override { return true; }
5417 : : bool sizeMattersLhs() const override { return false; }
5418 : : bool sameNode(const AstNode* /*samep*/) const override { return true; }
5419 : : };
5420 : : class AstExtend final : public AstNodeUniop {
5421 : : // Expand a value into a wider entity by 0 extension. Width is implied from nodep->width()
5422 : : // @astgen makeDfgVertex
5423 : : public:
5424 : : AstExtend(FileLine* fl, AstNodeExpr* lhsp)
5425 : : : ASTGEN_SUPER_Extend(fl, lhsp) {}
5426 : : AstExtend(FileLine* fl, AstNodeExpr* lhsp, int width)
5427 : : : ASTGEN_SUPER_Extend(fl, lhsp) {
5428 : : dtypeSetLogicSized(width, VSigning::UNSIGNED);
5429 : : }
5430 : : ASTGEN_MEMBERS_AstExtend;
5431 : : void numberOperate(V3Number& out, const V3Number& lhs) override { out.opAssign(lhs); }
5432 : : string emitVerilog() override { return "%l"; }
5433 : : string emitC() override { return "VL_EXTEND_%nq%lq(%nw,%lw, %P, %li)"; }
5434 : : string emitSMT() const override {
5435 : : return "((_ zero_extend " + cvtToStr(width() - lhsp()->width()) + ") %l)";
5436 : : }
5437 : : bool cleanOut() const override { return true; }
5438 : : bool cleanLhs() const override { return true; }
5439 : : bool sizeMattersLhs() const override {
5440 : : return false; // Because the EXTEND operator self-casts
5441 : : }
5442 : : int instrCount() const override { return 0; }
5443 : : };
5444 : : class AstExtendS final : public AstNodeUniop {
5445 : : // Expand a value into a wider entity by sign extension. Width is implied from nodep->width()
5446 : : // @astgen makeDfgVertex
5447 : : public:
5448 : : AstExtendS(FileLine* fl, AstNodeExpr* lhsp)
5449 : : : ASTGEN_SUPER_ExtendS(fl, lhsp) {}
5450 : : AstExtendS(FileLine* fl, AstNodeExpr* lhsp, int width)
5451 : : // Important that widthMin be correct, as opExtend requires it after V3Expand
5452 : : : ASTGEN_SUPER_ExtendS(fl, lhsp) {
5453 : : dtypeSetLogicSized(width, VSigning::UNSIGNED);
5454 : : }
5455 : : ASTGEN_MEMBERS_AstExtendS;
5456 : : void numberOperate(V3Number& out, const V3Number& lhs) override {
5457 : : out.opExtendS(lhs, lhsp()->widthMinV());
5458 : : }
5459 : : string emitVerilog() override { return "%l"; }
5460 : : string emitC() override { return "VL_EXTENDS_%nq%lq(%nw,%lw, %P, %li)"; }
5461 : : string emitSMT() const override {
5462 : : return "((_ sign_extend " + cvtToStr(width() - lhsp()->width()) + ") %l)";
5463 : : }
5464 : : bool cleanOut() const override { return false; }
5465 : : bool cleanLhs() const override { return true; }
5466 : : bool sizeMattersLhs() const override {
5467 : : return false; // Because the EXTEND operator self-casts
5468 : : }
5469 : : int instrCount() const override { return 0; }
5470 : : bool signedFlavor() const override { return true; }
5471 : : };
5472 : : class AstFEof final : public AstNodeUniop {
5473 : : public:
5474 : : AstFEof(FileLine* fl, AstNodeExpr* lhsp)
5475 : : : ASTGEN_SUPER_FEof(fl, lhsp) {}
5476 : : ASTGEN_MEMBERS_AstFEof;
5477 : : void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; }
5478 : : string emitVerilog() override { return "%f$feof(%l)"; }
5479 : : string emitC() override { return "(%li ? feof(VL_CVT_I_FP(%li)) : true)"; }
5480 : : bool cleanOut() const override { return true; }
5481 : : bool cleanLhs() const override { return true; }
5482 : : bool sizeMattersLhs() const override { return false; }
5483 : : int instrCount() const override { return widthInstrs() * 16; }
5484 : : bool isPredictOptimizable() const override { return false; }
5485 : : bool isPure() override { return false; } // SPECIAL: $display has 'visual' ordering
5486 : : bool isSystemFunc() const override { return true; }
5487 : : AstNode* filep() const { return lhsp(); }
5488 : : };
5489 : : class AstFGetC final : public AstNodeUniop {
5490 : : public:
5491 : : AstFGetC(FileLine* fl, AstNodeExpr* lhsp)
5492 : : : ASTGEN_SUPER_FGetC(fl, lhsp) {}
5493 : : ASTGEN_MEMBERS_AstFGetC;
5494 : : void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; }
5495 : : string emitVerilog() override { return "%f$fgetc(%l)"; }
5496 : : // Non-existent filehandle returns EOF
5497 : : string emitC() override { return "(%li ? fgetc(VL_CVT_I_FP(%li)) : -1)"; }
5498 : : bool cleanOut() const override { return false; }
5499 : : bool cleanLhs() const override { return true; }
5500 : : bool sizeMattersLhs() const override { return false; }
5501 : : int instrCount() const override { return widthInstrs() * 64; }
5502 : : bool isPredictOptimizable() const override { return false; }
5503 : : bool isPure() override { return false; } // SPECIAL: $display has 'visual' ordering
5504 : : AstNode* filep() const { return lhsp(); }
5505 : : bool isSystemFunc() const override { return true; }
5506 : : };
5507 : : class AstISToRD final : public AstNodeUniop {
5508 : : // $itor where lhs is signed
5509 : : public:
5510 : : AstISToRD(FileLine* fl, AstNodeExpr* lhsp)
5511 : : : ASTGEN_SUPER_ISToRD(fl, lhsp) {
5512 : : dtypeSetDouble();
5513 : : }
5514 : : ASTGEN_MEMBERS_AstISToRD;
5515 : : void numberOperate(V3Number& out, const V3Number& lhs) override { out.opISToRD(lhs); }
5516 : : string emitVerilog() override { return "%f$itor($signed(%l))"; }
5517 : : string emitC() override { return "VL_ISTOR_D_%lq(%lw, %li)"; }
5518 : : bool emitCheckMaxWords() override { return true; }
5519 : : bool cleanOut() const override { return false; }
5520 : : bool cleanLhs() const override { return true; }
5521 : : bool sizeMattersLhs() const override { return false; }
5522 : : int instrCount() const override { return INSTR_COUNT_DBL; }
5523 : : bool isSystemFunc() const override { return true; }
5524 : : };
5525 : : class AstIToRD final : public AstNodeUniop {
5526 : : // $itor where lhs is unsigned
5527 : : public:
5528 : : AstIToRD(FileLine* fl, AstNodeExpr* lhsp)
5529 : : : ASTGEN_SUPER_IToRD(fl, lhsp) {
5530 : : dtypeSetDouble();
5531 : : }
5532 : : ASTGEN_MEMBERS_AstIToRD;
5533 : : void numberOperate(V3Number& out, const V3Number& lhs) override { out.opIToRD(lhs); }
5534 : : string emitVerilog() override { return "%f$itor(%l)"; }
5535 : : string emitC() override { return "VL_ITOR_D_%lq(%lw, %li)"; }
5536 : : bool cleanOut() const override { return false; }
5537 : : bool cleanLhs() const override { return true; }
5538 : : bool sizeMattersLhs() const override { return false; }
5539 : : int instrCount() const override { return INSTR_COUNT_DBL; }
5540 : : bool isSystemFunc() const override { return true; }
5541 : : };
5542 : : class AstIsUnbounded final : public AstNodeUniop {
5543 : : // True if is unbounded ($)
5544 : : public:
5545 : : AstIsUnbounded(FileLine* fl, AstNodeExpr* lhsp)
5546 : : : ASTGEN_SUPER_IsUnbounded(fl, lhsp) {
5547 : : dtypeSetBit();
5548 : : }
5549 : : ASTGEN_MEMBERS_AstIsUnbounded;
5550 : : void numberOperate(V3Number& out, const V3Number&) override {
5551 : : // Any constant isn't unbounded
5552 : : out.setZero();
5553 : : }
5554 : : string emitVerilog() override { return "%f$isunbounded(%l)"; }
5555 : : string emitC() override { V3ERROR_NA_RETURN(""); }
5556 : : bool cleanOut() const override { return false; }
5557 : : bool cleanLhs() const override { return false; }
5558 : : bool sizeMattersLhs() const override { return false; }
5559 : : bool isSystemFunc() const override { return true; }
5560 : : };
5561 : : class AstIsUnknown final : public AstNodeUniop {
5562 : : // True if any unknown bits
5563 : : public:
5564 : : AstIsUnknown(FileLine* fl, AstNodeExpr* lhsp)
5565 : : : ASTGEN_SUPER_IsUnknown(fl, lhsp) {
5566 : : dtypeSetBit();
5567 : : }
5568 : : ASTGEN_MEMBERS_AstIsUnknown;
5569 : : void numberOperate(V3Number& out, const V3Number& lhs) override { out.opIsUnknown(lhs); }
5570 : : string emitVerilog() override { return "%f$isunknown(%l)"; }
5571 : : string emitC() override { V3ERROR_NA_RETURN(""); }
5572 : : bool cleanOut() const override { return false; }
5573 : : bool cleanLhs() const override { return false; }
5574 : : bool sizeMattersLhs() const override { return false; }
5575 : : bool isSystemFunc() const override { return true; }
5576 : : };
5577 : : class AstLenN final : public AstNodeUniop {
5578 : : // Length of a string
5579 : : public:
5580 : : AstLenN(FileLine* fl, AstNodeExpr* lhsp)
5581 : : : ASTGEN_SUPER_LenN(fl, lhsp) {
5582 : : dtypeSetSigned32();
5583 : : }
5584 : : ASTGEN_MEMBERS_AstLenN;
5585 : : void numberOperate(V3Number& out, const V3Number& lhs) override { out.opLenN(lhs); }
5586 : : string emitVerilog() override { return "%f(%l)"; }
5587 : : string emitC() override { return "VL_LEN_IN(%li)"; }
5588 : : bool cleanOut() const override { return true; }
5589 : : bool cleanLhs() const override { return true; }
5590 : : bool sizeMattersLhs() const override { return false; }
5591 : : };
5592 : : class AstLogNot final : public AstNodeUniop {
5593 : : // @astgen makeDfgVertex
5594 : : public:
5595 : : AstLogNot(FileLine* fl, AstNodeExpr* lhsp)
5596 : : : ASTGEN_SUPER_LogNot(fl, lhsp) {
5597 : : dtypeSetBit();
5598 : : }
5599 : : ASTGEN_MEMBERS_AstLogNot;
5600 : : void numberOperate(V3Number& out, const V3Number& lhs) override { out.opLogNot(lhs); }
5601 : : string emitVerilog() override { return "%f(! %l)"; }
5602 : : string emitC() override { return "VL_LOGNOT_%nq%lq(%nw,%lw, %P, %li)"; }
5603 : : string emitSMT() const override { return "(__Vbv (not (__Vbool %l)))"; }
5604 : : string emitSimpleOperator() override { return "!"; }
5605 : : bool cleanOut() const override { return true; }
5606 : : bool cleanLhs() const override { return true; }
5607 : : bool sizeMattersLhs() const override { return false; }
5608 : : };
5609 : : class AstNToI final : public AstNodeUniop {
5610 : : // String to any-size integral
5611 : : public:
5612 : : AstNToI(FileLine* fl, AstNodeExpr* lhsp, AstNodeDType* dtypep = nullptr)
5613 : : : ASTGEN_SUPER_NToI(fl, lhsp) {
5614 : : this->dtypep(dtypep);
5615 : : }
5616 : : ASTGEN_MEMBERS_AstNToI;
5617 : : void numberOperate(V3Number& out, const V3Number& lhs) override { out.opNToI(lhs); }
5618 : : string emitVerilog() override { return "'(%l)"; }
5619 : : string emitC() override { return "VL_NTOI_%nq(%nw, %P, %li)"; }
5620 : : bool cleanOut() const override { return true; }
5621 : : bool cleanLhs() const override { return true; }
5622 : : bool sizeMattersLhs() const override { return false; }
5623 : : };
5624 : : class AstNegate final : public AstNodeUniop {
5625 : : // @astgen makeDfgVertex
5626 : : public:
5627 : : AstNegate(FileLine* fl, AstNodeExpr* lhsp)
5628 : : : ASTGEN_SUPER_Negate(fl, lhsp) {
5629 : : dtypeFrom(lhsp);
5630 : : }
5631 : : ASTGEN_MEMBERS_AstNegate;
5632 : : void numberOperate(V3Number& out, const V3Number& lhs) override { out.opNegate(lhs); }
5633 : : string emitVerilog() override { return "%f(- %l)"; }
5634 : : string emitC() override { return "VL_NEGATE_%lq(%lW, %P, %li)"; }
5635 : : string emitSMT() const override { return "(bvneg %l)"; }
5636 : : string emitSimpleOperator() override { return "-"; }
5637 : : bool cleanOut() const override { return false; }
5638 : : bool cleanLhs() const override { return false; }
5639 : : bool sizeMattersLhs() const override { return true; }
5640 : : };
5641 : : class AstNegateD final : public AstNodeUniop {
5642 : : public:
5643 : : AstNegateD(FileLine* fl, AstNodeExpr* lhsp)
5644 : : : ASTGEN_SUPER_NegateD(fl, lhsp) {
5645 : : dtypeSetDouble();
5646 : : }
5647 : : ASTGEN_MEMBERS_AstNegateD;
5648 : : void numberOperate(V3Number& out, const V3Number& lhs) override { out.opNegateD(lhs); }
5649 : : string emitVerilog() override { return "%f(- %l)"; }
5650 : : string emitC() override { V3ERROR_NA_RETURN(""); }
5651 : : string emitSimpleOperator() override { return "-"; }
5652 : : bool cleanOut() const override { return true; }
5653 : : bool cleanLhs() const override { return false; }
5654 : : bool sizeMattersLhs() const override { return false; }
5655 : : int instrCount() const override { return INSTR_COUNT_DBL; }
5656 : : bool doubleFlavor() const override { return true; }
5657 : : };
5658 : : class AstNot final : public AstNodeUniop {
5659 : : // @astgen makeDfgVertex
5660 : : public:
5661 : : AstNot(FileLine* fl, AstNodeExpr* lhsp)
5662 : : : ASTGEN_SUPER_Not(fl, lhsp) {
5663 : : dtypeFrom(lhsp);
5664 : : }
5665 : : ASTGEN_MEMBERS_AstNot;
5666 : : void numberOperate(V3Number& out, const V3Number& lhs) override { out.opNot(lhs); }
5667 : : string emitVerilog() override { return "%f(~ %l)"; }
5668 : : string emitC() override { return "VL_NOT_%lq(%lW, %P, %li)"; }
5669 : : string emitSMT() const override { return "(bvnot %l)"; }
5670 : : string emitSimpleOperator() override { return "~"; }
5671 : : bool cleanOut() const override { return false; }
5672 : : bool cleanLhs() const override { return false; }
5673 : : bool sizeMattersLhs() const override { return true; }
5674 : : const char* widthMismatch() const override VL_MT_STABLE;
5675 : : };
5676 : : class AstNullCheck final : public AstNodeUniop {
5677 : : // Return LHS after checking that LHS is non-null
5678 : : public:
5679 : : AstNullCheck(FileLine* fl, AstNodeExpr* lhsp)
5680 : : : ASTGEN_SUPER_NullCheck(fl, lhsp) {
5681 : : dtypeFrom(lhsp);
5682 : : }
5683 : : ASTGEN_MEMBERS_AstNullCheck;
5684 : : void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; }
5685 : : int instrCount() const override { return 1; } // Rarely executes
5686 : : string emitVerilog() override { return "%l"; }
5687 : : string emitC() override { V3ERROR_NA_RETURN(""); }
5688 : : string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
5689 : : bool cleanOut() const override { return true; }
5690 : : bool cleanLhs() const override { return true; }
5691 : : bool sizeMattersLhs() const override { return false; }
5692 : : bool sameNode(const AstNode* samep) const override { return fileline() == samep->fileline(); }
5693 : : };
5694 : : class AstOneHot final : public AstNodeUniop {
5695 : : // True if only single bit set in vector
5696 : : public:
5697 : : AstOneHot(FileLine* fl, AstNodeExpr* lhsp)
5698 : : : ASTGEN_SUPER_OneHot(fl, lhsp) {
5699 : : dtypeSetBit();
5700 : : }
5701 : : ASTGEN_MEMBERS_AstOneHot;
5702 : : void numberOperate(V3Number& out, const V3Number& lhs) override { out.opOneHot(lhs); }
5703 : : string emitVerilog() override { return "%f$onehot(%l)"; }
5704 : : string emitC() override { return "VL_ONEHOT_%lq(%lW, %P, %li)"; }
5705 : : bool cleanOut() const override { return true; }
5706 : : bool cleanLhs() const override { return true; }
5707 : : bool sizeMattersLhs() const override { return false; }
5708 : : int instrCount() const override { return widthInstrs() * 4; }
5709 : : bool isSystemFunc() const override { return true; }
5710 : : };
5711 : : class AstOneHot0 final : public AstNodeUniop {
5712 : : // True if only single bit, or no bits set in vector
5713 : : public:
5714 : : AstOneHot0(FileLine* fl, AstNodeExpr* lhsp)
5715 : : : ASTGEN_SUPER_OneHot0(fl, lhsp) {
5716 : : dtypeSetBit();
5717 : : }
5718 : : ASTGEN_MEMBERS_AstOneHot0;
5719 : : void numberOperate(V3Number& out, const V3Number& lhs) override { out.opOneHot0(lhs); }
5720 : : string emitVerilog() override { return "%f$onehot0(%l)"; }
5721 : : string emitC() override { return "VL_ONEHOT0_%lq(%lW, %P, %li)"; }
5722 : : bool cleanOut() const override { return true; }
5723 : : bool cleanLhs() const override { return true; }
5724 : : bool sizeMattersLhs() const override { return false; }
5725 : : int instrCount() const override { return widthInstrs() * 3; }
5726 : : bool isSystemFunc() const override { return true; }
5727 : : };
5728 : : class AstRToIRoundS final : public AstNodeUniop {
5729 : : // Convert real to integer, with arbitrary sized output (not just "integer" format)
5730 : : public:
5731 : : AstRToIRoundS(FileLine* fl, AstNodeExpr* lhsp)
5732 : : : ASTGEN_SUPER_RToIRoundS(fl, lhsp) {
5733 : : dtypeSetSigned32();
5734 : : }
5735 : : ASTGEN_MEMBERS_AstRToIRoundS;
5736 : : void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRToIRoundS(lhs); }
5737 : : string emitVerilog() override { return "%f$rtoi_rounded(%l)"; }
5738 : : string emitC() override {
5739 : : return isWide() ? "VL_RTOIROUND_%nq_D(%nw, %P, %li)" : "VL_RTOIROUND_%nq_D(%li)";
5740 : : }
5741 : : bool cleanOut() const override { return false; }
5742 : : bool cleanLhs() const override { return false; }
5743 : : bool sizeMattersLhs() const override { return false; }
5744 : : int instrCount() const override { return INSTR_COUNT_DBL; }
5745 : : bool isSystemFunc() const override { return true; }
5746 : : };
5747 : : class AstRToIS final : public AstNodeUniop {
5748 : : // $rtoi(lhs)
5749 : : public:
5750 : : AstRToIS(FileLine* fl, AstNodeExpr* lhsp)
5751 : : : ASTGEN_SUPER_RToIS(fl, lhsp) {
5752 : : dtypeSetSigned32();
5753 : : }
5754 : : ASTGEN_MEMBERS_AstRToIS;
5755 : : void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRToIS(lhs); }
5756 : : string emitVerilog() override { return "%f$rtoi(%l)"; }
5757 : : string emitC() override { return "VL_RTOI_I_D(%li)"; }
5758 : : bool cleanOut() const override { return false; }
5759 : : bool cleanLhs() const override { return false; } // Eliminated before matters
5760 : : bool sizeMattersLhs() const override { return false; } // Eliminated before matters
5761 : : int instrCount() const override { return INSTR_COUNT_DBL; }
5762 : : bool isSystemFunc() const override { return true; }
5763 : : };
5764 : : class AstRealToBits final : public AstNodeUniop {
5765 : : public:
5766 : : AstRealToBits(FileLine* fl, AstNodeExpr* lhsp)
5767 : : : ASTGEN_SUPER_RealToBits(fl, lhsp) {
5768 : : dtypeSetUInt64();
5769 : : }
5770 : : ASTGEN_MEMBERS_AstRealToBits;
5771 : : void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRealToBits(lhs); }
5772 : : string emitVerilog() override { return "%f$realtobits(%l)"; }
5773 : : string emitC() override { return "VL_CVT_Q_D(%li)"; }
5774 : : bool cleanOut() const override { return false; }
5775 : : bool cleanLhs() const override { return false; } // Eliminated before matters
5776 : : bool sizeMattersLhs() const override { return false; } // Eliminated before matters
5777 : : int instrCount() const override { return INSTR_COUNT_DBL; }
5778 : : bool isSystemFunc() const override { return true; }
5779 : : };
5780 : : class AstRedAnd final : public AstNodeUniop {
5781 : : // @astgen makeDfgVertex
5782 : : public:
5783 : : AstRedAnd(FileLine* fl, AstNodeExpr* lhsp)
5784 : : : ASTGEN_SUPER_RedAnd(fl, lhsp) {
5785 : : dtypeSetBit();
5786 : : }
5787 : : ASTGEN_MEMBERS_AstRedAnd;
5788 : : void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedAnd(lhs); }
5789 : : string emitVerilog() override { return "%f(& %l)"; }
5790 : : string emitC() override { return "VL_REDAND_%nq%lq(%lw, %P, %li)"; }
5791 : : bool cleanOut() const override { return true; }
5792 : : bool cleanLhs() const override { return true; }
5793 : : bool sizeMattersLhs() const override { return false; }
5794 : : };
5795 : : class AstRedOr final : public AstNodeUniop {
5796 : : // @astgen makeDfgVertex
5797 : : public:
5798 : : AstRedOr(FileLine* fl, AstNodeExpr* lhsp)
5799 : : : ASTGEN_SUPER_RedOr(fl, lhsp) {
5800 : : dtypeSetBit();
5801 : : }
5802 : : ASTGEN_MEMBERS_AstRedOr;
5803 : : void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedOr(lhs); }
5804 : : string emitVerilog() override { return "%f(| %l)"; }
5805 : : string emitC() override { return "VL_REDOR_%lq(%lW, %P, %li)"; }
5806 : : bool cleanOut() const override { return true; }
5807 : : bool cleanLhs() const override { return true; }
5808 : : bool sizeMattersLhs() const override { return false; }
5809 : : };
5810 : : class AstRedXor final : public AstNodeUniop {
5811 : : // @astgen makeDfgVertex
5812 : : public:
5813 : : AstRedXor(FileLine* fl, AstNodeExpr* lhsp)
5814 : : : ASTGEN_SUPER_RedXor(fl, lhsp) {
5815 : : dtypeSetBit();
5816 : : }
5817 : : ASTGEN_MEMBERS_AstRedXor;
5818 : : void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedXor(lhs); }
5819 : : string emitVerilog() override { return "%f(^ %l)"; }
5820 : : string emitC() override { return "VL_REDXOR_%lq(%lW, %P, %li)"; }
5821 : : bool cleanOut() const override { return false; }
5822 : : bool cleanLhs() const override {
5823 : : const int w = lhsp()->width();
5824 : : return (w != 1 && w != 2 && w != 4 && w != 8 && w != 16);
5825 : : }
5826 : : bool sizeMattersLhs() const override { return false; }
5827 : : int instrCount() const override { return 1 + V3Number::log2b(width()); }
5828 : : };
5829 : : class AstResizeLValue final : public AstNodeUniop {
5830 : : // Resize a LValue into a wider/narrower entity at function argument boundry
5831 : : // Width and signness is implied from nodep->width()
5832 : : public:
5833 : : AstResizeLValue(FileLine* fl, AstNodeExpr* lhsp)
5834 : : : ASTGEN_SUPER_ResizeLValue(fl, lhsp) {}
5835 : : ASTGEN_MEMBERS_AstResizeLValue;
5836 : : void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; }
5837 : : string emitVerilog() override { return "%l"; }
5838 : : string emitC() final override { V3ERROR_NA_RETURN(""); }
5839 : : bool cleanOut() const override { return true; }
5840 : : bool cleanLhs() const override { return true; }
5841 : : bool sizeMattersLhs() const override { return false; }
5842 : : int instrCount() const override { return 0; }
5843 : : };
5844 : : class AstSigned final : public AstNodeUniop {
5845 : : // $signed(lhs)
5846 : : public:
5847 : : AstSigned(FileLine* fl, AstNodeExpr* lhsp)
5848 : : : ASTGEN_SUPER_Signed(fl, lhsp) {
5849 : : UASSERT_OBJ(!v3Global.assertDTypesResolved(), this,
5850 : : "not coded to create after dtypes resolved");
5851 : : }
5852 : : ASTGEN_MEMBERS_AstSigned;
5853 : : void numberOperate(V3Number& out, const V3Number& lhs) override {
5854 : : out.opAssign(lhs);
5855 : : out.isSigned(false);
5856 : : }
5857 : : string emitVerilog() override { return "%f$signed(%l)"; }
5858 : : string emitC() override { V3ERROR_NA_RETURN(""); }
5859 : : bool cleanOut() const override { return false; }
5860 : : bool cleanLhs() const override { return false; } // Eliminated before matters
5861 : : bool sizeMattersLhs() const override { return true; } // Eliminated before matters
5862 : : int instrCount() const override { return 0; }
5863 : : bool isSystemFunc() const override { return true; }
5864 : : };
5865 : : class AstTimeImport final : public AstNodeUniop {
5866 : : // Take a constant that represents a time and needs conversion based on time units
5867 : : VTimescale m_timeunit; // Parent module time unit
5868 : : public:
5869 : : AstTimeImport(FileLine* fl, AstNodeExpr* lhsp)
5870 : : : ASTGEN_SUPER_TimeImport(fl, lhsp) {}
5871 : : ASTGEN_MEMBERS_AstTimeImport;
5872 : : void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; }
5873 : : string emitVerilog() override { return "%l"; }
5874 : : string emitC() override { V3ERROR_NA_RETURN(""); }
5875 : : bool cleanOut() const override { return false; }
5876 : : bool cleanLhs() const override { return false; }
5877 : : bool sizeMattersLhs() const override { return false; }
5878 : : void dump(std::ostream& str = std::cout) const override;
5879 : : void dumpJson(std::ostream& str = std::cout) const override;
5880 : : VTimescale timeunit() const { return m_timeunit; }
5881 : : void timeunit(const VTimescale& flag) { m_timeunit = flag; }
5882 : : };
5883 : : class AstToLowerN final : public AstNodeUniop {
5884 : : // string.tolower()
5885 : : public:
5886 : : AstToLowerN(FileLine* fl, AstNodeExpr* lhsp)
5887 : : : ASTGEN_SUPER_ToLowerN(fl, lhsp) {
5888 : : dtypeSetString();
5889 : : }
5890 : : ASTGEN_MEMBERS_AstToLowerN;
5891 : : void numberOperate(V3Number& out, const V3Number& lhs) override { out.opToLowerN(lhs); }
5892 : : string emitVerilog() override { return "%l.tolower()"; }
5893 : : string emitC() override { return "VL_TOLOWER_NN(%li)"; }
5894 : : bool cleanOut() const override { return true; }
5895 : : bool cleanLhs() const override { return true; }
5896 : : bool sizeMattersLhs() const override { return false; }
5897 : : };
5898 : : class AstToStringN final : public AstNodeUniop {
5899 : : public:
5900 : : AstToStringN(FileLine* fl, AstNodeExpr* lhsp)
5901 : : : ASTGEN_SUPER_ToStringN(fl, lhsp) {
5902 : : dtypeSetString();
5903 : : }
5904 : : ASTGEN_MEMBERS_AstToStringN;
5905 : : void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; }
5906 : : string emitVerilog() override { return "$sformatf(\"%p\", %l)"; }
5907 : : string emitC() override {
5908 : : return isWide() ? "VL_TO_STRING_W(%nw, %li)" : "VL_TO_STRING_DEREF(%li)";
5909 : : }
5910 : : bool cleanOut() const override { return true; }
5911 : : bool cleanLhs() const override { return true; }
5912 : : bool sizeMattersLhs() const override { return false; }
5913 : : };
5914 : : class AstToUpperN final : public AstNodeUniop {
5915 : : // string.toupper()
5916 : : public:
5917 : : AstToUpperN(FileLine* fl, AstNodeExpr* lhsp)
5918 : : : ASTGEN_SUPER_ToUpperN(fl, lhsp) {
5919 : : dtypeSetString();
5920 : : }
5921 : : ASTGEN_MEMBERS_AstToUpperN;
5922 : : void numberOperate(V3Number& out, const V3Number& lhs) override { out.opToUpperN(lhs); }
5923 : : string emitVerilog() override { return "%l.toupper()"; }
5924 : : string emitC() override { return "VL_TOUPPER_NN(%li)"; }
5925 : : bool cleanOut() const override { return true; }
5926 : : bool cleanLhs() const override { return true; }
5927 : : bool sizeMattersLhs() const override { return false; }
5928 : : };
5929 : : class AstUnsigned final : public AstNodeUniop {
5930 : : // $unsigned(lhs)
5931 : : public:
5932 : : AstUnsigned(FileLine* fl, AstNodeExpr* lhsp)
5933 : : : ASTGEN_SUPER_Unsigned(fl, lhsp) {
5934 : : UASSERT_OBJ(!v3Global.assertDTypesResolved(), this,
5935 : : "not coded to create after dtypes resolved");
5936 : : }
5937 : : ASTGEN_MEMBERS_AstUnsigned;
5938 : : void numberOperate(V3Number& out, const V3Number& lhs) override {
5939 : : out.opAssign(lhs);
5940 : : out.isSigned(false);
5941 : : }
5942 : : string emitVerilog() override { return "%f$unsigned(%l)"; }
5943 : : string emitC() override { V3ERROR_NA_RETURN(""); }
5944 : : bool cleanOut() const override { return false; }
5945 : : bool cleanLhs() const override { return false; } // Eliminated before matters
5946 : : bool sizeMattersLhs() const override { return true; } // Eliminated before matters
5947 : : int instrCount() const override { return 0; }
5948 : : bool isSystemFunc() const override { return true; }
5949 : : };
5950 : :
5951 : : // === AstNodeSystemUniopD ===
5952 : : class AstAcosD final : public AstNodeSystemUniopD {
5953 : : public:
5954 : : AstAcosD(FileLine* fl, AstNodeExpr* lhsp)
5955 : : : ASTGEN_SUPER_AcosD(fl, lhsp) {}
5956 : : ASTGEN_MEMBERS_AstAcosD;
5957 : : void numberOperate(V3Number& out, const V3Number& lhs) override {
5958 : : out.setDouble(std::acos(lhs.toDouble()));
5959 : : }
5960 : : string emitVerilog() override { return "%f$acos(%l)"; }
5961 : : string emitC() override { return "acos(%li)"; }
5962 : : };
5963 : : class AstAcoshD final : public AstNodeSystemUniopD {
5964 : : public:
5965 : : AstAcoshD(FileLine* fl, AstNodeExpr* lhsp)
5966 : : : ASTGEN_SUPER_AcoshD(fl, lhsp) {}
5967 : : ASTGEN_MEMBERS_AstAcoshD;
5968 : : void numberOperate(V3Number& out, const V3Number& lhs) override {
5969 : : out.setDouble(std::acosh(lhs.toDouble()));
5970 : : }
5971 : : string emitVerilog() override { return "%f$acosh(%l)"; }
5972 : : string emitC() override { return "acosh(%li)"; }
5973 : : };
5974 : : class AstAsinD final : public AstNodeSystemUniopD {
5975 : : public:
5976 : : AstAsinD(FileLine* fl, AstNodeExpr* lhsp)
5977 : : : ASTGEN_SUPER_AsinD(fl, lhsp) {}
5978 : : ASTGEN_MEMBERS_AstAsinD;
5979 : : void numberOperate(V3Number& out, const V3Number& lhs) override {
5980 : : out.setDouble(std::asin(lhs.toDouble()));
5981 : : }
5982 : : string emitVerilog() override { return "%f$asin(%l)"; }
5983 : : string emitC() override { return "asin(%li)"; }
5984 : : };
5985 : : class AstAsinhD final : public AstNodeSystemUniopD {
5986 : : public:
5987 : : AstAsinhD(FileLine* fl, AstNodeExpr* lhsp)
5988 : : : ASTGEN_SUPER_AsinhD(fl, lhsp) {}
5989 : : ASTGEN_MEMBERS_AstAsinhD;
5990 : : void numberOperate(V3Number& out, const V3Number& lhs) override {
5991 : : out.setDouble(std::asinh(lhs.toDouble()));
5992 : : }
5993 : : string emitVerilog() override { return "%f$asinh(%l)"; }
5994 : : string emitC() override { return "asinh(%li)"; }
5995 : : };
5996 : : class AstAtanD final : public AstNodeSystemUniopD {
5997 : : public:
5998 : : AstAtanD(FileLine* fl, AstNodeExpr* lhsp)
5999 : : : ASTGEN_SUPER_AtanD(fl, lhsp) {}
6000 : : ASTGEN_MEMBERS_AstAtanD;
6001 : : void numberOperate(V3Number& out, const V3Number& lhs) override {
6002 : : out.setDouble(std::atan(lhs.toDouble()));
6003 : : }
6004 : : string emitVerilog() override { return "%f$atan(%l)"; }
6005 : : string emitC() override { return "atan(%li)"; }
6006 : : };
6007 : : class AstAtanhD final : public AstNodeSystemUniopD {
6008 : : public:
6009 : : AstAtanhD(FileLine* fl, AstNodeExpr* lhsp)
6010 : : : ASTGEN_SUPER_AtanhD(fl, lhsp) {}
6011 : : ASTGEN_MEMBERS_AstAtanhD;
6012 : : void numberOperate(V3Number& out, const V3Number& lhs) override {
6013 : : out.setDouble(std::atanh(lhs.toDouble()));
6014 : : }
6015 : : string emitVerilog() override { return "%f$atanh(%l)"; }
6016 : : string emitC() override { return "atanh(%li)"; }
6017 : : };
6018 : : class AstCeilD final : public AstNodeSystemUniopD {
6019 : : public:
6020 : : AstCeilD(FileLine* fl, AstNodeExpr* lhsp)
6021 : : : ASTGEN_SUPER_CeilD(fl, lhsp) {}
6022 : : ASTGEN_MEMBERS_AstCeilD;
6023 : : void numberOperate(V3Number& out, const V3Number& lhs) override {
6024 : : out.setDouble(std::ceil(lhs.toDouble()));
6025 : : }
6026 : : string emitVerilog() override { return "%f$ceil(%l)"; }
6027 : : string emitC() override { return "ceil(%li)"; }
6028 : : };
6029 : : class AstCosD final : public AstNodeSystemUniopD {
6030 : : public:
6031 : : AstCosD(FileLine* fl, AstNodeExpr* lhsp)
6032 : : : ASTGEN_SUPER_CosD(fl, lhsp) {}
6033 : : ASTGEN_MEMBERS_AstCosD;
6034 : : void numberOperate(V3Number& out, const V3Number& lhs) override {
6035 : : out.setDouble(std::cos(lhs.toDouble()));
6036 : : }
6037 : : string emitVerilog() override { return "%f$cos(%l)"; }
6038 : : string emitC() override { return "cos(%li)"; }
6039 : : };
6040 : : class AstCoshD final : public AstNodeSystemUniopD {
6041 : : public:
6042 : : AstCoshD(FileLine* fl, AstNodeExpr* lhsp)
6043 : : : ASTGEN_SUPER_CoshD(fl, lhsp) {}
6044 : : ASTGEN_MEMBERS_AstCoshD;
6045 : : void numberOperate(V3Number& out, const V3Number& lhs) override {
6046 : : out.setDouble(std::cosh(lhs.toDouble()));
6047 : : }
6048 : : string emitVerilog() override { return "%f$cosh(%l)"; }
6049 : : string emitC() override { return "cosh(%li)"; }
6050 : : };
6051 : : class AstExpD final : public AstNodeSystemUniopD {
6052 : : public:
6053 : : AstExpD(FileLine* fl, AstNodeExpr* lhsp)
6054 : : : ASTGEN_SUPER_ExpD(fl, lhsp) {}
6055 : : ASTGEN_MEMBERS_AstExpD;
6056 : : void numberOperate(V3Number& out, const V3Number& lhs) override {
6057 : : out.setDouble(std::exp(lhs.toDouble()));
6058 : : }
6059 : : string emitVerilog() override { return "%f$exp(%l)"; }
6060 : : string emitC() override { return "exp(%li)"; }
6061 : : };
6062 : : class AstFloorD final : public AstNodeSystemUniopD {
6063 : : public:
6064 : : AstFloorD(FileLine* fl, AstNodeExpr* lhsp)
6065 : : : ASTGEN_SUPER_FloorD(fl, lhsp) {}
6066 : : ASTGEN_MEMBERS_AstFloorD;
6067 : : void numberOperate(V3Number& out, const V3Number& lhs) override {
6068 : : out.setDouble(std::floor(lhs.toDouble()));
6069 : : }
6070 : : string emitVerilog() override { return "%f$floor(%l)"; }
6071 : : string emitC() override { return "floor(%li)"; }
6072 : : };
6073 : : class AstLog10D final : public AstNodeSystemUniopD {
6074 : : public:
6075 : : AstLog10D(FileLine* fl, AstNodeExpr* lhsp)
6076 : : : ASTGEN_SUPER_Log10D(fl, lhsp) {}
6077 : : ASTGEN_MEMBERS_AstLog10D;
6078 : : void numberOperate(V3Number& out, const V3Number& lhs) override {
6079 : : out.setDouble(std::log10(lhs.toDouble()));
6080 : : }
6081 : : string emitVerilog() override { return "%f$log10(%l)"; }
6082 : : string emitC() override { return "log10(%li)"; }
6083 : : };
6084 : : class AstLogD final : public AstNodeSystemUniopD {
6085 : : public:
6086 : : AstLogD(FileLine* fl, AstNodeExpr* lhsp)
6087 : : : ASTGEN_SUPER_LogD(fl, lhsp) {}
6088 : : ASTGEN_MEMBERS_AstLogD;
6089 : : void numberOperate(V3Number& out, const V3Number& lhs) override {
6090 : : out.setDouble(std::log(lhs.toDouble()));
6091 : : }
6092 : : string emitVerilog() override { return "%f$ln(%l)"; }
6093 : : string emitC() override { return "log(%li)"; }
6094 : : };
6095 : : class AstSinD final : public AstNodeSystemUniopD {
6096 : : public:
6097 : : AstSinD(FileLine* fl, AstNodeExpr* lhsp)
6098 : : : ASTGEN_SUPER_SinD(fl, lhsp) {}
6099 : : ASTGEN_MEMBERS_AstSinD;
6100 : : void numberOperate(V3Number& out, const V3Number& lhs) override {
6101 : : out.setDouble(std::sin(lhs.toDouble()));
6102 : : }
6103 : : string emitVerilog() override { return "%f$sin(%l)"; }
6104 : : string emitC() override { return "sin(%li)"; }
6105 : : };
6106 : : class AstSinhD final : public AstNodeSystemUniopD {
6107 : : public:
6108 : : AstSinhD(FileLine* fl, AstNodeExpr* lhsp)
6109 : : : ASTGEN_SUPER_SinhD(fl, lhsp) {}
6110 : : ASTGEN_MEMBERS_AstSinhD;
6111 : : void numberOperate(V3Number& out, const V3Number& lhs) override {
6112 : : out.setDouble(std::sinh(lhs.toDouble()));
6113 : : }
6114 : : string emitVerilog() override { return "%f$sinh(%l)"; }
6115 : : string emitC() override { return "sinh(%li)"; }
6116 : : };
6117 : : class AstSqrtD final : public AstNodeSystemUniopD {
6118 : : public:
6119 : : AstSqrtD(FileLine* fl, AstNodeExpr* lhsp)
6120 : : : ASTGEN_SUPER_SqrtD(fl, lhsp) {}
6121 : : ASTGEN_MEMBERS_AstSqrtD;
6122 : : void numberOperate(V3Number& out, const V3Number& lhs) override {
6123 : : out.setDouble(std::sqrt(lhs.toDouble()));
6124 : : }
6125 : : string emitVerilog() override { return "%f$sqrt(%l)"; }
6126 : : string emitC() override { return "sqrt(%li)"; }
6127 : : };
6128 : : class AstTanD final : public AstNodeSystemUniopD {
6129 : : public:
6130 : : AstTanD(FileLine* fl, AstNodeExpr* lhsp)
6131 : : : ASTGEN_SUPER_TanD(fl, lhsp) {}
6132 : : ASTGEN_MEMBERS_AstTanD;
6133 : : void numberOperate(V3Number& out, const V3Number& lhs) override {
6134 : : out.setDouble(std::tan(lhs.toDouble()));
6135 : : }
6136 : : string emitVerilog() override { return "%f$tan(%l)"; }
6137 : : string emitC() override { return "tan(%li)"; }
6138 : : };
6139 : : class AstTanhD final : public AstNodeSystemUniopD {
6140 : : public:
6141 : : AstTanhD(FileLine* fl, AstNodeExpr* lhsp)
6142 : : : ASTGEN_SUPER_TanhD(fl, lhsp) {}
6143 : : ASTGEN_MEMBERS_AstTanhD;
6144 : : void numberOperate(V3Number& out, const V3Number& lhs) override {
6145 : : out.setDouble(std::tanh(lhs.toDouble()));
6146 : : }
6147 : : string emitVerilog() override { return "%f$tanh(%l)"; }
6148 : : string emitC() override { return "tanh(%li)"; }
6149 : : };
6150 : :
6151 : : // === AstNodeVarRef ===
6152 : : class AstVarRef final : public AstNodeVarRef {
6153 : : // A reference to a variable (lvalue or rvalue)
6154 : : std::string m_name; // Name of varref, though name() favors varp()->namep()
6155 : : // if non-null pointer (e.g.: 'this')
6156 : : public:
6157 : : // This form only allowed post-link because output/wire compression may
6158 : : // lead to deletion of AstVar's
6159 : : inline AstVarRef(FileLine* fl, AstVar* varp, const VAccess& access);
6160 : : inline AstVarRef(FileLine* fl, AstNodeModule* classOrPackagep, AstVar* varp,
6161 : : const VAccess& access);
6162 : : // This form only allowed post-link (see above)
6163 : : inline AstVarRef(FileLine* fl, AstVarScope* varscp, const VAccess& access);
6164 : : ASTGEN_MEMBERS_AstVarRef;
6165 : : std::string nameThis() const { return m_name; }
6166 : : inline string name() const override; // * = Var name
6167 : : void name(const string& name) override { m_name = name; }
6168 : : void dump(std::ostream& str) const override;
6169 : : void dumpJson(std::ostream& str) const override;
6170 : : const char* broken() const override;
6171 : : bool sameNode(const AstNode* samep) const override;
6172 : : inline bool sameNode(const AstVarRef* samep) const;
6173 : : inline bool sameNoLvalue(const AstVarRef* samep) const;
6174 : : int instrCount() const override;
6175 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
6176 : : string emitC() override { V3ERROR_NA_RETURN(""); }
6177 : : bool cleanOut() const override { return true; }
6178 : : };
6179 : : class AstVarXRef final : public AstNodeVarRef {
6180 : : // A VarRef to something in another module before AstScope.
6181 : : // Includes pin on a cell, as part of a ASSIGN statement to connect I/Os until AstScope
6182 : : string m_name;
6183 : : string m_dotted; // Dotted part of scope the name()'ed reference is under or ""
6184 : : string m_inlinedDots; // Dotted hierarchy flattened out
6185 : : bool m_containsGenBlock = false; // Contains gen block reference
6186 : : public:
6187 : : AstVarXRef(FileLine* fl, const string& name, const string& dotted, const VAccess& access)
6188 : : : ASTGEN_SUPER_VarXRef(fl, nullptr, access)
6189 : : , m_name{name}
6190 : : , m_dotted{dotted} {}
6191 : : inline AstVarXRef(FileLine* fl, AstVar* varp, const string& dotted, const VAccess& access);
6192 : : ASTGEN_MEMBERS_AstVarXRef;
6193 : : string name() const override VL_MT_STABLE { return m_name; } // * = Var name
6194 : : void name(const std::string& name) override { m_name = name; } // * = Var name
6195 : : void dump(std::ostream& str) const override;
6196 : : void dumpJson(std::ostream& str) const override;
6197 : : string dotted() const { return m_dotted; }
6198 : : void dotted(const string& dotted) { m_dotted = dotted; }
6199 : : string inlinedDots() const { return m_inlinedDots; }
6200 : : void inlinedDots(const string& flag) { m_inlinedDots = flag; }
6201 : : bool containsGenBlock() const { return m_containsGenBlock; }
6202 : : void containsGenBlock(const bool flag) { m_containsGenBlock = flag; }
6203 : : string emitVerilog() override { V3ERROR_NA_RETURN(""); }
6204 : : string emitC() override { V3ERROR_NA_RETURN(""); }
6205 : : bool cleanOut() const override { return true; }
6206 : : int instrCount() const override { return widthInstrs(); }
6207 : : bool sameNode(const AstNode* samep) const override {
6208 : : const AstVarXRef* asamep = VN_DBG_AS(samep, VarXRef);
6209 : : return (selfPointer() == asamep->selfPointer() && varp() == asamep->varp()
6210 : : && name() == asamep->name() && dotted() == asamep->dotted());
6211 : : }
6212 : : };
6213 : :
6214 : : #endif // Guard
|