forked from github/verilator
Support 'with item.index'.
This commit is contained in:
parent
103ba1fb6d
commit
e85a2e860e
2
Changes
2
Changes
@ -7,6 +7,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
|
||||
|
||||
*** Support $random and $urandom seeds.
|
||||
|
||||
*** Support 'with item.index'.
|
||||
|
||||
**** Fix trace signal names getting hashed (#2643). [Barbara Gigerl]
|
||||
|
||||
**** Fix unpacked array parameters near functions (#2639). [Anderson Ignacio da Silva]
|
||||
|
@ -250,14 +250,18 @@ public:
|
||||
void sort() { std::sort(m_deque.begin(), m_deque.end()); }
|
||||
template <typename Func> void sort(Func with_func) {
|
||||
// with_func returns arbitrary type to use for the sort comparison
|
||||
std::sort(m_deque.begin(), m_deque.end(),
|
||||
[=](const T_Value& a, const T_Value& b) { return with_func(a) < with_func(b); });
|
||||
std::sort(m_deque.begin(), m_deque.end(), [=](const T_Value& a, const T_Value& b) {
|
||||
// index number is meaninless with sort, as it changes
|
||||
return with_func(0, a) < with_func(0, b);
|
||||
});
|
||||
}
|
||||
void rsort() { std::sort(m_deque.rbegin(), m_deque.rend()); }
|
||||
template <typename Func> void rsort(Func with_func) {
|
||||
// with_func returns arbitrary type to use for the sort comparison
|
||||
std::sort(m_deque.rbegin(), m_deque.rend(),
|
||||
[=](const T_Value& a, const T_Value& b) { return with_func(a) < with_func(b); });
|
||||
std::sort(m_deque.rbegin(), m_deque.rend(), [=](const T_Value& a, const T_Value& b) {
|
||||
// index number is meaninless with sort, as it changes
|
||||
return with_func(0, a) < with_func(0, b);
|
||||
});
|
||||
}
|
||||
void reverse() { std::reverse(m_deque.begin(), m_deque.end()); }
|
||||
void shuffle() { std::shuffle(m_deque.begin(), m_deque.end(), VlURNG()); }
|
||||
@ -289,39 +293,54 @@ public:
|
||||
}
|
||||
template <typename Func> VlQueue find(Func with_func) const {
|
||||
VlQueue out;
|
||||
for (const auto& i : m_deque)
|
||||
if (with_func(i)) out.push_back(i);
|
||||
IData index = 0;
|
||||
for (const auto& i : m_deque) {
|
||||
if (with_func(index, i)) out.push_back(i);
|
||||
++index;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
template <typename Func> VlQueue<IData> find_index(Func with_func) const {
|
||||
VlQueue<IData> out;
|
||||
IData index = 0;
|
||||
for (const auto& i : m_deque) {
|
||||
if (with_func(i)) out.push_back(index);
|
||||
if (with_func(index, i)) out.push_back(index);
|
||||
++index;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
template <typename Func> VlQueue find_first(Func with_func) const {
|
||||
const auto it = std::find_if(m_deque.begin(), m_deque.end(), with_func);
|
||||
if (it == m_deque.end()) return VlQueue{};
|
||||
return VlQueue::cons(*it);
|
||||
// Can't use std::find_if as need index number
|
||||
IData index = 0;
|
||||
for (const auto& i : m_deque) {
|
||||
if (with_func(index, i)) return VlQueue::cons(i);
|
||||
++index;
|
||||
}
|
||||
return VlQueue{};
|
||||
}
|
||||
template <typename Func> VlQueue<IData> find_first_index(Func with_func) const {
|
||||
const auto it = std::find_if(m_deque.begin(), m_deque.end(), with_func);
|
||||
if (it == m_deque.end()) return VlQueue<IData>{};
|
||||
return VlQueue<IData>::cons(std::distance(m_deque.begin(), it));
|
||||
IData index = 0;
|
||||
for (const auto& i : m_deque) {
|
||||
if (with_func(index, i)) return VlQueue<IData>::cons(index);
|
||||
++index;
|
||||
}
|
||||
return VlQueue<IData>{};
|
||||
}
|
||||
template <typename Func> VlQueue find_last(Func with_func) const {
|
||||
const auto it = std::find_if(m_deque.rbegin(), m_deque.rend(), with_func);
|
||||
if (it == m_deque.rend()) return VlQueue{};
|
||||
return VlQueue::cons(*it);
|
||||
IData index = m_deque.size() - 1;
|
||||
for (auto it = m_deque.rbegin(); it != m_deque.rend(); ++it) {
|
||||
if (with_func(index, *it)) return VlQueue::cons(*it);
|
||||
--index;
|
||||
}
|
||||
return VlQueue{};
|
||||
}
|
||||
template <typename Func> VlQueue<IData> find_last_index(Func with_func) const {
|
||||
const auto it = std::find_if(m_deque.rbegin(), m_deque.rend(), with_func);
|
||||
if (it == m_deque.rend()) return VlQueue<IData>{};
|
||||
// Return index must be relative to beginning
|
||||
return VlQueue<IData>::cons(m_deque.size() - 1 - std::distance(m_deque.rbegin(), it));
|
||||
IData index = m_deque.size() - 1;
|
||||
for (auto it = m_deque.rbegin(); it != m_deque.rend(); ++it) {
|
||||
if (with_func(index, *it)) return VlQueue<IData>::cons(index);
|
||||
--index;
|
||||
}
|
||||
return VlQueue<IData>{};
|
||||
}
|
||||
|
||||
// Reduction operators
|
||||
@ -343,7 +362,8 @@ public:
|
||||
}
|
||||
template <typename Func> T_Value r_sum(Func with_func) const {
|
||||
T_Value out(0); // Type must have assignment operator
|
||||
for (const auto& i : m_deque) out += with_func(i);
|
||||
IData index = 0;
|
||||
for (const auto& i : m_deque) out += with_func(index++, i);
|
||||
return out;
|
||||
}
|
||||
T_Value r_product() const {
|
||||
@ -357,9 +377,11 @@ public:
|
||||
template <typename Func> T_Value r_product(Func with_func) const {
|
||||
if (m_deque.empty()) return T_Value(0);
|
||||
auto it = m_deque.begin();
|
||||
T_Value out{with_func(*it)};
|
||||
IData index = 0;
|
||||
T_Value out{with_func(index, *it)};
|
||||
++it;
|
||||
for (; it != m_deque.end(); ++it) out *= with_func(*it);
|
||||
++index;
|
||||
for (; it != m_deque.end(); ++it) out *= with_func(index++, *it);
|
||||
return out;
|
||||
}
|
||||
T_Value r_and() const {
|
||||
@ -373,9 +395,11 @@ public:
|
||||
template <typename Func> T_Value r_and(Func with_func) const {
|
||||
if (m_deque.empty()) return T_Value(0);
|
||||
auto it = m_deque.begin();
|
||||
T_Value out{with_func(*it)};
|
||||
IData index = 0;
|
||||
T_Value out{with_func(index, *it)};
|
||||
++it;
|
||||
for (; it != m_deque.end(); ++it) out &= with_func(*it);
|
||||
++index;
|
||||
for (; it != m_deque.end(); ++it) out &= with_func(index, *it);
|
||||
return out;
|
||||
}
|
||||
T_Value r_or() const {
|
||||
@ -385,7 +409,8 @@ public:
|
||||
}
|
||||
template <typename Func> T_Value r_or(Func with_func) const {
|
||||
T_Value out(0); // Type must have assignment operator
|
||||
for (const auto& i : m_deque) out |= with_func(i);
|
||||
IData index = 0;
|
||||
for (const auto& i : m_deque) out |= with_func(index++, i);
|
||||
return out;
|
||||
}
|
||||
T_Value r_xor() const {
|
||||
@ -395,7 +420,8 @@ public:
|
||||
}
|
||||
template <typename Func> T_Value r_xor(Func with_func) const {
|
||||
T_Value out(0); // Type must have assignment operator
|
||||
for (const auto& i : m_deque) out ^= with_func(i);
|
||||
IData index = 0;
|
||||
for (const auto& i : m_deque) out ^= with_func(index++, i);
|
||||
return out;
|
||||
}
|
||||
|
||||
@ -588,19 +614,19 @@ public:
|
||||
template <typename Func> VlQueue<T_Value> find(Func with_func) const {
|
||||
VlQueue<T_Value> out;
|
||||
for (const auto& i : m_map)
|
||||
if (with_func(i.second)) out.push_back(i.second);
|
||||
if (with_func(i.first, i.second)) out.push_back(i.second);
|
||||
return out;
|
||||
}
|
||||
template <typename Func> VlQueue<T_Key> find_index(Func with_func) const {
|
||||
VlQueue<T_Key> out;
|
||||
for (const auto& i : m_map)
|
||||
if (with_func(i.second)) out.push_back(i.first);
|
||||
if (with_func(i.first, i.second)) out.push_back(i.first);
|
||||
return out;
|
||||
}
|
||||
template <typename Func> VlQueue<T_Value> find_first(Func with_func) const {
|
||||
const auto it
|
||||
= std::find_if(m_map.begin(), m_map.end(), [=](const std::pair<T_Key, T_Value>& i) {
|
||||
return with_func(i.second);
|
||||
return with_func(i.first, i.second);
|
||||
});
|
||||
if (it == m_map.end()) return VlQueue<T_Value>{};
|
||||
return VlQueue<T_Value>::cons(it->second);
|
||||
@ -608,7 +634,7 @@ public:
|
||||
template <typename Func> VlQueue<T_Key> find_first_index(Func with_func) const {
|
||||
const auto it
|
||||
= std::find_if(m_map.begin(), m_map.end(), [=](const std::pair<T_Key, T_Value>& i) {
|
||||
return with_func(i.second);
|
||||
return with_func(i.first, i.second);
|
||||
});
|
||||
if (it == m_map.end()) return VlQueue<T_Value>{};
|
||||
return VlQueue<T_Key>::cons(it->first);
|
||||
@ -616,7 +642,7 @@ public:
|
||||
template <typename Func> VlQueue<T_Value> find_last(Func with_func) const {
|
||||
const auto it
|
||||
= std::find_if(m_map.rbegin(), m_map.rend(), [=](const std::pair<T_Key, T_Value>& i) {
|
||||
return with_func(i.second);
|
||||
return with_func(i.first, i.second);
|
||||
});
|
||||
if (it == m_map.rend()) return VlQueue<T_Value>{};
|
||||
return VlQueue<T_Value>::cons(it->second);
|
||||
@ -624,7 +650,7 @@ public:
|
||||
template <typename Func> VlQueue<T_Key> find_last_index(Func with_func) const {
|
||||
const auto it
|
||||
= std::find_if(m_map.rbegin(), m_map.rend(), [=](const std::pair<T_Key, T_Value>& i) {
|
||||
return with_func(i.second);
|
||||
return with_func(i.first, i.second);
|
||||
});
|
||||
if (it == m_map.rend()) return VlQueue<T_Value>{};
|
||||
return VlQueue<T_Key>::cons(it->first);
|
||||
@ -657,7 +683,7 @@ public:
|
||||
}
|
||||
template <typename Func> T_Value r_sum(Func with_func) const {
|
||||
T_Value out(0); // Type must have assignment operator
|
||||
for (const auto& i : m_map) out += with_func(i.second);
|
||||
for (const auto& i : m_map) out += with_func(i.first, i.second);
|
||||
return out;
|
||||
}
|
||||
T_Value r_product() const {
|
||||
@ -671,9 +697,9 @@ public:
|
||||
template <typename Func> T_Value r_product(Func with_func) const {
|
||||
if (m_map.empty()) return T_Value(0);
|
||||
auto it = m_map.begin();
|
||||
T_Value out{with_func(it->second)};
|
||||
T_Value out{with_func(it->first, it->second)};
|
||||
++it;
|
||||
for (; it != m_map.end(); ++it) out *= with_func(it->second);
|
||||
for (; it != m_map.end(); ++it) out *= with_func(it->first, it->second);
|
||||
return out;
|
||||
}
|
||||
T_Value r_and() const {
|
||||
@ -687,9 +713,9 @@ public:
|
||||
template <typename Func> T_Value r_and(Func with_func) const {
|
||||
if (m_map.empty()) return T_Value(0);
|
||||
auto it = m_map.begin();
|
||||
T_Value out{with_func(it->second)};
|
||||
T_Value out{with_func(it->first, it->second)};
|
||||
++it;
|
||||
for (; it != m_map.end(); ++it) out &= with_func(it->second);
|
||||
for (; it != m_map.end(); ++it) out &= with_func(it->first, it->second);
|
||||
return out;
|
||||
}
|
||||
T_Value r_or() const {
|
||||
@ -699,7 +725,7 @@ public:
|
||||
}
|
||||
template <typename Func> T_Value r_or(Func with_func) const {
|
||||
T_Value out(0); // Type must have assignment operator
|
||||
for (const auto& i : m_map) out |= with_func(i.second);
|
||||
for (const auto& i : m_map) out |= with_func(i.first, i.second);
|
||||
return out;
|
||||
}
|
||||
T_Value r_xor() const {
|
||||
@ -709,7 +735,7 @@ public:
|
||||
}
|
||||
template <typename Func> T_Value r_xor(Func with_func) const {
|
||||
T_Value out(0); // Type must have assignment operator
|
||||
for (const auto& i : m_map) out ^= with_func(i.second);
|
||||
for (const auto& i : m_map) out ^= with_func(i.first, i.second);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
@ -3107,11 +3107,13 @@ class AstLambdaArgRef final : public AstNodeMath {
|
||||
// optimizations and AstVar's are painful to remove.
|
||||
private:
|
||||
string m_name; // Name of variable
|
||||
bool m_index; // Index, not value
|
||||
|
||||
public:
|
||||
AstLambdaArgRef(FileLine* fl, const string& name)
|
||||
AstLambdaArgRef(FileLine* fl, const string& name, bool index)
|
||||
: ASTGEN_SUPER(fl)
|
||||
, m_name{name} {}
|
||||
, m_name{name}
|
||||
, m_index(index) {}
|
||||
ASTNODE_NODE_FUNCS(LambdaArgRef)
|
||||
virtual V3Hash sameHash() const override { return V3Hash(); }
|
||||
virtual bool same(const AstNode* samep) const override { return true; }
|
||||
@ -3122,31 +3124,37 @@ public:
|
||||
virtual int instrCount() const override { return widthInstrs(); }
|
||||
virtual string name() const override { return m_name; } // * = Var name
|
||||
virtual void name(const string& name) override { m_name = name; }
|
||||
bool index() const { return m_index; }
|
||||
};
|
||||
|
||||
class AstWith final : public AstNodeStmt {
|
||||
// Used as argument to method, then to AstCMethodHard
|
||||
// dtypep() contains the with lambda's return dtype
|
||||
// Parents: funcref (similar to AstArg)
|
||||
// Children: VAR that declares the index variable
|
||||
// Children: LambdaArgRef that declares the item variable
|
||||
// Children: LambdaArgRef that declares the item.index variable
|
||||
// Children: math (equation establishing the with)
|
||||
public:
|
||||
AstWith(FileLine* fl, AstLambdaArgRef* argrefp, AstNode* exprp)
|
||||
AstWith(FileLine* fl, AstLambdaArgRef* indexArgRefp, AstLambdaArgRef* valueArgRefp,
|
||||
AstNode* exprp)
|
||||
: ASTGEN_SUPER(fl) {
|
||||
addOp1p(argrefp);
|
||||
addNOp2p(exprp);
|
||||
addOp1p(indexArgRefp);
|
||||
addOp2p(valueArgRefp);
|
||||
addNOp3p(exprp);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(With)
|
||||
virtual V3Hash sameHash() const override { return V3Hash(); }
|
||||
virtual bool same(const AstNode* samep) const override { return true; }
|
||||
virtual bool hasDType() const override { return true; }
|
||||
virtual const char* broken() const override {
|
||||
BROKEN_RTN(!argrefp()); // varp needed to know lambda's arg dtype
|
||||
BROKEN_RTN(!indexArgRefp()); // varp needed to know lambda's arg dtype
|
||||
BROKEN_RTN(!valueArgRefp()); // varp needed to know lambda's arg dtype
|
||||
return nullptr;
|
||||
}
|
||||
//
|
||||
AstLambdaArgRef* argrefp() const { return VN_CAST(op1p(), LambdaArgRef); }
|
||||
AstNode* exprp() const { return op2p(); }
|
||||
AstLambdaArgRef* indexArgRefp() const { return VN_CAST(op1p(), LambdaArgRef); }
|
||||
AstLambdaArgRef* valueArgRefp() const { return VN_CAST(op2p(), LambdaArgRef); }
|
||||
AstNode* exprp() const { return op3p(); }
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
@ -430,8 +430,12 @@ public:
|
||||
virtual void visit(AstWith* nodep) override {
|
||||
// With uses a C++11 lambda
|
||||
putbs("[=](");
|
||||
if (auto* argrefp = nodep->argrefp()) {
|
||||
putbs(argrefp->dtypep()->cType(nodep->argrefp()->nameProtect(), false, false));
|
||||
if (auto* argrefp = nodep->indexArgRefp()) {
|
||||
putbs(argrefp->dtypep()->cType(argrefp->nameProtect(), false, false));
|
||||
puts(",");
|
||||
}
|
||||
if (auto* argrefp = nodep->valueArgRefp()) {
|
||||
putbs(argrefp->dtypep()->cType(argrefp->nameProtect(), false, false));
|
||||
}
|
||||
// Probably fragile, V3Task may need to convert to a AstCReturn
|
||||
puts(") { return ");
|
||||
|
@ -1281,9 +1281,10 @@ class LinkDotFindVisitor final : public AstNVisitor {
|
||||
VL_DO_DANGLING(argp->unlinkFrBackWithNext()->deleteTree(), argp);
|
||||
}
|
||||
// Type depends on the method used, let V3Width figure it out later
|
||||
auto* argrefp = new AstLambdaArgRef(argFl, name);
|
||||
auto* newp
|
||||
= new AstWith(nodep->fileline(), argrefp, nodep->exprp()->unlinkFrBackWithNext());
|
||||
auto* indexArgRefp = new AstLambdaArgRef(argFl, name + "__DOT__index", true);
|
||||
auto* valueArgRefp = new AstLambdaArgRef(argFl, name, false);
|
||||
auto* newp = new AstWith(nodep->fileline(), indexArgRefp, valueArgRefp,
|
||||
nodep->exprp()->unlinkFrBackWithNext());
|
||||
funcrefp->addPinsp(newp);
|
||||
nodep->replaceWith(funcrefp->unlinkFrBack());
|
||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||
@ -1298,9 +1299,11 @@ class LinkDotFindVisitor final : public AstNVisitor {
|
||||
m_curSymp = m_statep->insertBlock(m_curSymp, "__Vwith" + cvtToStr(m_modWithNum), nodep,
|
||||
m_packagep);
|
||||
m_curSymp->fallbackp(oldCurSymp);
|
||||
UASSERT_OBJ(nodep->argrefp(), nodep, "Missing lambda argref");
|
||||
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->argrefp()->name(), nodep->argrefp(), nullptr);
|
||||
m_statep->insertSym(m_curSymp, nodep->valueArgRefp()->name(), nodep->valueArgRefp(),
|
||||
nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2034,6 +2037,7 @@ private:
|
||||
&& (VN_IS(nodep->lhsp(), CellRef) || VN_IS(nodep->lhsp(), CellArrayRef))) {
|
||||
m_ds.m_unlinkedScopep = nodep->lhsp();
|
||||
}
|
||||
if (VN_IS(nodep->lhsp(), LambdaArgRef)) { m_ds.m_unlinkedScopep = nodep->lhsp(); }
|
||||
if (!m_ds.m_dotErr) { // Once something wrong, give up
|
||||
// Top 'final' dot RHS is final RHS, else it's a
|
||||
// DOT(DOT(x,*here*),real-rhs) which we consider a RHS
|
||||
@ -2089,7 +2093,16 @@ private:
|
||||
nodep->v3warn(E_UNSUPPORTED, "Unsupported: super");
|
||||
m_ds.m_dotErr = true;
|
||||
}
|
||||
if (m_ds.m_dotPos == DP_MEMBER) {
|
||||
if (m_ds.m_dotPos == DP_FINAL && VN_IS(m_ds.m_unlinkedScopep, LambdaArgRef)
|
||||
&& nodep->name() == "index") {
|
||||
// 'with' statement's 'item.index'
|
||||
iterateChildren(nodep);
|
||||
auto newp = new AstLambdaArgRef(nodep->fileline(),
|
||||
m_ds.m_unlinkedScopep->name() + "__DOT__index", true);
|
||||
nodep->replaceWith(newp);
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
return;
|
||||
} else if (m_ds.m_dotPos == DP_MEMBER) {
|
||||
// Found a Var, everything following is membership. {scope}.{var}.HERE {member}
|
||||
AstNode* varEtcp = m_ds.m_dotp->lhsp()->unlinkFrBack();
|
||||
AstNode* newp
|
||||
@ -2301,7 +2314,7 @@ private:
|
||||
}
|
||||
} else if (AstLambdaArgRef* argrefp = VN_CAST(foundp->nodep(), LambdaArgRef)) {
|
||||
if (allowVar) {
|
||||
AstNode* newp = new AstLambdaArgRef(nodep->fileline(), argrefp->name());
|
||||
AstNode* newp = new AstLambdaArgRef(nodep->fileline(), argrefp->name(), false);
|
||||
nodep->replaceWith(newp);
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
ok = true;
|
||||
@ -2730,6 +2743,11 @@ private:
|
||||
}
|
||||
m_ds.m_dotSymp = m_curSymp = oldCurSymp;
|
||||
}
|
||||
virtual void visit(AstLambdaArgRef* nodep) override {
|
||||
UINFO(5, " " << nodep << endl);
|
||||
// No checknodot(nodep), visit(AstScope) will check for LambdaArgRef
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstClass* nodep) override {
|
||||
UINFO(5, " " << nodep << endl);
|
||||
checkNoDot(nodep);
|
||||
|
@ -201,7 +201,7 @@ private:
|
||||
AstCell* m_cellp = nullptr; // Current cell for arrayed instantiations
|
||||
AstNodeFTask* m_ftaskp = nullptr; // Current function/task
|
||||
AstNodeProcedure* m_procedurep = nullptr; // Current final/always
|
||||
AstLambdaArgRef* m_lambdaArgRefp = nullptr; // Argument to above lambda
|
||||
AstWith* m_withp = nullptr; // Current 'with' statement
|
||||
AstFunc* m_funcp = nullptr; // Current function
|
||||
AstAttrOf* m_attrp = nullptr; // Current attribute
|
||||
bool m_doGenerate; // Do errors later inside generate statement
|
||||
@ -2373,10 +2373,12 @@ private:
|
||||
}
|
||||
}
|
||||
AstWith* methodWithArgument(AstMethodCall* nodep, bool required, bool arbReturn,
|
||||
AstNodeDType* returnDtp, AstNodeDType* argDtp) {
|
||||
AstNodeDType* returnDtp, AstNodeDType* indexDtp,
|
||||
AstNodeDType* valueDtp) {
|
||||
UASSERT_OBJ(arbReturn || returnDtp, nodep, "Null return type");
|
||||
if (AstWith* withp = VN_CAST(nodep->pinsp(), With)) {
|
||||
withp->argrefp()->dtypep(argDtp);
|
||||
withp->indexArgRefp()->dtypep(indexDtp);
|
||||
withp->valueArgRefp()->dtypep(valueDtp);
|
||||
userIterate(withp, WidthVP(returnDtp, BOTH).p());
|
||||
withp->unlinkFrBack();
|
||||
return withp;
|
||||
@ -2570,7 +2572,7 @@ private:
|
||||
|| nodep->name() == "sum" || nodep->name() == "product") {
|
||||
// All value return
|
||||
AstWith* withp = methodWithArgument(nodep, false, false, adtypep->subDTypep(),
|
||||
adtypep->subDTypep());
|
||||
adtypep->keyDTypep(), adtypep->subDTypep());
|
||||
methodOkArguments(nodep, 0, 0);
|
||||
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
|
||||
newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(),
|
||||
@ -2592,7 +2594,7 @@ private:
|
||||
} else if (nodep->name() == "find" || nodep->name() == "find_first"
|
||||
|| nodep->name() == "find_last") {
|
||||
AstWith* withp = methodWithArgument(nodep, true, false, nodep->findLogicBoolDType(),
|
||||
adtypep->subDTypep());
|
||||
adtypep->keyDTypep(), adtypep->subDTypep());
|
||||
methodOkArguments(nodep, 0, 0);
|
||||
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
|
||||
newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(),
|
||||
@ -2602,7 +2604,7 @@ private:
|
||||
} else if (nodep->name() == "find_index" || nodep->name() == "find_first_index"
|
||||
|| nodep->name() == "find_last_index") {
|
||||
AstWith* withp = methodWithArgument(nodep, true, false, nodep->findLogicBoolDType(),
|
||||
adtypep->subDTypep());
|
||||
adtypep->keyDTypep(), adtypep->subDTypep());
|
||||
methodOkArguments(nodep, 0, 0);
|
||||
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
|
||||
newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(),
|
||||
@ -2663,7 +2665,7 @@ private:
|
||||
|| nodep->name() == "sum" || nodep->name() == "product") {
|
||||
// All value return
|
||||
AstWith* withp = methodWithArgument(nodep, false, false, adtypep->subDTypep(),
|
||||
adtypep->subDTypep());
|
||||
nodep->findUInt32DType(), adtypep->subDTypep());
|
||||
methodOkArguments(nodep, 0, 0);
|
||||
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
|
||||
newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(),
|
||||
@ -2674,7 +2676,8 @@ private:
|
||||
|| nodep->name() == "sort" || nodep->name() == "rsort") {
|
||||
AstWith* withp = nullptr;
|
||||
if (nodep->name() == "sort" || nodep->name() == "rsort") {
|
||||
withp = methodWithArgument(nodep, false, true, nullptr, adtypep->subDTypep());
|
||||
withp = methodWithArgument(nodep, false, true, nullptr, nodep->findUInt32DType(),
|
||||
adtypep->subDTypep());
|
||||
}
|
||||
methodOkArguments(nodep, 0, 0);
|
||||
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::WRITE);
|
||||
@ -2696,7 +2699,7 @@ private:
|
||||
} else if (nodep->name() == "find" || nodep->name() == "find_first"
|
||||
|| nodep->name() == "find_last" || nodep->name() == "find_index") {
|
||||
AstWith* withp = methodWithArgument(nodep, true, false, nodep->findLogicBoolDType(),
|
||||
adtypep->subDTypep());
|
||||
nodep->findUInt32DType(), adtypep->subDTypep());
|
||||
methodOkArguments(nodep, 0, 0);
|
||||
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
|
||||
newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(),
|
||||
@ -2706,7 +2709,7 @@ private:
|
||||
} else if (nodep->name() == "find_index" || nodep->name() == "find_first_index"
|
||||
|| nodep->name() == "find_last_index") {
|
||||
AstWith* withp = methodWithArgument(nodep, true, false, nodep->findLogicBoolDType(),
|
||||
adtypep->subDTypep());
|
||||
nodep->findUInt32DType(), adtypep->subDTypep());
|
||||
methodOkArguments(nodep, 0, 0);
|
||||
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
|
||||
newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(),
|
||||
@ -2794,7 +2797,7 @@ private:
|
||||
} else if (nodep->name() == "and" || nodep->name() == "or" || nodep->name() == "xor"
|
||||
|| nodep->name() == "sum" || nodep->name() == "product") {
|
||||
AstWith* withp = methodWithArgument(nodep, false, false, adtypep->subDTypep(),
|
||||
adtypep->subDTypep());
|
||||
nodep->findUInt32DType(), adtypep->subDTypep());
|
||||
methodOkArguments(nodep, 0, 0);
|
||||
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
|
||||
newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(),
|
||||
@ -2805,7 +2808,8 @@ private:
|
||||
|| nodep->name() == "sort" || nodep->name() == "rsort") {
|
||||
AstWith* withp = nullptr;
|
||||
if (nodep->name() == "sort" || nodep->name() == "rsort") {
|
||||
withp = methodWithArgument(nodep, false, true, nullptr, adtypep->subDTypep());
|
||||
withp = methodWithArgument(nodep, false, true, nullptr, nodep->findUInt32DType(),
|
||||
adtypep->subDTypep());
|
||||
}
|
||||
methodOkArguments(nodep, 0, 0);
|
||||
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::WRITE);
|
||||
@ -2827,7 +2831,7 @@ private:
|
||||
} else if (nodep->name() == "find" || nodep->name() == "find_first"
|
||||
|| nodep->name() == "find_last") {
|
||||
AstWith* withp = methodWithArgument(nodep, true, false, nodep->findLogicBoolDType(),
|
||||
adtypep->subDTypep());
|
||||
nodep->findUInt32DType(), adtypep->subDTypep());
|
||||
methodOkArguments(nodep, 0, 0);
|
||||
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
|
||||
newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(),
|
||||
@ -2837,7 +2841,7 @@ private:
|
||||
} else if (nodep->name() == "find_index" || nodep->name() == "find_first_index"
|
||||
|| nodep->name() == "find_last_index") {
|
||||
AstWith* withp = methodWithArgument(nodep, true, false, nodep->findLogicBoolDType(),
|
||||
adtypep->subDTypep());
|
||||
nodep->findUInt32DType(), adtypep->subDTypep());
|
||||
methodOkArguments(nodep, 0, 0);
|
||||
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
|
||||
newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(),
|
||||
@ -4422,10 +4426,11 @@ private:
|
||||
virtual void visit(AstWith* nodep) override {
|
||||
// Should otherwise be underneath a method call
|
||||
AstNodeDType* vdtypep = m_vup->dtypeNullSkipRefp();
|
||||
VL_RESTORER(m_lambdaArgRefp);
|
||||
VL_RESTORER(m_withp);
|
||||
{
|
||||
m_lambdaArgRefp = nodep->argrefp();
|
||||
userIterateChildren(nodep->argrefp(), nullptr);
|
||||
m_withp = nodep;
|
||||
userIterateChildren(nodep->indexArgRefp(), nullptr);
|
||||
userIterateChildren(nodep->valueArgRefp(), nullptr);
|
||||
if (vdtypep) {
|
||||
userIterateAndNext(nodep->exprp(), WidthVP(nodep->dtypep(), PRELIM).p());
|
||||
} else { // 'sort with' allows arbitrary type
|
||||
@ -4437,8 +4442,12 @@ private:
|
||||
}
|
||||
}
|
||||
virtual void visit(AstLambdaArgRef* nodep) override {
|
||||
UASSERT_OBJ(m_lambdaArgRefp, nodep, "LambdaArgRef not underneath with lambda");
|
||||
nodep->dtypeFrom(m_lambdaArgRefp);
|
||||
UASSERT_OBJ(m_withp, nodep, "LambdaArgRef not underneath 'with' lambda");
|
||||
if (nodep->index()) {
|
||||
nodep->dtypeFrom(m_withp->indexArgRefp());
|
||||
} else {
|
||||
nodep->dtypeFrom(m_withp->valueArgRefp());
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNetlist* nodep) override {
|
||||
// Iterate modules backwards, in bottom-up order. That's faster
|
||||
|
@ -67,6 +67,11 @@ module t (/*AUTOARG*/);
|
||||
qi = q.find_last_index with (item == 20);
|
||||
v = $sformatf("%p", qi); `checks(v, "'{}");
|
||||
|
||||
qi = q.find_index with (item.index == 12);
|
||||
v = $sformatf("%p", qi); `checks(v, "'{'hc} ");
|
||||
qi = q.find with (item.index == 12);
|
||||
v = $sformatf("%p", qi); `checks(v, "'{'h2} ");
|
||||
|
||||
qv = q.min;
|
||||
v = $sformatf("%p", qv); `checks(v, "'{'h1} ");
|
||||
qv = q.max;
|
||||
|
@ -100,6 +100,9 @@ module t (/*AUTOARG*/);
|
||||
qi = d.find_last_index with (item == 20);
|
||||
`checkh(qi.size, 0);
|
||||
|
||||
qi = d.find_index with (item.index == 2);
|
||||
v = $sformatf("%p", qi); `checks(v, "'{'h2} ");
|
||||
|
||||
qv = d.min;
|
||||
v = $sformatf("%p", qv); `checks(v, "'{'h1} ");
|
||||
qv = d.max;
|
||||
|
@ -95,6 +95,11 @@ module t (/*AUTOARG*/);
|
||||
qi = q.find_last_index with (item == 20);
|
||||
`checkh(qi.size, 0);
|
||||
|
||||
qi = q.find_index with (item.index == 2);
|
||||
v = $sformatf("%p", qi); `checks(v, "'{'h2} ");
|
||||
qi = q.find_index with (item.index == item);
|
||||
v = $sformatf("%p", qi); `checks(v, "'{'h2, 'h3, 'h4} ");
|
||||
|
||||
qv = q.min;
|
||||
v = $sformatf("%p", qv); `checks(v, "'{'h1} ");
|
||||
qv = q.max;
|
||||
|
Loading…
Reference in New Issue
Block a user