Support 'with' in unique, unique_index, min, max in queues (#3772)

This commit is contained in:
Ryszard Rozak 2022-11-22 15:10:25 +01:00 committed by GitHub
parent 66d85b3381
commit 57975c82b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 85 additions and 29 deletions

View File

@ -429,9 +429,9 @@ public:
void shuffle() { std::shuffle(m_deque.begin(), m_deque.end(), VlURNG{}); }
VlQueue unique() const {
VlQueue out;
std::unordered_set<T_Value> saw;
std::set<T_Value> saw;
for (const auto& i : m_deque) {
auto it = saw.find(i);
const auto it = saw.find(i);
if (it == saw.end()) {
saw.insert(it, i);
out.push_back(i);
@ -439,12 +439,26 @@ public:
}
return out;
}
template <typename Func>
VlQueue unique(Func with_func) const {
VlQueue out;
std::set<T_Value> saw;
for (const auto& i : m_deque) {
const auto i_mapped = with_func(0, i);
const auto it = saw.find(i_mapped);
if (it == saw.end()) {
saw.insert(it, i_mapped);
out.push_back(i);
}
}
return out;
}
VlQueue<IData> unique_index() const {
VlQueue<IData> out;
IData index = 0;
std::unordered_set<T_Value> saw;
std::set<T_Value> saw;
for (const auto& i : m_deque) {
auto it = saw.find(i);
const auto it = saw.find(i);
if (it == saw.end()) {
saw.insert(it, i);
out.push_back(index);
@ -454,6 +468,22 @@ public:
return out;
}
template <typename Func>
VlQueue<IData> unique_index(Func with_func) const {
VlQueue<IData> out;
IData index = 0;
std::unordered_set<T_Value> saw;
for (const auto& i : m_deque) {
const auto i_mapped = with_func(index, i);
auto it = saw.find(i_mapped);
if (it == saw.end()) {
saw.insert(it, i_mapped);
out.push_back(index);
}
++index;
}
return out;
}
template <typename Func>
VlQueue find(Func with_func) const {
VlQueue out;
IData index = 0;
@ -517,11 +547,29 @@ public:
const auto it = std::min_element(m_deque.begin(), m_deque.end());
return VlQueue::cons(*it);
}
template <typename Func>
VlQueue min(Func with_func) const {
if (m_deque.empty()) return VlQueue{};
const auto it = std::min_element(m_deque.begin(), m_deque.end(),
[&with_func](const IData& a, const IData& b) {
return with_func(0, a) < with_func(0, b);
});
return VlQueue::cons(*it);
}
VlQueue max() const {
if (m_deque.empty()) return VlQueue{};
const auto it = std::max_element(m_deque.begin(), m_deque.end());
return VlQueue::cons(*it);
}
template <typename Func>
VlQueue max(Func with_func) const {
if (m_deque.empty()) return VlQueue{};
const auto it = std::max_element(m_deque.begin(), m_deque.end(),
[&with_func](const IData& a, const IData& b) {
return with_func(0, a) < with_func(0, b);
});
return VlQueue::cons(*it);
}
T_Value r_sum() const {
T_Value out(0); // Type must have assignment operator

View File

@ -3231,10 +3231,12 @@ private:
newp->dtypeSetVoid();
} else if (nodep->name() == "min" || nodep->name() == "max" || nodep->name() == "unique"
|| nodep->name() == "unique_index") {
AstWith* const withp = methodWithArgument(
nodep, false, true, nullptr, nodep->findUInt32DType(), adtypep->subDTypep());
methodOkArguments(nodep, 0, 0);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
nodep->name()};
nodep->name(), withp};
if (nodep->name() == "unique_index") {
newp->dtypep(newp->findQueueIndexDType());
} else {

View File

@ -44,10 +44,17 @@ module t (/*AUTOARG*/);
v = $sformatf("%p", qv); `checks(v, "'{'h2, 'h4, 'h1, 'h3} ");
qv = qe.unique;
`checkh(qv.size(), 0);
qv = q.unique(x) with (x % 2);
`checkh(qv.size(), 2);
qi = q.unique_index; qv.sort;
v = $sformatf("%p", qi); `checks(v, "'{'h0, 'h2, 'h3, 'h4} ");
// According to 7.12.1 of IEEE Std 1800-2017, it is not specified which index of duplicated value should be returned
`checkh(qi.size(), 4);
qi.delete(1);
v = $sformatf("%p", qi); `checks(v, "'{'h0, 'h3, 'h4} ");
qi = qe.unique_index;
`checkh(qi.size(), 0);
qi = q.unique_index(x) with (x % 3); qv.sort;
`checkh(qi.size(), 3);
q.reverse;
v = $sformatf("%p", q); `checks(v, "'{'h3, 'h1, 'h4, 'h2, 'h2} ");
@ -104,8 +111,12 @@ module t (/*AUTOARG*/);
qv = q.min;
v = $sformatf("%p", qv); `checks(v, "'{'h1} ");
qv = q.min(x) with (x + 1);
v = $sformatf("%p", qv); `checks(v, "'{'h1} ");
qv = q.max;
v = $sformatf("%p", qv); `checks(v, "'{'h4} ");
qv = q.max(x) with ((x % 4) + 100);
v = $sformatf("%p", qv); `checks(v, "'{'h3} ");
qv = qe.min;
v = $sformatf("%p", qv); `checks(v, "'{}");
qv = qe.max;

View File

@ -1,41 +1,37 @@
%Error: t/t_queue_method_bad.v:15:21: 'with' not legal on this method
: ... In instance t
15 | qv = q.unique with (1);
| ^~~~
%Error: t/t_queue_method_bad.v:16:9: The 1 arguments passed to .reverse method does not match its requiring 0 arguments
%Error: t/t_queue_method_bad.v:15:9: The 1 arguments passed to .reverse method does not match its requiring 0 arguments
: ... In instance t
16 | q.reverse(1);
15 | q.reverse(1);
| ^~~~~~~
%Error: t/t_queue_method_bad.v:17:9: The 1 arguments passed to .shuffle method does not match its requiring 0 arguments
%Error: t/t_queue_method_bad.v:16:9: The 1 arguments passed to .shuffle method does not match its requiring 0 arguments
: ... In instance t
17 | q.shuffle(1);
16 | q.shuffle(1);
| ^~~~~~~
%Error: t/t_queue_method_bad.v:18:14: 'with' statement is required for .find method
%Error: t/t_queue_method_bad.v:17:14: 'with' statement is required for .find method
: ... In instance t
18 | qv = q.find;
17 | qv = q.find;
| ^~~~
%Error: t/t_queue_method_bad.v:19:14: 'with' statement is required for .find_first method
%Error: t/t_queue_method_bad.v:18:14: 'with' statement is required for .find_first method
: ... In instance t
19 | qv = q.find_first;
18 | qv = q.find_first;
| ^~~~~~~~~~
%Error: t/t_queue_method_bad.v:20:14: 'with' statement is required for .find_last method
%Error: t/t_queue_method_bad.v:19:14: 'with' statement is required for .find_last method
: ... In instance t
20 | qv = q.find_last;
19 | qv = q.find_last;
| ^~~~~~~~~
%Error: t/t_queue_method_bad.v:21:14: 'with' statement is required for .find_index method
%Error: t/t_queue_method_bad.v:20:14: 'with' statement is required for .find_index method
: ... In instance t
21 | qi = q.find_index;
20 | qi = q.find_index;
| ^~~~~~~~~~
%Error: t/t_queue_method_bad.v:22:14: 'with' statement is required for .find_first_index method
%Error: t/t_queue_method_bad.v:21:14: 'with' statement is required for .find_first_index method
: ... In instance t
22 | qi = q.find_first_index;
21 | qi = q.find_first_index;
| ^~~~~~~~~~~~~~~~
%Error: t/t_queue_method_bad.v:23:14: 'with' statement is required for .find_last_index method
%Error: t/t_queue_method_bad.v:22:14: 'with' statement is required for .find_last_index method
: ... In instance t
23 | qi = q.find_last_index;
22 | qi = q.find_last_index;
| ^~~~~~~~~~~~~~~
%Error: t/t_queue_method_bad.v:25:19: 'with' not legal on this method
%Error: t/t_queue_method_bad.v:24:19: 'with' not legal on this method
: ... In instance t
25 | qi = q.size with (1);
24 | qi = q.size with (1);
| ^~~~
%Error: Exiting due to

View File

@ -12,7 +12,6 @@ module t (/*AUTOARG*/);
int qi[$]; // Index returns
q = '{2, 2, 4, 1, 3};
qv = q.unique with (1); // Bad no with allowed
q.reverse(1); // Bad no args allowed
q.shuffle(1); // Bad no args allowed
qv = q.find; // Bad missing with