Internals: Refactor to create VCMethod (#3715). No functional change intended.

This commit is contained in:
Wilson Snyder 2025-09-27 08:22:17 -04:00
parent 89cd5417ef
commit 3b623dc12e
20 changed files with 467 additions and 244 deletions

View File

@ -233,7 +233,8 @@ private:
new AstSenItem{flp, VEdgeType::ET_CHANGED, skewedReadRefp->cloneTree(false)});
AstCMethodHard* const trigp = new AstCMethodHard{
nodep->fileline(),
new AstVarRef{flp, m_clockingp->ensureEventp(), VAccess::READ}, "isTriggered"};
new AstVarRef{flp, m_clockingp->ensureEventp(), VAccess::READ},
VCMethod::EVENT_IS_TRIGGERED};
trigp->dtypeSetBit();
ifp->condp(new AstLogAnd{flp, ifp->condp()->unlinkFrBack(), trigp});
m_clockingp->addNextHere(new AstAlwaysReactive{flp, senTreep, ifp});
@ -285,7 +286,7 @@ private:
// Create a process like this:
// always queue.push(<sampled var>);
AstCMethodHard* const pushp = new AstCMethodHard{
flp, new AstVarRef{flp, queueVarp, VAccess::WRITE}, "push",
flp, new AstVarRef{flp, queueVarp, VAccess::WRITE}, VCMethod::DYN_PUSH,
new AstTime{nodep->fileline(), m_modp->timeunit()}};
pushp->addPinsp(exprp->cloneTreePure(false));
pushp->dtypeSetVoid();
@ -294,7 +295,7 @@ private:
// Create a process like this:
// always @<clocking event> queue.pop(<skew>, /*out*/<skewed var>);
AstCMethodHard* const popp = new AstCMethodHard{
flp, new AstVarRef{flp, queueVarp, VAccess::READWRITE}, "pop",
flp, new AstVarRef{flp, queueVarp, VAccess::READWRITE}, VCMethod::DYN_POP,
new AstTime{nodep->fileline(), m_modp->timeunit()}};
popp->addPinsp(skewp->unlinkFrBack());
popp->addPinsp(refp);

View File

@ -49,6 +49,28 @@ bool VNUser4InUse::s_userBusy = false;
int AstNodeDType::s_uniqueNum = 0;
V3AST_VCMETHOD_ITEMDATA_DECL;
//======================================================================
// VCMethod information
VCMethod VCMethod::arrayMethod(const string& name) {
for (auto& it : s_itemData)
if (it.m_name == name) return it.m_e;
v3fatalSrc("Not a method name known to VCMethod::s_itemData: '" << name << '\'');
return VCMethod{};
}
void VCMethod::selfTest() {
int i = 0;
for (auto& it : s_itemData) {
VCMethod exp{i};
UASSERT_STATIC(it.m_e == exp,
"VCMethod::s_itemData table rows are out-of-order, starting at row "s
+ cvtToStr(i) + " '" + +it.m_name + '\'');
++i;
}
}
//######################################################################
// VNType

View File

