Fix `with` inside a `with`
This commit is contained in:
parent
61de46cea2
commit
14e3448ba6
|
|
@ -1229,8 +1229,8 @@ public:
|
|||
return out;
|
||||
}
|
||||
template <typename T_Func>
|
||||
T_Value r_or(T_Func with_func) const {
|
||||
T_Value out = T_Value(0);
|
||||
WithFuncReturnType<T_Func> r_or(T_Func with_func) const {
|
||||
WithFuncReturnType<T_Func> out = WithFuncReturnType<T_Func>(0);
|
||||
for (const auto& i : m_map) out |= with_func(i.first, i.second);
|
||||
return out;
|
||||
}
|
||||
|
|
@ -1570,8 +1570,9 @@ public:
|
|||
return out;
|
||||
}
|
||||
template <typename T_Func>
|
||||
T_Value r_sum(T_Func with_func) const {
|
||||
T_Value out(0); // Type must have assignment operator
|
||||
WithFuncReturnType<T_Func> r_sum(T_Func with_func) const {
|
||||
WithFuncReturnType<T_Func> out
|
||||
= WithFuncReturnType<T_Func>(0); // Type must have assignment operator
|
||||
for (const auto& i : m_storage) out += with_func(0, i);
|
||||
return out;
|
||||
}
|
||||
|
|
@ -1581,8 +1582,8 @@ public:
|
|||
return out;
|
||||
}
|
||||
template <typename T_Func>
|
||||
T_Value r_product(T_Func with_func) const {
|
||||
T_Value out = T_Value(1);
|
||||
WithFuncReturnType<T_Func> r_product(T_Func with_func) const {
|
||||
WithFuncReturnType<T_Func> out = WithFuncReturnType<T_Func>(1);
|
||||
for (const auto& i : m_storage) out *= with_func(0, i);
|
||||
return out;
|
||||
}
|
||||
|
|
@ -1593,8 +1594,8 @@ public:
|
|||
return out;
|
||||
}
|
||||
template <typename T_Func>
|
||||
T_Value r_and(T_Func with_func) const {
|
||||
T_Value out = ~T_Value(0);
|
||||
WithFuncReturnType<T_Func> r_and(T_Func with_func) const {
|
||||
WithFuncReturnType<T_Func> out = ~WithFuncReturnType<T_Func>(0);
|
||||
for (const auto& i : m_storage) out &= with_func(0, i);
|
||||
return out;
|
||||
}
|
||||
|
|
@ -1604,8 +1605,8 @@ public:
|
|||
return out;
|
||||
}
|
||||
template <typename T_Func>
|
||||
T_Value r_or(T_Func with_func) const {
|
||||
T_Value out = T_Value(0);
|
||||
WithFuncReturnType<T_Func> r_or(T_Func with_func) const {
|
||||
WithFuncReturnType<T_Func> out = WithFuncReturnType<T_Func>(0);
|
||||
for (const auto& i : m_storage) out |= with_func(0, i);
|
||||
return out;
|
||||
}
|
||||
|
|
@ -1615,8 +1616,8 @@ public:
|
|||
return out;
|
||||
}
|
||||
template <typename T_Func>
|
||||
T_Value r_xor(T_Func with_func) const {
|
||||
T_Value out = T_Value(0);
|
||||
WithFuncReturnType<T_Func> r_xor(T_Func with_func) const {
|
||||
WithFuncReturnType<T_Func> out = WithFuncReturnType<T_Func>(0);
|
||||
for (const auto& i : m_storage) out ^= with_func(0, i);
|
||||
return out;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -735,7 +735,9 @@ public:
|
|||
if (auto* const argrefp = nodep->valueArgRefp()) {
|
||||
putnbs(argrefp, argrefp->dtypep()->cType(argrefp->nameProtect(), false, false));
|
||||
}
|
||||
puts(") {\n");
|
||||
puts(") -> ");
|
||||
putnbs(nodep, nodep->dtypep()->cType("", false, false));
|
||||
puts(" {\n");
|
||||
VL_RESTORER(m_createdScopeHash);
|
||||
iterateAndNextConstNull(nodep->exprp());
|
||||
puts("}\n");
|
||||
|
|
|
|||
|
|
@ -1013,7 +1013,7 @@ class LinkDotFindVisitor final : public VNVisitor {
|
|||
}
|
||||
void visit(AstTypeTable*) override {} // FindVisitor::
|
||||
void visit(AstConstPool*) override {} // FindVisitor::
|
||||
void visit(AstIfaceRefDType* nodep) override {
|
||||
void visit(AstIfaceRefDType* nodep) override { // FindVisitor::
|
||||
if (m_statep->forPrimary() && nodep->isVirtual() && nodep->ifacep()
|
||||
&& !nodep->ifacep()->user3()) {
|
||||
m_virtIfaces.push_back(nodep->ifacep());
|
||||
|
|
@ -1872,18 +1872,16 @@ class LinkDotFindVisitor final : public VNVisitor {
|
|||
// Symbol table needs nodep->name() as the index variable's name
|
||||
// Iteration will pickup the AstVar we made under AstWith
|
||||
VL_RESTORER(m_curSymp);
|
||||
{
|
||||
++m_modWithNum;
|
||||
m_curSymp = m_statep->insertBlock(m_curSymp, "__Vwith" + cvtToStr(m_modWithNum), nodep,
|
||||
m_classOrPackagep);
|
||||
m_curSymp->fallbackp(VL_RESTORER_PREV(m_curSymp));
|
||||
UASSERT_OBJ(nodep->indexArgRefp(), nodep, "Missing lambda argref");
|
||||
UASSERT_OBJ(nodep->valueArgRefp(), nodep, "Missing lambda argref");
|
||||
// Insert argref's name into symbol table
|
||||
m_statep->insertSym(m_curSymp, nodep->valueArgRefp()->name(), nodep->valueArgRefp(),
|
||||
nullptr);
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
++m_modWithNum;
|
||||
m_curSymp = m_statep->insertBlock(m_curSymp, "__Vwith" + cvtToStr(m_modWithNum), nodep,
|
||||
m_classOrPackagep);
|
||||
m_curSymp->fallbackp(VL_RESTORER_PREV(m_curSymp));
|
||||
UASSERT_OBJ(nodep->indexArgRefp(), nodep, "Missing lambda argref");
|
||||
UASSERT_OBJ(nodep->valueArgRefp(), nodep, "Missing lambda argref");
|
||||
// Insert argref's name into symbol table
|
||||
m_statep->insertSym(m_curSymp, nodep->valueArgRefp()->name(), nodep->valueArgRefp(),
|
||||
nullptr);
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
|
||||
void visit(AstNode* nodep) override { iterateChildren(nodep); } // FindVisitor::
|
||||
|
|
@ -1982,7 +1980,7 @@ class LinkDotFindIfaceVisitor final : public VNVisitor {
|
|||
}
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
void visit(AstVar* nodep) override { // FindVisitor::
|
||||
void visit(AstVar* nodep) override { // FindIfaceVisitor::
|
||||
VL_RESTORER(m_declp);
|
||||
m_declp = nodep;
|
||||
iterateChildren(nodep);
|
||||
|
|
@ -2304,7 +2302,7 @@ private:
|
|||
void visit(AstWith* nodep) override { // ScopeVisitor::
|
||||
VSymEnt* const symp = m_statep->insertBlock(m_modSymp, nodep->name(), nodep, nullptr);
|
||||
symp->fallbackp(m_modSymp);
|
||||
// No recursion, we don't want to pick up variables
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
void visit(AstAlias* nodep) override { // ScopeVisitor::
|
||||
// Track aliases
|
||||
|
|
@ -2379,7 +2377,7 @@ private:
|
|||
// We have stored the link, we don't need these any more
|
||||
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
||||
}
|
||||
void visit(AstNodeGen* nodep) override { // LCOV_EXCL_LINE
|
||||
void visit(AstNodeGen* nodep) override { // ScopeVisitor:: // LCOV_EXCL_LINE
|
||||
nodep->v3fatalSrc("Generate constructs should have been reduced out");
|
||||
}
|
||||
// For speed, don't recurse things that can't have scope
|
||||
|
|
|
|||
|
|
@ -3972,6 +3972,8 @@ class WidthVisitor final : public VNVisitor {
|
|||
methodCallLValueRecurse(nodep, ichildp->fromp(), access);
|
||||
} else if (const AstNodeSel* const ichildp = VN_CAST(childp, NodeSel)) {
|
||||
methodCallLValueRecurse(nodep, ichildp->fromp(), access);
|
||||
} else if (VN_IS(childp, LambdaArgRef)) {
|
||||
// NOP
|
||||
} else {
|
||||
UINFO(1, " Related node: " << childp);
|
||||
nodep->v3warn(E_UNSUPPORTED, "Unsupported: Non-variable on LHS of built-in method '"
|
||||
|
|
|
|||
|
|
@ -6,56 +6,84 @@
|
|||
// any use, without warranty, 2020 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// verilog_format: off
|
||||
`define stop $stop
|
||||
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
|
||||
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
|
||||
`define checkh(gotv, expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
|
||||
// verilog_format: on
|
||||
|
||||
module t;
|
||||
|
||||
initial begin
|
||||
int tofind;
|
||||
int aliases[$];
|
||||
int found[$];
|
||||
int i;
|
||||
byte byteq[$] = {2, -1, 127};
|
||||
initial begin
|
||||
int tofind;
|
||||
int aliases[$];
|
||||
int found[$];
|
||||
int i;
|
||||
byte byteq[$] = {2, -1, 127};
|
||||
byte b[];
|
||||
logic [7:0] m[2][2];
|
||||
logic bit_arr[1024];
|
||||
|
||||
aliases = '{ 1, 4, 6, 8};
|
||||
tofind = 6;
|
||||
found = aliases.find with (item == 1);
|
||||
`checkh(found.size, 1);
|
||||
found = aliases.find(j) with (j == tofind);
|
||||
`checkh(found.size, 1);
|
||||
// And as function
|
||||
aliases.find(i) with (i == tofind);
|
||||
aliases = '{1, 4, 6, 8};
|
||||
tofind = 6;
|
||||
found = aliases.find with (item == 1);
|
||||
`checkh(found.size, 1);
|
||||
found = aliases.find(j) with (j == tofind);
|
||||
`checkh(found.size, 1);
|
||||
// And as function
|
||||
aliases.find(i) with (i == tofind);
|
||||
|
||||
// No parenthesis
|
||||
tofind = 0;
|
||||
found = aliases.find with (item == tofind);
|
||||
`checkh(found.size, 0);
|
||||
aliases.find with (item == tofind);
|
||||
// No parenthesis
|
||||
tofind = 0;
|
||||
found = aliases.find with (item == tofind);
|
||||
`checkh(found.size, 0);
|
||||
aliases.find with (item == tofind);
|
||||
|
||||
// bug3387
|
||||
i = aliases.sum();
|
||||
`checkh(i, 'h13);
|
||||
i = byteq.sum() with (int'(item));
|
||||
`checkh(i, 128);
|
||||
// bug3387
|
||||
i = aliases.sum();
|
||||
`checkh(i, 'h13);
|
||||
i = byteq.sum() with (int'(item));
|
||||
`checkh(i, 128);
|
||||
|
||||
// Unique (array method)
|
||||
tofind = 4;
|
||||
found = aliases.find with (tofind); // "true" match
|
||||
`checkh(found.size, 4);
|
||||
found = aliases.find() with (item == tofind);
|
||||
`checkh(found.size, 1);
|
||||
found = aliases.find(i) with (i == tofind);
|
||||
`checkh(found.size, 1);
|
||||
i = aliases.or(v) with (v);
|
||||
`checkh(i, 'hf);
|
||||
i = aliases.and(v) with (v);
|
||||
`checkh(i, 0);
|
||||
i = aliases.xor(v) with (v);
|
||||
`checkh(i, 'hb);
|
||||
// Unique (array method)
|
||||
tofind = 4;
|
||||
found = aliases.find with (tofind); // "true" match
|
||||
`checkh(found.size, 4);
|
||||
found = aliases.find() with (item == tofind);
|
||||
`checkh(found.size, 1);
|
||||
found = aliases.find(i) with (i == tofind);
|
||||
`checkh(found.size, 1);
|
||||
i = aliases.or(v) with (v);
|
||||
`checkh(i, 'hf);
|
||||
i = aliases.and(v) with (v);
|
||||
`checkh(i, 0);
|
||||
i = aliases.xor(v) with (v);
|
||||
`checkh(i, 'hb);
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
// Based roughly on IEEE 1800-2023 7.12.3
|
||||
// verilator lint_off WIDTHEXPAND
|
||||
b = {1, 2, 3, 4};
|
||||
i = b.sum; // = 10 <= 1 + 2 + 3 + 4
|
||||
`checkd(i, 10);
|
||||
|
||||
i = b.product; // = 24 <= 1 * 2 * 3 * 4
|
||||
`checkd(i, 24);
|
||||
|
||||
i = b.xor with (item + 4); // = 12 <= 5 ^ 6 ^ 7 ^ 8
|
||||
`checkd(i, 12);
|
||||
|
||||
m = '{'{5, 10}, '{15, 20}};
|
||||
i = m.sum with (item.sum with (item)); // = 50 <= 5+10+15+20
|
||||
`checkd(i, 50);
|
||||
|
||||
// Width of the reduction method's result is the dtype of the with's expression
|
||||
// verilator lint_on WIDTHEXPAND
|
||||
for (i = 0; i < 1024; ++i) bit_arr[i] = 1'b1;
|
||||
i = bit_arr.sum with (int'(item)); // forces result to be 32-bit
|
||||
`checkd(i, 1024);
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
|
|||
Loading…
Reference in New Issue