Support assoc array methods with wide value types (#7680)
This commit is contained in:
parent
d1319cf81e
commit
75993ca9ea
|
|
@ -97,6 +97,28 @@ struct VlWide final {
|
|||
bool operator!=(const VlWide<N_Words>& that) const VL_PURE { return !(*this == that); }
|
||||
EData& operator[](size_t index) VL_MT_SAFE { return m_storage[index]; }
|
||||
const EData& operator[](size_t index) const VL_MT_SAFE { return m_storage[index]; }
|
||||
VlWide<N_Words>& operator&=(const VlWide& rhs) {
|
||||
VL_AND_W(N_Words, *this, *this, rhs);
|
||||
return *this;
|
||||
}
|
||||
VlWide<N_Words>& operator|=(const VlWide& rhs) {
|
||||
VL_OR_W(N_Words, *this, *this, rhs);
|
||||
return *this;
|
||||
}
|
||||
VlWide<N_Words>& operator^=(const VlWide& rhs) {
|
||||
VL_XOR_W(N_Words, *this, *this, rhs);
|
||||
return *this;
|
||||
}
|
||||
VlWide<N_Words>& operator+=(const VlWide& rhs) {
|
||||
VL_ADD_W(N_Words, *this, *this, rhs);
|
||||
return *this;
|
||||
}
|
||||
VlWide<N_Words>& operator*=(const VlWide& rhs) {
|
||||
VlWide<N_Words> out{};
|
||||
VL_MUL_W(N_Words, out, *this, rhs);
|
||||
for (size_t i = 0; i < N_Words; ++i) m_storage[i] = out.m_storage[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
// METHODS
|
||||
EData& at(size_t index) VL_MT_SAFE { return m_storage[index]; }
|
||||
|
|
@ -1280,7 +1302,7 @@ public:
|
|||
}
|
||||
|
||||
T_Value r_sum() const {
|
||||
T_Value out(0); // Type must have assignment operator
|
||||
T_Value out = T_Value{};
|
||||
for (const auto& i : m_map) out += i.second;
|
||||
return out;
|
||||
}
|
||||
|
|
@ -1291,8 +1313,9 @@ public:
|
|||
return out;
|
||||
}
|
||||
T_Value r_product() const {
|
||||
if (m_map.empty()) return T_Value(0); // The big three do it this way
|
||||
T_Value out = T_Value(1);
|
||||
// The big three return 0 when assoc array is empty
|
||||
if (m_map.empty()) return T_Value{};
|
||||
T_Value out = T_Value{1};
|
||||
for (const auto& i : m_map) out *= i.second;
|
||||
return out;
|
||||
}
|
||||
|
|
@ -1304,8 +1327,9 @@ public:
|
|||
return out;
|
||||
}
|
||||
T_Value r_and() const {
|
||||
if (m_map.empty()) return T_Value(0); // The big three do it this way
|
||||
T_Value out = ~T_Value(0);
|
||||
// The big three return 0 when assoc array is empty
|
||||
if (m_map.empty()) return T_Value{};
|
||||
T_Value out = m_map.cbegin()->second;
|
||||
for (const auto& i : m_map) out &= i.second;
|
||||
return out;
|
||||
}
|
||||
|
|
@ -1317,7 +1341,7 @@ public:
|
|||
return out;
|
||||
}
|
||||
T_Value r_or() const {
|
||||
T_Value out = T_Value(0);
|
||||
T_Value out = T_Value{};
|
||||
for (const auto& i : m_map) out |= i.second;
|
||||
return out;
|
||||
}
|
||||
|
|
@ -1328,7 +1352,7 @@ public:
|
|||
return out;
|
||||
}
|
||||
T_Value r_xor() const {
|
||||
T_Value out = T_Value(0);
|
||||
T_Value out = T_Value{};
|
||||
for (const auto& i : m_map) out ^= i.second;
|
||||
return out;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4352,6 +4352,12 @@ class WidthVisitor final : public VNVisitor {
|
|||
}
|
||||
void methodCallAssoc(AstMethodCall* nodep, AstAssocArrayDType* adtypep) {
|
||||
AstCMethodHard* newp = nullptr;
|
||||
if (nodep->withp() && adtypep->subDTypep()->isWide()) {
|
||||
nodep->v3warn(
|
||||
E_UNSUPPORTED,
|
||||
"Unsupported: `with` clause on assoc arrays with wide value types in method '"
|
||||
<< nodep->prettyName() << "'");
|
||||
}
|
||||
if (nodep->name() == "num" // function int num()
|
||||
|| nodep->name() == "size") {
|
||||
methodOkArguments(nodep, 0, 0);
|
||||
|
|
|
|||
|
|
@ -22,15 +22,23 @@ module t;
|
|||
int qe[int]; // Empty
|
||||
int qv[$]; // Value returns
|
||||
int qi[$]; // Index returns
|
||||
bit[229:0] qw[int]; // Wide values
|
||||
bit[229:0] qwe[int]; // Wide values - empty
|
||||
bit[229:0] qwv[$]; // Wide values - Value returns
|
||||
int qwi[$]; // Wide values - Index returns
|
||||
point points_q[int];
|
||||
point points_qe[int]; // Empty points
|
||||
point points_qv[$];
|
||||
int i;
|
||||
bit b;
|
||||
bit[229:0] w;
|
||||
|
||||
q = '{10: 1, 11: 2, 12: 2, 13: 4, 14: 3};
|
||||
`checkp(q, "'{'ha:'h1, 'hb:'h2, 'hc:'h2, 'hd:'h4, 'he:'h3}");
|
||||
|
||||
qw = '{10: 1, 11: 2, 12: 2, 13: 4, 14: 3};
|
||||
`checkp(qw, "'{'ha:'h1, 'hb:'h2, 'hc:'h2, 'hd:'h4, 'he:'h3}");
|
||||
|
||||
// NOT tested: with ... selectors
|
||||
|
||||
//q.sort; // Not legal on assoc - see t_assoc_meth_bad
|
||||
|
|
@ -43,16 +51,34 @@ module t;
|
|||
`checkp(qv, "'{'h1, 'h2, 'h4, 'h3}");
|
||||
qv = qe.unique;
|
||||
`checkp(qv, "'{}");
|
||||
|
||||
qwv = qw.unique;
|
||||
`checkp(qwv, "'{'h1, 'h2, 'h4, 'h3}");
|
||||
qwv = qwe.unique;
|
||||
`checkp(qwv, "'{}");
|
||||
|
||||
qi = q.unique_index;
|
||||
qi.sort;
|
||||
`checkp(qi, "'{'ha, 'hb, 'hd, 'he}");
|
||||
qi = qe.unique_index;
|
||||
`checkp(qi, "'{}");
|
||||
|
||||
qwi = qw.unique_index;
|
||||
qwi.sort;
|
||||
`checkp(qwi, "'{'ha, 'hb, 'hd, 'he}");
|
||||
qwi = qwe.unique_index;
|
||||
`checkp(qwi, "'{}");
|
||||
|
||||
points_q[0] = point'{1, 2};
|
||||
points_q[1] = point'{2, 4};
|
||||
points_q[5] = point'{1, 4};
|
||||
|
||||
qi = points_qe.unique_index();
|
||||
`checkp(qi, "'{}");
|
||||
|
||||
qi = points_q.unique_index();
|
||||
`checkh(qi.size, 3);
|
||||
|
||||
points_qv = points_q.unique(p) with (p.x);
|
||||
`checkh(points_qv.size, 2);
|
||||
qi = points_q.unique_index (p) with (p.x + p.y);
|
||||
|
|
@ -113,6 +139,10 @@ module t;
|
|||
|
||||
qv = q.min;
|
||||
`checkp(qv, "'{'h1}");
|
||||
|
||||
qwv = qw.min;
|
||||
`checkp(qwv, "'{'h1}");
|
||||
|
||||
points_qv = points_q.min(p) with (p.x + p.y);
|
||||
if (points_qv[0].x != 1 || points_qv[0].y != 2) $stop;
|
||||
|
||||
|
|
@ -130,8 +160,13 @@ module t;
|
|||
qv = qe.max(x) with (x + 1);
|
||||
`checkp(qv, "'{}");
|
||||
|
||||
// Reduction methods
|
||||
// Wide
|
||||
qwv = qwe.min;
|
||||
`checkp(qwv, "'{}");
|
||||
qwv = qwe.max;
|
||||
`checkp(qwv, "'{}");
|
||||
|
||||
// Reduction methods
|
||||
i = q.sum;
|
||||
`checkh(i, 32'hc);
|
||||
i = q.sum with (item + 1);
|
||||
|
|
@ -141,6 +176,12 @@ module t;
|
|||
i = q.product with (item + 1);
|
||||
`checkh(i, 32'h168);
|
||||
|
||||
// Wide
|
||||
w = qw.sum;
|
||||
`checkh(w, 230'hc);
|
||||
w = qw.product;
|
||||
`checkh(w, 230'h30);
|
||||
|
||||
i = qe.sum;
|
||||
`checkh(i, 32'h0);
|
||||
i = qe.sum with (item + 1);
|
||||
|
|
@ -150,6 +191,12 @@ module t;
|
|||
i = qe.product with (item + 1);
|
||||
`checkh(i, 32'h0);
|
||||
|
||||
// Wide
|
||||
w = qwe.sum;
|
||||
`checkh(w, 230'h0);
|
||||
w = qwe.product;
|
||||
`checkh(w, 230'h0);
|
||||
|
||||
q = '{10: 32'b1100, 11: 32'b1010};
|
||||
i = q.and;
|
||||
`checkh(i, 32'b1000);
|
||||
|
|
@ -164,6 +211,14 @@ module t;
|
|||
i = q.xor with (item + 1);
|
||||
`checkh(i, 32'b0110);
|
||||
|
||||
qw = '{10: 230'b1100, 11: 230'b1010};
|
||||
w = qw.and;
|
||||
`checkh(w, 230'b1000);
|
||||
w = qw.or;
|
||||
`checkh(w, 230'b1110);
|
||||
w = qw.xor;
|
||||
`checkh(w, 230'b0110);
|
||||
|
||||
i = qe.and;
|
||||
`checkh(i, 32'b0);
|
||||
i = qe.and with (item + 1);
|
||||
|
|
@ -177,6 +232,14 @@ module t;
|
|||
i = qe.xor with (item + 1);
|
||||
`checkh(i, 32'b0);
|
||||
|
||||
// Wide
|
||||
w = qwe.and;
|
||||
`checkh(w, 230'b0);
|
||||
w = qwe.or;
|
||||
`checkh(w, 230'b0);
|
||||
w = qwe.xor;
|
||||
`checkh(w, 230'b0);
|
||||
|
||||
i = q.and();
|
||||
`checkh(i, 32'b1000);
|
||||
i = q.and() with (item + 1);
|
||||
|
|
@ -190,6 +253,14 @@ module t;
|
|||
i = q.xor() with (item + 1);
|
||||
`checkh(i, 32'b0110);
|
||||
|
||||
// Wide
|
||||
w = qw.and();
|
||||
`checkh(w, 230'b1000);
|
||||
w = qw.or();
|
||||
`checkh(w, 230'b1110);
|
||||
w = qw.xor();
|
||||
`checkh(w, 230'b0110);
|
||||
|
||||
i = qe.and();
|
||||
`checkh(i, 32'b0);
|
||||
i = qe.or();
|
||||
|
|
@ -197,6 +268,14 @@ module t;
|
|||
i = qe.xor();
|
||||
`checkh(i, 32'b0);
|
||||
|
||||
// Wide
|
||||
w = qwe.and();
|
||||
`checkh(w, 230'b0);
|
||||
w = qwe.or();
|
||||
`checkh(w, 230'b0);
|
||||
w = qwe.xor();
|
||||
`checkh(w, 230'b0);
|
||||
|
||||
q = '{10: 1, 11: 2};
|
||||
qe = '{10: 1, 11: 2};
|
||||
`checkh(q == qe, 1'b1);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,78 @@
|
|||
%Error-UNSUPPORTED: t/t_assoc_unsup.v:17:15: Unsupported: `with` clause on assoc arrays with wide value types in method 'min'
|
||||
: ... note: In instance 't'
|
||||
17 | qwv = qwe.min(x) with (x + 1);
|
||||
| ^~~
|
||||
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
|
||||
%Error-UNSUPPORTED: t/t_assoc_unsup.v:18:15: Unsupported: `with` clause on assoc arrays with wide value types in method 'max'
|
||||
: ... note: In instance 't'
|
||||
18 | qwv = qwe.max(x) with (x + 1);
|
||||
| ^~~
|
||||
%Error-UNSUPPORTED: t/t_assoc_unsup.v:20:12: Unsupported: `with` clause on assoc arrays with wide value types in method 'sum'
|
||||
: ... note: In instance 't'
|
||||
20 | w = qw.sum with (item + 1);
|
||||
| ^~~
|
||||
%Error-UNSUPPORTED: t/t_assoc_unsup.v:21:12: Unsupported: `with` clause on assoc arrays with wide value types in method 'product'
|
||||
: ... note: In instance 't'
|
||||
21 | w = qw.product with (item + 1);
|
||||
| ^~~~~~~
|
||||
%Error-UNSUPPORTED: t/t_assoc_unsup.v:23:13: Unsupported: `with` clause on assoc arrays with wide value types in method 'sum'
|
||||
: ... note: In instance 't'
|
||||
23 | w = qwe.sum with (item + 1);
|
||||
| ^~~
|
||||
%Error-UNSUPPORTED: t/t_assoc_unsup.v:24:13: Unsupported: `with` clause on assoc arrays with wide value types in method 'product'
|
||||
: ... note: In instance 't'
|
||||
24 | w = qwe.product with (item + 1);
|
||||
| ^~~~~~~
|
||||
%Error-UNSUPPORTED: t/t_assoc_unsup.v:27:12: Unsupported: `with` clause on assoc arrays with wide value types in method 'and'
|
||||
: ... note: In instance 't'
|
||||
27 | w = qw.and with (item + 1);
|
||||
| ^~~
|
||||
%Error-UNSUPPORTED: t/t_assoc_unsup.v:28:12: Unsupported: `with` clause on assoc arrays with wide value types in method 'or'
|
||||
: ... note: In instance 't'
|
||||
28 | w = qw.or with (item + 1);
|
||||
| ^~
|
||||
%Error-UNSUPPORTED: t/t_assoc_unsup.v:29:12: Unsupported: `with` clause on assoc arrays with wide value types in method 'xor'
|
||||
: ... note: In instance 't'
|
||||
29 | w = qw.xor with (item + 1);
|
||||
| ^~~
|
||||
%Error-UNSUPPORTED: t/t_assoc_unsup.v:31:12: Unsupported: `with` clause on assoc arrays with wide value types in method 'and'
|
||||
: ... note: In instance 't'
|
||||
31 | w = qw.and() with (item + 1);
|
||||
| ^~~
|
||||
%Error-UNSUPPORTED: t/t_assoc_unsup.v:32:12: Unsupported: `with` clause on assoc arrays with wide value types in method 'or'
|
||||
: ... note: In instance 't'
|
||||
32 | w = qw.or() with (item + 1);
|
||||
| ^~
|
||||
%Error-UNSUPPORTED: t/t_assoc_unsup.v:33:12: Unsupported: `with` clause on assoc arrays with wide value types in method 'xor'
|
||||
: ... note: In instance 't'
|
||||
33 | w = qw.xor() with (item + 1);
|
||||
| ^~~
|
||||
%Error-UNSUPPORTED: t/t_assoc_unsup.v:35:14: Unsupported: `with` clause on assoc arrays with wide value types in method 'find'
|
||||
: ... note: In instance 't'
|
||||
35 | qwv = qw.find with (item == 2);
|
||||
| ^~~~
|
||||
%Error-UNSUPPORTED: t/t_assoc_unsup.v:36:14: Unsupported: `with` clause on assoc arrays with wide value types in method 'find_first'
|
||||
: ... note: In instance 't'
|
||||
36 | qwv = qw.find_first with (item == 2);
|
||||
| ^~~~~~~~~~
|
||||
%Error-UNSUPPORTED: t/t_assoc_unsup.v:37:14: Unsupported: `with` clause on assoc arrays with wide value types in method 'find_last'
|
||||
: ... note: In instance 't'
|
||||
37 | qwv = qw.find_last with (item == 2);
|
||||
| ^~~~~~~~~
|
||||
%Error-UNSUPPORTED: t/t_assoc_unsup.v:39:13: Unsupported: `with` clause on assoc arrays with wide value types in method 'find_index'
|
||||
: ... note: In instance 't'
|
||||
39 | qi = qw.find_index with (item == 2);
|
||||
| ^~~~~~~~~~
|
||||
%Error-UNSUPPORTED: t/t_assoc_unsup.v:40:13: Unsupported: `with` clause on assoc arrays with wide value types in method 'find_first_index'
|
||||
: ... note: In instance 't'
|
||||
40 | qi = qw.find_first_index with (item == 2);
|
||||
| ^~~~~~~~~~~~~~~~
|
||||
%Error-UNSUPPORTED: t/t_assoc_unsup.v:41:13: Unsupported: `with` clause on assoc arrays with wide value types in method 'find_last_index'
|
||||
: ... note: In instance 't'
|
||||
41 | qi = qw.find_last_index with (item == 2);
|
||||
| ^~~~~~~~~~~~~~~
|
||||
%Error-UNSUPPORTED: t/t_assoc_unsup.v:45:14: Unsupported: `with` clause on assoc arrays with wide value types in method 'map'
|
||||
: ... note: In instance 't'
|
||||
45 | qwv = qw.map(el) with (el / 100);
|
||||
| ^~~
|
||||
%Error: Exiting due to
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of either the GNU Lesser General Public License Version 3
|
||||
# or the Perl Artistic License Version 2.0.
|
||||
# SPDX-FileCopyrightText: 2024 Wilson Snyder
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios("linter")
|
||||
|
||||
test.lint(fails=True, expect_filename=test.golden_filename)
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 Antmicro
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t;
|
||||
initial begin
|
||||
bit[229:0] qw[int]; // Wide values
|
||||
bit[229:0] qwe[int]; // Wide values - empty
|
||||
bit[229:0] qwv[$]; // Wide values - Value returns
|
||||
int qi[$]; // Index returns
|
||||
bit[229:0] w;
|
||||
|
||||
qw = '{10: 1, 11: 2, 12: 2, 13: 4, 14: 3};
|
||||
|
||||
qwv = qwe.min(x) with (x + 1);
|
||||
qwv = qwe.max(x) with (x + 1);
|
||||
|
||||
w = qw.sum with (item + 1);
|
||||
w = qw.product with (item + 1);
|
||||
|
||||
w = qwe.sum with (item + 1);
|
||||
w = qwe.product with (item + 1);
|
||||
|
||||
qw = '{10: 230'b1100, 11: 230'b1010};
|
||||
w = qw.and with (item + 1);
|
||||
w = qw.or with (item + 1);
|
||||
w = qw.xor with (item + 1);
|
||||
|
||||
w = qw.and() with (item + 1);
|
||||
w = qw.or() with (item + 1);
|
||||
w = qw.xor() with (item + 1);
|
||||
|
||||
qwv = qw.find with (item == 2);
|
||||
qwv = qw.find_first with (item == 2);
|
||||
qwv = qw.find_last with (item == 2);
|
||||
|
||||
qi = qw.find_index with (item == 2);
|
||||
qi = qw.find_first_index with (item == 2);
|
||||
qi = qw.find_last_index with (item == 2);
|
||||
|
||||
// Map method (IEEE 1800-2023 7.12.5)
|
||||
qw = '{1: 100, 2: 200, 3: 300};
|
||||
qwv = qw.map(el) with (el / 100);
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
Loading…
Reference in New Issue