Merge branch 'master' into develop-v5

This commit is contained in:
Geza Lore 2022-04-23 15:38:30 +01:00
commit 46de9460a6
49 changed files with 684 additions and 492 deletions

View File

@ -23,12 +23,15 @@ Verilator 4.221 devel
* Split --prof-threads into --prof-exec and --prof-pgo (#3365). [Geza Lore, Shunyao CAD] * Split --prof-threads into --prof-exec and --prof-pgo (#3365). [Geza Lore, Shunyao CAD]
* Deprecate 'vluint64_t' and similar types (#3255). * Deprecate 'vluint64_t' and similar types (#3255).
* Raise error on assignment to const in initial blocks. [Geza Lore, Shunyao CAD]
* Fix MSVC localtime_s (#3124). * Fix MSVC localtime_s (#3124).
* Fix Bison 3.8.2 error (#3366). [elike-ypq] * Fix Bison 3.8.2 error (#3366). [elike-ypq]
* Fix rare bug in -Oz (V3Localize) (#3286). [Geza Lore, Shunyao CAD] * Fix rare bug in -Oz (V3Localize) (#3286). [Geza Lore, Shunyao CAD]
* Fix tracing interfaces inside interfaces (#3309). [Kevin Millis]
* Fix filenames with dots overwriting debug .vpp files (#3373). * Fix filenames with dots overwriting debug .vpp files (#3373).
* Fix including VK_USER_OBJS in make library (#3370). [Julien Margetts] * Fix including VK_USER_OBJS in make library (#3370). [Julien Margetts]
* Fix crash in recursive module inlining (#3393). [david-sawatzke]
* Fix --protect-ids mangling names of library methods. [Geza Lore, Shunyao CAD]
Verilator 4.220 2022-03-12 Verilator 4.220 2022-03-12
========================== ==========================

View File

@ -410,16 +410,16 @@ public:
} }
template <typename Func> VlQueue find_last(Func with_func) const { template <typename Func> VlQueue find_last(Func with_func) const {
IData index = m_deque.size() - 1; IData index = m_deque.size() - 1;
for (auto it = m_deque.rbegin(); it != m_deque.rend(); ++it) { for (auto& item : vlstd::reverse_view(m_deque)) {
if (with_func(index, *it)) return VlQueue::cons(*it); if (with_func(index, item)) return VlQueue::cons(item);
--index; --index;
} }
return VlQueue{}; return VlQueue{};
} }
template <typename Func> VlQueue<IData> find_last_index(Func with_func) const { template <typename Func> VlQueue<IData> find_last_index(Func with_func) const {
IData index = m_deque.size() - 1; IData index = m_deque.size() - 1;
for (auto it = m_deque.rbegin(); it != m_deque.rend(); ++it) { for (auto& item : vlstd::reverse_view(m_deque)) {
if (with_func(index, *it)) return VlQueue<IData>::cons(index); if (with_func(index, item)) return VlQueue<IData>::cons(index);
--index; --index;
} }
return VlQueue<IData>{}; return VlQueue<IData>{};

View File

@ -521,6 +521,19 @@ using ssize_t = uint32_t; ///< signed size_t; returned from read()
// Conversions // Conversions
namespace vlstd { namespace vlstd {
template <typename T> struct reverse_wrapper {
const T& m_v;
explicit reverse_wrapper(const T& a_v)
: m_v(a_v) {}
inline auto begin() -> decltype(m_v.rbegin()) { return m_v.rbegin(); }
inline auto end() -> decltype(m_v.rend()) { return m_v.rend(); }
};
// C++20's std::ranges::reverse_view
template <typename T> reverse_wrapper<T> reverse_view(const T& v) { return reverse_wrapper<T>(v); }
// C++17's std::as_const // C++17's std::as_const
template <class T> T const& as_const(T& v) { return v; } template <class T> T const& as_const(T& v) { return v; }
}; // namespace vlstd }; // namespace vlstd

View File

@ -422,6 +422,14 @@ private:
virtual void visit(AstActive* nodep) override { virtual void visit(AstActive* nodep) override {
// Actives are being formed, so we can ignore any already made // Actives are being formed, so we can ignore any already made
} }
virtual void visit(AstInitialStatic* nodep) override {
// Relink to IACTIVE, unless already under it
UINFO(4, " INITIAL " << nodep << endl);
const ActiveDlyVisitor dlyvisitor{nodep, ActiveDlyVisitor::CT_INITIAL};
AstActive* const wantactivep = m_namer.getIActive(nodep->fileline());
nodep->unlinkFrBack();
wantactivep->addStmtsp(nodep);
}
virtual void visit(AstInitial* nodep) override { virtual void visit(AstInitial* nodep) override {
// Relink to IACTIVE, unless already under it // Relink to IACTIVE, unless already under it
UINFO(4, " INITIAL " << nodep << endl); UINFO(4, " INITIAL " << nodep << endl);

View File

@ -98,7 +98,7 @@ private:
? static_cast<AstNode*>( ? static_cast<AstNode*>(
new AstCMath(fl, "vlSymsp->_vm_contextp__->assertOn()", 1)) new AstCMath(fl, "vlSymsp->_vm_contextp__->assertOn()", 1))
: static_cast<AstNode*>(new AstConst(fl, AstConst::BitFalse())))), : static_cast<AstNode*>(new AstConst(fl, AstConst::BitFalse())))),
nodep, nullptr); nodep);
newp->user1(true); // Don't assert/cover this if newp->user1(true); // Don't assert/cover this if
return newp; return newp;
} }
@ -154,7 +154,7 @@ private:
} }
if (bodysp && passsp) bodysp = bodysp->addNext(passsp); if (bodysp && passsp) bodysp = bodysp->addNext(passsp);
ifp = new AstIf(nodep->fileline(), propp, bodysp, nullptr); ifp = new AstIf(nodep->fileline(), propp, bodysp);
bodysp = ifp; bodysp = ifp;
} else if (VN_IS(nodep, Assert) || VN_IS(nodep, AssertIntrinsic)) { } else if (VN_IS(nodep, Assert) || VN_IS(nodep, AssertIntrinsic)) {
if (nodep->immediate()) { if (nodep->immediate()) {
@ -313,8 +313,7 @@ private:
AstIf* const ifp = new AstIf( AstIf* const ifp = new AstIf(
nodep->fileline(), new AstLogNot(nodep->fileline(), ohot), nodep->fileline(), new AstLogNot(nodep->fileline(), ohot),
newFireAssert(nodep, newFireAssert(nodep,
"synthesis parallel_case, but multiple matches found"), "synthesis parallel_case, but multiple matches found"));
nullptr);
ifp->branchPred(VBranchPred::BP_UNLIKELY); ifp->branchPred(VBranchPred::BP_UNLIKELY);
nodep->addNotParallelp(ifp); nodep->addNotParallelp(ifp);
} }
@ -384,7 +383,7 @@ private:
new AstLogAnd{fl, new AstLogNot{fl, newMonitorOffVarRefp(nodep, VAccess::READ)}, new AstLogAnd{fl, new AstLogNot{fl, newMonitorOffVarRefp(nodep, VAccess::READ)},
new AstEq{fl, new AstConst{fl, monNum}, new AstEq{fl, new AstConst{fl, monNum},
newMonitorNumVarRefp(nodep, VAccess::READ)}}, newMonitorNumVarRefp(nodep, VAccess::READ)}},
stmtsp, nullptr}; stmtsp};
ifp->branchPred(VBranchPred::BP_UNLIKELY); ifp->branchPred(VBranchPred::BP_UNLIKELY);
AstNode* const newp = new AstAlwaysPostponed{fl, ifp}; AstNode* const newp = new AstAlwaysPostponed{fl, ifp};
m_modp->addStmtp(newp); m_modp->addStmtp(newp);
@ -402,8 +401,7 @@ private:
nodep->replaceWith(newsetp); nodep->replaceWith(newsetp);
// Add "always_comb if (__Vstrobe) begin $display(...); __Vstrobe = '0; end" // Add "always_comb if (__Vstrobe) begin $display(...); __Vstrobe = '0; end"
AstNode* const stmtsp = nodep; AstNode* const stmtsp = nodep;
AstIf* const ifp AstIf* const ifp = new AstIf{fl, new AstVarRef{fl, varp, VAccess::READ}, stmtsp};
= new AstIf{fl, new AstVarRef{fl, varp, VAccess::READ}, stmtsp, nullptr};
ifp->branchPred(VBranchPred::BP_UNLIKELY); ifp->branchPred(VBranchPred::BP_UNLIKELY);
AstNode* const newp = new AstAlwaysPostponed{fl, ifp}; AstNode* const newp = new AstAlwaysPostponed{fl, ifp};
stmtsp->addNext(new AstAssign{fl, new AstVarRef{fl, varp, VAccess::WRITE}, stmtsp->addNext(new AstAssign{fl, new AstVarRef{fl, varp, VAccess::WRITE},

View File

@ -1135,49 +1135,33 @@ void AstNode::v3errorEndFatal(std::ostringstream& str) const {
VL_UNREACHABLE VL_UNREACHABLE
} }
string AstNode::locationStr() const { string AstNode::instanceStr() const {
string str = "... In instance "; // Max iterations before giving up on location search,
const AstNode* backp = this; // in case we have some circular reference bug.
int itmax = 10000; // Max iterations before giving up on location search constexpr unsigned maxIterations = 10000;
while (backp) { unsigned iterCount = 0;
if (VL_UNCOVERABLE(--itmax < 0)) {
// Likely some circular back link, and V3Ast is trying to report a low-level error
UINFO(1, "Ran out of iterations finding locationStr on " << backp << endl);
return ""; // LCOV_EXCL_LINE
}
const AstScope* scopep;
if ((scopep = VN_CAST(backp, Scope))) {
// The design is flattened and there are no useful scopes
// This is probably because of inlining
if (scopep->isTop()) break;
str += scopep->prettyName(); for (const AstNode* backp = this; backp; backp = backp->backp(), ++iterCount) {
return str; if (VL_UNCOVERABLE(iterCount >= maxIterations)) return ""; // LCOV_EXCL_LINE
// Prefer the enclosing scope, if there is one. This is always under the enclosing module,
// so just pick it up when encountered
if (const AstScope* const scopep = VN_CAST(backp, Scope)) {
return scopep->isTop() ? "" : "... In instance " + scopep->prettyName();
} }
backp = backp->backp();
} // If scopes don't exist, report an example instance of the enclosing module
backp = this; if (const AstModule* const modp = VN_CAST(backp, Module)) {
while (backp) { const string instanceName = modp->someInstanceName();
const AstModule* modp; return instanceName.empty() ? "" : "... In instance " + instanceName;
const AstNodeVarRef* nvrp;
if ((modp = VN_CAST(backp, Module)) && !modp->hierName().empty()) {
str += modp->hierName();
return str;
} else if ((nvrp = VN_CAST(backp, NodeVarRef))) {
const string prettyName = nvrp->prettyName();
// VarRefs have not been flattened yet and do not contain location information
if (prettyName != nvrp->name()) {
str += prettyName;
return str;
}
} }
backp = backp->backp();
} }
return ""; return "";
} }
void AstNode::v3errorEnd(std::ostringstream& str) const { void AstNode::v3errorEnd(std::ostringstream& str) const {
if (!m_fileline) { if (!m_fileline) {
V3Error::v3errorEnd(str, locationStr()); V3Error::v3errorEnd(str, instanceStr());
} else { } else {
std::ostringstream nsstr; std::ostringstream nsstr;
nsstr << str.str(); nsstr << str.str();
@ -1187,7 +1171,7 @@ void AstNode::v3errorEnd(std::ostringstream& str) const {
const_cast<AstNode*>(this)->dump(nsstr); const_cast<AstNode*>(this)->dump(nsstr);
nsstr << endl; nsstr << endl;
} }
m_fileline->v3errorEnd(nsstr, locationStr()); m_fileline->v3errorEnd(nsstr, instanceStr());
} }
} }

View File

@ -1447,7 +1447,7 @@ private:
bool gateOnly); bool gateOnly);
void deleteTreeIter(); void deleteTreeIter();
void deleteNode(); void deleteNode();
string locationStr() const; string instanceStr() const;
public: public:
static void relinkOneLink(AstNode*& pointpr, AstNode* newp); static void relinkOneLink(AstNode*& pointpr, AstNode* newp);
@ -3077,7 +3077,8 @@ class AstNodeModule VL_NOT_FINAL : public AstNode {
private: private:
string m_name; // Name of the module string m_name; // Name of the module
const string m_origName; // Name of the module, ignoring name() changes, for dot lookup const string m_origName; // Name of the module, ignoring name() changes, for dot lookup
string m_hierName; // Hierarchical name for errors, etc. string m_someInstanceName; // Hierarchical name of some arbitrary instance of this module.
// Used for user messages only.
bool m_modPublic : 1; // Module has public references bool m_modPublic : 1; // Module has public references
bool m_modTrace : 1; // Tracing this module bool m_modTrace : 1; // Tracing this module
bool m_inLibrary : 1; // From a library, no error if not used, never top level bool m_inLibrary : 1; // From a library, no error if not used, never top level
@ -3119,8 +3120,8 @@ public:
// ACCESSORS // ACCESSORS
virtual void name(const string& name) override { m_name = name; } virtual void name(const string& name) override { m_name = name; }
virtual string origName() const override { return m_origName; } virtual string origName() const override { return m_origName; }
string hierName() const { return m_hierName; } string someInstanceName() const { return m_someInstanceName; }
void hierName(const string& hierName) { m_hierName = hierName; } void someInstanceName(const string& name) { m_someInstanceName = name; }
bool inLibrary() const { return m_inLibrary; } bool inLibrary() const { return m_inLibrary; }
void inLibrary(bool flag) { m_inLibrary = flag; } void inLibrary(bool flag) { m_inLibrary = flag; }
void level(int level) { m_level = level; } void level(int level) { m_level = level; }

View File

@ -1914,14 +1914,14 @@ private:
bool m_pure = false; // Pure optimizable bool m_pure = false; // Pure optimizable
public: public:
AstCMethodHard(FileLine* fl, AstNode* fromp, VFlagChildDType, const string& name, AstCMethodHard(FileLine* fl, AstNode* fromp, VFlagChildDType, const string& name,
AstNode* pinsp) AstNode* pinsp = nullptr)
: ASTGEN_SUPER_CMethodHard(fl, false) : ASTGEN_SUPER_CMethodHard(fl, false)
, m_name{name} { , m_name{name} {
setOp1p(fromp); setOp1p(fromp);
dtypep(nullptr); // V3Width will resolve dtypep(nullptr); // V3Width will resolve
addNOp2p(pinsp); addNOp2p(pinsp);
} }
AstCMethodHard(FileLine* fl, AstNode* fromp, const string& name, AstNode* pinsp) AstCMethodHard(FileLine* fl, AstNode* fromp, const string& name, AstNode* pinsp = nullptr)
: ASTGEN_SUPER_CMethodHard(fl, false) : ASTGEN_SUPER_CMethodHard(fl, false)
, m_name{name} { , m_name{name} {
setOp1p(fromp); setOp1p(fromp);
@ -3407,7 +3407,7 @@ public:
}; };
class AstInitialAutomatic final : public AstNodeProcedure { class AstInitialAutomatic final : public AstNodeProcedure {
// initial for automatic variables // Automatic variable initialization
// That is, it runs every function start, or class construction // That is, it runs every function start, or class construction
public: public:
AstInitialAutomatic(FileLine* fl, AstNode* bodysp) AstInitialAutomatic(FileLine* fl, AstNode* bodysp)
@ -3415,6 +3415,15 @@ public:
ASTNODE_NODE_FUNCS(InitialAutomatic) ASTNODE_NODE_FUNCS(InitialAutomatic)
}; };
class AstInitialStatic final : public AstNodeProcedure {
// Static variable initialization
// That is, it runs at the beginning of simulation, before 'initial' blocks
public:
AstInitialStatic(FileLine* fl, AstNode* bodysp)
: ASTGEN_SUPER_InitialStatic(fl, bodysp) {}
ASTNODE_NODE_FUNCS(InitialStatic)
};
class AstAlways final : public AstNodeProcedure { class AstAlways final : public AstNodeProcedure {
const VAlwaysKwd m_keyword; const VAlwaysKwd m_keyword;
@ -4610,7 +4619,7 @@ public:
class AstWhile final : public AstNodeStmt { class AstWhile final : public AstNodeStmt {
public: public:
AstWhile(FileLine* fl, AstNode* condp, AstNode* bodysp, AstNode* incsp = nullptr) AstWhile(FileLine* fl, AstNode* condp, AstNode* bodysp = nullptr, AstNode* incsp = nullptr)
: ASTGEN_SUPER_While(fl) { : ASTGEN_SUPER_While(fl) {
setOp2p(condp); setOp2p(condp);
addNOp3p(bodysp); addNOp3p(bodysp);
@ -4714,7 +4723,7 @@ private:
bool m_unique0Pragma; // unique0 case bool m_unique0Pragma; // unique0 case
bool m_priorityPragma; // priority case bool m_priorityPragma; // priority case
public: public:
AstIf(FileLine* fl, AstNode* condp, AstNode* ifsp, AstNode* elsesp = nullptr) AstIf(FileLine* fl, AstNode* condp, AstNode* ifsp = nullptr, AstNode* elsesp = nullptr)
: ASTGEN_SUPER_If(fl, condp, ifsp, elsesp) { : ASTGEN_SUPER_If(fl, condp, ifsp, elsesp) {
m_uniquePragma = false; m_uniquePragma = false;
m_unique0Pragma = false; m_unique0Pragma = false;

View File

@ -427,8 +427,7 @@ private:
if (++depth > CASE_ENCODER_GROUP_DEPTH) depth = 1; if (++depth > CASE_ENCODER_GROUP_DEPTH) depth = 1;
if (depth == 1) { // First group or starting new group if (depth == 1) { // First group or starting new group
itemnextp = nullptr; itemnextp = nullptr;
AstIf* const newp AstIf* const newp = new AstIf(itemp->fileline(), ifexprp->cloneTree(true));
= new AstIf(itemp->fileline(), ifexprp->cloneTree(true), nullptr, nullptr);
if (groupnextp) { if (groupnextp) {
groupnextp->addElsesp(newp); groupnextp->addElsesp(newp);
} else { } else {
@ -448,7 +447,7 @@ private:
VL_DO_DANGLING(itemexprp->deleteTree(), itemexprp); VL_DO_DANGLING(itemexprp->deleteTree(), itemexprp);
itemexprp = new AstConst(itemp->fileline(), AstConst::BitTrue()); itemexprp = new AstConst(itemp->fileline(), AstConst::BitTrue());
} }
AstIf* const newp = new AstIf(itemp->fileline(), itemexprp, istmtsp, nullptr); AstIf* const newp = new AstIf(itemp->fileline(), itemexprp, istmtsp);
if (itemnextp) { if (itemnextp) {
itemnextp->addElsesp(newp); itemnextp->addElsesp(newp);
} else { } else {

View File

@ -716,6 +716,7 @@ private:
// Ignores // Ignores
virtual void visit(AstInitial*) override {} virtual void visit(AstInitial*) override {}
virtual void visit(AstInitialAutomatic*) override {} virtual void visit(AstInitialAutomatic*) override {}
virtual void visit(AstInitialStatic*) override {}
virtual void visit(AstTraceDecl*) override {} virtual void visit(AstTraceDecl*) override {}
virtual void visit(AstCoverToggle*) override {} virtual void visit(AstCoverToggle*) override {}
virtual void visit(AstNodeDType*) override {} virtual void visit(AstNodeDType*) override {}

View File

@ -153,6 +153,11 @@ private:
iterateChildren(nodep); iterateChildren(nodep);
if (m_packageScopep) { m_toScopeMoves.push_back(std::make_pair(nodep, m_packageScopep)); } if (m_packageScopep) { m_toScopeMoves.push_back(std::make_pair(nodep, m_packageScopep)); }
} }
virtual void visit(AstInitialStatic* nodep) override {
// But not AstInitialAutomatic, which remains under the class
iterateChildren(nodep);
if (m_packageScopep) { m_toScopeMoves.push_back(std::make_pair(nodep, m_packageScopep)); }
}
virtual void visit(AstNodeMath* nodep) override {} // Short circuit virtual void visit(AstNodeMath* nodep) override {} // Short circuit
virtual void visit(AstNodeStmt* nodep) override {} // Short circuit virtual void visit(AstNodeStmt* nodep) override {} // Short circuit
@ -173,7 +178,7 @@ public:
vscp->scopep(scopep); vscp->scopep(scopep);
vscp->unlinkFrBack(); vscp->unlinkFrBack();
scopep->addVarp(vscp); scopep->addVarp(vscp);
} else if (VN_IS(nodep, Initial)) { } else if (VN_IS(nodep, Initial) || VN_IS(nodep, InitialStatic)) {
nodep->unlinkFrBack(); nodep->unlinkFrBack();
scopep->addActivep(nodep); scopep->addActivep(nodep);
} else { } else {

View File

@ -185,7 +185,7 @@ private:
AstIf* makeActiveIf(AstSenTree* sensesp) { AstIf* makeActiveIf(AstSenTree* sensesp) {
AstNode* const senEqnp = createSenseEquation(sensesp->sensesp()); AstNode* const senEqnp = createSenseEquation(sensesp->sensesp());
UASSERT_OBJ(senEqnp, sensesp, "No sense equation, shouldn't be in sequent activation."); UASSERT_OBJ(senEqnp, sensesp, "No sense equation, shouldn't be in sequent activation.");
AstIf* const newifp = new AstIf(sensesp->fileline(), senEqnp, nullptr, nullptr); AstIf* const newifp = new AstIf(sensesp->fileline(), senEqnp);
return newifp; return newifp;
} }
void clearLastSen() { void clearLastSen() {
@ -310,8 +310,8 @@ private:
AstNode* const origp = nodep->origp()->unlinkFrBack(); AstNode* const origp = nodep->origp()->unlinkFrBack();
AstNode* const changeWrp = nodep->changep()->unlinkFrBack(); AstNode* const changeWrp = nodep->changep()->unlinkFrBack();
AstNode* const changeRdp = ConvertWriteRefsToRead::main(changeWrp->cloneTree(false)); AstNode* const changeRdp = ConvertWriteRefsToRead::main(changeWrp->cloneTree(false));
AstIf* const newp = new AstIf( AstIf* const newp
nodep->fileline(), new AstXor(nodep->fileline(), origp, changeRdp), incp, nullptr); = new AstIf(nodep->fileline(), new AstXor(nodep->fileline(), origp, changeRdp), incp);
// We could add another IF to detect posedges, and only increment if so. // We could add another IF to detect posedges, and only increment if so.
// It's another whole branch though versus a potential memory miss. // It's another whole branch though versus a potential memory miss.
// We'll go with the miss. // We'll go with the miss.

View File

@ -351,8 +351,7 @@ private:
"Delayed assignment misoptimized; prev var found w/o associated IF"); "Delayed assignment misoptimized; prev var found w/o associated IF");
} else { } else {
postLogicp = new AstIf(nodep->fileline(), postLogicp = new AstIf(nodep->fileline(),
new AstVarRef(nodep->fileline(), setvscp, VAccess::READ), new AstVarRef(nodep->fileline(), setvscp, VAccess::READ));
nullptr, nullptr);
UINFO(9, " Created " << postLogicp << endl); UINFO(9, " Created " << postLogicp << endl);
finalp->addStmtp(postLogicp); finalp->addStmtp(postLogicp);
finalp->user3p(setvscp); // Remember IF's vset variable finalp->user3p(setvscp); // Remember IF's vset variable

View File

@ -161,7 +161,7 @@ private:
new AstCMath(funcp->fileline(), new AstCMath(funcp->fileline(),
string("&(") + funcp->scopep()->nameVlSym() + ")", string("&(") + funcp->scopep()->nameVlSym() + ")",
64)), 64)),
returnp, nullptr); returnp);
newfuncp->addStmtsp(ifp); newfuncp->addStmtsp(ifp);
} else { } else {
newfuncp->addStmtsp(returnp); newfuncp->addStmtsp(returnp);

View File

@ -406,7 +406,7 @@ public:
virtual void visit(AstCMethodHard* nodep) override { virtual void visit(AstCMethodHard* nodep) override {
iterate(nodep->fromp()); iterate(nodep->fromp());
puts("."); puts(".");
puts(nodep->nameProtect()); puts(nodep->name());
puts("("); puts("(");
bool comma = false; bool comma = false;
for (AstNode* subnodep = nodep->pinsp(); subnodep; subnodep = subnodep->nextp()) { for (AstNode* subnodep = nodep->pinsp(); subnodep; subnodep = subnodep->nextp()) {

View File

@ -333,8 +333,8 @@ class EmitMkHierVerilation final {
const V3HierBlockPlan::HierVector blocks const V3HierBlockPlan::HierVector blocks
= m_planp->hierBlocksSorted(); // leaf comes first = m_planp->hierBlocksSorted(); // leaf comes first
// List in order of leaf-last order so that linker can resolve dependency // List in order of leaf-last order so that linker can resolve dependency
for (auto it = blocks.rbegin(); it != blocks.rend(); ++it) { for (auto& block : vlstd::reverse_view(blocks)) {
of.puts("\t" + (*it)->hierLib(true) + " \\\n"); of.puts("\t" + block->hierLib(true) + " \\\n");
} }
of.puts("\n"); of.puts("\n");

View File

@ -52,10 +52,10 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
} }
// VISITORS // VISITORS
virtual void visit(AstNetlist* nodep) override { iterateAndNextNull(nodep->modulesp()); } virtual void visit(AstNetlist* nodep) override { iterateAndNextConstNull(nodep->modulesp()); }
virtual void visit(AstNodeModule* nodep) override { virtual void visit(AstNodeModule* nodep) override {
putfs(nodep, nodep->verilogKwd() + " " + prefixNameProtect(nodep) + ";\n"); putfs(nodep, nodep->verilogKwd() + " " + prefixNameProtect(nodep) + ";\n");
iterateChildren(nodep); iterateChildrenConst(nodep);
putqs(nodep, "end" + nodep->verilogKwd() + "\n"); putqs(nodep, "end" + nodep->verilogKwd() + "\n");
} }
virtual void visit(AstPort* nodep) override {} virtual void visit(AstPort* nodep) override {}
@ -65,7 +65,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
puts(nodep->prettyName()); puts(nodep->prettyName());
puts(";\n"); puts(";\n");
// Only putfs the first time for each visitor; later for same node is putqs // Only putfs the first time for each visitor; later for same node is putqs
iterateAndNextNull(nodep->stmtsp()); iterateAndNextConstNull(nodep->stmtsp());
putfs(nodep, nodep->isFunction() ? "endfunction\n" : "endtask\n"); putfs(nodep, nodep->isFunction() ? "endfunction\n" : "endtask\n");
} }
@ -75,7 +75,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
} else { } else {
putbs("begin : " + nodep->name() + "\n"); putbs("begin : " + nodep->name() + "\n");
} }
iterateChildren(nodep); iterateChildrenConst(nodep);
puts("end\n"); puts("end\n");
} }
virtual void visit(AstFork* nodep) override { virtual void visit(AstFork* nodep) override {
@ -84,75 +84,76 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
} else { } else {
putbs("fork : " + nodep->name() + "\n"); putbs("fork : " + nodep->name() + "\n");
} }
iterateChildren(nodep); iterateChildrenConst(nodep);
puts(nodep->joinType().verilogKwd()); puts(nodep->joinType().verilogKwd());
puts("\n"); puts("\n");
} }
virtual void visit(AstFinal* nodep) override { virtual void visit(AstFinal* nodep) override {
putfs(nodep, "final begin\n"); putfs(nodep, "final begin\n");
iterateChildren(nodep); iterateChildrenConst(nodep);
putqs(nodep, "end\n"); putqs(nodep, "end\n");
} }
virtual void visit(AstInitial* nodep) override { virtual void visit(AstInitial* nodep) override {
putfs(nodep, "initial begin\n"); putfs(nodep, "initial begin\n");
iterateChildren(nodep); iterateChildrenConst(nodep);
putqs(nodep, "end\n"); putqs(nodep, "end\n");
} }
virtual void visit(AstInitialAutomatic* nodep) override { iterateChildren(nodep); } virtual void visit(AstInitialAutomatic* nodep) override { iterateChildrenConst(nodep); }
virtual void visit(AstInitialStatic* nodep) override { iterateChildrenConst(nodep); }
virtual void visit(AstAlways* nodep) override { virtual void visit(AstAlways* nodep) override {
putfs(nodep, "always "); putfs(nodep, "always ");
if (m_sensesp) { if (m_sensesp) {
iterateAndNextNull(m_sensesp); iterateAndNextConstNull(m_sensesp);
} // In active } // In active
else { else {
iterateAndNextNull(nodep->sensesp()); iterateAndNextConstNull(nodep->sensesp());
} }
putbs(" begin\n"); putbs(" begin\n");
iterateAndNextNull(nodep->bodysp()); iterateAndNextConstNull(nodep->bodysp());
putqs(nodep, "end\n"); putqs(nodep, "end\n");
} }
virtual void visit(AstAlwaysPublic* nodep) override { virtual void visit(AstAlwaysPublic* nodep) override {
putfs(nodep, "/*verilator public_flat_rw "); putfs(nodep, "/*verilator public_flat_rw ");
if (m_sensesp) { if (m_sensesp) {
iterateAndNextNull(m_sensesp); iterateAndNextConstNull(m_sensesp);
} // In active } // In active
else { else {
iterateAndNextNull(nodep->sensesp()); iterateAndNextConstNull(nodep->sensesp());
} }
putqs(nodep, " "); putqs(nodep, " ");
iterateAndNextNull(nodep->bodysp()); iterateAndNextConstNull(nodep->bodysp());
putqs(nodep, "*/\n"); putqs(nodep, "*/\n");
} }
virtual void visit(AstNodeAssign* nodep) override { virtual void visit(AstNodeAssign* nodep) override {
if (VN_IS(nodep, AssignForce)) puts("force "); if (VN_IS(nodep, AssignForce)) puts("force ");
iterateAndNextNull(nodep->lhsp()); iterateAndNextConstNull(nodep->lhsp());
putfs(nodep, " " + nodep->verilogKwd() + " "); putfs(nodep, " " + nodep->verilogKwd() + " ");
iterateAndNextNull(nodep->rhsp()); iterateAndNextConstNull(nodep->rhsp());
if (!m_suppressSemi) puts(";\n"); if (!m_suppressSemi) puts(";\n");
} }
virtual void visit(AstAssignDly* nodep) override { virtual void visit(AstAssignDly* nodep) override {
iterateAndNextNull(nodep->lhsp()); iterateAndNextConstNull(nodep->lhsp());
putfs(nodep, " <= "); putfs(nodep, " <= ");
iterateAndNextNull(nodep->rhsp()); iterateAndNextConstNull(nodep->rhsp());
puts(";\n"); puts(";\n");
} }
virtual void visit(AstAssignAlias* nodep) override { virtual void visit(AstAssignAlias* nodep) override {
putbs("alias "); putbs("alias ");
iterateAndNextNull(nodep->lhsp()); iterateAndNextConstNull(nodep->lhsp());
putfs(nodep, " = "); putfs(nodep, " = ");
iterateAndNextNull(nodep->rhsp()); iterateAndNextConstNull(nodep->rhsp());
if (!m_suppressSemi) puts(";\n"); if (!m_suppressSemi) puts(";\n");
} }
virtual void visit(AstAssignW* nodep) override { virtual void visit(AstAssignW* nodep) override {
putfs(nodep, "assign "); putfs(nodep, "assign ");
iterateAndNextNull(nodep->lhsp()); iterateAndNextConstNull(nodep->lhsp());
putbs(" = "); putbs(" = ");
iterateAndNextNull(nodep->rhsp()); iterateAndNextConstNull(nodep->rhsp());
if (!m_suppressSemi) puts(";\n"); if (!m_suppressSemi) puts(";\n");
} }
virtual void visit(AstRelease* nodep) override { virtual void visit(AstRelease* nodep) override {
puts("release "); puts("release ");
iterateAndNextNull(nodep->lhsp()); iterateAndNextConstNull(nodep->lhsp());
if (!m_suppressSemi) puts(";\n"); if (!m_suppressSemi) puts(";\n");
} }
virtual void visit(AstBreak*) override { virtual void visit(AstBreak*) override {
@ -172,7 +173,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
putfs(nodep, ""); putfs(nodep, "");
puts(nodep->edgeType().verilogKwd()); puts(nodep->edgeType().verilogKwd());
if (nodep->sensp()) puts(" "); if (nodep->sensp()) puts(" ");
iterateChildren(nodep); iterateChildrenConst(nodep);
} }
virtual void visit(AstNodeCase* nodep) override { virtual void visit(AstNodeCase* nodep) override {
putfs(nodep, ""); putfs(nodep, "");
@ -183,7 +184,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
} }
puts(nodep->verilogKwd()); puts(nodep->verilogKwd());
puts(" ("); puts(" (");
iterateAndNextNull(nodep->exprp()); iterateAndNextConstNull(nodep->exprp());
puts(")\n"); puts(")\n");
if (const AstCase* const casep = VN_CAST(nodep, Case)) { if (const AstCase* const casep = VN_CAST(nodep, Case)) {
if (casep->fullPragma() || casep->parallelPragma()) { if (casep->fullPragma() || casep->parallelPragma()) {
@ -192,22 +193,22 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
if (casep->parallelPragma()) puts(" parallel_case"); if (casep->parallelPragma()) puts(" parallel_case");
} }
} }
iterateAndNextNull(nodep->itemsp()); iterateAndNextConstNull(nodep->itemsp());
putqs(nodep, "endcase\n"); putqs(nodep, "endcase\n");
} }
virtual void visit(AstCaseItem* nodep) override { virtual void visit(AstCaseItem* nodep) override {
if (nodep->condsp()) { if (nodep->condsp()) {
iterateAndNextNull(nodep->condsp()); iterateAndNextConstNull(nodep->condsp());
} else { } else {
putbs("default"); putbs("default");
} }
putfs(nodep, ": begin "); putfs(nodep, ": begin ");
iterateAndNextNull(nodep->bodysp()); iterateAndNextConstNull(nodep->bodysp());
putqs(nodep, "end\n"); putqs(nodep, "end\n");
} }
virtual void visit(AstComment* nodep) override { virtual void visit(AstComment* nodep) override {
puts(string("// ") + nodep->name() + "\n"); puts(string("// ") + nodep->name() + "\n");
iterateChildren(nodep); iterateChildrenConst(nodep);
} }
virtual void visit(AstContinue*) override { virtual void visit(AstContinue*) override {
putbs("continue"); putbs("continue");
@ -222,13 +223,13 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
putfs(nodep, nodep->verilogKwd()); putfs(nodep, nodep->verilogKwd());
putbs("("); putbs("(");
if (fileOrStrgp) { if (fileOrStrgp) {
iterateAndNextNull(fileOrStrgp); iterateAndNextConstNull(fileOrStrgp);
putbs(", "); putbs(", ");
} }
putsQuoted(text); putsQuoted(text);
for (AstNode* expp = exprsp; expp; expp = expp->nextp()) { for (AstNode* expp = exprsp; expp; expp = expp->nextp()) {
puts(", "); puts(", ");
iterateAndNextNull(expp); iterateAndNextConstNull(expp);
} }
puts(");\n"); puts(");\n");
} }
@ -254,32 +255,32 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
virtual void visit(AstFOpen* nodep) override { virtual void visit(AstFOpen* nodep) override {
putfs(nodep, nodep->verilogKwd()); putfs(nodep, nodep->verilogKwd());
putbs("("); putbs("(");
iterateAndNextNull(nodep->filenamep()); iterateAndNextConstNull(nodep->filenamep());
putbs(", "); putbs(", ");
iterateAndNextNull(nodep->modep()); iterateAndNextConstNull(nodep->modep());
puts(");\n"); puts(");\n");
} }
virtual void visit(AstFOpenMcd* nodep) override { virtual void visit(AstFOpenMcd* nodep) override {
putfs(nodep, nodep->verilogKwd()); putfs(nodep, nodep->verilogKwd());
putbs("("); putbs("(");
iterateAndNextNull(nodep->filenamep()); iterateAndNextConstNull(nodep->filenamep());
puts(");\n"); puts(");\n");
} }
virtual void visit(AstFClose* nodep) override { virtual void visit(AstFClose* nodep) override {
putfs(nodep, nodep->verilogKwd()); putfs(nodep, nodep->verilogKwd());
putbs("("); putbs("(");
if (nodep->filep()) iterateAndNextNull(nodep->filep()); if (nodep->filep()) iterateAndNextConstNull(nodep->filep());
puts(");\n"); puts(");\n");
} }
virtual void visit(AstFFlush* nodep) override { virtual void visit(AstFFlush* nodep) override {
putfs(nodep, nodep->verilogKwd()); putfs(nodep, nodep->verilogKwd());
putbs("("); putbs("(");
if (nodep->filep()) iterateAndNextNull(nodep->filep()); if (nodep->filep()) iterateAndNextConstNull(nodep->filep());
puts(");\n"); puts(");\n");
} }
virtual void visit(AstJumpBlock* nodep) override { virtual void visit(AstJumpBlock* nodep) override {
putbs("begin : label" + cvtToStr(nodep->labelNum()) + "\n"); putbs("begin : label" + cvtToStr(nodep->labelNum()) + "\n");
if (nodep->stmtsp()) iterateAndNextNull(nodep->stmtsp()); if (nodep->stmtsp()) iterateAndNextConstNull(nodep->stmtsp());
puts("end\n"); puts("end\n");
} }
virtual void visit(AstJumpGo* nodep) override { virtual void visit(AstJumpGo* nodep) override {
@ -291,27 +292,27 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
virtual void visit(AstNodeReadWriteMem* nodep) override { virtual void visit(AstNodeReadWriteMem* nodep) override {
putfs(nodep, nodep->verilogKwd()); putfs(nodep, nodep->verilogKwd());
putbs("("); putbs("(");
if (nodep->filenamep()) iterateAndNextNull(nodep->filenamep()); if (nodep->filenamep()) iterateAndNextConstNull(nodep->filenamep());
putbs(", "); putbs(", ");
if (nodep->memp()) iterateAndNextNull(nodep->memp()); if (nodep->memp()) iterateAndNextConstNull(nodep->memp());
if (nodep->lsbp()) { if (nodep->lsbp()) {
putbs(", "); putbs(", ");
iterateAndNextNull(nodep->lsbp()); iterateAndNextConstNull(nodep->lsbp());
} }
if (nodep->msbp()) { if (nodep->msbp()) {
putbs(", "); putbs(", ");
iterateAndNextNull(nodep->msbp()); iterateAndNextConstNull(nodep->msbp());
} }
puts(");\n"); puts(");\n");
} }
virtual void visit(AstSysFuncAsTask* nodep) override { virtual void visit(AstSysFuncAsTask* nodep) override {
iterateAndNextNull(nodep->lhsp()); iterateAndNextConstNull(nodep->lhsp());
puts(";\n"); puts(";\n");
} }
virtual void visit(AstSysIgnore* nodep) override { virtual void visit(AstSysIgnore* nodep) override {
putfs(nodep, nodep->verilogKwd()); putfs(nodep, nodep->verilogKwd());
putbs("("); putbs("(");
iterateAndNextNull(nodep->exprsp()); iterateAndNextConstNull(nodep->exprsp());
puts(");\n"); puts(");\n");
} }
virtual void visit(AstNodeFor* nodep) override { virtual void visit(AstNodeFor* nodep) override {
@ -319,31 +320,31 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
{ {
VL_RESTORER(m_suppressSemi); VL_RESTORER(m_suppressSemi);
m_suppressSemi = true; m_suppressSemi = true;
iterateAndNextNull(nodep->initsp()); iterateAndNextConstNull(nodep->initsp());
puts(";"); puts(";");
iterateAndNextNull(nodep->condp()); iterateAndNextConstNull(nodep->condp());
puts(";"); puts(";");
iterateAndNextNull(nodep->incsp()); iterateAndNextConstNull(nodep->incsp());
} }
puts(") begin\n"); puts(") begin\n");
iterateAndNextNull(nodep->bodysp()); iterateAndNextConstNull(nodep->bodysp());
putqs(nodep, "end\n"); putqs(nodep, "end\n");
} }
virtual void visit(AstRepeat* nodep) override { virtual void visit(AstRepeat* nodep) override {
putfs(nodep, "repeat ("); putfs(nodep, "repeat (");
iterateAndNextNull(nodep->countp()); iterateAndNextConstNull(nodep->countp());
puts(") begin\n"); puts(") begin\n");
iterateAndNextNull(nodep->bodysp()); iterateAndNextConstNull(nodep->bodysp());
putfs(nodep, "end\n"); putfs(nodep, "end\n");
} }
virtual void visit(AstWhile* nodep) override { virtual void visit(AstWhile* nodep) override {
iterateAndNextNull(nodep->precondsp()); iterateAndNextConstNull(nodep->precondsp());
putfs(nodep, "while ("); putfs(nodep, "while (");
iterateAndNextNull(nodep->condp()); iterateAndNextConstNull(nodep->condp());
puts(") begin\n"); puts(") begin\n");
iterateAndNextNull(nodep->bodysp()); iterateAndNextConstNull(nodep->bodysp());
iterateAndNextNull(nodep->incsp()); iterateAndNextConstNull(nodep->incsp());
iterateAndNextNull(nodep->precondsp()); // Need to recompute before next loop iterateAndNextConstNull(nodep->precondsp()); // Need to recompute before next loop
putfs(nodep, "end\n"); putfs(nodep, "end\n");
} }
virtual void visit(AstNodeIf* nodep) override { virtual void visit(AstNodeIf* nodep) override {
@ -354,28 +355,28 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
if (ifp->unique0Pragma()) puts("unique0 "); if (ifp->unique0Pragma()) puts("unique0 ");
} }
puts("if ("); puts("if (");
iterateAndNextNull(nodep->condp()); iterateAndNextConstNull(nodep->condp());
puts(") begin\n"); puts(") begin\n");
iterateAndNextNull(nodep->ifsp()); iterateAndNextConstNull(nodep->ifsp());
if (nodep->elsesp()) { if (nodep->elsesp()) {
putqs(nodep, "end\n"); putqs(nodep, "end\n");
putqs(nodep, "else begin\n"); putqs(nodep, "else begin\n");
iterateAndNextNull(nodep->elsesp()); iterateAndNextConstNull(nodep->elsesp());
} }
putqs(nodep, "end\n"); putqs(nodep, "end\n");
} }
virtual void visit(AstPast* nodep) override { virtual void visit(AstPast* nodep) override {
putfs(nodep, "$past("); putfs(nodep, "$past(");
iterateAndNextNull(nodep->exprp()); iterateAndNextConstNull(nodep->exprp());
if (nodep->ticksp()) { if (nodep->ticksp()) {
puts(", "); puts(", ");
iterateAndNextNull(nodep->ticksp()); iterateAndNextConstNull(nodep->ticksp());
} }
puts(")"); puts(")");
} }
virtual void visit(AstReturn* nodep) override { virtual void visit(AstReturn* nodep) override {
putfs(nodep, "return "); putfs(nodep, "return ");
iterateAndNextNull(nodep->lhsp()); iterateAndNextConstNull(nodep->lhsp());
puts(";\n"); puts(";\n");
} }
virtual void visit(AstStop* nodep) override { putfs(nodep, "$stop;\n"); } virtual void visit(AstStop* nodep) override { putfs(nodep, "$stop;\n"); }
@ -401,22 +402,22 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
virtual void visit(AstScopeName* nodep) override {} virtual void visit(AstScopeName* nodep) override {}
virtual void visit(AstCStmt* nodep) override { virtual void visit(AstCStmt* nodep) override {
putfs(nodep, "$_CSTMT("); putfs(nodep, "$_CSTMT(");
iterateAndNextNull(nodep->bodysp()); iterateAndNextConstNull(nodep->bodysp());
puts(");\n"); puts(");\n");
} }
virtual void visit(AstCMath* nodep) override { virtual void visit(AstCMath* nodep) override {
putfs(nodep, "$_CMATH("); putfs(nodep, "$_CMATH(");
iterateAndNextNull(nodep->bodysp()); iterateAndNextConstNull(nodep->bodysp());
puts(");\n"); puts(");\n");
} }
virtual void visit(AstUCStmt* nodep) override { virtual void visit(AstUCStmt* nodep) override {
putfs(nodep, "$c("); putfs(nodep, "$c(");
iterateAndNextNull(nodep->bodysp()); iterateAndNextConstNull(nodep->bodysp());
puts(");\n"); puts(");\n");
} }
virtual void visit(AstUCFunc* nodep) override { virtual void visit(AstUCFunc* nodep) override {
putfs(nodep, "$c("); putfs(nodep, "$c(");
iterateAndNextNull(nodep->bodysp()); iterateAndNextConstNull(nodep->bodysp());
puts(")"); puts(")");
} }
@ -450,27 +451,27 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
case 'k': putbs(""); break; case 'k': putbs(""); break;
case 'l': { case 'l': {
UASSERT_OBJ(lhsp, nodep, "emitVerilog() references undef node"); UASSERT_OBJ(lhsp, nodep, "emitVerilog() references undef node");
iterateAndNextNull(lhsp); iterateAndNextConstNull(lhsp);
break; break;
} }
case 'r': { case 'r': {
UASSERT_OBJ(rhsp, nodep, "emitVerilog() references undef node"); UASSERT_OBJ(rhsp, nodep, "emitVerilog() references undef node");
iterateAndNextNull(rhsp); iterateAndNextConstNull(rhsp);
break; break;
} }
case 't': { case 't': {
UASSERT_OBJ(thsp, nodep, "emitVerilog() references undef node"); UASSERT_OBJ(thsp, nodep, "emitVerilog() references undef node");
iterateAndNextNull(thsp); iterateAndNextConstNull(thsp);
break; break;
} }
case 'o': { case 'o': {
UASSERT_OBJ(thsp, nodep, "emitVerilog() references undef node"); UASSERT_OBJ(thsp, nodep, "emitVerilog() references undef node");
iterateAndNextNull(fhsp); iterateAndNextConstNull(fhsp);
break; break;
} }
case 'd': { case 'd': {
UASSERT_OBJ(nodep->dtypep(), nodep, "emitVerilog() references undef node"); UASSERT_OBJ(nodep->dtypep(), nodep, "emitVerilog() references undef node");
iterateAndNextNull(nodep->dtypep()); iterateAndNextConstNull(nodep->dtypep());
break; break;
} }
default: nodep->v3fatalSrc("Unknown emitVerilog format code: %" << c); break; default: nodep->v3fatalSrc("Unknown emitVerilog format code: %" << c); break;
@ -494,10 +495,10 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
} }
virtual void visit(AstAttrOf* nodep) override { virtual void visit(AstAttrOf* nodep) override {
putfs(nodep, "$_ATTROF("); putfs(nodep, "$_ATTROF(");
iterateAndNextNull(nodep->fromp()); iterateAndNextConstNull(nodep->fromp());
if (nodep->dimp()) { if (nodep->dimp()) {
putbs(", "); putbs(", ");
iterateAndNextNull(nodep->dimp()); iterateAndNextConstNull(nodep->dimp());
} }
puts(")"); puts(")");
} }
@ -516,11 +517,11 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
} }
virtual void visit(AstNodeCond* nodep) override { virtual void visit(AstNodeCond* nodep) override {
putbs("("); putbs("(");
iterateAndNextNull(nodep->condp()); iterateAndNextConstNull(nodep->condp());
putfs(nodep, " ? "); putfs(nodep, " ? ");
iterateAndNextNull(nodep->expr1p()); iterateAndNextConstNull(nodep->expr1p());
putbs(" : "); putbs(" : ");
iterateAndNextNull(nodep->expr2p()); iterateAndNextConstNull(nodep->expr2p());
puts(")"); puts(")");
} }
virtual void visit(AstRange* nodep) override { virtual void visit(AstRange* nodep) override {
@ -532,21 +533,21 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
puts(cvtToStr(nodep->rightConst())); puts(cvtToStr(nodep->rightConst()));
puts("]"); puts("]");
} else { } else {
iterateAndNextNull(nodep->leftp()); iterateAndNextConstNull(nodep->leftp());
puts(":"); puts(":");
iterateAndNextNull(nodep->rightp()); iterateAndNextConstNull(nodep->rightp());
puts("]"); puts("]");
} }
} }
virtual void visit(AstSel* nodep) override { virtual void visit(AstSel* nodep) override {
iterateAndNextNull(nodep->fromp()); iterateAndNextConstNull(nodep->fromp());
puts("["); puts("[");
if (VN_IS(nodep->lsbp(), Const)) { if (VN_IS(nodep->lsbp(), Const)) {
if (nodep->widthp()->isOne()) { if (nodep->widthp()->isOne()) {
if (VN_IS(nodep->lsbp(), Const)) { if (VN_IS(nodep->lsbp(), Const)) {
puts(cvtToStr(VN_AS(nodep->lsbp(), Const)->toSInt())); puts(cvtToStr(VN_AS(nodep->lsbp(), Const)->toSInt()));
} else { } else {
iterateAndNextNull(nodep->lsbp()); iterateAndNextConstNull(nodep->lsbp());
} }
} else { } else {
puts(cvtToStr(VN_AS(nodep->lsbp(), Const)->toSInt() puts(cvtToStr(VN_AS(nodep->lsbp(), Const)->toSInt()
@ -555,20 +556,20 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
puts(cvtToStr(VN_AS(nodep->lsbp(), Const)->toSInt())); puts(cvtToStr(VN_AS(nodep->lsbp(), Const)->toSInt()));
} }
} else { } else {
iterateAndNextNull(nodep->lsbp()); iterateAndNextConstNull(nodep->lsbp());
putfs(nodep, "+:"); putfs(nodep, "+:");
iterateAndNextNull(nodep->widthp()); iterateAndNextConstNull(nodep->widthp());
puts("]"); puts("]");
} }
puts("]"); puts("]");
} }
virtual void visit(AstSliceSel* nodep) override { virtual void visit(AstSliceSel* nodep) override {
iterateAndNextNull(nodep->fromp()); iterateAndNextConstNull(nodep->fromp());
puts(cvtToStr(nodep->declRange())); puts(cvtToStr(nodep->declRange()));
} }
virtual void visit(AstTypedef* nodep) override { virtual void visit(AstTypedef* nodep) override {
putfs(nodep, "typedef "); putfs(nodep, "typedef ");
iterateAndNextNull(nodep->dtypep()); iterateAndNextConstNull(nodep->dtypep());
puts(" "); puts(" ");
puts(nodep->prettyName()); puts(nodep->prettyName());
puts(";\n"); puts(";\n");
@ -578,7 +579,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
putfs(nodep, nodep->prettyName()); putfs(nodep, nodep->prettyName());
if (nodep->rangep()) { if (nodep->rangep()) {
puts(" "); puts(" ");
iterateAndNextNull(nodep->rangep()); iterateAndNextConstNull(nodep->rangep());
puts(" "); puts(" ");
} else if (nodep->isRanged()) { } else if (nodep->isRanged()) {
puts(" ["); puts(" [");
@ -592,14 +593,14 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
} }
virtual void visit(AstNodeArrayDType* nodep) override { virtual void visit(AstNodeArrayDType* nodep) override {
iterate(nodep->subDTypep()); iterate(nodep->subDTypep());
iterateAndNextNull(nodep->rangep()); iterateAndNextConstNull(nodep->rangep());
} }
virtual void visit(AstNodeUOrStructDType* nodep) override { virtual void visit(AstNodeUOrStructDType* nodep) override {
puts(nodep->verilogKwd() + " "); puts(nodep->verilogKwd() + " ");
if (nodep->packed()) puts("packed "); if (nodep->packed()) puts("packed ");
puts("\n"); puts("\n");
puts("{"); puts("{");
iterateAndNextNull(nodep->membersp()); iterateAndNextConstNull(nodep->membersp());
puts("}"); puts("}");
} }
virtual void visit(AstMemberDType* nodep) override { virtual void visit(AstMemberDType* nodep) override {
@ -616,10 +617,10 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
putfs(nodep, nodep->prettyName()); putfs(nodep, nodep->prettyName());
} }
puts("("); puts("(");
iterateAndNextNull(nodep->pinsp()); iterateAndNextConstNull(nodep->pinsp());
puts(")"); puts(")");
} }
virtual void visit(AstArg* nodep) override { iterateAndNextNull(nodep->exprp()); } virtual void visit(AstArg* nodep) override { iterateAndNextConstNull(nodep->exprp()); }
virtual void visit(AstPrintTimeScale* nodep) override { virtual void visit(AstPrintTimeScale* nodep) override {
puts(nodep->verilogKwd()); puts(nodep->verilogKwd());
puts(";\n"); puts(";\n");
@ -654,8 +655,8 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
virtual void visit(AstConst* nodep) override { putfs(nodep, nodep->num().ascii(true, true)); } virtual void visit(AstConst* nodep) override { putfs(nodep, nodep->num().ascii(true, true)); }
// Just iterate // Just iterate
virtual void visit(AstTopScope* nodep) override { iterateChildren(nodep); } virtual void visit(AstTopScope* nodep) override { iterateChildrenConst(nodep); }
virtual void visit(AstScope* nodep) override { iterateChildren(nodep); } virtual void visit(AstScope* nodep) override { iterateChildrenConst(nodep); }
virtual void visit(AstVar* nodep) override { virtual void visit(AstVar* nodep) override {
if (nodep->isIO()) { if (nodep->isIO()) {
putfs(nodep, nodep->verilogKwd()); putfs(nodep, nodep->verilogKwd());
@ -686,7 +687,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
} }
virtual void visit(AstActive* nodep) override { virtual void visit(AstActive* nodep) override {
m_sensesp = nodep->sensesp(); m_sensesp = nodep->sensesp();
iterateAndNextNull(nodep->stmtsp()); iterateAndNextConstNull(nodep->stmtsp());
m_sensesp = nullptr; m_sensesp = nullptr;
} }
virtual void visit(AstParseRef* nodep) override { puts(nodep->prettyName()); } virtual void visit(AstParseRef* nodep) override { puts(nodep->prettyName()); }
@ -700,7 +701,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
// Default // Default
virtual void visit(AstNode* nodep) override { virtual void visit(AstNode* nodep) override {
puts(string("\n???? // ") + nodep->prettyTypeName() + "\n"); puts(string("\n???? // ") + nodep->prettyTypeName() + "\n");
iterateChildren(nodep); iterateChildrenConst(nodep);
// Not v3fatalSrc so we keep processing // Not v3fatalSrc so we keep processing
if (!m_suppressUnknown) { if (!m_suppressUnknown) {
nodep->v3error( nodep->v3error(
@ -754,10 +755,10 @@ class EmitVStreamVisitor final : public EmitVBaseVisitor {
virtual void putqs(AstNode*, const string& str) override { putbs(str); } virtual void putqs(AstNode*, const string& str) override { putbs(str); }
public: public:
EmitVStreamVisitor(AstNode* nodep, std::ostream& os) EmitVStreamVisitor(const AstNode* nodep, std::ostream& os)
: EmitVBaseVisitor{false, nullptr} : EmitVBaseVisitor{false, nullptr}
, m_os(os) { // Need () or GCC 4.8 false warning , m_os(os) { // Need () or GCC 4.8 false warning
iterate(nodep); iterate(const_cast<AstNode*>(nodep));
} }
virtual ~EmitVStreamVisitor() override = default; virtual ~EmitVStreamVisitor() override = default;
}; };
@ -828,12 +829,12 @@ class EmitVPrefixedVisitor final : public EmitVBaseVisitor {
} }
public: public:
EmitVPrefixedVisitor(AstNode* nodep, std::ostream& os, const string& prefix, int flWidth, EmitVPrefixedVisitor(const AstNode* nodep, std::ostream& os, const string& prefix, int flWidth,
AstSenTree* domainp, bool user3mark) AstSenTree* domainp, bool user3mark)
: EmitVBaseVisitor{false, domainp} : EmitVBaseVisitor{false, domainp}
, m_formatter{os, prefix, flWidth} { , m_formatter{os, prefix, flWidth} {
if (user3mark) VNUser3InUse::check(); if (user3mark) VNUser3InUse::check();
iterate(nodep); iterate(const_cast<AstNode*>(nodep));
} }
virtual ~EmitVPrefixedVisitor() override = default; virtual ~EmitVPrefixedVisitor() override = default;
}; };
@ -841,11 +842,11 @@ public:
//###################################################################### //######################################################################
// EmitV class functions // EmitV class functions
void V3EmitV::verilogForTree(AstNode* nodep, std::ostream& os) { void V3EmitV::verilogForTree(const AstNode* nodep, std::ostream& os) {
{ EmitVStreamVisitor{nodep, os}; } { EmitVStreamVisitor{nodep, os}; }
} }
void V3EmitV::verilogPrefixedTree(AstNode* nodep, std::ostream& os, const string& prefix, void V3EmitV::verilogPrefixedTree(const AstNode* nodep, std::ostream& os, const string& prefix,
int flWidth, AstSenTree* domainp, bool user3mark) { int flWidth, AstSenTree* domainp, bool user3mark) {
{ EmitVPrefixedVisitor{nodep, os, prefix, flWidth, domainp, user3mark}; } { EmitVPrefixedVisitor{nodep, os, prefix, flWidth, domainp, user3mark}; }
} }

View File

@ -27,8 +27,8 @@ class AstSenTree;
class V3EmitV final { class V3EmitV final {
public: public:
static void verilogForTree(AstNode* nodep, std::ostream& os = std::cout); static void verilogForTree(const AstNode* nodep, std::ostream& os = std::cout);
static void verilogPrefixedTree(AstNode* nodep, std::ostream& os, const string& prefix, static void verilogPrefixedTree(const AstNode* nodep, std::ostream& os, const string& prefix,
int flWidth, AstSenTree* domainp, bool user3mark); int flWidth, AstSenTree* domainp, bool user3mark);
static void emitvFiles(); static void emitvFiles();
static void debugEmitV(const string& filename); static void debugEmitV(const string& filename);

View File

@ -183,7 +183,7 @@ void V3Error::suppressThisWarning() {
string V3Error::warnMore() { return string(msgPrefix().size(), ' '); } string V3Error::warnMore() { return string(msgPrefix().size(), ' '); }
void V3Error::v3errorEnd(std::ostringstream& sstr, const string& locationStr) { void V3Error::v3errorEnd(std::ostringstream& sstr, const string& extra) {
#if defined(__COVERITY__) || defined(__cppcheck__) #if defined(__COVERITY__) || defined(__cppcheck__)
if (s_errorCode == V3ErrorCode::EC_FATAL) __coverity_panic__(x); if (s_errorCode == V3ErrorCode::EC_FATAL) __coverity_panic__(x);
#endif #endif
@ -209,10 +209,10 @@ void V3Error::v3errorEnd(std::ostringstream& sstr, const string& locationStr) {
// Suppress duplicate messages // Suppress duplicate messages
if (s_messages.find(msg) != s_messages.end()) return; if (s_messages.find(msg) != s_messages.end()) return;
s_messages.insert(msg); s_messages.insert(msg);
if (!locationStr.empty()) { if (!extra.empty()) {
const string locationMsg = warnMore() + locationStr + "\n"; const string extraMsg = warnMore() + extra + "\n";
const size_t pos = msg.find('\n'); const size_t pos = msg.find('\n');
msg.insert(pos + 1, locationMsg); msg.insert(pos + 1, extraMsg);
} }
// Output // Output
if ( if (

View File

@ -313,7 +313,7 @@ public:
static void vlAbortOrExit(); static void vlAbortOrExit();
static void vlAbort(); static void vlAbort();
// static, but often overridden in classes. // static, but often overridden in classes.
static void v3errorEnd(std::ostringstream& sstr, const string& locationStr = ""); static void v3errorEnd(std::ostringstream& sstr, const string& extra = "");
}; };
// Global versions, so that if the class doesn't define a operator, we get the functions anyways. // Global versions, so that if the class doesn't define a operator, we get the functions anyways.

View File

@ -340,15 +340,15 @@ void FileLine::modifyStateInherit(const FileLine* fromp) {
} }
} }
void FileLine::v3errorEnd(std::ostringstream& sstr, const string& locationStr) { void FileLine::v3errorEnd(std::ostringstream& sstr, const string& extra) {
std::ostringstream nsstr; std::ostringstream nsstr;
if (lastLineno()) nsstr << this; if (lastLineno()) nsstr << this;
nsstr << sstr.str(); nsstr << sstr.str();
nsstr << endl; nsstr << endl;
std::ostringstream lstr; std::ostringstream lstr;
if (!locationStr.empty()) { if (!extra.empty()) {
lstr << std::setw(ascii().length()) << " " lstr << std::setw(ascii().length()) << " "
<< ": " << locationStr; << ": " << extra;
} }
m_waive = V3Config::waive(this, V3Error::errorCode(), sstr.str()); m_waive = V3Config::waive(this, V3Error::errorCode(), sstr.str());
if (warnIsOff(V3Error::errorCode()) || m_waive) { if (warnIsOff(V3Error::errorCode()) || m_waive) {

View File

@ -245,7 +245,7 @@ public:
void modifyWarnOff(V3ErrorCode code, bool flag) { warnOff(code, flag); } void modifyWarnOff(V3ErrorCode code, bool flag) { warnOff(code, flag); }
// OPERATORS // OPERATORS
void v3errorEnd(std::ostringstream& str, const string& locationStr = ""); void v3errorEnd(std::ostringstream& str, const string& extra = "");
void v3errorEndFatal(std::ostringstream& str); void v3errorEndFatal(std::ostringstream& str);
/// When building an error, prefix for printing continuation lines /// When building an error, prefix for printing continuation lines
/// e.g. information referring to the same FileLine as before /// e.g. information referring to the same FileLine as before

View File

@ -299,9 +299,8 @@ private:
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() {}); m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() {});
} }
virtual void visit(AstNodeModule* nodep) override { virtual void visit(AstNodeModule* nodep) override {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, false, [=]() { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, false, [=]() { //
m_hash += nodep->origName(); m_hash += nodep->origName();
m_hash += nodep->hierName();
}); });
} }
virtual void visit(AstNodePreSel* nodep) override { virtual void visit(AstNodePreSel* nodep) override {

View File

@ -190,8 +190,7 @@ private:
// Iterate through all modules in bottom-up order. // Iterate through all modules in bottom-up order.
// Make a final inlining decision for each. // Make a final inlining decision for each.
for (auto it = m_allMods.rbegin(); it != m_allMods.rend(); ++it) { for (AstNodeModule* const modp : vlstd::reverse_view(m_allMods)) {
AstNodeModule* const modp = *it;
// If we're going to inline some modules into this one, // If we're going to inline some modules into this one,
// update user4 (statement count) to reflect that: // update user4 (statement count) to reflect that:
@ -647,7 +646,11 @@ private:
m_scope += "__DOT__" + nodep->name(); m_scope += "__DOT__" + nodep->name();
} }
if (AstModule* const modp = VN_CAST(nodep->modp(), Module)) { if (VN_IS(nodep->modp(), Iface)) {
nodep->addIntfRefp(new AstIntfRef{nodep->fileline(), m_scope});
}
{
AstNodeModule* const modp = nodep->modp();
// Pass Cell pointers down to the next module // Pass Cell pointers down to the next module
for (AstPin* pinp = nodep->pinsp(); pinp; pinp = VN_AS(pinp->nextp(), Pin)) { for (AstPin* pinp = nodep->pinsp(); pinp; pinp = VN_AS(pinp->nextp(), Pin)) {
AstVar* const varp = pinp->modVarp(); AstVar* const varp = pinp->modVarp();
@ -666,9 +669,6 @@ private:
} }
iterateChildren(modp); iterateChildren(modp);
} else if (VN_IS(nodep->modp(), Iface)) {
nodep->addIntfRefp(new AstIntfRef(nodep->fileline(), m_scope));
// No need to iterate on interface cells
} }
} }
virtual void visit(AstAssignVarScope* nodep) override { virtual void visit(AstAssignVarScope* nodep) override {

View File

@ -263,10 +263,10 @@ private:
UINFO(8, " DISABLE " << nodep << endl); UINFO(8, " DISABLE " << nodep << endl);
iterateChildren(nodep); iterateChildren(nodep);
AstNodeBlock* blockp = nullptr; AstNodeBlock* blockp = nullptr;
for (auto it = m_blockStack.rbegin(); it != m_blockStack.rend(); ++it) { for (AstNodeBlock* const stackp : vlstd::reverse_view(m_blockStack)) {
UINFO(9, " UNDERBLK " << *it << endl); UINFO(9, " UNDERBLK " << stackp << endl);
if ((*it)->name() == nodep->name()) { if (stackp->name() == nodep->name()) {
blockp = *it; blockp = stackp;
break; break;
} }
} }

View File

@ -275,7 +275,7 @@ private:
if (nodep->lifetime().isAutomatic()) { if (nodep->lifetime().isAutomatic()) {
nodep->addNextHere(new AstInitialAutomatic{newfl, assp}); nodep->addNextHere(new AstInitialAutomatic{newfl, assp});
} else { } else {
nodep->addNextHere(new AstInitial{newfl, assp}); nodep->addNextHere(new AstInitialStatic{newfl, assp});
} }
} // 4. Under blocks, it's an initial value to be under an assign } // 4. Under blocks, it's an initial value to be under an assign
else { else {

View File

@ -266,7 +266,7 @@ private:
// and we also need to keep track of it for comparisons later. // and we also need to keep track of it for comparisons later.
m_mgCondp = m_mgCondp->cloneTree(false); m_mgCondp = m_mgCondp->cloneTree(false);
// Create equivalent 'if' statement and insert it before the first node // Create equivalent 'if' statement and insert it before the first node
AstIf* const resultp = new AstIf(m_mgCondp->fileline(), m_mgCondp, nullptr, nullptr); AstIf* const resultp = new AstIf(m_mgCondp->fileline(), m_mgCondp);
m_mgFirstp->addHereThisAsNext(resultp); m_mgFirstp->addHereThisAsNext(resultp);
// Unzip the list and insert under branches // Unzip the list and insert under branches
AstNode* nextp = m_mgFirstp; AstNode* nextp = m_mgFirstp;

View File

@ -662,6 +662,9 @@ class OrderBuildVisitor final : public VNVisitor {
virtual void visit(AstInitialAutomatic* nodep) override { // virtual void visit(AstInitialAutomatic* nodep) override { //
iterateLogic(nodep); iterateLogic(nodep);
} }
virtual void visit(AstInitialStatic* nodep) override { //
iterateLogic(nodep);
}
virtual void visit(AstAlways* nodep) override { // virtual void visit(AstAlways* nodep) override { //
iterateLogic(nodep); iterateLogic(nodep);
} }

View File

@ -555,14 +555,12 @@ class ParamProcessor final {
cellp->v3error("Exceeded maximum --module-recursion-depth of " cellp->v3error("Exceeded maximum --module-recursion-depth of "
<< v3Global.opt.moduleRecursionDepth()); << v3Global.opt.moduleRecursionDepth());
} }
// Keep tree sorted by level. Append to end of sub-list at the same level. This is // Keep tree sorted by level. Note: Different parametrizations of the same recursive module
// important because due to the way recursive modules are handled, different // end up with the same level, which we will need to fix up at the end, as we do not know
// parametrizations of the same recursive module end up with the same level (which in // up front how recursive modules are expanded, and a later expansion might re-use an
// itself is a bit unfortunate). Nevertheless, as a later parametrization must not be above // earlier expansion (see t_recursive_module_bug_2).
// an earlier parametrization of a recursive module, it is sufficient to add to the end of
// the sub-list to keep the modules topologically sorted.
AstNodeModule* insertp = srcModp; AstNodeModule* insertp = srcModp;
while (VN_IS(insertp->nextp(), NodeModule) while (insertp->nextp()
&& VN_AS(insertp->nextp(), NodeModule)->level() <= newmodp->level()) { && VN_AS(insertp->nextp(), NodeModule)->level() <= newmodp->level()) {
insertp = VN_AS(insertp->nextp(), NodeModule); insertp = VN_AS(insertp->nextp(), NodeModule);
} }
@ -761,7 +759,7 @@ class ParamProcessor final {
} }
public: public:
void cellDeparam(AstCell* nodep, AstNodeModule* modp, const string& hierName) { void cellDeparam(AstCell* nodep, AstNodeModule* modp, const string& someInstanceName) {
m_modp = modp; m_modp = modp;
// Cell: Check for parameters in the instantiation. // Cell: Check for parameters in the instantiation.
// We always run this, even if no parameters, as need to look for interfaces, // We always run this, even if no parameters, as need to look for interfaces,
@ -772,7 +770,7 @@ public:
// Evaluate all module constants // Evaluate all module constants
V3Const::constifyParamsEdit(nodep); V3Const::constifyParamsEdit(nodep);
AstNodeModule* const srcModp = nodep->modp(); AstNodeModule* const srcModp = nodep->modp();
srcModp->hierName(hierName + "." + nodep->name()); srcModp->someInstanceName(someInstanceName + "." + nodep->name());
// Make sure constification worked // Make sure constification worked
// Must be a separate loop, as constant conversion may have changed some pointers. // Must be a separate loop, as constant conversion may have changed some pointers.
@ -843,79 +841,99 @@ public:
// Process parameter visitor // Process parameter visitor
class ParamVisitor final : public VNVisitor { class ParamVisitor final : public VNVisitor {
// NODE STATE
// AstNodeModule::user1 -> bool: already fixed level
// STATE // STATE
ParamProcessor m_processor; // De-parameterize a cell, build modules ParamProcessor m_processor; // De-parameterize a cell, build modules
UnrollStateful m_unroller; // Loop unroller UnrollStateful m_unroller; // Loop unroller
AstNodeModule* m_modp = nullptr; // Current module being processed bool m_iterateModule = false; // Iterating module body
string m_generateHierName; // Generate portion of hierarchy name string m_generateHierName; // Generate portion of hierarchy name
string m_unlinkedTxt; // Text for AstUnlinkedRef string m_unlinkedTxt; // Text for AstUnlinkedRef
std::deque<AstCell*> m_cellps; // Cells left to process (in this module) std::deque<AstCell*> m_cellps; // Cells left to process (in current module)
std::multimap<int, AstNodeModule*> m_todoModps; // Modules left to process // Map from AstNodeModule to set of all AstNodeModules that instantiates it.
std::unordered_map<AstNodeModule*, std::unordered_set<AstNodeModule*>> m_parentps;
// METHODS // METHODS
VL_DEBUG_FUNC; // Declare debug() VL_DEBUG_FUNC; // Declare debug()
void visitCellDeparam(AstCell* nodep, const string& hierName) { void visitCells(AstNodeModule* nodep) {
// Cell: Check for parameters in the instantiation. UASSERT_OBJ(!m_iterateModule, nodep, "Should not nest");
iterateChildren(nodep); std::multimap<int, AstNodeModule*> workQueue;
UASSERT_OBJ(nodep->modp(), nodep, "Not linked?"); workQueue.emplace(nodep->level(), nodep);
m_processor.cellDeparam(nodep, m_modp, hierName); m_generateHierName = "";
// Remember to process the child module at the end of the module m_iterateModule = true;
m_todoModps.emplace(nodep->modp()->level(), nodep->modp());
} // Visit all cells under module, recursively
void visitModules() { do {
// Loop on all modules left to process const auto itm = workQueue.cbegin();
// Hitting a cell adds to the appropriate level of this level-sorted list, AstNodeModule* const modp = itm->second;
// so since cells originally exist top->bottom we process in top->bottom order too. workQueue.erase(itm);
while (!m_todoModps.empty()) {
const auto itm = m_todoModps.cbegin(); // Process once; note user5 will be cleared on specialization, so we will do the
AstNodeModule* const nodep = itm->second; // specialized module if needed
m_todoModps.erase(itm); if (modp->user5SetOnce()) continue;
if (!nodep->user5SetOnce()) { // Process once; note clone() must clear so we do it
// again // TODO: this really should be an assert, but classes and hier_blocks are special...
m_modp = nodep; if (modp->someInstanceName().empty()) modp->someInstanceName(modp->origName());
UINFO(4, " MOD " << nodep << endl);
if (m_modp->hierName().empty()) m_modp->hierName(m_modp->origName()); // Iterate the body
iterateChildren(nodep); iterateChildren(modp);
// Note above iterate may add to m_todoModps
// // Process interface cells, then non-interface cells, which may reference an interface
// Process interface cells, then non-interface which may ref an interface cell // cell.
for (int nonIf = 0; nonIf < 2; ++nonIf) { for (bool doInterface : {true, false}) {
for (AstCell* const cellp : m_cellps) { for (AstCell* const cellp : m_cellps) {
if ((nonIf == 0 && VN_IS(cellp->modp(), Iface)) if (doInterface != VN_IS(cellp->modp(), Iface)) continue;
|| (nonIf == 1 && !VN_IS(cellp->modp(), Iface))) {
string fullName(m_modp->hierName()); // Visit parameters in the instantiation.
if (const string* const genHierNamep = (string*)cellp->user5p()) { iterateChildren(cellp);
fullName += *genHierNamep;
cellp->user5p(nullptr); // Update path
VL_DO_DANGLING(delete genHierNamep, genHierNamep); string someInstanceName(modp->someInstanceName());
} if (const string* const genHierNamep = cellp->user5u().to<string*>()) {
VL_DO_DANGLING(visitCellDeparam(cellp, fullName), cellp); someInstanceName += *genHierNamep;
} cellp->user5p(nullptr);
VL_DO_DANGLING(delete genHierNamep, genHierNamep);
} }
// Apply parameter specialization
m_processor.cellDeparam(cellp, modp, someInstanceName);
// Add the (now potentially specialized) child module to the work queue
workQueue.emplace(cellp->modp()->level(), cellp->modp());
// Add to the hierarchy registry
m_parentps[cellp->modp()].insert(modp);
} }
m_cellps.clear();
m_modp = nullptr;
UINFO(4, " MOD-done\n");
} }
m_cellps.clear();
} while (!workQueue.empty());
m_iterateModule = false;
}
// Fix up level of module, based on who instantiates it
void fixLevel(AstNodeModule* modp) {
if (modp->user1SetOnce()) return; // Already fixed
if (m_parentps[modp].empty()) return; // Leave top levels alone
int maxParentLevel = 0;
for (AstNodeModule* parentp : m_parentps[modp]) {
fixLevel(parentp); // Ensure parent level is correct
maxParentLevel = std::max(maxParentLevel, parentp->level());
} }
if (modp->level() <= maxParentLevel) modp->level(maxParentLevel + 1);
} }
// VISITORS // VISITORS
virtual void visit(AstNodeModule* nodep) override { virtual void visit(AstNodeModule* nodep) override {
if (nodep->dead()) { if (nodep->recursiveClone()) nodep->dead(true); // Fake, made for recursive elimination
UINFO(4, " MOD-dead. " << nodep << endl); // Marked by LinkDot if (nodep->dead()) return; // Marked by LinkDot (and above)
return;
} else if (nodep->recursiveClone()) { // Warn on unsupported parametrised class
// Fake, made for recursive elimination if (VN_IS(nodep, Class)) {
UINFO(4, " MOD-recursive-dead. " << nodep << endl);
nodep->dead(true); // So Dead checks won't count references to it
return;
}
//
if (!nodep->dead() && VN_IS(nodep, Class)) {
for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp = stmtp->nextp()) { for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
if (const AstVar* const varp = VN_CAST(stmtp, Var)) { if (const AstVar* const varp = VN_CAST(stmtp, Var)) {
if (varp->isParam()) { if (varp->isParam()) {
@ -924,24 +942,21 @@ class ParamVisitor final : public VNVisitor {
} }
} }
} }
//
if (m_modp) { if (m_iterateModule) { // Iterating body
UINFO(4, " MOD-under-MOD. " << nodep << endl); UINFO(4, " MOD-under-MOD. " << nodep << endl);
iterateChildren(nodep); iterateChildren(nodep);
} else if (nodep->level() <= 2 // Haven't added top yet, so level 2 is the top return;
|| VN_IS(nodep, Class) // Nor moved classes }
|| VN_IS(nodep, Package)) { // Likewise haven't done wrapTopPackages yet
// Add request to END of modules left to process // Start traversal at root-like things
m_todoModps.emplace(nodep->level(), nodep); if (nodep->level() <= 2 // Haven't added top yet, so level 2 is the top
m_generateHierName = ""; || VN_IS(nodep, Class) // Nor moved classes
visitModules(); || VN_IS(nodep, Package)) { // Likewise haven't done wrapTopPackages yet
} else if (nodep->user5()) { visitCells(nodep);
UINFO(4, " MOD-done " << nodep << endl); // Already did it
} else {
// Should have been done by now, if not dead
UINFO(4, " MOD-dead? " << nodep << endl);
} }
} }
virtual void visit(AstCell* nodep) override { virtual void visit(AstCell* nodep) override {
// Must do ifaces first, so push to list and do in proper order // Must do ifaces first, so push to list and do in proper order
string* const genHierNamep = new string(m_generateHierName); string* const genHierNamep = new string(m_generateHierName);
@ -1195,10 +1210,38 @@ class ParamVisitor final : public VNVisitor {
public: public:
// CONSTRUCTORS // CONSTRUCTORS
explicit ParamVisitor(AstNetlist* nodep) explicit ParamVisitor(AstNetlist* netlistp)
: m_processor{nodep} { : m_processor{netlistp} {
// Relies on modules already being in top-down-order // Relies on modules already being in top-down-order
iterate(nodep); iterate(netlistp);
// Re-sort module list to be in topological order and fix-up incorrect levels. We need to
// do this globally at the end due to the presence of recursive modules, which might be
// expanded in orders that reuse earlier specializations later at a lower level.
{
// Gather modules
std::vector<AstNodeModule*> modps;
for (AstNodeModule *modp = netlistp->modulesp(), *nextp; modp; modp = nextp) {
nextp = VN_AS(modp->nextp(), NodeModule);
modp->unlinkFrBack();
modps.push_back(modp);
}
// Fix-up levels
{
const VNUser1InUse user1InUse;
for (AstNodeModule* const modp : modps) fixLevel(modp);
}
// Sort by level
std::stable_sort(modps.begin(), modps.end(),
[](const AstNodeModule* ap, const AstNodeModule* bp) {
return ap->level() < bp->level();
});
// Re-insert modules
for (AstNodeModule* const modp : modps) netlistp->addModulep(modp);
}
} }
virtual ~ParamVisitor() override = default; virtual ~ParamVisitor() override = default;
VL_UNCOPYABLE(ParamVisitor); VL_UNCOPYABLE(ParamVisitor);

View File

@ -128,8 +128,7 @@ public:
} }
void showUpward() { // LCOV_EXCL_START void showUpward() { // LCOV_EXCL_START
UINFO(1, "ParseSym Stack:\n"); UINFO(1, "ParseSym Stack:\n");
for (auto it = m_sympStack.rbegin(); it != m_sympStack.rend(); ++it) { for (VSymEnt* const symp : vlstd::reverse_view(m_sympStack)) {
VSymEnt* const symp = *it;
UINFO(1, " " << symp->nodep() << endl); UINFO(1, " " << symp->nodep() << endl);
} }
UINFO(1, "ParseSym Current: " << symCurrentp()->nodep() << endl); UINFO(1, "ParseSym Current: " << symCurrentp()->nodep() << endl);

View File

@ -526,9 +526,9 @@ public:
} }
void checkRelativesCp(GraphWay way) const { void checkRelativesCp(GraphWay way) const {
const EdgeSet& edges = m_edges[way]; const EdgeSet& edges = m_edges[way];
for (EdgeSet::const_reverse_iterator it = edges.rbegin(); it != edges.rend(); ++it) { for (const auto& edge : vlstd::reverse_view(edges)) {
const LogicMTask* const relativep = (*it).key(); const LogicMTask* const relativep = edge.key();
const uint32_t cachedCp = (*it).value(); const uint32_t cachedCp = edge.value();
partCheckCachedScoreVsActual(cachedCp, relativep->critPathCost(way.invert()) partCheckCachedScoreVsActual(cachedCp, relativep->critPathCost(way.invert())
+ relativep->stepCost()); + relativep->stepCost());
} }
@ -555,12 +555,12 @@ public:
// wayEdgeEndp(way, withoutp). This should take 2 iterations max. // wayEdgeEndp(way, withoutp). This should take 2 iterations max.
const EdgeSet& edges = m_edges[way.invert()]; const EdgeSet& edges = m_edges[way.invert()];
uint32_t result = 0; uint32_t result = 0;
for (EdgeSet::const_reverse_iterator it = edges.rbegin(); it != edges.rend(); ++it) { for (const auto& edge : vlstd::reverse_view(edges)) {
if ((*it).key() != withoutp->furtherp(way.invert())) { if (edge.key() != withoutp->furtherp(way.invert())) {
// Use the cached cost. It could be a small overestimate // Use the cached cost. It could be a small overestimate
// due to stepping. This is consistent with critPathCost() // due to stepping. This is consistent with critPathCost()
// which also returns the cached cost. // which also returns the cached cost.
result = (*it).value(); result = edge.value();
break; break;
} }
} }

View File

@ -182,11 +182,11 @@ public:
} }
m_whyNotOptimizable = why; m_whyNotOptimizable = why;
std::ostringstream stack; std::ostringstream stack;
for (auto it = m_callStack.rbegin(); it != m_callStack.rend(); ++it) { for (auto& callstack : vlstd::reverse_view(m_callStack)) {
AstFuncRef* const funcp = (*it)->m_funcp; AstFuncRef* const funcp = callstack->m_funcp;
stack << "\n " << funcp->fileline() << "... Called from " stack << "\n " << funcp->fileline() << "... Called from "
<< funcp->prettyName() << "() with parameters:"; << funcp->prettyName() << "() with parameters:";
V3TaskConnects* tconnects = (*it)->m_tconnects; V3TaskConnects* tconnects = callstack->m_tconnects;
for (V3TaskConnects::iterator conIt = tconnects->begin(); for (V3TaskConnects::iterator conIt = tconnects->begin();
conIt != tconnects->end(); ++conIt) { conIt != tconnects->end(); ++conIt) {
AstVar* const portp = conIt->first; AstVar* const portp = conIt->first;

View File

@ -367,7 +367,7 @@ private:
AstNode* const condp AstNode* const condp
= new AstAnd(fl, select(fl, outputAssignedTableVscp, indexVscp), = new AstAnd(fl, select(fl, outputAssignedTableVscp, indexVscp),
new AstConst(fl, outputChgMask)); new AstConst(fl, outputChgMask));
outsetp = new AstIf(fl, condp, outsetp, nullptr); outsetp = new AstIf(fl, condp, outsetp);
} }
stmtsp->addNext(outsetp); stmtsp->addNext(outsetp);

View File

@ -656,7 +656,7 @@ private:
condp = condp ? new AstOr(flp, condp, selp) : selp; condp = condp ? new AstOr(flp, condp, selp) : selp;
} }
} }
ifp = new AstIf(flp, condp, nullptr, nullptr); ifp = new AstIf(flp, condp);
if (!always) ifp->branchPred(VBranchPred::BP_UNLIKELY); if (!always) ifp->branchPred(VBranchPred::BP_UNLIKELY);
subFuncp->addStmtsp(ifp); subFuncp->addStmtsp(ifp);
subStmts += ifp->nodeCount(); subStmts += ifp->nodeCount();

View File

@ -190,6 +190,27 @@ private:
std::string getScopeChar(VltTraceScope sct) { return std::string(1, (char)(0x80 + sct)); } std::string getScopeChar(VltTraceScope sct) { return std::string(1, (char)(0x80 + sct)); }
std::string addAboveInterface(const std::string& scopeName) {
std::string out;
// Hierarchical interfaces didn't know if interface vs module
// above them. so convert a scope string to have the interface character.
// Uses list of scopes to see what's an interface above.
size_t begin = 0;
while (true) {
const size_t end = scopeName.find(' ', begin);
if (end == string::npos) break;
const string& extra = scopeName.substr(begin, end - begin);
out += extra;
if (m_scopeSubFuncps.count(out + getScopeChar(VLT_TRACE_SCOPE_INTERFACE) + " ")) {
out += getScopeChar(VLT_TRACE_SCOPE_INTERFACE) + " ";
} else {
out += " ";
}
begin = end + 1;
}
return out;
}
void addTraceDecl(const VNumRange& arrayRange, void addTraceDecl(const VNumRange& arrayRange,
int widthOverride) { // If !=0, is packed struct/array where basicp size int widthOverride) { // If !=0, is packed struct/array where basicp size
// misreflects one element // misreflects one element
@ -199,8 +220,10 @@ private:
} else if (const AstBasicDType* const bdtypep = m_traValuep->dtypep()->basicp()) { } else if (const AstBasicDType* const bdtypep = m_traValuep->dtypep()->basicp()) {
bitRange = bdtypep->nrange(); bitRange = bdtypep->nrange();
} }
addToSubFunc(new AstTraceDecl{m_traVscp->fileline(), m_traName, m_traVscp->varp(), auto* const newp
m_traValuep->cloneTree(false), bitRange, arrayRange}); = new AstTraceDecl{m_traVscp->fileline(), m_traName, m_traVscp->varp(),
m_traValuep->cloneTree(false), bitRange, arrayRange};
addToSubFunc(newp);
} }
void addIgnore(const char* why) { void addIgnore(const char* why) {
@ -217,17 +240,14 @@ private:
UASSERT_OBJ(!m_traVscp, nodep, "Should not nest"); UASSERT_OBJ(!m_traVscp, nodep, "Should not nest");
UASSERT_OBJ(m_traName.empty(), nodep, "Should not nest"); UASSERT_OBJ(m_traName.empty(), nodep, "Should not nest");
FileLine* const flp = nodep->fileline(); VL_RESTORER(m_currScopep);
m_currScopep = nodep; m_currScopep = nodep;
// Gather all signals under this AstScope // Gather all signals under this AstScope
iterateChildrenConst(nodep); iterateChildrenConst(nodep);
// If nothing to trace in this scope, then job done // If nothing to trace in this scope, then job done
if (m_signals.empty()) { if (m_signals.empty()) return;
m_currScopep = nullptr;
return;
}
// Sort signals, first by enclosing instance, then by source location, then by name // Sort signals, first by enclosing instance, then by source location, then by name
std::stable_sort(m_signals.begin(), m_signals.end(), [](const Signal& a, const Signal& b) { std::stable_sort(m_signals.begin(), m_signals.end(), [](const Signal& a, const Signal& b) {
@ -239,6 +259,7 @@ private:
}); });
// Build trace initialization functions for this AstScope // Build trace initialization functions for this AstScope
FileLine* const flp = nodep->fileline();
PathAdjustor pathAdjustor{flp, [&](AstNodeStmt* stmtp) { addToSubFunc(stmtp); }}; PathAdjustor pathAdjustor{flp, [&](AstNodeStmt* stmtp) { addToSubFunc(stmtp); }};
for (const Signal& signal : m_signals) { for (const Signal& signal : m_signals) {
// Adjust name prefix based on path in hierarchy // Adjust name prefix based on path in hierarchy
@ -278,6 +299,7 @@ private:
scopeName = scopeName.substr(0, lastDot + 1); scopeName = scopeName.substr(0, lastDot + 1);
const size_t scopeLen = scopeName.length(); const size_t scopeLen = scopeName.length();
UASSERT_OBJ(cellp->intfRefp(), cellp, "Interface without tracing reference");
for (AstIntfRef *irp = cellp->intfRefp(), *nextIrp; irp; irp = nextIrp) { for (AstIntfRef *irp = cellp->intfRefp(), *nextIrp; irp; irp = nextIrp) {
nextIrp = VN_AS(irp->nextp(), IntfRef); nextIrp = VN_AS(irp->nextp(), IntfRef);
@ -288,6 +310,9 @@ private:
string scopeName = AstNode::vcdName(irp->name()); string scopeName = AstNode::vcdName(irp->name());
if (scopeName.substr(0, 4) == "TOP ") scopeName.erase(0, 4); if (scopeName.substr(0, 4) == "TOP ") scopeName.erase(0, 4);
// Note this insert doesn't know what above is interfaces.
// Perhaps all scopes should be changed to include the VLT_TRACE_SCOPE characters.
// Instead we fix up when printing m_scopeSubFuncps
scopeName += getScopeChar(VLT_TRACE_SCOPE_INTERFACE) + ' '; scopeName += getScopeChar(VLT_TRACE_SCOPE_INTERFACE) + ' ';
m_scopeSubFuncps.emplace(scopeName, m_subFuncps); m_scopeSubFuncps.emplace(scopeName, m_subFuncps);
@ -300,8 +325,6 @@ private:
if (VString::startsWith(scopeName, "TOP ")) scopeName.erase(0, 4); if (VString::startsWith(scopeName, "TOP ")) scopeName.erase(0, 4);
m_scopeSubFuncps.emplace(scopeName, std::move(m_subFuncps)); m_scopeSubFuncps.emplace(scopeName, std::move(m_subFuncps));
} }
m_currScopep = nullptr;
} }
virtual void visit(AstVarScope* nodep) override { virtual void visit(AstVarScope* nodep) override {
UASSERT_OBJ(m_currScopep, nodep, "AstVarScope not under AstScope"); UASSERT_OBJ(m_currScopep, nodep, "AstVarScope not under AstScope");
@ -454,9 +477,10 @@ public:
// Build top level trace initialization functions // Build top level trace initialization functions
PathAdjustor pathAdjustor{flp, [&](AstNodeStmt* stmtp) { addToTopFunc(stmtp); }}; PathAdjustor pathAdjustor{flp, [&](AstNodeStmt* stmtp) { addToTopFunc(stmtp); }};
for (const auto& item : m_scopeSubFuncps) { for (const auto& item : m_scopeSubFuncps) {
const std::string scopeName = item.first;
const std::string scopeNameInterfaced = addAboveInterface(scopeName);
// Adjust name prefix based on path in hierarchy // Adjust name prefix based on path in hierarchy
pathAdjustor.adjust(item.first); pathAdjustor.adjust(scopeNameInterfaced);
// Call all sub functions for this path // Call all sub functions for this path
for (AstCFunc* const subFuncp : item.second) { for (AstCFunc* const subFuncp : item.second) {
AstCCall* const callp = new AstCCall{flp, subFuncp}; AstCCall* const callp = new AstCCall{flp, subFuncp};

View File

@ -127,8 +127,7 @@ private:
(needDly ? static_cast<AstNode*>( (needDly ? static_cast<AstNode*>(
new AstAssignDly(fl, prep, new AstVarRef(fl, varp, VAccess::READ))) new AstAssignDly(fl, prep, new AstVarRef(fl, varp, VAccess::READ)))
: static_cast<AstNode*>( : static_cast<AstNode*>(
new AstAssign(fl, prep, new AstVarRef(fl, varp, VAccess::READ)))), new AstAssign(fl, prep, new AstVarRef(fl, varp, VAccess::READ)))));
nullptr);
newp->branchPred(VBranchPred::BP_LIKELY); newp->branchPred(VBranchPred::BP_LIKELY);
newp->isBoundsCheck(true); newp->isBoundsCheck(true);
if (debug() >= 9) newp->dumpTree(cout, " _new: "); if (debug() >= 9) newp->dumpTree(cout, " _new: ");

View File

@ -1366,7 +1366,7 @@ private:
switch (nodep->attrType()) { switch (nodep->attrType()) {
case VAttrType::DIM_SIZE: { case VAttrType::DIM_SIZE: {
AstNode* const newp = new AstCMethodHard( AstNode* const newp = new AstCMethodHard(
nodep->fileline(), nodep->fromp()->unlinkFrBack(), "size", nullptr); nodep->fileline(), nodep->fromp()->unlinkFrBack(), "size");
newp->dtypeSetSigned32(); newp->dtypeSetSigned32();
newp->didWidth(true); newp->didWidth(true);
newp->protect(false); newp->protect(false);
@ -1384,7 +1384,7 @@ private:
case VAttrType::DIM_RIGHT: case VAttrType::DIM_RIGHT:
case VAttrType::DIM_HIGH: { case VAttrType::DIM_HIGH: {
AstNode* const sizep = new AstCMethodHard( AstNode* const sizep = new AstCMethodHard(
nodep->fileline(), nodep->fromp()->unlinkFrBack(), "size", nullptr); nodep->fileline(), nodep->fromp()->unlinkFrBack(), "size");
sizep->dtypeSetSigned32(); sizep->dtypeSetSigned32();
sizep->didWidth(true); sizep->didWidth(true);
sizep->protect(false); sizep->protect(false);
@ -2041,7 +2041,8 @@ private:
if (nodep->access().isWriteOrRW() && nodep->varp()->direction() == VDirection::CONSTREF) { if (nodep->access().isWriteOrRW() && nodep->varp()->direction() == VDirection::CONSTREF) {
nodep->v3error("Assigning to const ref variable: " << nodep->prettyNameQ()); nodep->v3error("Assigning to const ref variable: " << nodep->prettyNameQ());
} else if (nodep->access().isWriteOrRW() && nodep->varp()->isConst() && !m_paramsOnly } else if (nodep->access().isWriteOrRW() && nodep->varp()->isConst() && !m_paramsOnly
&& (!m_ftaskp || !m_ftaskp->isConstructor()) && !VN_IS(m_procedurep, Initial)) { && (!m_ftaskp || !m_ftaskp->isConstructor())
&& !VN_IS(m_procedurep, InitialStatic)) {
// Too loose, but need to allow our generated first assignment // Too loose, but need to allow our generated first assignment
// Move this to a property of the AstInitial block // Move this to a property of the AstInitial block
nodep->v3error("Assigning to const variable: " << nodep->prettyNameQ()); nodep->v3error("Assigning to const variable: " << nodep->prettyNameQ());
@ -2676,8 +2677,8 @@ private:
if (nodep->name() == "num" // function int num() if (nodep->name() == "num" // function int num()
|| nodep->name() == "size") { || nodep->name() == "size") {
methodOkArguments(nodep, 0, 0); methodOkArguments(nodep, 0, 0);
newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), "size", newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(),
nullptr); // So don't need num() "size"); // So don't need num()
newp->dtypeSetSigned32(); newp->dtypeSetSigned32();
} else if (nodep->name() == "first" // function int first(ref index) } else if (nodep->name() == "first" // function int first(ref index)
|| nodep->name() == "last" // || nodep->name() == "last" //
@ -2703,7 +2704,7 @@ private:
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::WRITE); methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::WRITE);
if (!nodep->pinsp()) { if (!nodep->pinsp()) {
newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(),
"clear", nullptr); "clear");
newp->makeStatement(); newp->makeStatement();
} else { } else {
AstNode* const index_exprp = methodCallAssocIndexExpr(nodep, adtypep); AstNode* const index_exprp = methodCallAssocIndexExpr(nodep, adtypep);
@ -2731,7 +2732,7 @@ private:
methodOkArguments(nodep, 0, 0); methodOkArguments(nodep, 0, 0);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ); methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(),
nodep->name(), nullptr); nodep->name());
if (nodep->name() == "unique_index") { if (nodep->name() == "unique_index") {
newp->dtypep(queueDTypeIndexedBy(adtypep->keyDTypep())); newp->dtypep(queueDTypeIndexedBy(adtypep->keyDTypep()));
} else { } else {
@ -2794,19 +2795,16 @@ private:
if (nodep->name() == "at") { // Created internally for [] if (nodep->name() == "at") { // Created internally for []
methodOkArguments(nodep, 1, 1); methodOkArguments(nodep, 1, 1);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::WRITE); methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::WRITE);
newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), "at", newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), "at");
nullptr);
newp->dtypeFrom(adtypep->subDTypep()); newp->dtypeFrom(adtypep->subDTypep());
} else if (nodep->name() == "size") { } else if (nodep->name() == "size") {
methodOkArguments(nodep, 0, 0); methodOkArguments(nodep, 0, 0);
newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), "size", newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), "size");
nullptr);
newp->dtypeSetSigned32(); newp->dtypeSetSigned32();
} else if (nodep->name() == "delete") { // function void delete() } else if (nodep->name() == "delete") { // function void delete()
methodOkArguments(nodep, 0, 0); methodOkArguments(nodep, 0, 0);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::WRITE); methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::WRITE);
newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), "clear", newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), "clear");
nullptr);
newp->makeStatement(); newp->makeStatement();
} else if (nodep->name() == "and" || nodep->name() == "or" || nodep->name() == "xor" } else if (nodep->name() == "and" || nodep->name() == "or" || nodep->name() == "xor"
|| nodep->name() == "sum" || nodep->name() == "product") { || nodep->name() == "sum" || nodep->name() == "product") {
@ -2837,7 +2835,7 @@ private:
methodOkArguments(nodep, 0, 0); methodOkArguments(nodep, 0, 0);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ); methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(),
nodep->name(), nullptr); nodep->name());
if (nodep->name() == "unique_index") { if (nodep->name() == "unique_index") {
newp->dtypep(newp->findQueueIndexDType()); newp->dtypep(newp->findQueueIndexDType());
} else { } else {
@ -2883,27 +2881,25 @@ private:
if (nodep->name() == "at") { // Created internally for [] if (nodep->name() == "at") { // Created internally for []
methodOkArguments(nodep, 1, 1); methodOkArguments(nodep, 1, 1);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::WRITE); methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::WRITE);
newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), "at", newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), "at");
nullptr);
newp->dtypeFrom(adtypep->subDTypep()); newp->dtypeFrom(adtypep->subDTypep());
} else if (nodep->name() == "num" // function int num() } else if (nodep->name() == "num" // function int num()
|| nodep->name() == "size") { || nodep->name() == "size") {
methodOkArguments(nodep, 0, 0); methodOkArguments(nodep, 0, 0);
newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), "size", newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), "size");
nullptr);
newp->dtypeSetSigned32(); newp->dtypeSetSigned32();
} else if (nodep->name() == "delete") { // function void delete([input integer index]) } else if (nodep->name() == "delete") { // function void delete([input integer index])
methodOkArguments(nodep, 0, 1); methodOkArguments(nodep, 0, 1);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::WRITE); methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::WRITE);
if (!nodep->pinsp()) { if (!nodep->pinsp()) {
newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(),
"clear", nullptr); "clear");
newp->makeStatement(); newp->makeStatement();
} else { } else {
AstNode* const index_exprp = methodCallQueueIndexExpr(nodep); AstNode* const index_exprp = methodCallQueueIndexExpr(nodep);
if (index_exprp->isZero()) { // delete(0) is a pop_front if (index_exprp->isZero()) { // delete(0) is a pop_front
newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(),
"pop_front", nullptr); "pop_front");
newp->dtypeFrom(adtypep->subDTypep()); newp->dtypeFrom(adtypep->subDTypep());
newp->makeStatement(); newp->makeStatement();
} else { } else {
@ -2933,7 +2929,7 @@ private:
// Returns element, so method both consumes (reads) and modifies the queue // Returns element, so method both consumes (reads) and modifies the queue
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READWRITE); methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READWRITE);
newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(),
nodep->name(), nullptr); nodep->name());
newp->dtypeFrom(adtypep->subDTypep()); newp->dtypeFrom(adtypep->subDTypep());
if (!nodep->firstAbovep()) newp->makeStatement(); if (!nodep->firstAbovep()) newp->makeStatement();
} else if (nodep->name() == "push_back" || nodep->name() == "push_front") { } else if (nodep->name() == "push_back" || nodep->name() == "push_front") {
@ -2972,7 +2968,7 @@ private:
methodOkArguments(nodep, 0, 0); methodOkArguments(nodep, 0, 0);
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ); methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(),
nodep->name(), nullptr); nodep->name());
if (nodep->name() == "unique_index") { if (nodep->name() == "unique_index") {
newp->dtypep(newp->findQueueIndexDType()); newp->dtypep(newp->findQueueIndexDType());
} else { } else {
@ -3850,8 +3846,7 @@ private:
} else if (VN_IS(fromDtp, DynArrayDType) || VN_IS(fromDtp, QueueDType)) { } else if (VN_IS(fromDtp, DynArrayDType) || VN_IS(fromDtp, QueueDType)) {
if (varp) { if (varp) {
auto* const leftp = new AstConst{fl, AstConst::Signed32{}, 0}; auto* const leftp = new AstConst{fl, AstConst::Signed32{}, 0};
auto* const sizep auto* const sizep = new AstCMethodHard{fl, fromp->cloneTree(false), "size"};
= new AstCMethodHard{fl, fromp->cloneTree(false), "size", nullptr};
sizep->dtypeSetSigned32(); sizep->dtypeSetSigned32();
sizep->didWidth(true); sizep->didWidth(true);
sizep->protect(false); sizep->protect(false);

View File

@ -3111,7 +3111,7 @@ statement_item<nodep>: // IEEE: statement_item
// //
// // IEEE: conditional_statement // // IEEE: conditional_statement
| unique_priorityE yIF '(' expr ')' stmtBlock %prec prLOWER_THAN_ELSE | unique_priorityE yIF '(' expr ')' stmtBlock %prec prLOWER_THAN_ELSE
{ AstIf* const newp = new AstIf{$2, $4, $6, nullptr}; { AstIf* const newp = new AstIf{$2, $4, $6};
$$ = newp; $$ = newp;
if ($1 == uniq_UNIQUE) newp->uniquePragma(true); if ($1 == uniq_UNIQUE) newp->uniquePragma(true);
if ($1 == uniq_UNIQUE0) newp->unique0Pragma(true); if ($1 == uniq_UNIQUE0) newp->unique0Pragma(true);
@ -3180,7 +3180,7 @@ statement_item<nodep>: // IEEE: statement_item
$$ = $2->cloneTree(true); $$ = $2->cloneTree(true);
$$->addNext(new AstWhile($1,$5,$2)); $$->addNext(new AstWhile($1,$5,$2));
} }
else $$ = new AstWhile($1,$5,nullptr); } else $$ = new AstWhile($1,$5); }
// // IEEE says array_identifier here, but dotted accepted in VMM and 1800-2009 // // IEEE says array_identifier here, but dotted accepted in VMM and 1800-2009
| yFOREACH '(' idClassSelForeach ')' stmtBlock { $$ = new AstForeach($1, $3, $5); } | yFOREACH '(' idClassSelForeach ')' stmtBlock { $$ = new AstForeach($1, $3, $5); }
// //

View File

@ -8,19 +8,28 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
# Version 2.0. # Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 # SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(vlt => 1); scenarios(simulator => 1);
compile(); compile();
if ($Self->{vlt_all}) { if ($Self->{vlt_all}) {
# The word 'this' (but only the whole word 'this' should have been replaced # The word 'this' (but only the whole word 'this' should have been replaced
# in the contents. # in the contents.
my $file = glob_one("$Self->{obj_dir}/$Self->{VM_PREFIX}___024root__DepSet_*__0.cpp"); my $has_this = 0;
my $text = file_contents($file); my $has_xthis = 0;
error("$file has 'this->clk'") if ($text =~ m/\bthis->clk\b/); my $has_thisx = 0;
error("$file does not have 'xthis'") if ($text !~ m/\bxthis\b/); my $has_xthisx = 0;
error("$file does not have 'thisx'") if ($text !~ m/\bthisx\b/); for my $file (glob_all("$Self->{obj_dir}/$Self->{VM_PREFIX}___024root__DepSet_*__0.cpp")) {
error("$file does not have 'xthisx'") if ($text !~ m/\bxthisx\b/); my $text = file_contents($file);
$has_this = 1 if ($text =~ m/\bthis->clk\b/);
$has_xthis = 1 if ($text =~ m/\bxthis\b/);
$has_thisx = 1 if ($text =~ m/\bthisx\b/);
$has_xthisx = 1 if ($text =~ m/\bxthisx\b/);
}
error("Some file has 'this->clk'") if $has_this;
error("No file has 'xthis'") if !$has_xthis;
error("No file has 'thisx'") if !$has_thisx;
error("No file has 'xthisx'") if !$has_xthisx;
} }
ok(1); ok(1);

View File

@ -22,9 +22,9 @@ module t(/*AUTOARG*/
event ev [3:0]; event ev [3:0];
`endif `endif
int cyc; int cyc = 0;
int last_event; int last_event = 0;
always @(e1) begin always @(e1) begin
`WRITE_VERBOSE(("[%0t] e1\n", $time)); `WRITE_VERBOSE(("[%0t] e1\n", $time));
if (!e1.triggered) $stop; if (!e1.triggered) $stop;

View File

@ -1,5 +1,4 @@
%Error: t/t_force_bad_rw.v:14:20: Unsupported: Signals used via read-write reference cannot be forced %Error: t/t_force_bad_rw.v:14:20: Unsupported: Signals used via read-write reference cannot be forced
: ... In instance t.unnamedblk1.unnamedblk1.index
14 | foreach (ass[index]) begin 14 | foreach (ass[index]) begin
| ^~~~~ | ^~~~~
%Error: Exiting due to %Error: Exiting due to

View File

@ -1,5 +1,4 @@
%Error: t/t_fuzz_eqne_bad.v:12:23: Slice operator VARREF 't.b' on non-slicable (e.g. non-vector) right-hand-side operand %Error: t/t_fuzz_eqne_bad.v:12:23: Slice operator VARREF 't.b' on non-slicable (e.g. non-vector) right-hand-side operand
: ... In instance t.b
12 | initial c = (a != &b); 12 | initial c = (a != &b);
| ^ | ^
%Error: Exiting due to %Error: Exiting due to

View File

@ -1,7 +1,6 @@
$version Generated by VerilatedVcd $end $version Generated by VerilatedVcd $end
$date Wed Dec 4 07:47:51 2019 $date Thu Apr 14 07:06:40 2022 $end
$end $timescale 1ps $end
$timescale 1ps $end
$scope module top $end $scope module top $end
$var wire 1 0 clk $end $var wire 1 0 clk $end
@ -57,6 +56,10 @@ $timescale 1ps $end
$var wire 1 0 clk $end $var wire 1 0 clk $end
$var wire 32 # cyc [31:0] $end $var wire 32 # cyc [31:0] $end
$var wire 32 * value [31:0] $end $var wire 32 * value [31:0] $end
$scope interface inner $end
$var wire 32 # cyc [31:0] $end
$var wire 32 3 value [31:0] $end
$upscope $end
$scope struct the_struct $end $scope struct the_struct $end
$var wire 32 + val100 [31:0] $end $var wire 32 + val100 [31:0] $end
$var wire 32 , val200 [31:0] $end $var wire 32 , val200 [31:0] $end
@ -130,6 +133,10 @@ $timescale 1ps $end
$var wire 1 0 clk $end $var wire 1 0 clk $end
$var wire 32 # cyc [31:0] $end $var wire 32 # cyc [31:0] $end
$var wire 32 - value [31:0] $end $var wire 32 - value [31:0] $end
$scope interface inner $end
$var wire 32 # cyc [31:0] $end
$var wire 32 4 value [31:0] $end
$upscope $end
$scope struct the_struct $end $scope struct the_struct $end
$var wire 32 . val100 [31:0] $end $var wire 32 . val100 [31:0] $end
$var wire 32 / val200 [31:0] $end $var wire 32 / val200 [31:0] $end
@ -180,6 +187,10 @@ $timescale 1ps $end
$var wire 1 0 clk $end $var wire 1 0 clk $end
$var wire 32 # cyc [31:0] $end $var wire 32 # cyc [31:0] $end
$var wire 32 $ value [31:0] $end $var wire 32 $ value [31:0] $end
$scope interface inner $end
$var wire 32 # cyc [31:0] $end
$var wire 32 1 value [31:0] $end
$upscope $end
$scope struct the_struct $end $scope struct the_struct $end
$var wire 32 % val100 [31:0] $end $var wire 32 % val100 [31:0] $end
$var wire 32 & val200 [31:0] $end $var wire 32 & val200 [31:0] $end
@ -189,6 +200,10 @@ $timescale 1ps $end
$var wire 1 0 clk $end $var wire 1 0 clk $end
$var wire 32 # cyc [31:0] $end $var wire 32 # cyc [31:0] $end
$var wire 32 ' value [31:0] $end $var wire 32 ' value [31:0] $end
$scope interface inner $end
$var wire 32 # cyc [31:0] $end
$var wire 32 2 value [31:0] $end
$upscope $end
$scope struct the_struct $end $scope struct the_struct $end
$var wire 32 ( val100 [31:0] $end $var wire 32 ( val100 [31:0] $end
$var wire 32 ) val200 [31:0] $end $var wire 32 ) val200 [31:0] $end
@ -236,6 +251,10 @@ b00000000000000000000001111101010 -
b00000000000000000000010001001110 . b00000000000000000000010001001110 .
b00000000000000000000010010110010 / b00000000000000000000010010110010 /
00 00
b00000000000000000000000000000000 1
b00000000000000000000000000000000 2
b00000000000000000000000000000000 3
b00000000000000000000000000000000 4
#10 #10
b00000000000000000000000000000001 # b00000000000000000000000000000001 #
b00000000000000000000000000000010 $ b00000000000000000000000000000010 $

View File

@ -11,10 +11,16 @@ typedef struct packed {
integer val200; integer val200;
} struct_t; } struct_t;
// This interface is not connected to any cells
interface ifc_inner(input integer cyc);
integer value;
endinterface
interface ifc (input logic clk, interface ifc (input logic clk,
input integer cyc); input integer cyc);
integer value; integer value;
struct_t the_struct; struct_t the_struct;
ifc_inner inner (.*);
endinterface endinterface
module t (/*AUTOARG*/ module t (/*AUTOARG*/

View File

@ -1,5 +1,5 @@
$date $date
Tue Feb 22 23:55:07 2022 Thu Apr 14 07:06:50 2022
$end $end
$version $version
@ -59,6 +59,10 @@ $upscope $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$scope interface intf_in_sub_all $end $scope interface intf_in_sub_all $end
$scope interface inner $end
$var wire 32 " cyc [31:0] $end
$var integer 32 , value [31:0] $end
$upscope $end
$var wire 1 ! clk $end $var wire 1 ! clk $end
$var wire 32 " cyc [31:0] $end $var wire 32 " cyc [31:0] $end
$var integer 32 ) value [31:0] $end $var integer 32 ) value [31:0] $end
@ -113,10 +117,10 @@ $scope module ac3 $end
$scope interface intf_for_check $end $scope interface intf_for_check $end
$var wire 1 ! clk $end $var wire 1 ! clk $end
$var wire 32 " cyc [31:0] $end $var wire 32 " cyc [31:0] $end
$var integer 32 , value [31:0] $end $var integer 32 - value [31:0] $end
$scope struct the_struct $end $scope struct the_struct $end
$var logic 32 - val100 [31:0] $end $var logic 32 . val100 [31:0] $end
$var logic 32 . val200 [31:0] $end $var logic 32 / val200 [31:0] $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$upscope $end $upscope $end
@ -124,20 +128,24 @@ $scope module as3 $end
$scope interface intf_for_struct $end $scope interface intf_for_struct $end
$var wire 1 ! clk $end $var wire 1 ! clk $end
$var wire 32 " cyc [31:0] $end $var wire 32 " cyc [31:0] $end
$var integer 32 , value [31:0] $end $var integer 32 - value [31:0] $end
$scope struct the_struct $end $scope struct the_struct $end
$var logic 32 - val100 [31:0] $end $var logic 32 . val100 [31:0] $end
$var logic 32 . val200 [31:0] $end $var logic 32 / val200 [31:0] $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$scope interface intf_in_sub_all $end $scope interface intf_in_sub_all $end
$scope interface inner $end
$var wire 32 " cyc [31:0] $end
$var integer 32 0 value [31:0] $end
$upscope $end
$var wire 1 ! clk $end $var wire 1 ! clk $end
$var wire 32 " cyc [31:0] $end $var wire 32 " cyc [31:0] $end
$var integer 32 , value [31:0] $end $var integer 32 - value [31:0] $end
$scope struct the_struct $end $scope struct the_struct $end
$var logic 32 - val100 [31:0] $end $var logic 32 . val100 [31:0] $end
$var logic 32 . val200 [31:0] $end $var logic 32 / val200 [31:0] $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$scope interface intf_one $end $scope interface intf_one $end
@ -182,6 +190,10 @@ $upscope $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$scope interface intf_1 $end $scope interface intf_1 $end
$scope interface inner $end
$var wire 32 " cyc [31:0] $end
$var integer 32 1 value [31:0] $end
$upscope $end
$var wire 1 ! clk $end $var wire 1 ! clk $end
$var wire 32 " cyc [31:0] $end $var wire 32 " cyc [31:0] $end
$var integer 32 # value [31:0] $end $var integer 32 # value [31:0] $end
@ -191,6 +203,10 @@ $var logic 32 % val200 [31:0] $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$scope interface intf_2 $end $scope interface intf_2 $end
$scope interface inner $end
$var wire 32 " cyc [31:0] $end
$var integer 32 2 value [31:0] $end
$upscope $end
$var wire 1 ! clk $end $var wire 1 ! clk $end
$var wire 32 " cyc [31:0] $end $var wire 32 " cyc [31:0] $end
$var integer 32 & value [31:0] $end $var integer 32 & value [31:0] $end
@ -226,9 +242,13 @@ $upscope $end
$enddefinitions $end $enddefinitions $end
#0 #0
$dumpvars $dumpvars
b00000000000000000000010010110010 . b00000000000000000000000000000000 2
b00000000000000000000010001001110 - b00000000000000000000000000000000 1
b00000000000000000000001111101010 , b00000000000000000000000000000000 0
b00000000000000000000010010110010 /
b00000000000000000000010001001110 .
b00000000000000000000001111101010 -
b00000000000000000000000000000000 ,
b00000000000000000000010010110001 + b00000000000000000000010010110001 +
b00000000000000000000010001001101 * b00000000000000000000010001001101 *
b00000000000000000000001111101001 ) b00000000000000000000001111101001 )
@ -253,16 +273,16 @@ b00000000000000000000000011001011 (
b00000000000000000000001111101010 ) b00000000000000000000001111101010 )
b00000000000000000000010001001110 * b00000000000000000000010001001110 *
b00000000000000000000010010110010 + b00000000000000000000010010110010 +
b00000000000000000000001111101011 , b00000000000000000000001111101011 -
b00000000000000000000010001001111 - b00000000000000000000010001001111 .
b00000000000000000000010010110011 . b00000000000000000000010010110011 /
#15 #15
0! 0!
#20 #20
1! 1!
b00000000000000000000010010110100 . b00000000000000000000010010110100 /
b00000000000000000000010001010000 - b00000000000000000000010001010000 .
b00000000000000000000001111101100 , b00000000000000000000001111101100 -
b00000000000000000000010010110011 + b00000000000000000000010010110011 +
b00000000000000000000010001001111 * b00000000000000000000010001001111 *
b00000000000000000000001111101011 ) b00000000000000000000001111101011 )
@ -287,16 +307,16 @@ b00000000000000000000000011001101 (
b00000000000000000000001111101100 ) b00000000000000000000001111101100 )
b00000000000000000000010001010000 * b00000000000000000000010001010000 *
b00000000000000000000010010110100 + b00000000000000000000010010110100 +
b00000000000000000000001111101101 , b00000000000000000000001111101101 -
b00000000000000000000010001010001 - b00000000000000000000010001010001 .
b00000000000000000000010010110101 . b00000000000000000000010010110101 /
#35 #35
0! 0!
#40 #40
1! 1!
b00000000000000000000010010110110 . b00000000000000000000010010110110 /
b00000000000000000000010001010010 - b00000000000000000000010001010010 .
b00000000000000000000001111101110 , b00000000000000000000001111101110 -
b00000000000000000000010010110101 + b00000000000000000000010010110101 +
b00000000000000000000010001010001 * b00000000000000000000010001010001 *
b00000000000000000000001111101101 ) b00000000000000000000001111101101 )
@ -321,16 +341,16 @@ b00000000000000000000000011001111 (
b00000000000000000000001111101110 ) b00000000000000000000001111101110 )
b00000000000000000000010001010010 * b00000000000000000000010001010010 *
b00000000000000000000010010110110 + b00000000000000000000010010110110 +
b00000000000000000000001111101111 , b00000000000000000000001111101111 -
b00000000000000000000010001010011 - b00000000000000000000010001010011 .
b00000000000000000000010010110111 . b00000000000000000000010010110111 /
#55 #55
0! 0!
#60 #60
1! 1!
b00000000000000000000010010111000 . b00000000000000000000010010111000 /
b00000000000000000000010001010100 - b00000000000000000000010001010100 .
b00000000000000000000001111110000 , b00000000000000000000001111110000 -
b00000000000000000000010010110111 + b00000000000000000000010010110111 +
b00000000000000000000010001010011 * b00000000000000000000010001010011 *
b00000000000000000000001111101111 ) b00000000000000000000001111101111 )
@ -355,16 +375,16 @@ b00000000000000000000000011010001 (
b00000000000000000000001111110000 ) b00000000000000000000001111110000 )
b00000000000000000000010001010100 * b00000000000000000000010001010100 *
b00000000000000000000010010111000 + b00000000000000000000010010111000 +
b00000000000000000000001111110001 , b00000000000000000000001111110001 -
b00000000000000000000010001010101 - b00000000000000000000010001010101 .
b00000000000000000000010010111001 . b00000000000000000000010010111001 /
#75 #75
0! 0!
#80 #80
1! 1!
b00000000000000000000010010111010 . b00000000000000000000010010111010 /
b00000000000000000000010001010110 - b00000000000000000000010001010110 .
b00000000000000000000001111110010 , b00000000000000000000001111110010 -
b00000000000000000000010010111001 + b00000000000000000000010010111001 +
b00000000000000000000010001010101 * b00000000000000000000010001010101 *
b00000000000000000000001111110001 ) b00000000000000000000001111110001 )
@ -389,16 +409,16 @@ b00000000000000000000000011010011 (
b00000000000000000000001111110010 ) b00000000000000000000001111110010 )
b00000000000000000000010001010110 * b00000000000000000000010001010110 *
b00000000000000000000010010111010 + b00000000000000000000010010111010 +
b00000000000000000000001111110011 , b00000000000000000000001111110011 -
b00000000000000000000010001010111 - b00000000000000000000010001010111 .
b00000000000000000000010010111011 . b00000000000000000000010010111011 /
#95 #95
0! 0!
#100 #100
1! 1!
b00000000000000000000010010111100 . b00000000000000000000010010111100 /
b00000000000000000000010001011000 - b00000000000000000000010001011000 .
b00000000000000000000001111110100 , b00000000000000000000001111110100 -
b00000000000000000000010010111011 + b00000000000000000000010010111011 +
b00000000000000000000010001010111 * b00000000000000000000010001010111 *
b00000000000000000000001111110011 ) b00000000000000000000001111110011 )
@ -423,16 +443,16 @@ b00000000000000000000000011010101 (
b00000000000000000000001111110100 ) b00000000000000000000001111110100 )
b00000000000000000000010001011000 * b00000000000000000000010001011000 *
b00000000000000000000010010111100 + b00000000000000000000010010111100 +
b00000000000000000000001111110101 , b00000000000000000000001111110101 -
b00000000000000000000010001011001 - b00000000000000000000010001011001 .
b00000000000000000000010010111101 . b00000000000000000000010010111101 /
#115 #115
0! 0!
#120 #120
1! 1!
b00000000000000000000010010111110 . b00000000000000000000010010111110 /
b00000000000000000000010001011010 - b00000000000000000000010001011010 .
b00000000000000000000001111110110 , b00000000000000000000001111110110 -
b00000000000000000000010010111101 + b00000000000000000000010010111101 +
b00000000000000000000010001011001 * b00000000000000000000010001011001 *
b00000000000000000000001111110101 ) b00000000000000000000001111110101 )
@ -457,16 +477,16 @@ b00000000000000000000000011010111 (
b00000000000000000000001111110110 ) b00000000000000000000001111110110 )
b00000000000000000000010001011010 * b00000000000000000000010001011010 *
b00000000000000000000010010111110 + b00000000000000000000010010111110 +
b00000000000000000000001111110111 , b00000000000000000000001111110111 -
b00000000000000000000010001011011 - b00000000000000000000010001011011 .
b00000000000000000000010010111111 . b00000000000000000000010010111111 /
#135 #135
0! 0!
#140 #140
1! 1!
b00000000000000000000010011000000 . b00000000000000000000010011000000 /
b00000000000000000000010001011100 - b00000000000000000000010001011100 .
b00000000000000000000001111111000 , b00000000000000000000001111111000 -
b00000000000000000000010010111111 + b00000000000000000000010010111111 +
b00000000000000000000010001011011 * b00000000000000000000010001011011 *
b00000000000000000000001111110111 ) b00000000000000000000001111110111 )
@ -491,16 +511,16 @@ b00000000000000000000000011011001 (
b00000000000000000000001111111000 ) b00000000000000000000001111111000 )
b00000000000000000000010001011100 * b00000000000000000000010001011100 *
b00000000000000000000010011000000 + b00000000000000000000010011000000 +
b00000000000000000000001111111001 , b00000000000000000000001111111001 -
b00000000000000000000010001011101 - b00000000000000000000010001011101 .
b00000000000000000000010011000001 . b00000000000000000000010011000001 /
#155 #155
0! 0!
#160 #160
1! 1!
b00000000000000000000010011000010 . b00000000000000000000010011000010 /
b00000000000000000000010001011110 - b00000000000000000000010001011110 .
b00000000000000000000001111111010 , b00000000000000000000001111111010 -
b00000000000000000000010011000001 + b00000000000000000000010011000001 +
b00000000000000000000010001011101 * b00000000000000000000010001011101 *
b00000000000000000000001111111001 ) b00000000000000000000001111111001 )
@ -525,16 +545,16 @@ b00000000000000000000000011011011 (
b00000000000000000000001111111010 ) b00000000000000000000001111111010 )
b00000000000000000000010001011110 * b00000000000000000000010001011110 *
b00000000000000000000010011000010 + b00000000000000000000010011000010 +
b00000000000000000000001111111011 , b00000000000000000000001111111011 -
b00000000000000000000010001011111 - b00000000000000000000010001011111 .
b00000000000000000000010011000011 . b00000000000000000000010011000011 /
#175 #175
0! 0!
#180 #180
1! 1!
b00000000000000000000010011000100 . b00000000000000000000010011000100 /
b00000000000000000000010001100000 - b00000000000000000000010001100000 .
b00000000000000000000001111111100 , b00000000000000000000001111111100 -
b00000000000000000000010011000011 + b00000000000000000000010011000011 +
b00000000000000000000010001011111 * b00000000000000000000010001011111 *
b00000000000000000000001111111011 ) b00000000000000000000001111111011 )
@ -559,16 +579,16 @@ b00000000000000000000000011011101 (
b00000000000000000000001111111100 ) b00000000000000000000001111111100 )
b00000000000000000000010001100000 * b00000000000000000000010001100000 *
b00000000000000000000010011000100 + b00000000000000000000010011000100 +
b00000000000000000000001111111101 , b00000000000000000000001111111101 -
b00000000000000000000010001100001 - b00000000000000000000010001100001 .
b00000000000000000000010011000101 . b00000000000000000000010011000101 /
#195 #195
0! 0!
#200 #200
1! 1!
b00000000000000000000010011000110 . b00000000000000000000010011000110 /
b00000000000000000000010001100010 - b00000000000000000000010001100010 .
b00000000000000000000001111111110 , b00000000000000000000001111111110 -
b00000000000000000000010011000101 + b00000000000000000000010011000101 +
b00000000000000000000010001100001 * b00000000000000000000010001100001 *
b00000000000000000000001111111101 ) b00000000000000000000001111111101 )
@ -593,6 +613,6 @@ b00000000000000000000000011011111 (
b00000000000000000000001111111110 ) b00000000000000000000001111111110 )
b00000000000000000000010001100010 * b00000000000000000000010001100010 *
b00000000000000000000010011000110 + b00000000000000000000010011000110 +
b00000000000000000000001111111111 , b00000000000000000000001111111111 -
b00000000000000000000010001100011 - b00000000000000000000010001100011 .
b00000000000000000000010011000111 . b00000000000000000000010011000111 /

