Internals: Make AstWith explicit in AstCMethodHard (#7129)

This makes it consistent with other usage in NodeFTaskRef. Also AstWith
is no longer a NodeExpr.
This commit is contained in:
Geza Lore 2026-02-22 20:38:28 +00:00 committed by GitHub
parent f74a581d97
commit 1e5a6901c8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 63 additions and 46 deletions

View File

@ -519,6 +519,35 @@ public:
void name(const std::string& name) override { m_name = name; }
bool emptyConnectNoNext() const { return !exprp() && name() == "" && !nextp(); }
};
class AstWith final : public AstNode {
// Similar to AstArg, but this is essentially a lambda passed to a call.
// Not an AstNodeExpr as there is no concept of function values in Verilator
// The dtypep() contains the with lambda's return dtype, not a function type.
// Parents: NodeFTaskRef, CMethodHard
// Children: LambdaArgRef that declares the item variable
// Children: LambdaArgRef that declares the item.index variable
// Children: expression (equation establishing the with)
// @astgen op1 := indexArgRefp : AstLambdaArgRef
// @astgen op2 := valueArgRefp : AstLambdaArgRef
// @astgen op3 := exprp : List[AstNode] // Pins, expression and constraints
// TODO: Separate expression and constraints
public:
AstWith(FileLine* fl, AstLambdaArgRef* indexArgRefp, AstLambdaArgRef* valueArgRefp,
AstNode* exprp)
: ASTGEN_SUPER_With(fl) {
this->indexArgRefp(indexArgRefp);
this->valueArgRefp(valueArgRefp);
addExprp(exprp);
}
ASTGEN_MEMBERS_AstWith;
bool hasDType() const override { return true; }
bool sameNode(const AstNode* /*samep*/) const override { return true; }
const char* broken() const override {
BROKEN_RTN(!indexArgRefp()); // varp needed to know lambda's arg dtype
BROKEN_RTN(!valueArgRefp()); // varp needed to know lambda's arg dtype
return nullptr;
}
};
// === AstNodeExpr ===
class AstAddrOfCFunc final : public AstNodeExpr {
@ -639,6 +668,7 @@ class AstCMethodHard final : public AstNodeExpr {
// PARENTS: stmt/expr
// @astgen op1 := fromp : AstNodeExpr // Subject of method call
// @astgen op2 := pinsp : List[AstNodeExpr] // Arguments
// @astgen op3 := withp : Optional[AstWith] // With clause
VCMethod m_method; // Which method to call
bool m_pure = false; // Pure optimizable
bool m_usePtr = false; // Use '->' not '.'
@ -2599,37 +2629,6 @@ public:
bool cleanOut() const override { return true; }
bool sameNode(const AstNode* /*samep*/) const override { return true; }
};
class AstWith final : public AstNodeExpr {
// Used as argument to method, then to AstCMethodHard
// dtypep() contains the with lambda's return dtype
// Parents: funcref (similar to AstArg)
// Children: LambdaArgRef that declares the item variable
// Children: LambdaArgRef that declares the item.index variable
// Children: expression (equation establishing the with)
// @astgen op1 := indexArgRefp : AstLambdaArgRef
// @astgen op2 := valueArgRefp : AstLambdaArgRef
// @astgen op3 := exprp : List[AstNode] // Pins, expression and constraints
// TODO: Separate expression and constraints
public:
AstWith(FileLine* fl, AstLambdaArgRef* indexArgRefp, AstLambdaArgRef* valueArgRefp,
AstNode* exprp)
: ASTGEN_SUPER_With(fl) {
this->indexArgRefp(indexArgRefp);
this->valueArgRefp(valueArgRefp);
addExprp(exprp);
}
ASTGEN_MEMBERS_AstWith;
bool sameNode(const AstNode* /*samep*/) const override { return true; }
const char* broken() const override {
BROKEN_RTN(!indexArgRefp()); // varp needed to know lambda's arg dtype
BROKEN_RTN(!valueArgRefp()); // varp needed to know lambda's arg dtype
return nullptr;
}
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
string emitC() override { V3ERROR_NA_RETURN(""); }
bool cleanOut() const override { V3ERROR_NA_RETURN(true); }
};
class AstWithParse final : public AstNodeExpr {
// In early parse, FUNC(index) WITH equation-using-index
// Replaced with AstWith

View File

@ -763,6 +763,10 @@ public:
comma = true;
argNum++;
}
if (nodep->withp()) {
if (comma) puts(", ");
iterateConst(nodep->withp());
}
puts(")");
}
void visit(AstLambdaArgRef* nodep) override { putbs(nodep->nameProtect()); }

