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]
* 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 Bison 3.8.2 error (#3366). [elike-ypq]
* 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 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
==========================

View File

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

View File

@ -521,6 +521,19 @@ using ssize_t = uint32_t; ///< signed size_t; returned from read()
// Conversions
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
template <class T> T const& as_const(T& v) { return v; }
}; // namespace vlstd

View File

@ -422,6 +422,14 @@ private:
virtual void visit(AstActive* nodep) override {
// 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 {
// Relink to IACTIVE, unless already under it
UINFO(4, " INITIAL " << nodep << endl);

View File

@ -98,7 +98,7 @@ private:
? static_cast<AstNode*>(
new AstCMath(fl, "vlSymsp->_vm_contextp__->assertOn()", 1))
: static_cast<AstNode*>(new AstConst(fl, AstConst::BitFalse())))),
nodep, nullptr);
nodep);
newp->user1(true); // Don't assert/cover this if
return newp;
}
@ -154,7 +154,7 @@ private:
}
if (bodysp && passsp) bodysp = bodysp->addNext(passsp);
ifp = new AstIf(nodep->fileline(), propp, bodysp, nullptr);
ifp = new AstIf(nodep->fileline(), propp, bodysp);
bodysp = ifp;
} else if (VN_IS(nodep, Assert) || VN_IS(nodep, AssertIntrinsic)) {
if (nodep->immediate()) {
@ -313,8 +313,7 @@ private:
AstIf* const ifp = new AstIf(
nodep->fileline(), new AstLogNot(nodep->fileline(), ohot),
newFireAssert(nodep,
"synthesis parallel_case, but multiple matches found"),
nullptr);
"synthesis parallel_case, but multiple matches found"));
ifp->branchPred(VBranchPred::BP_UNLIKELY);
nodep->addNotParallelp(ifp);
}
@ -384,7 +383,7 @@ private:
new AstLogAnd{fl, new AstLogNot{fl, newMonitorOffVarRefp(nodep, VAccess::READ)},
new AstEq{fl, new AstConst{fl, monNum},
newMonitorNumVarRefp(nodep, VAccess::READ)}},
stmtsp, nullptr};
stmtsp};
ifp->branchPred(VBranchPred::BP_UNLIKELY);
AstNode* const newp = new AstAlwaysPostponed{fl, ifp};
m_modp->addStmtp(newp);
@ -402,8 +401,7 @@ private:
nodep->replaceWith(newsetp);
// Add "always_comb if (__Vstrobe) begin $display(...); __Vstrobe = '0; end"
AstNode* const stmtsp = nodep;
AstIf* const ifp
= new AstIf{fl, new AstVarRef{fl, varp, VAccess::READ}, stmtsp, nullptr};
AstIf* const ifp = new AstIf{fl, new AstVarRef{fl, varp, VAccess::READ}, stmtsp};
ifp->branchPred(VBranchPred::BP_UNLIKELY);
AstNode* const newp = new AstAlwaysPostponed{fl, ifp};
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
}
string AstNode::locationStr() const {
string str = "... In instance ";
const AstNode* backp = this;
int itmax = 10000; // Max iterations before giving up on location search
while (backp) {
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;
string AstNode::instanceStr() const {
// Max iterations before giving up on location search,
// in case we have some circular reference bug.
constexpr unsigned maxIterations = 10000;
unsigned iterCount = 0;
str += scopep->prettyName();
return str;
for (const AstNode* backp = this; backp; backp = backp->backp(), ++iterCount) {
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();
}
backp = this;
while (backp) {
const AstModule* modp;
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;
}
// If scopes don't exist, report an example instance of the enclosing module
if (const AstModule* const modp = VN_CAST(backp, Module)) {
const string instanceName = modp->someInstanceName();
return instanceName.empty() ? "" : "... In instance " + instanceName;
}
backp = backp->backp();
}
return "";
}
void AstNode::v3errorEnd(std::ostringstream& str) const {
if (!m_fileline) {
V3Error::v3errorEnd(str, locationStr());
V3Error::v3errorEnd(str, instanceStr());
} else {
std::ostringstream nsstr;
nsstr << str.str();
@ -1187,7 +1171,7 @@ void AstNode::v3errorEnd(std::ostringstream& str) const {
const_cast<AstNode*>(this)->dump(nsstr);
nsstr << endl;
}
m_fileline->v3errorEnd(nsstr, locationStr());
m_fileline->v3errorEnd(nsstr, instanceStr());
}
}

View File

@ -1447,7 +1447,7 @@ private:
bool gateOnly);
void deleteTreeIter();
void deleteNode();
string locationStr() const;
string instanceStr() const;
public:
static void relinkOneLink(AstNode*& pointpr, AstNode* newp);
@ -3077,7 +3077,8 @@ class AstNodeModule VL_NOT_FINAL : public AstNode {
private:
string m_name; // Name of the module
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_modTrace : 1; // Tracing this module
bool m_inLibrary : 1; // From a library, no error if not used, never top level
@ -3119,8 +3120,8 @@ public:
// ACCESSORS
virtual void name(const string& name) override { m_name = name; }
virtual string origName() const override { return m_origName; }
string hierName() const { return m_hierName; }
void hierName(const string& hierName) { m_hierName = hierName; }
string someInstanceName() const { return m_someInstanceName; }
void someInstanceName(const string& name) { m_someInstanceName = name; }
bool inLibrary() const { return m_inLibrary; }
void inLibrary(bool flag) { m_inLibrary = flag; }
void level(int level) { m_level = level; }

View File

@ -1914,14 +1914,14 @@ private:
bool m_pure = false; // Pure optimizable
public:
AstCMethodHard(FileLine* fl, AstNode* fromp, VFlagChildDType, const string& name,
AstNode* pinsp)
AstNode* pinsp = nullptr)
: ASTGEN_SUPER_CMethodHard(fl, false)
, m_name{name} {
setOp1p(fromp);
dtypep(nullptr); // V3Width will resolve
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)
, m_name{name} {
setOp1p(fromp);
@ -3407,7 +3407,7 @@ public:
};
class AstInitialAutomatic final : public AstNodeProcedure {
// initial for automatic variables
// Automatic variable initialization
// That is, it runs every function start, or class construction
public:
AstInitialAutomatic(FileLine* fl, AstNode* bodysp)
@ -3415,6 +3415,15 @@ public:
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 {
const VAlwaysKwd m_keyword;
@ -4610,7 +4619,7 @@ public:
class AstWhile final : public AstNodeStmt {
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) {
setOp2p(condp);
addNOp3p(bodysp);
@ -4714,7 +4723,7 @@ private:
bool m_unique0Pragma; // unique0 case
bool m_priorityPragma; // priority case
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) {
m_uniquePragma = false;
m_unique0Pragma = false;

View File

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

View File

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

View File

@ -153,6 +153,11 @@ private:
iterateChildren(nodep);
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(AstNodeStmt* nodep) override {} // Short circuit
@ -173,7 +178,7 @@ public:
vscp->scopep(scopep);
vscp->unlinkFrBack();
scopep->addVarp(vscp);
} else if (VN_IS(nodep, Initial)) {
} else if (VN_IS(nodep, Initial) || VN_IS(nodep, InitialStatic)) {
nodep->unlinkFrBack();
scopep->addActivep(nodep);
} else {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -313,7 +313,7 @@ public:
static void vlAbortOrExit();
static void vlAbort();
// 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.

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;
if (lastLineno()) nsstr << this;
nsstr << sstr.str();
nsstr << endl;
std::ostringstream lstr;
if (!locationStr.empty()) {
if (!extra.empty()) {
lstr << std::setw(ascii().length()) << " "
<< ": " << locationStr;
<< ": " << extra;
}
m_waive = V3Config::waive(this, V3Error::errorCode(), sstr.str());
if (warnIsOff(V3Error::errorCode()) || m_waive) {

View File

@ -245,7 +245,7 @@ public:
void modifyWarnOff(V3ErrorCode code, bool flag) { warnOff(code, flag); }
// OPERATORS
void v3errorEnd(std::ostringstream& str, const string& locationStr = "");
void v3errorEnd(std::ostringstream& str, const string& extra = "");
void v3errorEndFatal(std::ostringstream& str);
/// When building an error, prefix for printing continuation lines
/// 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, [=]() {});
}
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->hierName();
});
}
virtual void visit(AstNodePreSel* nodep) override {

View File

@ -190,8 +190,7 @@ private:
// Iterate through all modules in bottom-up order.
// Make a final inlining decision for each.
for (auto it = m_allMods.rbegin(); it != m_allMods.rend(); ++it) {
AstNodeModule* const modp = *it;
for (AstNodeModule* const modp : vlstd::reverse_view(m_allMods)) {
// If we're going to inline some modules into this one,
// update user4 (statement count) to reflect that:
@ -647,7 +646,11 @@ private:
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
for (AstPin* pinp = nodep->pinsp(); pinp; pinp = VN_AS(pinp->nextp(), Pin)) {
AstVar* const varp = pinp->modVarp();
@ -666,9 +669,6 @@ private:
}
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 {

View File

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

View File

@ -275,7 +275,7 @@ private:
if (nodep->lifetime().isAutomatic()) {
nodep->addNextHere(new AstInitialAutomatic{newfl, assp});
} 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
else {

View File

@ -266,7 +266,7 @@ private:
// and we also need to keep track of it for comparisons later.
m_mgCondp = m_mgCondp->cloneTree(false);
// 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);
// Unzip the list and insert under branches
AstNode* nextp = m_mgFirstp;

View File

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

View File

@ -555,14 +555,12 @@ class ParamProcessor final {
cellp->v3error("Exceeded maximum --module-recursion-depth of "
<< v3Global.opt.moduleRecursionDepth());
}
// Keep tree sorted by level. Append to end of sub-list at the same level. This is
// important because due to the way recursive modules are handled, different
// parametrizations of the same recursive module end up with the same level (which in
// itself is a bit unfortunate). Nevertheless, as a later parametrization must not be above
// 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.
// Keep tree sorted by level. Note: Different parametrizations of the same recursive module
// end up with the same level, which we will need to fix up at the end, as we do not know
// up front how recursive modules are expanded, and a later expansion might re-use an
// earlier expansion (see t_recursive_module_bug_2).
AstNodeModule* insertp = srcModp;
while (VN_IS(insertp->nextp(), NodeModule)
while (insertp->nextp()
&& VN_AS(insertp->nextp(), NodeModule)->level() <= newmodp->level()) {
insertp = VN_AS(insertp->nextp(), NodeModule);
}
@ -761,7 +759,7 @@ class ParamProcessor final {
}
public:
void cellDeparam(AstCell* nodep, AstNodeModule* modp, const string& hierName) {
void cellDeparam(AstCell* nodep, AstNodeModule* modp, const string& someInstanceName) {
m_modp = modp;
// Cell: Check for parameters in the instantiation.
// We always run this, even if no parameters, as need to look for interfaces,
@ -772,7 +770,7 @@ public:
// Evaluate all module constants
V3Const::constifyParamsEdit(nodep);
AstNodeModule* const srcModp = nodep->modp();
srcModp->hierName(hierName + "." + nodep->name());
srcModp->someInstanceName(someInstanceName + "." + nodep->name());
// Make sure constification worked
// Must be a separate loop, as constant conversion may have changed some pointers.
@ -843,79 +841,99 @@ public:
// Process parameter visitor
class ParamVisitor final : public VNVisitor {
// NODE STATE
// AstNodeModule::user1 -> bool: already fixed level
// STATE
ParamProcessor m_processor; // De-parameterize a cell, build modules
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_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
VL_DEBUG_FUNC; // Declare debug()
void visitCellDeparam(AstCell* nodep, const string& hierName) {
// Cell: Check for parameters in the instantiation.
iterateChildren(nodep);
UASSERT_OBJ(nodep->modp(), nodep, "Not linked?");
m_processor.cellDeparam(nodep, m_modp, hierName);
// Remember to process the child module at the end of the module
m_todoModps.emplace(nodep->modp()->level(), nodep->modp());
}
void visitModules() {
// Loop on all modules left to process
// Hitting a cell adds to the appropriate level of this level-sorted list,
// so since cells originally exist top->bottom we process in top->bottom order too.
while (!m_todoModps.empty()) {
const auto itm = m_todoModps.cbegin();
AstNodeModule* const nodep = itm->second;
m_todoModps.erase(itm);
if (!nodep->user5SetOnce()) { // Process once; note clone() must clear so we do it
// again
m_modp = nodep;
UINFO(4, " MOD " << nodep << endl);
if (m_modp->hierName().empty()) m_modp->hierName(m_modp->origName());
iterateChildren(nodep);
// Note above iterate may add to m_todoModps
//
// Process interface cells, then non-interface which may ref an interface cell
for (int nonIf = 0; nonIf < 2; ++nonIf) {
for (AstCell* const cellp : m_cellps) {
if ((nonIf == 0 && VN_IS(cellp->modp(), Iface))
|| (nonIf == 1 && !VN_IS(cellp->modp(), Iface))) {
string fullName(m_modp->hierName());
if (const string* const genHierNamep = (string*)cellp->user5p()) {
fullName += *genHierNamep;
cellp->user5p(nullptr);
VL_DO_DANGLING(delete genHierNamep, genHierNamep);
}
VL_DO_DANGLING(visitCellDeparam(cellp, fullName), cellp);
}
void visitCells(AstNodeModule* nodep) {
UASSERT_OBJ(!m_iterateModule, nodep, "Should not nest");
std::multimap<int, AstNodeModule*> workQueue;
workQueue.emplace(nodep->level(), nodep);
m_generateHierName = "";
m_iterateModule = true;
// Visit all cells under module, recursively
do {
const auto itm = workQueue.cbegin();
AstNodeModule* const modp = itm->second;
workQueue.erase(itm);
// Process once; note user5 will be cleared on specialization, so we will do the
// specialized module if needed
if (modp->user5SetOnce()) continue;
// TODO: this really should be an assert, but classes and hier_blocks are special...
if (modp->someInstanceName().empty()) modp->someInstanceName(modp->origName());
// Iterate the body
iterateChildren(modp);
// Process interface cells, then non-interface cells, which may reference an interface
// cell.
for (bool doInterface : {true, false}) {
for (AstCell* const cellp : m_cellps) {
if (doInterface != VN_IS(cellp->modp(), Iface)) continue;
// Visit parameters in the instantiation.
iterateChildren(cellp);
// Update path
string someInstanceName(modp->someInstanceName());
if (const string* const genHierNamep = cellp->user5u().to<string*>()) {
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
virtual void visit(AstNodeModule* nodep) override {
if (nodep->dead()) {
UINFO(4, " MOD-dead. " << nodep << endl); // Marked by LinkDot
return;
} else if (nodep->recursiveClone()) {
// Fake, made for recursive elimination
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)) {
if (nodep->recursiveClone()) nodep->dead(true); // Fake, made for recursive elimination
if (nodep->dead()) return; // Marked by LinkDot (and above)
// Warn on unsupported parametrised class
if (VN_IS(nodep, Class)) {
for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
if (const AstVar* const varp = VN_CAST(stmtp, Var)) {
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);
iterateChildren(nodep);
} else if (nodep->level() <= 2 // Haven't added top yet, so level 2 is the top
|| 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
m_todoModps.emplace(nodep->level(), nodep);
m_generateHierName = "";
visitModules();
} else if (nodep->user5()) {
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);
return;
}
// Start traversal at root-like things
if (nodep->level() <= 2 // Haven't added top yet, so level 2 is the top
|| VN_IS(nodep, Class) // Nor moved classes
|| VN_IS(nodep, Package)) { // Likewise haven't done wrapTopPackages yet
visitCells(nodep);
}
}
virtual void visit(AstCell* nodep) override {
// Must do ifaces first, so push to list and do in proper order
string* const genHierNamep = new string(m_generateHierName);
@ -1195,10 +1210,38 @@ class ParamVisitor final : public VNVisitor {
public:
// CONSTRUCTORS
explicit ParamVisitor(AstNetlist* nodep)
: m_processor{nodep} {
explicit ParamVisitor(AstNetlist* netlistp)
: m_processor{netlistp} {
// 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;
VL_UNCOPYABLE(ParamVisitor);

View File

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

View File

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

View File

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

View File

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

View File

@ -656,7 +656,7 @@ private:
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);
subFuncp->addStmtsp(ifp);
subStmts += ifp->nodeCount();

View File

@ -190,6 +190,27 @@ private:
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,
int widthOverride) { // If !=0, is packed struct/array where basicp size
// misreflects one element
@ -199,8 +220,10 @@ private:
} else if (const AstBasicDType* const bdtypep = m_traValuep->dtypep()->basicp()) {
bitRange = bdtypep->nrange();
}
addToSubFunc(new AstTraceDecl{m_traVscp->fileline(), m_traName, m_traVscp->varp(),
m_traValuep->cloneTree(false), bitRange, arrayRange});
auto* const newp
= new AstTraceDecl{m_traVscp->fileline(), m_traName, m_traVscp->varp(),
m_traValuep->cloneTree(false), bitRange, arrayRange};
addToSubFunc(newp);
}
void addIgnore(const char* why) {
@ -217,17 +240,14 @@ private:
UASSERT_OBJ(!m_traVscp, 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;
// Gather all signals under this AstScope
iterateChildrenConst(nodep);
// If nothing to trace in this scope, then job done
if (m_signals.empty()) {
m_currScopep = nullptr;
return;
}
if (m_signals.empty()) return;
// 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) {
@ -239,6 +259,7 @@ private:
});
// Build trace initialization functions for this AstScope
FileLine* const flp = nodep->fileline();
PathAdjustor pathAdjustor{flp, [&](AstNodeStmt* stmtp) { addToSubFunc(stmtp); }};
for (const Signal& signal : m_signals) {
// Adjust name prefix based on path in hierarchy
@ -278,6 +299,7 @@ private:
scopeName = scopeName.substr(0, lastDot + 1);
const size_t scopeLen = scopeName.length();
UASSERT_OBJ(cellp->intfRefp(), cellp, "Interface without tracing reference");
for (AstIntfRef *irp = cellp->intfRefp(), *nextIrp; irp; irp = nextIrp) {
nextIrp = VN_AS(irp->nextp(), IntfRef);
@ -288,6 +310,9 @@ private:
string scopeName = AstNode::vcdName(irp->name());
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) + ' ';
m_scopeSubFuncps.emplace(scopeName, m_subFuncps);
@ -300,8 +325,6 @@ private:
if (VString::startsWith(scopeName, "TOP ")) scopeName.erase(0, 4);
m_scopeSubFuncps.emplace(scopeName, std::move(m_subFuncps));
}
m_currScopep = nullptr;
}
virtual void visit(AstVarScope* nodep) override {
UASSERT_OBJ(m_currScopep, nodep, "AstVarScope not under AstScope");
@ -454,9 +477,10 @@ public:
// Build top level trace initialization functions
PathAdjustor pathAdjustor{flp, [&](AstNodeStmt* stmtp) { addToTopFunc(stmtp); }};
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
pathAdjustor.adjust(item.first);
pathAdjustor.adjust(scopeNameInterfaced);
// Call all sub functions for this path
for (AstCFunc* const subFuncp : item.second) {
AstCCall* const callp = new AstCCall{flp, subFuncp};

View File

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

View File

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

View File

@ -3111,7 +3111,7 @@ statement_item<nodep>: // IEEE: statement_item
//
// // IEEE: conditional_statement
| 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;
if ($1 == uniq_UNIQUE) newp->uniquePragma(true);
if ($1 == uniq_UNIQUE0) newp->unique0Pragma(true);
@ -3180,7 +3180,7 @@ statement_item<nodep>: // IEEE: statement_item
$$ = $2->cloneTree(true);
$$->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
| 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.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(vlt => 1);
scenarios(simulator => 1);
compile();
if ($Self->{vlt_all}) {
# The word 'this' (but only the whole word 'this' should have been replaced
# in the contents.
my $file = glob_one("$Self->{obj_dir}/$Self->{VM_PREFIX}___024root__DepSet_*__0.cpp");
my $text = file_contents($file);
error("$file has 'this->clk'") if ($text =~ m/\bthis->clk\b/);
error("$file does not have 'xthis'") if ($text !~ m/\bxthis\b/);
error("$file does not have 'thisx'") if ($text !~ m/\bthisx\b/);
error("$file does not have 'xthisx'") if ($text !~ m/\bxthisx\b/);
my $has_this = 0;
my $has_xthis = 0;
my $has_thisx = 0;
my $has_xthisx = 0;
for my $file (glob_all("$Self->{obj_dir}/$Self->{VM_PREFIX}___024root__DepSet_*__0.cpp")) {
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);

View File

@ -22,9 +22,9 @@ module t(/*AUTOARG*/
event ev [3:0];
`endif
int cyc;
int cyc = 0;
int last_event;
int last_event = 0;
always @(e1) begin
`WRITE_VERBOSE(("[%0t] e1\n", $time));
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
: ... In instance t.unnamedblk1.unnamedblk1.index
14 | foreach (ass[index]) begin
| ^~~~~
%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
: ... In instance t.b
12 | initial c = (a != &b);
| ^
%Error: Exiting due to

View File

@ -1,7 +1,6 @@
$version Generated by VerilatedVcd $end
$date Wed Dec 4 07:47:51 2019
$end
$timescale 1ps $end
$date Thu Apr 14 07:06:40 2022 $end
$timescale 1ps $end
$scope module top $end
$var wire 1 0 clk $end
@ -57,6 +56,10 @@ $timescale 1ps $end
$var wire 1 0 clk $end
$var wire 32 # cyc [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
$var wire 32 + val100 [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 32 # cyc [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
$var wire 32 . val100 [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 32 # cyc [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
$var wire 32 % val100 [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 32 # cyc [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
$var wire 32 ( val100 [31:0] $end
$var wire 32 ) val200 [31:0] $end
@ -236,6 +251,10 @@ b00000000000000000000001111101010 -
b00000000000000000000010001001110 .
b00000000000000000000010010110010 /
00
b00000000000000000000000000000000 1
b00000000000000000000000000000000 2
b00000000000000000000000000000000 3
b00000000000000000000000000000000 4
#10
b00000000000000000000000000000001 #
b00000000000000000000000000000010 $

View File

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

View File

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

View File

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

View File

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