View File

@ -1,5 +1,5 @@
$date $date
Tue Feb 22 23:55:19 2022 Thu Apr 14 07:06:59 2022
$end $end
$version $version
@ -58,6 +58,10 @@ $upscope $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$scope interface intf_in_sub_all $end $scope interface intf_in_sub_all $end
$scope interface inner $end
$var wire 32 " cyc [31:0] $end
$var integer 32 , value [31:0] $end
$upscope $end
$var wire 1 ! clk $end $var wire 1 ! clk $end
$var wire 32 " cyc [31:0] $end $var wire 32 " cyc [31:0] $end
$var integer 32 ) value [31:0] $end $var integer 32 ) value [31:0] $end
@ -112,10 +116,10 @@ $scope module ac3 $end
$scope interface intf_for_check $end $scope interface intf_for_check $end
$var wire 1 ! clk $end $var wire 1 ! clk $end
$var wire 32 " cyc [31:0] $end $var wire 32 " cyc [31:0] $end
$var integer 32 , value [31:0] $end $var integer 32 - value [31:0] $end
$scope struct the_struct $end $scope struct the_struct $end
$var logic 32 - val100 [31:0] $end $var logic 32 . val100 [31:0] $end
$var logic 32 . val200 [31:0] $end $var logic 32 / val200 [31:0] $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$upscope $end $upscope $end
@ -123,20 +127,24 @@ $scope module as3 $end
$scope interface intf_for_struct $end $scope interface intf_for_struct $end
$var wire 1 ! clk $end $var wire 1 ! clk $end
$var wire 32 " cyc [31:0] $end $var wire 32 " cyc [31:0] $end
$var integer 32 , value [31:0] $end $var integer 32 - value [31:0] $end
$scope struct the_struct $end $scope struct the_struct $end
$var logic 32 - val100 [31:0] $end $var logic 32 . val100 [31:0] $end
$var logic 32 . val200 [31:0] $end $var logic 32 / val200 [31:0] $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$scope interface intf_in_sub_all $end $scope interface intf_in_sub_all $end
$scope interface inner $end
$var wire 32 " cyc [31:0] $end
$var integer 32 0 value [31:0] $end
$upscope $end
$var wire 1 ! clk $end $var wire 1 ! clk $end
$var wire 32 " cyc [31:0] $end $var wire 32 " cyc [31:0] $end
$var integer 32 , value [31:0] $end $var integer 32 - value [31:0] $end
$scope struct the_struct $end $scope struct the_struct $end
$var logic 32 - val100 [31:0] $end $var logic 32 . val100 [31:0] $end
$var logic 32 . val200 [31:0] $end $var logic 32 / val200 [31:0] $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$scope interface intf_one $end $scope interface intf_one $end
@ -181,6 +189,10 @@ $upscope $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$scope interface intf_1 $end $scope interface intf_1 $end
$scope interface inner $end
$var wire 32 " cyc [31:0] $end
$var integer 32 1 value [31:0] $end
$upscope $end
$var wire 1 ! clk $end $var wire 1 ! clk $end
$var wire 32 " cyc [31:0] $end $var wire 32 " cyc [31:0] $end
$var integer 32 # value [31:0] $end $var integer 32 # value [31:0] $end
@ -190,6 +202,10 @@ $var logic 32 % val200 [31:0] $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$scope interface intf_2 $end $scope interface intf_2 $end
$scope interface inner $end
$var wire 32 " cyc [31:0] $end
$var integer 32 2 value [31:0] $end
$upscope $end
$var wire 1 ! clk $end $var wire 1 ! clk $end
$var wire 32 " cyc [31:0] $end $var wire 32 " cyc [31:0] $end
$var integer 32 & value [31:0] $end $var integer 32 & value [31:0] $end
@ -225,9 +241,13 @@ $upscope $end
$enddefinitions $end $enddefinitions $end
#0 #0
$dumpvars $dumpvars
b00000000000000000000010010110010 . b00000000000000000000000000000000 2
b00000000000000000000010001001110 - b00000000000000000000000000000000 1
b00000000000000000000001111101010 , b00000000000000000000000000000000 0
b00000000000000000000010010110010 /
b00000000000000000000010001001110 .
b00000000000000000000001111101010 -
b00000000000000000000000000000000 ,
b00000000000000000000010010110001 + b00000000000000000000010010110001 +
b00000000000000000000010001001101 * b00000000000000000000010001001101 *
b00000000000000000000001111101001 ) b00000000000000000000001111101001 )
@ -252,9 +272,9 @@ b00000000000000000000000011001011 (
b00000000000000000000001111101010 ) b00000000000000000000001111101010 )
b00000000000000000000010001001110 * b00000000000000000000010001001110 *
b00000000000000000000010010110010 + b00000000000000000000010010110010 +
b00000000000000000000001111101011 , b00000000000000000000001111101011 -
b00000000000000000000010001001111 - b00000000000000000000010001001111 .
b00000000000000000000010010110011 . b00000000000000000000010010110011 /
#11 #11
#12 #12
#13 #13
@ -267,9 +287,9 @@ b00000000000000000000010010110011 .
#19 #19
#20 #20
1! 1!
b00000000000000000000010010110100 . b00000000000000000000010010110100 /
b00000000000000000000010001010000 - b00000000000000000000010001010000 .
b00000000000000000000001111101100 , b00000000000000000000001111101100 -
b00000000000000000000010010110011 + b00000000000000000000010010110011 +
b00000000000000000000010001001111 * b00000000000000000000010001001111 *
b00000000000000000000001111101011 ) b00000000000000000000001111101011 )
@ -302,9 +322,9 @@ b00000000000000000000000011001101 (
b00000000000000000000001111101100 ) b00000000000000000000001111101100 )
b00000000000000000000010001010000 * b00000000000000000000010001010000 *
b00000000000000000000010010110100 + b00000000000000000000010010110100 +
b00000000000000000000001111101101 , b00000000000000000000001111101101 -
b00000000000000000000010001010001 - b00000000000000000000010001010001 .
b00000000000000000000010010110101 . b00000000000000000000010010110101 /
#31 #31
#32 #32
#33 #33
@ -317,9 +337,9 @@ b00000000000000000000010010110101 .
#39 #39
#40 #40
1! 1!
b00000000000000000000010010110110 . b00000000000000000000010010110110 /
b00000000000000000000010001010010 - b00000000000000000000010001010010 .
b00000000000000000000001111101110 , b00000000000000000000001111101110 -
b00000000000000000000010010110101 + b00000000000000000000010010110101 +
b00000000000000000000010001010001 * b00000000000000000000010001010001 *
b00000000000000000000001111101101 ) b00000000000000000000001111101101 )
@ -352,9 +372,9 @@ b00000000000000000000000011001111 (
b00000000000000000000001111101110 ) b00000000000000000000001111101110 )
b00000000000000000000010001010010 * b00000000000000000000010001010010 *
b00000000000000000000010010110110 + b00000000000000000000010010110110 +
b00000000000000000000001111101111 , b00000000000000000000001111101111 -
b00000000000000000000010001010011 - b00000000000000000000010001010011 .
b00000000000000000000010010110111 . b00000000000000000000010010110111 /
#51 #51
#52 #52
#53 #53
@ -367,9 +387,9 @@ b00000000000000000000010010110111 .
#59 #59
#60 #60
1! 1!
b00000000000000000000010010111000 . b00000000000000000000010010111000 /
b00000000000000000000010001010100 - b00000000000000000000010001010100 .
b00000000000000000000001111110000 , b00000000000000000000001111110000 -
b00000000000000000000010010110111 + b00000000000000000000010010110111 +
b00000000000000000000010001010011 * b00000000000000000000010001010011 *
b00000000000000000000001111101111 ) b00000000000000000000001111101111 )
@ -402,9 +422,9 @@ b00000000000000000000000011010001 (
b00000000000000000000001111110000 ) b00000000000000000000001111110000 )
b00000000000000000000010001010100 * b00000000000000000000010001010100 *
b00000000000000000000010010111000 + b00000000000000000000010010111000 +
b00000000000000000000001111110001 , b00000000000000000000001111110001 -
b00000000000000000000010001010101 - b00000000000000000000010001010101 .
b00000000000000000000010010111001 . b00000000000000000000010010111001 /
#71 #71
#72 #72
#73 #73
@ -417,9 +437,9 @@ b00000000000000000000010010111001 .
#79 #79
#80 #80
1! 1!
b00000000000000000000010010111010 . b00000000000000000000010010111010 /
b00000000000000000000010001010110 - b00000000000000000000010001010110 .
b00000000000000000000001111110010 , b00000000000000000000001111110010 -
b00000000000000000000010010111001 + b00000000000000000000010010111001 +
b00000000000000000000010001010101 * b00000000000000000000010001010101 *
b00000000000000000000001111110001 ) b00000000000000000000001111110001 )
@ -452,9 +472,9 @@ b00000000000000000000000011010011 (
b00000000000000000000001111110010 ) b00000000000000000000001111110010 )
b00000000000000000000010001010110 * b00000000000000000000010001010110 *
b00000000000000000000010010111010 + b00000000000000000000010010111010 +
b00000000000000000000001111110011 , b00000000000000000000001111110011 -
b00000000000000000000010001010111 - b00000000000000000000010001010111 .
b00000000000000000000010010111011 . b00000000000000000000010010111011 /
#91 #91
#92 #92
#93 #93
@ -467,9 +487,9 @@ b00000000000000000000010010111011 .
#99 #99
#100 #100
1! 1!
b00000000000000000000010010111100 . b00000000000000000000010010111100 /
b00000000000000000000010001011000 - b00000000000000000000010001011000 .
b00000000000000000000001111110100 , b00000000000000000000001111110100 -
b00000000000000000000010010111011 + b00000000000000000000010010111011 +
b00000000000000000000010001010111 * b00000000000000000000010001010111 *
b00000000000000000000001111110011 ) b00000000000000000000001111110011 )
@ -502,9 +522,9 @@ b00000000000000000000000011010101 (
b00000000000000000000001111110100 ) b00000000000000000000001111110100 )
b00000000000000000000010001011000 * b00000000000000000000010001011000 *
b00000000000000000000010010111100 + b00000000000000000000010010111100 +
b00000000000000000000001111110101 , b00000000000000000000001111110101 -
b00000000000000000000010001011001 - b00000000000000000000010001011001 .
b00000000000000000000010010111101 . b00000000000000000000010010111101 /
#111 #111
#112 #112
#113 #113
@ -517,9 +537,9 @@ b00000000000000000000010010111101 .
#119 #119
#120 #120
1! 1!
b00000000000000000000010010111110 . b00000000000000000000010010111110 /
b00000000000000000000010001011010 - b00000000000000000000010001011010 .
b00000000000000000000001111110110 , b00000000000000000000001111110110 -
b00000000000000000000010010111101 + b00000000000000000000010010111101 +
b00000000000000000000010001011001 * b00000000000000000000010001011001 *
b00000000000000000000001111110101 ) b00000000000000000000001111110101 )
@ -552,9 +572,9 @@ b00000000000000000000000011010111 (
b00000000000000000000001111110110 ) b00000000000000000000001111110110 )
b00000000000000000000010001011010 * b00000000000000000000010001011010 *
b00000000000000000000010010111110 + b00000000000000000000010010111110 +
b00000000000000000000001111110111 , b00000000000000000000001111110111 -
b00000000000000000000010001011011 - b00000000000000000000010001011011 .
b00000000000000000000010010111111 . b00000000000000000000010010111111 /
#131 #131
#132 #132
#133 #133
@ -567,9 +587,9 @@ b00000000000000000000010010111111 .
#139 #139
#140 #140
1! 1!
b00000000000000000000010011000000 . b00000000000000000000010011000000 /
b00000000000000000000010001011100 - b00000000000000000000010001011100 .
b00000000000000000000001111111000 , b00000000000000000000001111111000 -
b00000000000000000000010010111111 + b00000000000000000000010010111111 +
b00000000000000000000010001011011 * b00000000000000000000010001011011 *
b00000000000000000000001111110111 ) b00000000000000000000001111110111 )
@ -602,9 +622,9 @@ b00000000000000000000000011011001 (
b00000000000000000000001111111000 ) b00000000000000000000001111111000 )
b00000000000000000000010001011100 * b00000000000000000000010001011100 *
b00000000000000000000010011000000 + b00000000000000000000010011000000 +
b00000000000000000000001111111001 , b00000000000000000000001111111001 -
b00000000000000000000010001011101 - b00000000000000000000010001011101 .
b00000000000000000000010011000001 . b00000000000000000000010011000001 /
#151 #151
#152 #152
#153 #153
@ -617,9 +637,9 @@ b00000000000000000000010011000001 .
#159 #159
#160 #160
1! 1!
b00000000000000000000010011000010 . b00000000000000000000010011000010 /
b00000000000000000000010001011110 - b00000000000000000000010001011110 .
b00000000000000000000001111111010 , b00000000000000000000001111111010 -
b00000000000000000000010011000001 + b00000000000000000000010011000001 +
b00000000000000000000010001011101 * b00000000000000000000010001011101 *
b00000000000000000000001111111001 ) b00000000000000000000001111111001 )
@ -652,9 +672,9 @@ b00000000000000000000000011011011 (
b00000000000000000000001111111010 ) b00000000000000000000001111111010 )
b00000000000000000000010001011110 * b00000000000000000000010001011110 *
b00000000000000000000010011000010 + b00000000000000000000010011000010 +
b00000000000000000000001111111011 , b00000000000000000000001111111011 -
b00000000000000000000010001011111 - b00000000000000000000010001011111 .
b00000000000000000000010011000011 . b00000000000000000000010011000011 /
#171 #171
#172 #172
#173 #173
@ -667,9 +687,9 @@ b00000000000000000000010011000011 .
#179 #179
#180 #180
1! 1!
b00000000000000000000010011000100 . b00000000000000000000010011000100 /
b00000000000000000000010001100000 - b00000000000000000000010001100000 .
b00000000000000000000001111111100 , b00000000000000000000001111111100 -
b00000000000000000000010011000011 + b00000000000000000000010011000011 +
b00000000000000000000010001011111 * b00000000000000000000010001011111 *
b00000000000000000000001111111011 ) b00000000000000000000001111111011 )
@ -702,9 +722,9 @@ b00000000000000000000000011011101 (
b00000000000000000000001111111100 ) b00000000000000000000001111111100 )
b00000000000000000000010001100000 * b00000000000000000000010001100000 *
b00000000000000000000010011000100 + b00000000000000000000010011000100 +
b00000000000000000000001111111101 , b00000000000000000000001111111101 -
b00000000000000000000010001100001 - b00000000000000000000010001100001 .
b00000000000000000000010011000101 . b00000000000000000000010011000101 /
#191 #191
#192 #192
#193 #193
@ -717,9 +737,9 @@ b00000000000000000000010011000101 .
#199 #199
#200 #200
1! 1!
b00000000000000000000010011000110 . b00000000000000000000010011000110 /
b00000000000000000000010001100010 - b00000000000000000000010001100010 .
b00000000000000000000001111111110 , b00000000000000000000001111111110 -
b00000000000000000000010011000101 + b00000000000000000000010011000101 +
b00000000000000000000010001100001 * b00000000000000000000010001100001 *
b00000000000000000000001111111101 ) b00000000000000000000001111111101 )
@ -752,9 +772,9 @@ b00000000000000000000000011011111 (
b00000000000000000000001111111110 ) b00000000000000000000001111111110 )
b00000000000000000000010001100010 * b00000000000000000000010001100010 *
b00000000000000000000010011000110 + b00000000000000000000010011000110 +
b00000000000000000000001111111111 , b00000000000000000000001111111111 -
b00000000000000000000010001100011 - b00000000000000000000010001100011 .
b00000000000000000000010011000111 . b00000000000000000000010011000111 /
#211 #211
#212 #212
#213 #213