View File

@ -618,6 +618,7 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public VNVisitorConst {
puts("." + nodep->name() + "(");
iterateAndCommaConstNull(nodep->pinsp());
puts(")");
iterateConstNull(nodep->withp());
}
void visit(AstCMethodCall* nodep) override {
iterateConst(nodep->fromp());
@ -1025,7 +1026,7 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public VNVisitorConst {
}
void visit(AstArg* nodep) override { iterateAndNextConstNull(nodep->exprp()); }
void visit(AstWith* nodep) override {
putfs(nodep, "with (");
putfs(nodep, " with (");
iterateConstNull(nodep->exprp());
puts(") ");
}

View File

@ -3857,7 +3857,8 @@ class WidthVisitor final : public VNVisitor {
methodOkArguments(nodep, 0, 0);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
VCMethod::arrayMethod("r_" + nodep->name()), withp};
VCMethod::arrayMethod("r_" + nodep->name())};
newp->withp(withp);
newp->dtypeFrom(withp ? withp->dtypep() : adtypep->subDTypep());
if (!nodep->firstAbovep()) newp->dtypeSetVoid();
} else if (nodep->name() == "min" || nodep->name() == "max" || nodep->name() == "unique") {
@ -3875,7 +3876,8 @@ class WidthVisitor final : public VNVisitor {
methodOkArguments(nodep, 0, 0);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
VCMethod::arrayMethod(nodep->name()), withp};
VCMethod::arrayMethod(nodep->name())};
newp->withp(withp);
newp->dtypep(queueDTypeIndexedBy(adtypep->subDTypep()));
if (!nodep->firstAbovep()) newp->dtypeSetVoid();
} else if (nodep->name() == "map") {
@ -3950,7 +3952,8 @@ class WidthVisitor final : public VNVisitor {
methodOkArguments(nodep, 0, 0);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
VCMethod::arrayMethod("r_" + nodep->name()), withp};
VCMethod::arrayMethod("r_" + nodep->name())};
newp->withp(withp);
newp->dtypeFrom(withp ? withp->dtypep() : adtypep->subDTypep());
if (!nodep->firstAbovep()) newp->dtypeSetVoid();
} else if (nodep->name() == "min" || nodep->name() == "max" || nodep->name() == "unique"
@ -3960,7 +3963,8 @@ class WidthVisitor final : public VNVisitor {
methodOkArguments(nodep, 0, 0);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
VCMethod::arrayMethod(nodep->name()), withp};
VCMethod::arrayMethod(nodep->name())};
newp->withp(withp);
if (nodep->name() == "unique_index") {
newp->dtypep(queueDTypeIndexedBy(adtypep->keyDTypep()));
} else {
@ -3974,7 +3978,8 @@ class WidthVisitor final : public VNVisitor {
methodOkArguments(nodep, 0, 0);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
VCMethod::arrayMethod(nodep->name()), withp};
VCMethod::arrayMethod(nodep->name())};
newp->withp(withp);
newp->dtypep(queueDTypeIndexedBy(adtypep->subDTypep()));
if (!nodep->firstAbovep()) newp->dtypeSetVoid();
} else if (nodep->name() == "find_index" || nodep->name() == "find_first_index"
@ -3984,7 +3989,8 @@ class WidthVisitor final : public VNVisitor {
methodOkArguments(nodep, 0, 0);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
VCMethod::arrayMethod(nodep->name()), withp};
VCMethod::arrayMethod(nodep->name())};
newp->withp(withp);
newp->dtypep(queueDTypeIndexedBy(adtypep->keyDTypep()));
if (!nodep->firstAbovep()) newp->dtypeSetVoid();
} else if (nodep->name() == "map") {
@ -4079,7 +4085,8 @@ class WidthVisitor final : public VNVisitor {
methodOkArguments(nodep, 0, 0);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::WRITE);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
VCMethod::arrayMethod(nodep->name()), withp};
VCMethod::arrayMethod(nodep->name())};
newp->withp(withp);
newp->dtypeSetVoid();
} else if (nodep->name() == "min" || nodep->name() == "max" || nodep->name() == "unique"
|| nodep->name() == "unique_index") {
@ -4088,7 +4095,8 @@ class WidthVisitor final : public VNVisitor {
methodOkArguments(nodep, 0, 0);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
VCMethod::arrayMethod(nodep->name()), withp};
VCMethod::arrayMethod(nodep->name())};
newp->withp(withp);
if (nodep->name() == "unique_index") {
newp->dtypep(newp->findQueueIndexDType());
} else {
@ -4103,7 +4111,8 @@ class WidthVisitor final : public VNVisitor {
methodOkArguments(nodep, 0, 0);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
VCMethod::arrayMethod(nodep->name()), withp};
VCMethod::arrayMethod(nodep->name())};
newp->withp(withp);
newp->dtypep(queueDTypeIndexedBy(adtypep->subDTypep()));
if (!nodep->firstAbovep()) newp->dtypeSetVoid();
} else if (nodep->name() == "find_index" || nodep->name() == "find_first_index"
@ -4114,7 +4123,8 @@ class WidthVisitor final : public VNVisitor {
methodOkArguments(nodep, 0, 0);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
VCMethod::arrayMethod(nodep->name()), withp};
VCMethod::arrayMethod(nodep->name())};
newp->withp(withp);
newp->dtypep(newp->findQueueIndexDType());
if (!nodep->firstAbovep()) newp->dtypeSetVoid();
} else if (nodep->name() == "map") {
@ -4159,7 +4169,8 @@ class WidthVisitor final : public VNVisitor {
methodOkArguments(nodep, 0, 0);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
VCMethod::arrayMethod("r_" + nodep->name()), withp};
VCMethod::arrayMethod("r_" + nodep->name())};
newp->withp(withp);
newp->dtypeFrom(adtypep->subDTypep());
if (!nodep->firstAbovep()) newp->dtypeSetVoid();
} else if ((newp = methodCallArray(nodep, adtypep))) {
@ -4260,7 +4271,8 @@ class WidthVisitor final : public VNVisitor {
methodOkArguments(nodep, 0, 0);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
VCMethod::arrayMethod("r_" + nodep->name()), withp};
VCMethod::arrayMethod("r_" + nodep->name())};
newp->withp(withp);
newp->dtypeFrom(withp ? withp->dtypep() : adtypep->subDTypep());
if (!nodep->firstAbovep()) newp->dtypeSetVoid();
} else if ((newp = methodCallArray(nodep, adtypep))) {
@ -4579,7 +4591,8 @@ class WidthVisitor final : public VNVisitor {
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
AstCMethodHard* const newp
= new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
VCMethod::arrayMethod("r_" + nodep->name()), withp};
VCMethod::arrayMethod("r_" + nodep->name())};
newp->withp(withp);
newp->dtypeFrom(withp ? withp->dtypep() : adtypep->subDTypep());
if (!nodep->firstAbovep()) newp->dtypeSetVoid();
newp->protect(false);

View File

@ -291,7 +291,7 @@ module Vt_debug_emitv_t;
sum = $random('sha);
sum = $urandom();
sum = $urandom('sha);
sum = array.r_sum(with ((item * 'sh2)) );
sum = array.r_sum() with ((item * 'sh2)) ;
if ((PKG_PARAM != 'sh1)) begin
$stop;
end