@ -703,6 +703,247 @@ inline std::ostream& operator<<(std::ostream& os, const VBranchPred& rhs) {
// ######################################################################
class VCMethod final {
public:
// Entries in this table need to match below VCMethod::s_itemData[] table
enum en : uint8_t {
_NONE, // Unknown
ARRAY_AND,
ARRAY_AT,
ARRAY_AT_BACK,
ARRAY_AT_WRITE,
ARRAY_FIND,
ARRAY_FIND_FIRST,
ARRAY_FIND_FIRST_INDEX,
ARRAY_FIND_INDEX,
ARRAY_FIND_LAST,
ARRAY_FIND_LAST_INDEX,
ARRAY_FIRST,
ARRAY_INSIDE,
ARRAY_LAST,
ARRAY_MAX,
ARRAY_MIN,
ARRAY_NEXT,
ARRAY_OR,
ARRAY_POP_BACK,
ARRAY_POP_FRONT,
ARRAY_PREV,
ARRAY_PRODUCT,
ARRAY_PUSH_BACK,
ARRAY_PUSH_FRONT,
ARRAY_REVERSE,
ARRAY_RSORT,
ARRAY_R_AND,
ARRAY_R_OR,
ARRAY_R_PRODUCT,
ARRAY_R_SUM,
ARRAY_R_XOR,
ARRAY_SHUFFLE,
ARRAY_SORT,
ARRAY_SUM,
ARRAY_UNIQUE,
ARRAY_UNIQUE_INDEX,
ARRAY_XOR,
ASSOC_CLEAR,
ASSOC_ERASE,
ASSOC_EXISTS,
ASSOC_FIRST,
ASSOC_NEXT,
ASSOC_SIZE,
CLASS_SET_RANDMODE,
DYN_AT_WRITE_APPEND,
DYN_AT_WRITE_APPEND_BACK,
DYN_CLEAR,
DYN_ERASE,
DYN_INSERT,
DYN_POP,
DYN_POP_FRONT,
DYN_PUSH,
DYN_PUSH_FRONT,
DYN_RENEW,
DYN_RENEW_COPY,
DYN_RESIZE,
DYN_SIZE,
DYN_SLICE,
DYN_SLICE_BACK_BACK,
DYN_SLICE_FRONT_BACK,
EVENT_CLEAR_FIRED,
EVENT_CLEAR_TRIGGERED,
EVENT_FIRE,
EVENT_IS_FIRED,
EVENT_IS_TRIGGERED,
FORK_DONE,
FORK_INIT,
FORK_JOIN,
RANDOMIZER_BASIC_STD_RANDOMIZATION,
RANDOMIZER_CLEAR,
RANDOMIZER_HARD,
RANDOMIZER_WRITE_VAR,
RNG_GET_RANDSTATE,
RNG_SET_RANDSTATE,
SCHED_ANY_TRIGGERED,
SCHED_AWAITING_CURRENT_TIME,
SCHED_COMMIT,
SCHED_DELAY,
SCHED_DO_POST_UPDATES,
SCHED_ENQUEUE,
SCHED_EVALUATE,
SCHED_EVALUATION,
SCHED_POST_UPDATE,
SCHED_RESUME,
SCHED_RESUMPTION,
SCHED_TRIGGER,
SCHED_TRIGGERED,
TRIGGER_AND_NOT,
TRIGGER_ANY,
TRIGGER_CLEAR,
TRIGGER_SET_BIT,
TRIGGER_SET_WORD,
TRIGGER_THIS_OR,
TRIGGER_WORD,
UNPACKED_ASSIGN,
UNPACKED_FILL,
UNPACKED_NEQ,
_ENUM_MAX // Leave last
};
private:
struct Item final {
enum en m_e; // Method's enum mnemonic, for checking
const char* m_name; // Method name, printed into C++
bool m_pure; // Method being called is pure
};
static Item s_itemData[];
public:
enum en m_e;
VCMethod()
: m_e{_NONE} {}
// cppcheck-suppress noExplicitConstructor
constexpr VCMethod(en _e)
: m_e{_e} {}
explicit VCMethod(int _e)
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
constexpr operator en() const { return m_e; }
const char* ascii() const VL_PURE { return s_itemData[m_e].m_name; }
bool isPure() const VL_PURE { return s_itemData[m_e].m_pure; }
// Return array method for given name
static VCMethod arrayMethod(const string& name);
static void selfTest();
};
constexpr bool operator==(const VCMethod& lhs, const VCMethod& rhs) { return lhs.m_e == rhs.m_e; }
constexpr bool operator==(const VCMethod& lhs, VCMethod::en rhs) { return lhs.m_e == rhs; }
constexpr bool operator==(VCMethod::en lhs, const VCMethod& rhs) { return lhs == rhs.m_e; }
inline std::ostream& operator<<(std::ostream& os, const VCMethod& rhs) {
return os << rhs.ascii();
}
// Entries in this table need to match above VCMethod enum table
//
// {Mnemonic, C++ method, pure}
#define V3AST_VCMETHOD_ITEMDATA_DECL \
VCMethod::Item VCMethod::s_itemData[] \
= {{_NONE, "_none", false}, \
{ARRAY_AND, "and", true}, \
{ARRAY_AT, "at", true}, \
{ARRAY_AT_BACK, "atBack", true}, \
{ARRAY_AT_WRITE, "atWrite", true}, \
{ARRAY_FIND, "find", true}, \
{ARRAY_FIND_FIRST, "find_first", true}, \
{ARRAY_FIND_FIRST_INDEX, "find_first_index", true}, \
{ARRAY_FIND_INDEX, "find_index", true}, \
{ARRAY_FIND_LAST, "find_last", true}, \
{ARRAY_FIND_LAST_INDEX, "find_last_index", true}, \
{ARRAY_FIRST, "first", false}, \
{ARRAY_INSIDE, "inside", true}, \
{ARRAY_LAST, "last", false}, \
{ARRAY_MAX, "max", true}, \
{ARRAY_MIN, "min", true}, \
{ARRAY_NEXT, "next", false}, \
{ARRAY_OR, "or", true}, \
{ARRAY_POP_BACK, "pop_back", false}, \
{ARRAY_POP_FRONT, "pop_front", false}, \
{ARRAY_PREV, "prev", false}, \
{ARRAY_PRODUCT, "product", true}, \
{ARRAY_PUSH_BACK, "push_back", false}, \
{ARRAY_PUSH_FRONT, "push_front", false}, \
{ARRAY_REVERSE, "reverse", false}, \
{ARRAY_RSORT, "rsort", false}, \
{ARRAY_R_AND, "r_and", true}, \
{ARRAY_R_OR, "r_or", true}, \
{ARRAY_R_PRODUCT, "r_product", true}, \
{ARRAY_R_SUM, "r_sum", true}, \
{ARRAY_R_XOR, "r_xor", true}, \
{ARRAY_SHUFFLE, "shuffle", false}, \
{ARRAY_SORT, "sort", false}, \
{ARRAY_SUM, "sum", true}, \
{ARRAY_UNIQUE, "unique", true}, \
{ARRAY_UNIQUE_INDEX, "unique_index", true}, \
{ARRAY_XOR, "xor", true}, \
{ASSOC_CLEAR, "clear", false}, \
{ASSOC_ERASE, "erase", false}, \
{ASSOC_EXISTS, "exists", true}, \
{ASSOC_FIRST, "first", false}, \
{ASSOC_NEXT, "next", false}, \
{ASSOC_SIZE, "size", true}, \
{CLASS_SET_RANDMODE, "set_randmode", false}, \
{DYN_AT_WRITE_APPEND, "atWriteAppend", false}, \
{DYN_AT_WRITE_APPEND_BACK, "atWriteAppendBack", false}, \
{DYN_CLEAR, "clear", false}, \
{DYN_ERASE, "erase", false}, \
{DYN_INSERT, "insert", false}, \
{DYN_POP, "pop", false}, \
{DYN_POP_FRONT, "pop_front", false}, \
{DYN_PUSH, "push", false}, \
{DYN_PUSH_FRONT, "push_front", false}, \
{DYN_RENEW, "renew", false}, \
{DYN_RENEW_COPY, "renew_copy", false}, \
{DYN_RESIZE, "resize", false}, \
{DYN_SIZE, "size", true}, \
{DYN_SLICE, "slice", true}, \
{DYN_SLICE_BACK_BACK, "sliceBackBack", true}, \
{DYN_SLICE_FRONT_BACK, "sliceFrontBack", true}, \
{EVENT_CLEAR_FIRED, "clearFired", false}, \
{EVENT_CLEAR_TRIGGERED, "clearTriggered", false}, \
{EVENT_FIRE, "fire", false}, \
{EVENT_IS_FIRED, "isFired", true}, \
{EVENT_IS_TRIGGERED, "isTriggered", true}, \
{FORK_DONE, "done", false}, \
{FORK_INIT, "init", false}, \
{FORK_JOIN, "join", false}, \
{RANDOMIZER_BASIC_STD_RANDOMIZATION, "basicStdRandomization", false}, \
{RANDOMIZER_CLEAR, "clear", false}, \
{RANDOMIZER_HARD, "hard", false}, \
{RANDOMIZER_WRITE_VAR, "write_var", false}, \
{RNG_GET_RANDSTATE, "__Vm_rng.get_randstate", true}, \
{RNG_SET_RANDSTATE, "__Vm_rng.set_randstate", false}, \
{SCHED_ANY_TRIGGERED, "anyTriggered", false}, \
{SCHED_AWAITING_CURRENT_TIME, "awaitingCurrentTime", true}, \
{SCHED_COMMIT, "commit", false}, \
{SCHED_DELAY, "delay", false}, \
{SCHED_DO_POST_UPDATES, "doPostUpdates", false}, \
{SCHED_ENQUEUE, "enqueue", false}, \
{SCHED_EVALUATE, "evaluate", false}, \
{SCHED_EVALUATION, "evaluation", false}, \
{SCHED_POST_UPDATE, "postUpdate", false}, \
{SCHED_RESUME, "resume", false}, \
{SCHED_RESUMPTION, "resumption", false}, \
{SCHED_TRIGGER, "trigger", false}, \
{SCHED_TRIGGERED, "triggered", false}, \
{TRIGGER_AND_NOT, "andNot", false}, \
{TRIGGER_ANY, "any", true}, \
{TRIGGER_CLEAR, "clear", false}, \
{TRIGGER_SET_BIT, "setBit", false}, \
{TRIGGER_SET_WORD, "setWord", false}, \
{TRIGGER_THIS_OR, "thisOr", false}, \
{TRIGGER_WORD, "word", true}, \
{UNPACKED_ASSIGN, "assign", false}, \
{UNPACKED_FILL, "fill", false}, \
{UNPACKED_NEQ, "neq", true}, \
{_ENUM_MAX, "_ENUM_MAX", false}};
// ######################################################################
class VCaseType final {
public:
enum en : uint8_t { CT_CASE, CT_CASEX, CT_CASEZ, CT_CASEINSIDE };

View File

@ -618,24 +618,22 @@ class AstCMethodHard final : public AstNodeExpr {
// PARENTS: stmt/expr
// @astgen op1 := fromp : AstNodeExpr // Subject of method call
// @astgen op2 := pinsp : List[AstNodeExpr] // Arguments
string m_name; // Name of method
VCMethod m_method; // Which method to call
bool m_pure = false; // Pure optimizable
bool m_usePtr = false; // Use '->' not '.'
public:
AstCMethodHard(FileLine* fl, AstNodeExpr* fromp, const string& name,
AstNodeExpr* pinsp = nullptr)
AstCMethodHard(FileLine* fl, AstNodeExpr* fromp, VCMethod method, AstNodeExpr* pinsp = nullptr)
: ASTGEN_SUPER_CMethodHard(fl)
, m_name{name} {
, m_method{method} {
this->fromp(fromp);
addPinsp(pinsp);
setPurity();
}
ASTGEN_MEMBERS_AstCMethodHard;
string name() const override VL_MT_STABLE { return m_name; } // * = Var name
void name(const string& name) override { m_name = name; }
string name() const override VL_MT_STABLE { return method().ascii(); }
bool sameNode(const AstNode* samep) const override {
const AstCMethodHard* const asamep = VN_DBG_AS(samep, CMethodHard);
return (m_name == asamep->m_name);
return (m_method == asamep->m_method);
}
bool isPure() override { return m_pure; }
int instrCount() const override;
@ -644,6 +642,8 @@ public:
bool cleanOut() const override { return true; }
bool usePtr() const { return m_usePtr; }
void usePtr(bool flag) { m_usePtr = flag; }
VCMethod method() const VL_MT_STABLE { return m_method; }
void method(VCMethod value) { m_method = value; }
private:
void setPurity();

View File

@ -91,12 +91,10 @@ bool AstNodeFTaskRef::getPurityRecurse() const {
AstNodeFTask* const taskp = this->taskp();
// Unlinked yet, so treat as impure
if (!taskp) return false;
// First compute the purity of arguments
for (AstNode* pinp = this->pinsp(); pinp; pinp = pinp->nextp()) {
if (!pinp->isPure()) return false;
}
return taskp->isPure();
}
bool AstNodeFTaskRef::isGateOptimizable() const { return m_taskp && m_taskp->isGateOptimizable(); }
@ -3144,94 +3142,17 @@ void AstCAwait::dump(std::ostream& str) const {
void AstCAwait::dumpJson(std::ostream& str) const { dumpJsonGen(str); }
int AstCMethodHard::instrCount() const {
if (const AstBasicDType* const basicp = fromp()->dtypep()->basicp()) {
// TODO: add a more structured description of library methods, rather than using string
// matching. See issue #3715.
if (basicp->isTriggerVec() && m_name == "word") {
if (basicp->isTriggerVec() && m_method == VCMethod::TRIGGER_WORD) {
// This is an important special case for scheduling so we compute it precisely,
// it is simply a load.
return INSTR_COUNT_LD;
}
}
return 0;
return 0; // TODO
}
void AstCMethodHard::setPurity() {
static const std::map<std::string, bool> isPureMethod{{"__Vm_rng.get_randstate", true},
{"__Vm_rng.set_randstate", false},
{"andNot", false},
{"any", true},
{"anyTriggered", false},
{"assign", false},
{"at", true},
{"atBack", true},
{"atWrite", true},
{"awaitingCurrentTime", true},
{"basicStdRandomization", false},
{"clear", false},
{"clearFired", false},
{"commit", false},
{"delay", false},
{"done", false},
{"enqueue", false},
{"erase", false},
{"evaluate", false},
{"evaluation", false},
{"exists", true},
{"fill", false},
{"find", true},
{"find_first", true},
{"find_first_index", true},
{"find_index", true},
{"find_last", true},
{"find_last_index", true},
{"fire", false},
{"first", false},
{"hard", false},
{"init", false},
{"insert", false},
{"inside", true},
{"isFired", true},
{"isTriggered", true},
{"join", false},
{"last", false},
{"max", true},
{"min", true},
{"neq", true},
{"next", false},
{"pop", false},
{"pop_back", false},
{"pop_front", false},
{"prev", false},
{"push", false},
{"push_back", false},
{"push_front", false},
{"r_and", true},
{"r_or", true},
{"r_product", true},
{"r_sum", true},
{"r_xor", true},
{"renew", false},
{"renew_copy", false},
{"resize", false},
{"resume", false},
{"reverse", false},
{"rsort", false},
{"setBit", false},
{"setWord", false},
{"set_randmode", false},
{"shuffle", false},
{"size", true},
{"slice", true},
{"sliceBackBack", true},
{"sliceFrontBack", true},
{"sort", false},
{"thisOr", false},
{"trigger", false},
{"unique", true},
{"unique_index", true},
{"word", true},
{"write_var", false}};
if (name() == "atWriteAppend" || name() == "atWriteAppendBack") {
if (method() == VCMethod::DYN_AT_WRITE_APPEND
|| method() == VCMethod::DYN_AT_WRITE_APPEND_BACK) {
m_pure = false;
// Treat atWriteAppend as pure if the argument is a loop iterator
if (const AstNodeExpr* const argp = pinsp()) {
@ -3241,11 +3162,7 @@ void AstCMethodHard::setPurity() {
}
return;
}
auto isPureIt = isPureMethod.find(name());
// cppcheck-suppress derefInvalidIteratorRedundantCheck
UASSERT_OBJ(isPureIt != isPureMethod.end(), this, "Unknown purity of method " + name());
// cppcheck-suppress derefInvalidIteratorRedundantCheck
m_pure = isPureIt->second;
m_pure = method().isPure();
if (!m_pure) return;
if (!fromp()->isPure()) m_pure = false;
if (!m_pure) return;

View File

@ -485,9 +485,9 @@ AstNode* V3Begin::convertToWhile(AstForeach* nodep) {
? new AstArraySel{fl, subfromp->cloneTreePure(false),
new AstVarRef{fl, nestedIndexp, VAccess::READ}}
: subfromp->cloneTreePure(false),
"size"};
VCMethod::DYN_SIZE};
AstVarRef* varRefp = new AstVarRef{fl, varp, VAccess::READ};
subfromp = new AstCMethodHard{fl, subfromp, "at", varRefp};
subfromp = new AstCMethodHard{fl, subfromp, VCMethod::ARRAY_AT, varRefp};
subfromp->dtypep(fromDtp);
rightp->dtypeSetSigned32();
rightp->protect(false);
@ -503,15 +503,15 @@ AstNode* V3Begin::convertToWhile(AstForeach* nodep) {
first_varp->usedLoopIdx(true);
first_varp->lifetime(VLifetime::AUTOMATIC_EXPLICIT);
AstNodeExpr* const firstp
= new AstCMethodHard{fl, subfromp->cloneTreePure(false), "first",
= new AstCMethodHard{fl, subfromp->cloneTreePure(false), VCMethod::ASSOC_FIRST,
new AstVarRef{fl, varp, VAccess::READWRITE}};
firstp->dtypeSetSigned32();
AstNodeExpr* const nextp
= new AstCMethodHard{fl, subfromp->cloneTreePure(false), "next",
= new AstCMethodHard{fl, subfromp->cloneTreePure(false), VCMethod::ASSOC_NEXT,
new AstVarRef{fl, varp, VAccess::READWRITE}};
nextp->dtypeSetSigned32();
AstVarRef* varRefp = new AstVarRef{fl, varp, VAccess::READ};
subfromp = new AstCMethodHard{fl, subfromp, "at", varRefp};
subfromp = new AstCMethodHard{fl, subfromp, VCMethod::ARRAY_AT, varRefp};
subfromp->dtypep(fromDtp);
AstNode* const first_clearp
= new AstAssign{fl, new AstVarRef{fl, first_varp, VAccess::WRITE},

View File

@ -3012,8 +3012,8 @@ class ConstVisitor final : public VNVisitor {
if (const AstCMethodHard* const aCallp = VN_CAST(ap, CMethodHard)) {
const AstCMethodHard* const bCallp = VN_AS(bp, CMethodHard);
if (aCallp->name() < bCallp->name()) return -1;
if (aCallp->name() > bCallp->name()) return 1;
if (aCallp->method() < bCallp->method()) return -1;
if (aCallp->method() > bCallp->method()) return 1;
if (const int c = cmp(aCallp->fromp(), bCallp->fromp())) return c;
const AstNodeExpr* aPinsp = aCallp->pinsp();
const AstNodeExpr* bPinsp = bCallp->pinsp();

View File

@ -859,8 +859,8 @@ class DelayedVisitor final : public VNVisitor {
AstAlwaysPost* const postp = new AstAlwaysPost{flp};
activep->addStmtsp(postp);
// Add the commit
AstCMethodHard* const callp
= new AstCMethodHard{flp, new AstVarRef{flp, queueVscp, VAccess::READWRITE}, "commit"};
AstCMethodHard* const callp = new AstCMethodHard{
flp, new AstVarRef{flp, queueVscp, VAccess::READWRITE}, VCMethod::SCHED_COMMIT};
callp->dtypeSetVoid();
callp->addPinsp(new AstVarRef{flp, vscp, VAccess::WRITE});
postp->addStmtsp(callp->makeStmt());
@ -969,7 +969,8 @@ class DelayedVisitor final : public VNVisitor {
// Enqueue the update at the site of the original NBA
AstCMethodHard* const callp = new AstCMethodHard{
flp, new AstVarRef{flp, vscpInfo.valueQueueKit().vscp, VAccess::READWRITE}, "enqueue"};
flp, new AstVarRef{flp, vscpInfo.valueQueueKit().vscp, VAccess::READWRITE},
VCMethod::SCHED_ENQUEUE};
callp->dtypeSetVoid();
callp->addPinsp(valuep);
if (partial) callp->addPinsp(maskp);

View File

@ -280,7 +280,7 @@ void V3DfgPasses::binToOneHot(DfgGraph& dfg, V3DfgBinToOneHotContext& ctx) {
}
{ // tab.fill(0)
AstCMethodHard* const callp = new AstCMethodHard{
flp, new AstVarRef{flp, tabVtxp->varp(), VAccess::WRITE}, "fill"};
flp, new AstVarRef{flp, tabVtxp->varp(), VAccess::WRITE}, VCMethod::UNPACKED_FILL};
callp->addPinsp(new AstConst{flp, AstConst::BitFalse{}});
callp->dtypeSetVoid();
initp->addStmtsp(callp->makeStmt());

View File

@ -293,7 +293,7 @@ class HasherVisitor final : public VNVisitorConst {
}
void visit(AstCMethodHard* nodep) override {
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [this, nodep]() { //
m_hash += nodep->name();
m_hash += nodep->method();
});
}
void visit(AstCAwait* nodep) override {

View File

@ -233,7 +233,8 @@ class RandomizeMarkVisitor final : public VNVisitor {
nodep->v3error("Cannot call 'rand_mode()' on packed array element");
valid = false;
} else if (AstCMethodHard* const methodHardp = VN_CAST(fromp, CMethodHard)) {
if (methodHardp->name() == "at" || methodHardp->name() == "atWrite") {
if (methodHardp->method() == VCMethod::ARRAY_AT
|| methodHardp->method() == VCMethod::ARRAY_AT_WRITE) {
nodep->v3warn(E_UNSUPPORTED,
"Unsupported: 'rand_mode()' on dynamic array element");
valid = false;
@ -622,7 +623,7 @@ class ConstraintExprVisitor final : public VNVisitor {
AstNodeDType* const arrDtp = arrayp->unlinkFrBack()->dtypep();
AstNodeExpr* selp = nullptr;
if (VN_IS(arrDtp, QueueDType) || VN_IS(arrDtp, DynArrayDType))
selp = new AstCMethodHard{fl, arrayp, "at", idxp};
selp = new AstCMethodHard{fl, arrayp, VCMethod::ARRAY_AT, idxp};
else if (VN_IS(arrDtp, UnpackArrayDType))
selp = new AstArraySel{fl, arrayp, idxp};
else if (VN_IS(arrDtp, AssocArrayDType))
@ -662,7 +663,7 @@ class ConstraintExprVisitor final : public VNVisitor {
nodep->fileline(),
new AstVarRef{varp->fileline(), VN_AS(m_randModeVarp->user2p(), NodeModule),
m_randModeVarp, VAccess::READ},
"at", new AstConst{nodep->fileline(), randMode.index}};
VCMethod::ARRAY_AT, new AstConst{nodep->fileline(), randMode.index}};
atp->dtypeSetUInt32();
exprp = new AstCond{varp->fileline(), atp, exprp, constFormatp};
} else {
@ -675,7 +676,7 @@ class ConstraintExprVisitor final : public VNVisitor {
varp->fileline(),
new AstVarRef{varp->fileline(), VN_AS(m_genp->user2p(), NodeModule), m_genp,
VAccess::READWRITE},
"write_var"};
VCMethod::RANDOMIZER_WRITE_VAR};
uint32_t dimension = 0;
if (VN_IS(varp->dtypep(), UnpackArrayDType) || VN_IS(varp->dtypep(), DynArrayDType)
|| VN_IS(varp->dtypep(), QueueDType) || VN_IS(varp->dtypep(), AssocArrayDType)) {
@ -991,7 +992,7 @@ class ConstraintExprVisitor final : public VNVisitor {
nodep->fileline(),
new AstVarRef{nodep->fileline(), VN_AS(m_genp->user2p(), NodeModule), m_genp,
VAccess::READWRITE},
"hard", nodep->exprp()->unlinkFrBack()};
VCMethod::RANDOMIZER_HARD, nodep->exprp()->unlinkFrBack()};
callp->dtypeSetVoid();
nodep->replaceWith(callp->makeStmt());
VL_DO_DANGLING(nodep->deleteTree(), nodep);
@ -1000,7 +1001,7 @@ class ConstraintExprVisitor final : public VNVisitor {
if (editFormat(nodep)) return;
FileLine* const fl = nodep->fileline();
if (nodep->name() == "at" && nodep->fromp()->user1()) {
if (nodep->method() == VCMethod::ARRAY_AT && nodep->fromp()->user1()) {
iterateChildren(nodep);
AstNodeExpr* pinp = nodep->pinsp()->unlinkFrBack();
if (VN_IS(pinp, SFormatF) && m_structSel) VN_AS(pinp, SFormatF)->name("%x");
@ -1015,7 +1016,7 @@ class ConstraintExprVisitor final : public VNVisitor {
return;
}
if (nodep->name() == "inside") {
if (nodep->method() == VCMethod::ARRAY_INSIDE) {
bool randArr = nodep->fromp()->user1();
AstVar* const newVarp
@ -1455,7 +1456,7 @@ class RandomizeVisitor final : public VNVisitor {
FileLine* const fl = ftaskp->fileline();
AstCMethodHard* const setRandModep = new AstCMethodHard{
fl, new AstVarRef{fl, VN_AS(genp->user2p(), NodeModule), genp, VAccess::WRITE},
"set_randmode",
VCMethod::CLASS_SET_RANDMODE,
new AstVarRef{fl, VN_AS(randModeVarp->user2p(), NodeModule), randModeVarp,
VAccess::READ}};
setRandModep->dtypeSetVoid();
@ -1506,7 +1507,7 @@ class RandomizeVisitor final : public VNVisitor {
FileLine* fl = modeVarp->fileline();
AstCMethodHard* const dynarrayNewp
= new AstCMethodHard{fl, new AstVarRef{fl, modeVarModp, modeVarp, VAccess::WRITE},
"resize", new AstConst{fl, modeCount}};
VCMethod::DYN_RESIZE, new AstConst{fl, modeCount}};
dynarrayNewp->dtypeSetVoid();
AstNodeFTask* const newp = VN_AS(m_memberMap.findMember(classp, "new"), NodeFTask);
UASSERT_OBJ(newp, classp, "No new() in class");
@ -1520,10 +1521,11 @@ class RandomizeVisitor final : public VNVisitor {
AstVar* const iterVarp = new AstVar{fl, VVarType::BLOCKTEMP, "i", lhsp->findUInt32DType()};
iterVarp->funcLocal(inTask);
iterVarp->lifetime(VLifetime::AUTOMATIC_EXPLICIT);
AstCMethodHard* const sizep = new AstCMethodHard{fl, lhsp, "size", nullptr};
AstCMethodHard* const sizep = new AstCMethodHard{fl, lhsp, VCMethod::DYN_SIZE, nullptr};
sizep->dtypeSetUInt32();
AstCMethodHard* const setp = new AstCMethodHard{
fl, lhsp->cloneTree(false), "atWrite", new AstVarRef{fl, iterVarp, VAccess::READ}};
AstCMethodHard* const setp
= new AstCMethodHard{fl, lhsp->cloneTree(false), VCMethod::ARRAY_AT_WRITE,
new AstVarRef{fl, iterVarp, VAccess::READ}};
setp->dtypeSetUInt32();
AstNode* const stmtsp = iterVarp;
stmtsp->addNext(
@ -1550,7 +1552,7 @@ class RandomizeVisitor final : public VNVisitor {
if (mode.usesMode) {
AstCMethodHard* const atp = new AstCMethodHard{
fl, new AstVarRef{fl, VN_AS(modeVarp->user2p(), Class), modeVarp, VAccess::READ},
"at", new AstConst{fl, mode.index}};
VCMethod::ARRAY_AT, new AstConst{fl, mode.index}};
atp->dtypeSetUInt32();
return new AstIf{fl, atp, stmtp};
}
@ -1651,7 +1653,8 @@ class RandomizeVisitor final : public VNVisitor {
AstNodeExpr* const tempExprp = tempElementp ? tempElementp : exprp;
AstVarRef* const tempRefp = new AstVarRef{fl, newRandLoopIndxp, VAccess::READ};
if (VN_IS(tempDTypep, DynArrayDType)) {
tempElementp = new AstCMethodHard{fl, tempExprp, "atWrite", tempRefp};
tempElementp
= new AstCMethodHard{fl, tempExprp, VCMethod::ARRAY_AT_WRITE, tempRefp};
} else if (VN_IS(tempDTypep, UnpackArrayDType)) {
AstNodeArrayDType* const aryDTypep = VN_CAST(tempDTypep, NodeArrayDType);
// Adjust the bitp to ensure it covers all possible indices
@ -1665,7 +1668,8 @@ class RandomizeVisitor final : public VNVisitor {
} else if (VN_IS(tempDTypep, AssocArrayDType)) {
tempElementp = new AstAssocSel{fl, tempExprp, tempRefp};
} else if (VN_IS(tempDTypep, QueueDType)) {
tempElementp = new AstCMethodHard{fl, tempExprp, "atWriteAppend", tempRefp};
tempElementp
= new AstCMethodHard{fl, tempExprp, VCMethod::DYN_AT_WRITE_APPEND, tempRefp};
}
tempElementp->dtypep(tempDTypep->subDTypep());
tempDTypep = tempDTypep->virtRefDTypep();
@ -1797,7 +1801,7 @@ class RandomizeVisitor final : public VNVisitor {
AstCMethodHard* const clearp = new AstCMethodHard{
fileline,
new AstVarRef{fileline, VN_AS(genp->user2p(), NodeModule), genp, VAccess::READWRITE},
"clear"};
VCMethod::RANDOMIZER_CLEAR};
clearp->dtypeSetVoid();
return clearp->makeStmt();
}
@ -1909,7 +1913,7 @@ class RandomizeVisitor final : public VNVisitor {
nodep->fileline(),
new AstVarRef{fl, VN_AS(randModeVarp->user2p(), NodeModule), randModeVarp,
VAccess::WRITE},
"atWrite", new AstConst{nodep->fileline(), randMode.index}};
VCMethod::ARRAY_AT_WRITE, new AstConst{nodep->fileline(), randMode.index}};
setp->dtypeSetUInt32();
newp->addStmtsp(new AstAssign{fl, setp, new AstConst{fl, 0}});
}
@ -1973,8 +1977,8 @@ class RandomizeVisitor final : public VNVisitor {
// mode
const RandomizeMode rmode = {.asInt = receiverp->user1()};
UASSERT_OBJ(rmode.usesMode, ftaskRefp, "Failed to set usesMode");
AstCMethodHard* const setp
= new AstCMethodHard{fl, lhsp, "atWrite", new AstConst{fl, rmode.index}};
AstCMethodHard* const setp = new AstCMethodHard{fl, lhsp, VCMethod::ARRAY_AT_WRITE,
new AstConst{fl, rmode.index}};
setp->dtypeSetUInt32();
m_stmtp->replaceWith(new AstAssign{fl, setp, rhsp});
} else {
@ -1988,8 +1992,8 @@ class RandomizeVisitor final : public VNVisitor {
UASSERT_OBJ(receiverp, ftaskRefp, "Should have receiver");
const RandomizeMode rmode = {.asInt = receiverp->user1()};
UASSERT_OBJ(rmode.usesMode, ftaskRefp, "Failed to set usesMode");
AstCMethodHard* const setp
= new AstCMethodHard{fl, lhsp, "atWrite", new AstConst{fl, rmode.index}};
AstCMethodHard* const setp = new AstCMethodHard{fl, lhsp, VCMethod::ARRAY_AT_WRITE,
new AstConst{fl, rmode.index}};
setp->dtypeSetUInt32();
ftaskRefp->replaceWith(setp);
VL_DO_DANGLING(pushDeletep(ftaskRefp), ftaskRefp);
@ -2057,9 +2061,9 @@ class RandomizeVisitor final : public VNVisitor {
tmpVarps = AstNode::addNext(tmpVarps, randModeTmpVarp);
}
const RandomizeMode randMode = {.asInt = randVarp->user1()};
AstCMethodHard* setp
= new AstCMethodHard{fl, makeSiblingRefp(exprp, randModeVarp, VAccess::WRITE),
"atWrite", new AstConst{fl, randMode.index}};
AstCMethodHard* setp = new AstCMethodHard{
fl, makeSiblingRefp(exprp, randModeVarp, VAccess::WRITE),
VCMethod::ARRAY_AT_WRITE, new AstConst{fl, randMode.index}};
setp->dtypeSetUInt32();
setStmtsp
= AstNode::addNext(setStmtsp, new AstAssign{fl, setp, new AstConst{fl, 1}});
@ -2306,7 +2310,7 @@ class RandomizeVisitor final : public VNVisitor {
AstCMethodHard* const basicMethodp = new AstCMethodHard{
nodep->fileline(),
new AstVarRef{nodep->fileline(), stdrand, VAccess::READWRITE},
"basicStdRandomization"};
VCMethod::RANDOMIZER_BASIC_STD_RANDOMIZATION};
AstVar* const refvarp
= new AstVar{exprp->fileline(), VVarType::MEMBER,
"__Varg"s + std::to_string(++argn), exprp->dtypep()};
@ -2456,7 +2460,9 @@ class RandomizeVisitor final : public VNVisitor {
void visit(AstCMethodHard* nodep) override {
iterateChildren(nodep);
FileLine* const fl = nodep->fileline();
if (m_constraintp && nodep->fromp()->user1() && nodep->name() == "size") {
if (m_constraintp && nodep->fromp()->user1()
&& (nodep->method() == VCMethod::ASSOC_SIZE
|| nodep->method() == VCMethod::DYN_SIZE)) {
AstClass* const classp = VN_AS(m_modp, Class);
AstVarRef* const queueVarRefp = VN_CAST(nodep->fromp(), VarRef);
if (!queueVarRefp) {
@ -2480,7 +2486,7 @@ class RandomizeVisitor final : public VNVisitor {
m_constraintp->user3p(resizerTaskp);
}
AstCMethodHard* const resizep
= new AstCMethodHard{fl, nodep->fromp()->unlinkFrBack(), "resize",
= new AstCMethodHard{fl, nodep->fromp()->unlinkFrBack(), VCMethod::DYN_RESIZE,
new AstVarRef{fl, sizeVarp, VAccess::READ}};
resizep->dtypep(nodep->findVoidDType());
resizerTaskp->addStmtsp(new AstStmtExpr{fl, resizep});

View File

@ -221,8 +221,8 @@ EvalLoop createEvalLoop(
phaseFuncp->addStmtsp(phasePrepp);
// Check if any triggers are fired, save the result
AstCMethodHard* const callp
= new AstCMethodHard{flp, new AstVarRef{flp, trigp, VAccess::READ}, "any"};
AstCMethodHard* const callp = new AstCMethodHard{
flp, new AstVarRef{flp, trigp, VAccess::READ}, VCMethod::TRIGGER_ANY};
callp->dtypeSetBit();
phaseFuncp->addStmtsp(
new AstAssign{flp, new AstVarRef{flp, executeFlagp, VAccess::WRITE}, callp});
@ -523,7 +523,7 @@ struct TriggerKit final {
void addFirstIterationTriggerAssignment(AstVarScope* flagp, uint32_t index) const {
FileLine* const flp = flagp->fileline();
AstVarRef* const vrefp = new AstVarRef{flp, m_vscp, VAccess::WRITE};
AstCMethodHard* const callp = new AstCMethodHard{flp, vrefp, "setBit"};
AstCMethodHard* const callp = new AstCMethodHard{flp, vrefp, VCMethod::TRIGGER_SET_BIT};
callp->addPinsp(new AstConst{flp, index});
callp->addPinsp(new AstVarRef{flp, flagp, VAccess::READ});
callp->dtypeSetVoid();
@ -534,7 +534,7 @@ struct TriggerKit final {
void addExtraTriggerAssignment(AstVarScope* extraTriggerVscp, uint32_t index) const {
FileLine* const flp = extraTriggerVscp->fileline();
AstVarRef* const vrefp = new AstVarRef{flp, m_vscp, VAccess::WRITE};
AstCMethodHard* const callp = new AstCMethodHard{flp, vrefp, "setBit"};
AstCMethodHard* const callp = new AstCMethodHard{flp, vrefp, VCMethod::TRIGGER_SET_BIT};
callp->addPinsp(new AstConst{flp, index});
callp->addPinsp(new AstVarRef{flp, extraTriggerVscp, VAccess::READ});
callp->dtypeSetVoid();
@ -570,7 +570,7 @@ AstSenTree* createTriggerSenTree(AstNetlist* netlistp, AstVarScope* const vscp,
const uint32_t wordIndex = index / 64;
const uint32_t bitIndex = index % 64;
AstCMethodHard* const callp
= new AstCMethodHard{flp, vrefp, "word", new AstConst{flp, wordIndex}};
= new AstCMethodHard{flp, vrefp, VCMethod::TRIGGER_WORD, new AstConst{flp, wordIndex}};
callp->dtypeSetUInt64();
AstNodeExpr* const termp
= new AstAnd{flp, new AstConst{flp, AstConst::Unsized64{}, 1ULL << bitIndex}, callp};
@ -663,8 +663,8 @@ const TriggerKit createTriggers(AstNetlist* netlistp, AstCFunc* const initFuncp,
// Add a print to the dumping function if there are no triggers pending
{
AstCMethodHard* const callp
= new AstCMethodHard{flp, new AstVarRef{flp, vscp, VAccess::READ}, "any"};
AstCMethodHard* const callp = new AstCMethodHard{
flp, new AstVarRef{flp, vscp, VAccess::READ}, VCMethod::TRIGGER_ANY};
callp->dtypeSetBit();
AstIf* const ifp = new AstIf{flp, callp};
dumpp->addStmtsp(ifp);
@ -674,7 +674,7 @@ const TriggerKit createTriggers(AstNetlist* netlistp, AstCFunc* const initFuncp,
// Set the given trigger to the given value
const auto setTrigBit = [&](uint32_t index, AstNodeExpr* valp) {
AstVarRef* const vrefp = new AstVarRef{flp, vscp, VAccess::WRITE};
AstCMethodHard* const callp = new AstCMethodHard{flp, vrefp, "setBit"};
AstCMethodHard* const callp = new AstCMethodHard{flp, vrefp, VCMethod::TRIGGER_SET_BIT};
callp->addPinsp(new AstConst{flp, index});
callp->addPinsp(valp);
callp->dtypeSetVoid();
@ -687,7 +687,7 @@ const TriggerKit createTriggers(AstNetlist* netlistp, AstCFunc* const initFuncp,
const uint32_t wordIndex = index / 64;
const uint32_t bitIndex = index % 64;
AstCMethodHard* const callp
= new AstCMethodHard{flp, vrefp, "word", new AstConst{flp, wordIndex}};
= new AstCMethodHard{flp, vrefp, VCMethod::TRIGGER_WORD, new AstConst{flp, wordIndex}};
callp->dtypeSetUInt64();
AstNodeExpr* const termp
= new AstAnd{flp, new AstConst{flp, AstConst::Unsized64{}, 1ULL << bitIndex}, callp};
@ -776,7 +776,8 @@ const TriggerKit createTriggers(AstNetlist* netlistp, AstCFunc* const initFuncp,
}
// Set the whole word in the trigger vector
AstVarRef* const vrefp = new AstVarRef{flp, vscp, VAccess::WRITE};
AstCMethodHard* const callp = new AstCMethodHard{flp, vrefp, "setWord"};
AstCMethodHard* const callp
= new AstCMethodHard{flp, vrefp, VCMethod::TRIGGER_SET_WORD};
callp->addPinsp(new AstConst{flp, triggerBitIdx / TRIG_VEC_WORD_SIZE});
callp->addPinsp(trigExprps[0]);
callp->dtypeSetVoid();
@ -1015,7 +1016,7 @@ AstNode* createInputCombLoop(AstNetlist* netlistp, AstCFunc* const initFuncp,
AstStmtExpr* createTriggerClearCall(FileLine* const flp, AstVarScope* const vscp) { // Trigger
AstVarRef* const refp = new AstVarRef{flp, vscp, VAccess::WRITE};
AstCMethodHard* const callp = new AstCMethodHard{flp, refp, "clear"};
AstCMethodHard* const callp = new AstCMethodHard{flp, refp, VCMethod::TRIGGER_CLEAR};
callp->dtypeSetVoid();
return callp->makeStmt();
}
@ -1024,7 +1025,7 @@ AstStmtExpr* createTriggerSetCall(FileLine* const flp, AstVarScope* const toVscp
AstVarScope* const fromVscp) {
AstVarRef* const lhsp = new AstVarRef{flp, toVscp, VAccess::WRITE};
AstVarRef* const argp = new AstVarRef{flp, fromVscp, VAccess::READ};
AstCMethodHard* const callp = new AstCMethodHard{flp, lhsp, "thisOr", argp};
AstCMethodHard* const callp = new AstCMethodHard{flp, lhsp, VCMethod::TRIGGER_THIS_OR, argp};
callp->dtypeSetVoid();
return callp->makeStmt();
}
@ -1035,7 +1036,7 @@ AstStmtExpr* createTriggerAndNotCall(FileLine* const flp, AstVarScope* const lhs
AstVarRef* const opap = new AstVarRef{flp, aVscp, VAccess::READ};
AstVarRef* const opbp = new AstVarRef{flp, bVscp, VAccess::READ};
opap->addNext(opbp);
AstCMethodHard* const callp = new AstCMethodHard{flp, lhsp, "andNot", opap};
AstCMethodHard* const callp = new AstCMethodHard{flp, lhsp, VCMethod::TRIGGER_AND_NOT, opap};
callp->dtypeSetVoid();
return callp->makeStmt();
}
@ -1125,8 +1126,8 @@ void createEval(AstNetlist* netlistp, //
AstIf* const ifp = new AstIf{flp, new AstVarRef{flp, nbaEventTriggerp, VAccess::READ}};
ifp->addThensp(setVar(continuep, 1));
ifp->addThensp(setVar(nbaEventTriggerp, 0));
AstCMethodHard* const firep
= new AstCMethodHard{flp, new AstVarRef{flp, nbaEventp, VAccess::WRITE}, "fire"};
AstCMethodHard* const firep = new AstCMethodHard{
flp, new AstVarRef{flp, nbaEventp, VAccess::WRITE}, VCMethod::EVENT_FIRE};
firep->dtypeSetVoid();
ifp->addThensp(firep->makeStmt());
return ifp;

View File

@ -126,7 +126,7 @@ AstCCall* TimingKit::createCommit(AstNetlist* const netlistp) {
auto* const newactp = new AstActive{flp, "", negSentreep};
// Create the commit call and put it in the commit function
auto* const commitp = new AstCMethodHard{
flp, new AstVarRef{flp, schedulerp, VAccess::READWRITE}, "commit"};
flp, new AstVarRef{flp, schedulerp, VAccess::READWRITE}, VCMethod::SCHED_COMMIT};
if (resumep->pinsp()) commitp->addPinsp(resumep->pinsp()->cloneTree(false));
commitp->dtypeSetVoid();
newactp->addStmtsp(commitp->makeStmt());
@ -184,7 +184,7 @@ TimingKit prepareTiming(AstNetlist* const netlistp) {
FileLine* const flp = sentreep->fileline();
// Create a resume() call on the timing scheduler
auto* const resumep = new AstCMethodHard{
flp, new AstVarRef{flp, schedulerp, VAccess::READWRITE}, "resume"};
flp, new AstVarRef{flp, schedulerp, VAccess::READWRITE}, VCMethod::SCHED_RESUME};
resumep->dtypeSetVoid();
if (schedulerp->dtypep()->basicp()->isTriggerScheduler()) {
UASSERT_OBJ(methodp->pinsp(), methodp,
@ -197,7 +197,7 @@ TimingKit prepareTiming(AstNetlist* const netlistp) {
}
} else if (schedulerp->dtypep()->basicp()->isDynamicTriggerScheduler()) {
auto* const postp = resumep->cloneTree(false);
postp->name("doPostUpdates");
postp->method(VCMethod::SCHED_DO_POST_UPDATES);
m_postUpdatesr = AstNode::addNext(m_postUpdatesr, postp->makeStmt());
}
// Put it in an active and put that in the global resume function

View File

@ -133,7 +133,8 @@ private:
}
if (VN_IS(exprp->dtypep()->skipRefp(), UnpackArrayDType)) {
AstCMethodHard* const cmhp = new AstCMethodHard{flp, wrPrev(), "assign", rdCurr()};
AstCMethodHard* const cmhp
= new AstCMethodHard{flp, wrPrev(), VCMethod::UNPACKED_ASSIGN, rdCurr()};
cmhp->dtypeSetVoid();
m_results.m_postUpdates.push_back(cmhp->makeStmt());
} else {
@ -160,7 +161,8 @@ private:
if (VN_IS(senp->dtypep()->skipRefp(), UnpackArrayDType)) {
// operand order reversed to avoid calling neq() method on non-VlUnpacked type, see
// issue #5125
AstCMethodHard* const resultp = new AstCMethodHard{flp, prevp(), "neq", currp()};
AstCMethodHard* const resultp
= new AstCMethodHard{flp, prevp(), VCMethod::UNPACKED_NEQ, currp()};
resultp->dtypeSetBit();
return {resultp, true};
}
@ -176,13 +178,15 @@ private:
{
// Clear 'fired' state when done
// No need to check if the event was fired, we need the flag clear regardless
AstCMethodHard* const clearp = new AstCMethodHard{flp, currp(), "clearFired"};
AstCMethodHard* const clearp
= new AstCMethodHard{flp, currp(), VCMethod::EVENT_CLEAR_FIRED};
clearp->dtypeSetVoid();
m_results.m_postUpdates.push_back(clearp->makeStmt());
}
// Get 'fired' state
AstCMethodHard* const callp = new AstCMethodHard{flp, currp(), "isFired"};
AstCMethodHard* const callp
= new AstCMethodHard{flp, currp(), VCMethod::EVENT_IS_FIRED};
callp->dtypeSetBit();
return {callp, false};
}

View File

@ -506,10 +506,11 @@ class TaskVisitor final : public VNVisitor {
refArgOk = true;
} else if (AstCMethodHard* const cMethodp = VN_CAST(pinp, CMethodHard)) {
if (VN_IS(cMethodp->fromp()->dtypep()->skipRefp(), QueueDType)) {
refArgOk = cMethodp->name() == "atWriteAppend"
|| cMethodp->name() == "atWriteAppendBack";
refArgOk = cMethodp->method() == VCMethod::DYN_AT_WRITE_APPEND
|| cMethodp->method() == VCMethod::DYN_AT_WRITE_APPEND_BACK;
} else {
refArgOk = cMethodp->name() == "at" || cMethodp->name() == "atBack";
refArgOk = cMethodp->method() == VCMethod::ARRAY_AT
|| cMethodp->method() == VCMethod::ARRAY_AT_BACK;
}
}
if (refArgOk) {

View File

@ -543,7 +543,7 @@ class TimingControlVisitor final : public VNVisitor {
FileLine* const flp = m_scopeTopp->fileline();
auto* const awaitingCurrentTimep
= new AstCMethodHard{flp, new AstVarRef{flp, getCreateDelayScheduler(), VAccess::READ},
"awaitingCurrentTime"};
VCMethod::SCHED_AWAITING_CURRENT_TIME};
awaitingCurrentTimep->dtypeSetBit();
m_delaySensesp
= new AstSenTree{flp, new AstSenItem{flp, VEdgeType::ET_TRUE, awaitingCurrentTimep}};
@ -566,7 +566,7 @@ class TimingControlVisitor final : public VNVisitor {
FileLine* const flp = m_scopeTopp->fileline();
auto* const awaitingCurrentTimep = new AstCMethodHard{
flp, new AstVarRef{flp, getCreateDynamicTriggerScheduler(), VAccess::READ},
"evaluate"};
VCMethod::SCHED_EVALUATE};
awaitingCurrentTimep->dtypeSetBit();
m_dynamicSensesp
= new AstSenTree{flp, new AstSenItem{flp, VEdgeType::ET_TRUE, awaitingCurrentTimep}};
@ -712,7 +712,7 @@ class TimingControlVisitor final : public VNVisitor {
void addForkDone(AstBegin* const beginp, AstVarScope* const forkVscp) const {
FileLine* const flp = beginp->fileline();
auto* const donep = new AstCMethodHard{
beginp->fileline(), new AstVarRef{flp, forkVscp, VAccess::WRITE}, "done"};
beginp->fileline(), new AstVarRef{flp, forkVscp, VAccess::WRITE}, VCMethod::FORK_DONE};
donep->dtypeSetVoid();
addDebugInfo(donep);
beginp->addStmtsp(donep->makeStmt());
@ -735,13 +735,13 @@ class TimingControlVisitor final : public VNVisitor {
if (forkp->joinType().joinAny()) joinCount = 1;
// Set the join counter
auto* const initp = new AstCMethodHard{flp, new AstVarRef{flp, forkVscp, VAccess::WRITE},
"init", new AstConst{flp, joinCount}};
VCMethod::FORK_INIT, new AstConst{flp, joinCount}};
initp->dtypeSetVoid();
addProcessInfo(initp);
forkp->addHereThisAsNext(initp->makeStmt());
// Await the join at the end
auto* const joinp
= new AstCMethodHard{flp, new AstVarRef{flp, forkVscp, VAccess::WRITE}, "join"};
auto* const joinp = new AstCMethodHard{flp, new AstVarRef{flp, forkVscp, VAccess::WRITE},
VCMethod::FORK_JOIN};
joinp->dtypeSetVoid();
addProcessInfo(joinp);
addDebugInfo(joinp);
@ -884,7 +884,8 @@ class TimingControlVisitor final : public VNVisitor {
}
// Replace self with a 'co_await dlySched.delay(<valuep>)'
AstCMethodHard* const delayMethodp = new AstCMethodHard{
flp, new AstVarRef{flp, getCreateDelayScheduler(), VAccess::WRITE}, "delay", valuep};
flp, new AstVarRef{flp, getCreateDelayScheduler(), VAccess::WRITE},
VCMethod::SCHED_DELAY, valuep};
delayMethodp->dtypeSetVoid();
addProcessInfo(delayMethodp);
addDebugInfo(delayMethodp);
@ -922,7 +923,7 @@ class TimingControlVisitor final : public VNVisitor {
// call
auto* const evalMethodp = new AstCMethodHard{
flp, new AstVarRef{flp, getCreateDynamicTriggerScheduler(), VAccess::WRITE},
"evaluation"};
VCMethod::SCHED_EVALUATION};
evalMethodp->dtypeSetVoid();
addProcessInfo(evalMethodp);
auto* const sentreep = nodep->sentreep();
@ -954,21 +955,21 @@ class TimingControlVisitor final : public VNVisitor {
// If it was, a call to the scheduler's evaluate() will return true
AstCMethodHard* const anyTriggeredMethodp = new AstCMethodHard{
flp, new AstVarRef{flp, getCreateDynamicTriggerScheduler(), VAccess::WRITE},
"anyTriggered", new AstVarRef{flp, trigvscp, VAccess::READ}};
VCMethod::SCHED_ANY_TRIGGERED, new AstVarRef{flp, trigvscp, VAccess::READ}};
anyTriggeredMethodp->dtypeSetVoid();
loopp->addStmtsp(anyTriggeredMethodp->makeStmt());
// If the post update is destructive (e.g. event vars are cleared), create an await for
// the post update step
if (destructivePostUpdate(sentreep)) {
AstCAwait* const awaitPostUpdatep = awaitEvalp->cloneTree(false);
VN_AS(awaitPostUpdatep->exprp(), CMethodHard)->name("postUpdate");
VN_AS(awaitPostUpdatep->exprp(), CMethodHard)->method(VCMethod::SCHED_POST_UPDATE);
loopp->addStmtsp(awaitPostUpdatep->makeStmt());
}
// Put the post updates at the end of the loop
for (AstNodeStmt* const stmtp : senResults.m_postUpdates) loopp->addStmtsp(stmtp);
// Finally, await the resumption step in 'act'
AstCAwait* const awaitResumep = awaitEvalp->cloneTree(false);
VN_AS(awaitResumep->exprp(), CMethodHard)->name("resumption");
VN_AS(awaitResumep->exprp(), CMethodHard)->method(VCMethod::SCHED_RESUMPTION);
AstNode::addNext<AstNodeStmt, AstNodeStmt>(loopp, awaitResumep->makeStmt());
// Replace the event control with the loop
nodep->replaceWith(loopp);
@ -979,7 +980,7 @@ class TimingControlVisitor final : public VNVisitor {
// Replace self with a 'co_await trigSched.trigger()'
auto* const triggerMethodp = new AstCMethodHard{
flp, new AstVarRef{flp, getCreateTriggerSchedulerp(sentreep), VAccess::WRITE},
"trigger"};
VCMethod::SCHED_TRIGGER};
triggerMethodp->dtypeSetVoid();
// If it should be committed immediately, pass true, otherwise false
triggerMethodp->addPinsp(nodep->user2() ? new AstConst{flp, AstConst::BitTrue{}}

View File

@ -1800,7 +1800,8 @@ class WidthVisitor final : public VNVisitor {
switch (nodep->attrType()) {
case VAttrType::DIM_SIZE: {
AstNodeExpr* const fromp = VN_AS(nodep->fromp()->unlinkFrBack(), NodeExpr);
AstNode* const newp = new AstCMethodHard{nodep->fileline(), fromp, "size"};
AstNode* const newp
= new AstCMethodHard{nodep->fileline(), fromp, VCMethod::DYN_SIZE};
newp->dtypeSetSigned32();
newp->didWidth(true);
newp->protect(false);
@ -1819,7 +1820,7 @@ class WidthVisitor final : public VNVisitor {
case VAttrType::DIM_HIGH: {
AstNodeExpr* const fromp = VN_AS(nodep->fromp()->unlinkFrBack(), NodeExpr);
AstNodeExpr* const sizep
= new AstCMethodHard{nodep->fileline(), fromp, "size"};
= new AstCMethodHard{nodep->fileline(), fromp, VCMethod::DYN_SIZE};
sizep->dtypeSetSigned32();
sizep->didWidth(true);
sizep->protect(false);
@ -3076,8 +3077,8 @@ class WidthVisitor final : public VNVisitor {
|| VN_IS(itemDtp, QueueDType)) {
// Unsupported in parameters
AstNodeExpr* const cexprp = exprp->cloneTreePure(true);
AstNodeExpr* const inewp
= new AstCMethodHard{nodep->fileline(), itemp->unlinkFrBack(), "inside", cexprp};
AstNodeExpr* const inewp = new AstCMethodHard{nodep->fileline(), itemp->unlinkFrBack(),
VCMethod::ARRAY_INSIDE, cexprp};
iterateCheckTyped(nodep, "inside value", cexprp, itemDtp->subDTypep(), BOTH);
VL_DANGLING(cexprp); // Might have been replaced
inewp->dtypeSetBit();
@ -3708,7 +3709,7 @@ class WidthVisitor final : public VNVisitor {
|| nodep->name() == "size") {
methodOkArguments(nodep, 0, 0);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
"size"}; // So don't need num()
VCMethod::ASSOC_SIZE}; // So don't need num()
newp->dtypeSetSigned32();
} else if (nodep->name() == "first" // function int first(ref index)
|| nodep->name() == "last" //
@ -3724,21 +3725,21 @@ class WidthVisitor final : public VNVisitor {
methodOkArguments(nodep, 1, 1);
iterateCheckSelf(nodep, "argument", methodArg(nodep, 0), SELF, BOTH);
AstNodeExpr* const index_exprp = methodCallWildcardIndexExpr(nodep, adtypep);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(), "exists",
index_exprp->unlinkFrBack()};
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
VCMethod::ASSOC_EXISTS, index_exprp->unlinkFrBack()};
newp->dtypeSetLogicUnsized(32, 1, VSigning::SIGNED);
} else if (nodep->name() == "delete") { // function void delete([input integer index])
methodOkArguments(nodep, 0, 1);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::WRITE);
if (!nodep->pinsp()) {
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
"clear"};
VCMethod::ASSOC_CLEAR};
newp->dtypeSetVoid();
} else {
iterateCheckSelf(nodep, "argument", methodArg(nodep, 0), SELF, BOTH);
AstNodeExpr* const index_exprp = methodCallWildcardIndexExpr(nodep, adtypep);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
"erase", index_exprp->unlinkFrBack()};
VCMethod::ASSOC_ERASE, index_exprp->unlinkFrBack()};
newp->dtypeSetVoid();
}
} else if (nodep->name() == "sort" || nodep->name() == "rsort"
@ -3754,14 +3755,14 @@ class WidthVisitor final : public VNVisitor {
methodOkArguments(nodep, 0, 0);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
"r_" + nodep->name(), withp};
VCMethod::arrayMethod("r_" + nodep->name()), withp};
newp->dtypeFrom(withp ? withp->dtypep() : adtypep->subDTypep());
if (!nodep->firstAbovep()) newp->dtypeSetVoid();
} else if (nodep->name() == "min" || nodep->name() == "max" || nodep->name() == "unique") {
methodOkArguments(nodep, 0, 0);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
nodep->name()};
VCMethod::arrayMethod(nodep->name())};
newp->dtypep(queueDTypeIndexedBy(adtypep->subDTypep()));
if (!nodep->firstAbovep()) newp->dtypeSetVoid();
} else if (nodep->name() == "find" || nodep->name() == "find_first"
@ -3772,7 +3773,7 @@ class WidthVisitor final : public VNVisitor {
methodOkArguments(nodep, 0, 0);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
nodep->name(), withp};
VCMethod::arrayMethod(nodep->name()), withp};
newp->dtypep(queueDTypeIndexedBy(adtypep->subDTypep()));
if (!nodep->firstAbovep()) newp->dtypeSetVoid();
} else if (nodep->name() == "map") {
@ -3796,7 +3797,7 @@ class WidthVisitor final : public VNVisitor {
|| nodep->name() == "size") {
methodOkArguments(nodep, 0, 0);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
"size"}; // So don't need num()
VCMethod::ASSOC_SIZE}; // So don't need num()
newp->dtypeSetSigned32();
} else if (nodep->name() == "first" // function int first(ref index)
|| nodep->name() == "last" //
@ -3806,9 +3807,10 @@ class WidthVisitor final : public VNVisitor {
iterateCheckTyped(nodep, "argument", methodArg(nodep, 0), adtypep->keyDTypep(), BOTH);
AstNodeExpr* const index_exprp = methodCallAssocIndexExpr(nodep, adtypep);
methodCallLValueRecurse(nodep, index_exprp, VAccess::READWRITE);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
nodep->name(), // first/last/next/prev
index_exprp->unlinkFrBack()};
newp
= new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
VCMethod::arrayMethod(nodep->name()), // first/last/next/prev
index_exprp->unlinkFrBack()};
newp->dtypeSetSigned32();
if (!nodep->firstAbovep()) newp->dtypeSetVoid();
} else if (nodep->name() == "exists") { // function int exists(input index)
@ -3816,22 +3818,22 @@ class WidthVisitor final : public VNVisitor {
methodOkArguments(nodep, 1, 1);
iterateCheckTyped(nodep, "argument", methodArg(nodep, 0), adtypep->keyDTypep(), BOTH);
AstNodeExpr* const index_exprp = methodCallAssocIndexExpr(nodep, adtypep);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(), "exists",
index_exprp->unlinkFrBack()};
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
VCMethod::ASSOC_EXISTS, index_exprp->unlinkFrBack()};
newp->dtypeSetLogicUnsized(32, 1, VSigning::SIGNED);
} else if (nodep->name() == "delete") { // function void delete([input integer index])
methodOkArguments(nodep, 0, 1);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::WRITE);
if (!nodep->pinsp()) {
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
"clear"};
VCMethod::ASSOC_CLEAR};
newp->dtypeSetVoid();
} else {
iterateCheckTyped(nodep, "argument", methodArg(nodep, 0), adtypep->keyDTypep(),
BOTH);
AstNodeExpr* const index_exprp = methodCallAssocIndexExpr(nodep, adtypep);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
"erase", index_exprp->unlinkFrBack()};
VCMethod::ASSOC_ERASE, index_exprp->unlinkFrBack()};
newp->dtypeSetVoid();
}
} else if (nodep->name() == "sort" || nodep->name() == "rsort"
@ -3846,7 +3848,7 @@ class WidthVisitor final : public VNVisitor {
methodOkArguments(nodep, 0, 0);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
"r_" + nodep->name(), withp};
VCMethod::arrayMethod("r_" + nodep->name()), withp};
newp->dtypeFrom(withp ? withp->dtypep() : adtypep->subDTypep());
if (!nodep->firstAbovep()) newp->dtypeSetVoid();
} else if (nodep->name() == "min" || nodep->name() == "max" || nodep->name() == "unique"
@ -3856,7 +3858,7 @@ class WidthVisitor final : public VNVisitor {
methodOkArguments(nodep, 0, 0);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
nodep->name(), withp};
VCMethod::arrayMethod(nodep->name()), withp};
if (nodep->name() == "unique_index") {
newp->dtypep(queueDTypeIndexedBy(adtypep->keyDTypep()));
} else {
@ -3870,7 +3872,7 @@ class WidthVisitor final : public VNVisitor {
methodOkArguments(nodep, 0, 0);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
nodep->name(), withp};
VCMethod::arrayMethod(nodep->name()), withp};
newp->dtypep(queueDTypeIndexedBy(adtypep->subDTypep()));
if (!nodep->firstAbovep()) newp->dtypeSetVoid();
} else if (nodep->name() == "find_index" || nodep->name() == "find_first_index"
@ -3880,7 +3882,7 @@ class WidthVisitor final : public VNVisitor {
methodOkArguments(nodep, 0, 0);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
nodep->name(), withp};
VCMethod::arrayMethod(nodep->name()), withp};
newp->dtypep(queueDTypeIndexedBy(adtypep->keyDTypep()));
if (!nodep->firstAbovep()) newp->dtypeSetVoid();
} else if (nodep->name() == "map") {
@ -3915,16 +3917,31 @@ class WidthVisitor final : public VNVisitor {
}
void methodCallLValueRecurse(AstMethodCall* nodep, AstNode* childp, const VAccess& access) {
if (AstCMethodHard* const ichildp = VN_CAST(childp, CMethodHard)) {
const std::string name = ichildp->name();
if (name == "at" || name == "atWrite" || name == "atBack" || name == "atWriteAppend"
|| name == "atWriteAppendBack") {
bool methAt = false;
bool methAtBack = false;
bool methAtWrite = false;
switch (ichildp->method()) {
case VCMethod::ARRAY_AT: // FALLTHRU
methAt = true;
break;
case VCMethod::ARRAY_AT_BACK: // FALLTHRU
methAtBack = true;
break;
case VCMethod::ARRAY_AT_WRITE: // FALLTHRU
case VCMethod::DYN_AT_WRITE_APPEND: // FALLTHRU
case VCMethod::DYN_AT_WRITE_APPEND_BACK: //
methAtWrite = true;
break;
default: break;
}
if (methAt || methAtBack || methAtWrite) {
const AstNodeDType* const fromDtypep = ichildp->fromp()->dtypep()->skipRefp();
if (VN_IS(fromDtypep, QueueDType) || VN_IS(fromDtypep, DynArrayDType)) {
// Change access methods to writable ones
if (name == "at") {
ichildp->name("atWrite");
} else if (name == "atBack") {
ichildp->name("atWriteAppendBack");
if (methAt) {
ichildp->method(VCMethod::ARRAY_AT_WRITE);
} else if (methAtBack) {
ichildp->method(VCMethod::DYN_AT_WRITE_APPEND_BACK);
}
}
methodCallLValueRecurse(nodep, ichildp->fromp(), access);
@ -3958,7 +3975,7 @@ class WidthVisitor final : public VNVisitor {
methodOkArguments(nodep, 0, 0);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::WRITE);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
nodep->name(), withp};
VCMethod::arrayMethod(nodep->name()), withp};
newp->dtypeSetVoid();
} else if (nodep->name() == "min" || nodep->name() == "max" || nodep->name() == "unique"
|| nodep->name() == "unique_index") {
@ -3967,7 +3984,7 @@ class WidthVisitor final : public VNVisitor {
methodOkArguments(nodep, 0, 0);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
nodep->name(), withp};
VCMethod::arrayMethod(nodep->name()), withp};
if (nodep->name() == "unique_index") {
newp->dtypep(newp->findQueueIndexDType());
} else {
@ -3982,7 +3999,7 @@ class WidthVisitor final : public VNVisitor {
methodOkArguments(nodep, 0, 0);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
nodep->name(), withp};
VCMethod::arrayMethod(nodep->name()), withp};
newp->dtypep(queueDTypeIndexedBy(adtypep->subDTypep()));
if (!nodep->firstAbovep()) newp->dtypeSetVoid();
} else if (nodep->name() == "find_index" || nodep->name() == "find_first_index"
@ -3993,7 +4010,7 @@ class WidthVisitor final : public VNVisitor {
methodOkArguments(nodep, 0, 0);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
nodep->name(), withp};
VCMethod::arrayMethod(nodep->name()), withp};
newp->dtypep(newp->findQueueIndexDType());
if (!nodep->firstAbovep()) newp->dtypeSetVoid();
} else if (nodep->name() == "map") {
@ -4008,23 +4025,26 @@ class WidthVisitor final : public VNVisitor {
if (nodep->name() == "at") { // Created internally for []
methodOkArguments(nodep, 1, 1);
iterateCheckSigned32(nodep, "argument", methodArg(nodep, 0), BOTH);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(), "at"};
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
VCMethod::ARRAY_AT};
newp->dtypeFrom(adtypep->subDTypep());
} else if (nodep->name() == "atWrite") { // Created internally for []
methodOkArguments(nodep, 1, 1);
iterateCheckSigned32(nodep, "argument", methodArg(nodep, 0), BOTH);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::WRITE);
newp
= new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(), "atWrite"};
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
VCMethod::ARRAY_AT_WRITE};
newp->dtypeFrom(adtypep->subDTypep());
} else if (nodep->name() == "size") {
methodOkArguments(nodep, 0, 0);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(), "size"};
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
VCMethod::DYN_SIZE};
newp->dtypeSetSigned32();
} else if (nodep->name() == "delete") { // function void delete()
methodOkArguments(nodep, 0, 0);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::WRITE);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(), "clear"};
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
VCMethod::DYN_CLEAR};
newp->dtypeSetVoid();
} else if (nodep->name() == "and" || nodep->name() == "or" || nodep->name() == "xor"
|| nodep->name() == "sum" || nodep->name() == "product") {
@ -4035,7 +4055,7 @@ class WidthVisitor final : public VNVisitor {
methodOkArguments(nodep, 0, 0);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
"r_" + nodep->name(), withp};
VCMethod::arrayMethod("r_" + nodep->name()), withp};
newp->dtypeFrom(adtypep->subDTypep());
if (!nodep->firstAbovep()) newp->dtypeSetVoid();
} else if ((newp = methodCallArray(nodep, adtypep))) {
@ -4057,7 +4077,7 @@ class WidthVisitor final : public VNVisitor {
methodOkArguments(nodep, 1, 1);
iterateCheckSigned32(nodep, "argument", methodArg(nodep, 0), BOTH);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
nodep->name()};
VCMethod::arrayMethod(nodep->name())};
newp->dtypeFrom(adtypep->subDTypep());
} else if (nodep->name() == "atWriteAppend"
|| nodep->name() == "atWriteAppendBack") { // Created internally for []
@ -4065,31 +4085,32 @@ class WidthVisitor final : public VNVisitor {
iterateCheckSigned32(nodep, "argument", methodArg(nodep, 0), BOTH);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::WRITE);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
nodep->name()};
VCMethod::arrayMethod(nodep->name())};
newp->dtypeFrom(adtypep->subDTypep());
} else if (nodep->name() == "num" // function int num()
|| nodep->name() == "size") {
methodOkArguments(nodep, 0, 0);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(), "size"};
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
VCMethod::DYN_SIZE};
newp->dtypeSetSigned32();
} else if (nodep->name() == "delete") { // function void delete([input integer index])
methodOkArguments(nodep, 0, 1);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::WRITE);
if (!nodep->pinsp()) {
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
"clear"};
VCMethod::DYN_CLEAR};
newp->dtypeSetVoid();
} else {
iterateCheckSigned32(nodep, "argument", methodArg(nodep, 0), BOTH);
AstNodeExpr* const index_exprp = methodCallQueueIndexExpr(nodep);
if (index_exprp->isZero()) { // delete(0) is a pop_front
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
"pop_front"};
VCMethod::DYN_POP_FRONT};
newp->dtypeFrom(adtypep->subDTypep());
newp->dtypeSetVoid();
} else {
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
"erase", index_exprp->unlinkFrBack()};
VCMethod::DYN_ERASE, index_exprp->unlinkFrBack()};
newp->dtypeSetVoid();
}
}
@ -4102,11 +4123,11 @@ class WidthVisitor final : public VNVisitor {
iterateCheckTyped(nodep, "insert value", argp->exprp(), adtypep->subDTypep(), BOTH);
if (index_exprp->isZero()) { // insert(0, ...) is a push_front
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
"push_front", argp->exprp()->unlinkFrBack()};
VCMethod::DYN_PUSH_FRONT, argp->exprp()->unlinkFrBack()};
newp->dtypeSetVoid();
} else {
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
nodep->name(), index_exprp->unlinkFrBack()};
VCMethod::DYN_INSERT, index_exprp->unlinkFrBack()};
newp->addPinsp(argp->exprp()->unlinkFrBack());
newp->dtypeSetVoid();
}
@ -4115,7 +4136,7 @@ class WidthVisitor final : public VNVisitor {
// Returns element, so method both consumes (reads) and modifies the queue
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READWRITE);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
nodep->name()};
VCMethod::arrayMethod(nodep->name())};
newp->dtypeFrom(adtypep->subDTypep());
} else if (nodep->name() == "push_back" || nodep->name() == "push_front") {
methodOkArguments(nodep, 1, 1);
@ -4124,7 +4145,8 @@ class WidthVisitor final : public VNVisitor {
AstArg* const argp = VN_AS(nodep->pinsp(), Arg);
iterateCheckTyped(nodep, "push value", argp->exprp(), adtypep->subDTypep(), BOTH);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
nodep->name(), argp->exprp()->unlinkFrBack()};
VCMethod::arrayMethod(nodep->name()),
argp->exprp()->unlinkFrBack()};
newp->dtypeSetVoid();
} else if (nodep->name() == "and" || nodep->name() == "or" || nodep->name() == "xor"
|| nodep->name() == "sum" || nodep->name() == "product") {
@ -4134,7 +4156,7 @@ class WidthVisitor final : public VNVisitor {
methodOkArguments(nodep, 0, 0);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
"r_" + nodep->name(), withp};
VCMethod::arrayMethod("r_" + nodep->name()), withp};
newp->dtypeFrom(withp ? withp->dtypep() : adtypep->subDTypep());
if (!nodep->firstAbovep()) newp->dtypeSetVoid();
} else if ((newp = methodCallArray(nodep, adtypep))) {
@ -4353,7 +4375,7 @@ class WidthVisitor final : public VNVisitor {
v3Global.useRandomizeMethods(true);
AstCMethodHard* const newp
= new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
"__Vm_rng.get_randstate", nullptr};
VCMethod::RNG_GET_RANDSTATE, nullptr};
newp->usePtr(true);
newp->dtypeSetString();
nodep->replaceWith(newp);
@ -4368,7 +4390,7 @@ class WidthVisitor final : public VNVisitor {
v3Global.useRandomizeMethods(true);
AstCMethodHard* const newp
= new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
"__Vm_rng.set_randstate", exprp->unlinkFrBack()};
VCMethod::RNG_SET_RANDSTATE, exprp->unlinkFrBack()};
newp->usePtr(true);
newp->dtypeSetString();
nodep->replaceWith(newp);
@ -4456,7 +4478,7 @@ class WidthVisitor final : public VNVisitor {
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
AstCMethodHard* const newp
= new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
"r_" + nodep->name(), withp};
VCMethod::arrayMethod("r_" + nodep->name()), withp};
newp->dtypeFrom(withp ? withp->dtypep() : adtypep->subDTypep());
if (!nodep->firstAbovep()) newp->dtypeSetVoid();
newp->protect(false);
@ -4503,7 +4525,7 @@ class WidthVisitor final : public VNVisitor {
if (nodep->name() == "triggered") {
methodOkArguments(nodep, 0, 0);
AstCMethodHard* const callp = new AstCMethodHard{
nodep->fileline(), nodep->fromp()->unlinkFrBack(), "isTriggered"};
nodep->fileline(), nodep->fromp()->unlinkFrBack(), VCMethod::EVENT_IS_TRIGGERED};
callp->dtypeSetBit();
nodep->replaceWith(callp);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
@ -5634,10 +5656,10 @@ class WidthVisitor final : public VNVisitor {
AstCMethodHard* newp;
if (!dynp->rhsp()) {
newp = new AstCMethodHard{nodep->fileline(), nodep->lhsp()->unlinkFrBack(),
"renew", dynp->sizep()->unlinkFrBack()};
VCMethod::DYN_RENEW, dynp->sizep()->unlinkFrBack()};
} else {
newp = new AstCMethodHard{nodep->fileline(), nodep->lhsp()->unlinkFrBack(),
"renew_copy", dynp->sizep()->unlinkFrBack()};
VCMethod::DYN_RENEW_COPY, dynp->sizep()->unlinkFrBack()};
newp->addPinsp(dynp->rhsp()->unlinkFrBack());
}
newp->didWidth(true);

View File

@ -488,8 +488,8 @@ private:
}
void visit(AstCMethodHard* nodep) override {
VL_RESTORER(m_dynsizedelem);
if (nodep->name() == "atWrite" || nodep->name() == "atWriteAppend"
|| nodep->name() == "at")
if (nodep->method() == VCMethod::ARRAY_AT || nodep->method() == VCMethod::ARRAY_AT_WRITE
|| nodep->method() == VCMethod::DYN_AT_WRITE_APPEND)
m_dynsizedelem = true;
iterateChildren(nodep);
editDType(nodep);

View File

@ -286,9 +286,10 @@ class WidthSelVisitor final : public VNVisitor {
VL_DO_DANGLING(pushDeletep(nodep), nodep);
} else if (const AstDynArrayDType* const adtypep = VN_CAST(ddtypep, DynArrayDType)) {
// SELBIT(array, index) -> CMETHODCALL(queue, "at", index)
const char* methodName = nodep->access().isWriteOrRW() ? "atWrite" : "at";
const VCMethod method
= nodep->access().isWriteOrRW() ? VCMethod::ARRAY_AT_WRITE : VCMethod::ARRAY_AT;
AstCMethodHard* const newp
= new AstCMethodHard{nodep->fileline(), fromp, methodName, rhsp};
= new AstCMethodHard{nodep->fileline(), fromp, method, rhsp};
newp->dtypeFrom(adtypep->subDTypep()); // Need to strip off queue reference
UINFOTREE(9, newp, "", "SELBTq");
nodep->replaceWith(newp);
@ -296,12 +297,16 @@ class WidthSelVisitor final : public VNVisitor {
} else if (const AstQueueDType* const adtypep = VN_CAST(ddtypep, QueueDType)) {
// SELBIT(array, index) -> CMETHODCALL(queue, "at", index)
AstCMethodHard* newp;
const char* methodName = nodep->access().isWriteOrRW() ? "atWriteAppend" : "at";
if (AstNodeExpr* const backnessp = selQueueBackness(rhsp)) {
newp = new AstCMethodHard{nodep->fileline(), fromp,
std::string(methodName) + "Back", backnessp};
const VCMethod method = nodep->access().isWriteOrRW()
? VCMethod::DYN_AT_WRITE_APPEND_BACK
: VCMethod::ARRAY_AT_BACK;
newp = new AstCMethodHard{nodep->fileline(), fromp, method, backnessp};
} else {
newp = new AstCMethodHard{nodep->fileline(), fromp, methodName, rhsp};
const VCMethod method = nodep->access().isWriteOrRW()
? VCMethod::DYN_AT_WRITE_APPEND
: VCMethod::ARRAY_AT;
newp = new AstCMethodHard{nodep->fileline(), fromp, method, rhsp};
}
newp->dtypeFrom(adtypep->subDTypep()); // Need to strip off queue reference
UINFOTREE(9, newp, "", "SELBTq");
@ -379,10 +384,10 @@ class WidthSelVisitor final : public VNVisitor {
// queue size, this allows a single queue reference, to support
// for equations in side effects that select the queue to
// operate upon.
std::string name = (qleftBacknessp ? "sliceBackBack"
: qrightBacknessp ? "sliceFrontBack"
: "slice");
AstCMethodHard* const newp = new AstCMethodHard{nodep->fileline(), fromp, name};
VCMethod method = (qleftBacknessp ? VCMethod::DYN_SLICE_BACK_BACK
: qrightBacknessp ? VCMethod::DYN_SLICE_FRONT_BACK
: VCMethod::DYN_SLICE);
AstCMethodHard* const newp = new AstCMethodHard{nodep->fileline(), fromp, method};
if (qleftBacknessp) {
VL_DO_DANGLING(pushDeletep(qleftp), qleftp);
newp->addPinsp(qleftBacknessp);

View File

@ -701,6 +701,7 @@ static bool verilate(const string& argString) {
if (v3Global.opt.debugSelfTest()) {
V3Os::selfTest();
V3Number::selfTest();
VCMethod::selfTest();
VString::selfTest();
VHashSha256::selfTest();
VSpellCheck::selfTest();