View File

@ -25,11 +25,11 @@ module t (/*AUTOARG*/
// verilator lint_off UNOPTFLAT // verilator lint_off UNOPTFLAT
reg [31:0] e2,f2,g2,h2; reg [31:0] e2,f2,g2,h2;
always @ (/*AS*/f2) begin always @ (/*AS*/f2, g2) begin
h2 = {g2[15:0], g2[31:16]}; h2 = {g2[15:0], g2[31:16]};
g2 = {f2[15:0], f2[31:16]}; g2 = {f2[15:0], f2[31:16]};
end end
always @ (/*AS*/in_a) begin always @ (/*AS*/in_a, e2) begin
f2 = {e2[15:0], e2[31:16]}; f2 = {e2[15:0], e2[31:16]};
e2 = in_a; e2 = in_a;
end end

View File

@ -0,0 +1,16 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2022 by Geza Lore. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(simulator => 1);
compile();
ok(1);
1;

View File

@ -0,0 +1,21 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// Copyright 2022 by Geza Lore. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
module a #(parameter N) ();
generate if (N > 1) begin
// With N == 5, this will first expand N == 2, then expand N == 3,
// which instantiates N == 2. This requires fixing up topological order
// in V3Param.
a #(.N( N/2)) sub_lo();
a #(.N(N-N/2)) sub_hi();
end
endgenerate
endmodule
module top();
a #(.N(5)) root ();
endmodule