Optimize module inlining heuristic (#7837)

Rewrite module inlining decision to be based on a bipartite Module/Cell
graph, similar to V3InlineCFuncs. Preserved all old heuristics, but
added 2 new ones:

- If a module, and all the sub-hierarchy below it, is less than 10% the
  total flattened size of the design, then flatten the contents of that
  module (but the module itself is not necessarily inlined).

- If the flattened size of all instances of a module is less than 20% of
  the total flattened size of the design, then inline all instances of
  that module.

These are both relative to the total size of the design, so they
auto-scale with complexity. The net effect is that large shared
instances are preserved, but their contents are flattened out. E.g. in a
multi-core CPU this would keep the cores non-inlined but flatten out
most everything else. This still enables V3Combining and sharing those
later, but avoids potentially big overheads e.g. with small widely used
library modules.

Empirically this yields less generated C++ than the previous version
(due to removing lots of small functions), and can improve performance
10-20% while still having meaningful combining relative to the size of
the design.
This commit is contained in:
Geza Lore 2026-06-25 14:14:15 +01:00 committed by GitHub
parent 000afcf52d
commit b73a897db3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 550 additions and 351 deletions

View File

@ -29,6 +29,7 @@
#include "V3Inline.h"
#include "V3AstUserAllocator.h"
#include "V3Graph.h"
#include "V3Inst.h"
#include "V3Stats.h"
@ -41,208 +42,334 @@ VL_DEFINE_DEBUG_FUNCTIONS;
static const int INLINE_MODS_SMALLER = 100; // If a mod is < this # nodes, can always inline it
//######################################################################
// Inlining state. Kept as AstNodeModule::user1p via AstUser1Allocator
// Bipartite module instantiation graph containing module and cell vertices
namespace {
class InlineModModuleVertex;
class InlineModCellVertex;
struct ModuleState final {
bool m_inlined = false; // Whether to inline this module
unsigned m_cellRefs = 0; // Number of AstCells instantiating this module
std::vector<AstCell*> m_childCells; // AstCells under this module (to speed up traversal)
};
using ModuleStateUser1Allocator = AstUser1Allocator<AstNodeModule, ModuleState>;
} // namespace
//######################################################################
// Visitor that determines which modules will be inlined
class InlineMarkVisitor final : public VNVisitor {
class InlineModGraph final : public V3Graph {
// NODE STATE
// Output
// AstNodeModule::user1() // OUTPUT: ModuleState instance (via m_moduleState)
// Internal state (can be cleared after this visit completes)
// AstNodeModule::user2() // CIL_*. Allowed to automatically inline module
// AstNodeModule::user4() // int. Statements in module
const VNUser2InUse m_inuser2;
const VNUser4InUse m_inuser4;
// AstNodeModule::user4p() -> InlineModModuleVertex*, the module vertex
// AstCell::user4p() -> InlineModCellVertex*, the cell vertex
ModuleStateUser1Allocator& m_moduleState;
VNUser4InUse m_user4InUse;
// For the user2 field:
enum : uint8_t {
CIL_NOTHARD = 0, // Inline not supported
CIL_NOTSOFT, // Don't inline unless user overrides
CIL_MAYBE, // Might inline
CIL_USER
}; // Pragma suggests inlining
// STATE
AstNodeModule* m_modp = nullptr; // Current module
VDouble0 m_statUnsup; // Statistic tracking
std::vector<AstNodeModule*> m_allMods; // All modules, in top-down order.
// Within the context of a given module, LocalInstanceMap maps
// from child modules to the count of each child's local instantiations.
using LocalInstanceMap = std::unordered_map<AstNodeModule*, unsigned>;
// We keep a LocalInstanceMap for each module in the design
std::unordered_map<AstNodeModule*, LocalInstanceMap> m_instances;
public:
InlineModGraph()
: V3Graph{} {}
~InlineModGraph() override = default;
// METHODS
void cantInline(const char* reason, bool hard) {
if (hard) {
if (m_modp->user2() != CIL_NOTHARD) {
UINFO(4, " No inline hard: " << reason << " " << m_modp);
m_modp->user2(CIL_NOTHARD);
++m_statUnsup;
}
} else {
if (m_modp->user2() == CIL_MAYBE) {
UINFO(4, " No inline soft: " << reason << " " << m_modp);
m_modp->user2(CIL_NOTSOFT);
InlineModModuleVertex* getInlineModModuleVertexp(AstNodeModule* modp);
InlineModCellVertex* getInlineModCellVertexp(AstCell* cellp);
void addEdge(InlineModModuleVertex& from, InlineModCellVertex& to);
void addEdge(InlineModCellVertex& from, InlineModModuleVertex& to);
// debug
std::string dotRankDir() const override { return "LR"; }
};
class InlineModEitherVertex VL_NOT_FINAL : public V3GraphVertex {
VL_RTTI_IMPL(InlineModEitherVertex, V3GraphVertex)
protected:
explicit InlineModEitherVertex(InlineModGraph& graph)
: V3GraphVertex{&graph} {}
};
class InlineModModuleVertex final : public InlineModEitherVertex {
VL_RTTI_IMPL(InlineModModuleVertex, InlineModEitherVertex)
AstNodeModule* const m_modp; // The module
const char* m_noInlineHardWyp = nullptr; // First reason the module can never be inlined
const char* m_noInlineSoftWyp = nullptr; // First reason not to inline unless forced
const char* m_shouldInlineWhyp = nullptr; // First reason why this module should be inlined
size_t m_size = 0; // The size (statement count) of the module
size_t mutable m_flattenedSize = 0; // The size of the module if flattened
bool mutable m_flattenedSizeValid = false; // Whether the flattened size is valid
size_t mutable m_instanceCount = 0; // The number of total instances of this module
bool mutable m_instanceCountValid = false; // Whether the instance count is valid
public:
InlineModModuleVertex(InlineModGraph& graph, AstNodeModule* modp)
: InlineModEitherVertex{graph}
, m_modp{modp} {}
~InlineModModuleVertex() override = default;
// ACCESSORS
AstNodeModule* modp() const { return m_modp; }
size_t size() const { return m_size; }
void size(size_t value) { m_size = value; }
void sizeInc(size_t value = 1) { m_size += value; }
bool noInlineHard() const { return m_noInlineHardWyp; }
void setNoInlineHard(const char* whyp) {
if (!m_noInlineHardWyp) m_noInlineHardWyp = whyp;
}
bool noInlineSoft() const { return m_noInlineSoftWyp; }
void setNoInlineSoft(const char* whyp) {
if (!m_noInlineSoftWyp) m_noInlineSoftWyp = whyp;
}
bool shouldInline() const { return m_shouldInlineWhyp; }
void setShouldInline(const char* whyp) {
if (!m_shouldInlineWhyp) m_shouldInlineWhyp = whyp;
}
// Mark every instance below this module for inlining
void setFlatten();
// Total size of module, with all hierarchy below flattened
size_t flattenedSize() const {
if (!m_flattenedSizeValid) {
m_flattenedSizeValid = true;
m_flattenedSize = m_size;
for (const V3GraphEdge& e1 : outEdges()) {
for (const V3GraphEdge& e2 : e1.top()->outEdges()) {
InlineModModuleVertex* const mVtxp = e2.top()->as<InlineModModuleVertex>();
m_flattenedSize += mVtxp->flattenedSize();
}
}
}
return m_flattenedSize;
}
// Total number of instances of this module in the whole hierarchy of the design
size_t instanceCount() const {
if (!m_instanceCountValid) {
m_instanceCountValid = true;
m_instanceCount = 0;
for (const V3GraphEdge& e1 : inEdges()) {
for (const V3GraphEdge& e2 : e1.fromp()->inEdges()) {
InlineModModuleVertex* const mVtxp = e2.fromp()->as<InlineModModuleVertex>();
m_instanceCount += mVtxp->instanceCount();
}
}
if (!m_instanceCount) {
UASSERT_OBJ(m_modp->isTop(), m_modp, "non-top level module should have instances");
m_instanceCount = 1;
}
}
return m_instanceCount;
}
// debug
FileLine* fileline() const override { return m_modp->fileline(); }
std::string dotShape() const override { return "box"; }
std::string dotColor() const override {
return m_noInlineHardWyp ? "red"
: m_shouldInlineWhyp ? "blue"
: m_noInlineSoftWyp ? "orange"
: "black";
}
std::string name() const override VL_MT_STABLE {
std::string str = m_modp->typeName() + " "s + cvtToHex(m_modp);
str += "\n" + m_modp->name() + " @ " + fileline()->ascii();
str += "\ninstanceCount: " + std::to_string(instanceCount());
str += "\nsize: " + std::to_string(m_size);
str += "\nflattenedSize: " + std::to_string(flattenedSize());
if (m_shouldInlineWhyp) str += "\nShouldInline: "s + m_shouldInlineWhyp;
if (m_noInlineHardWyp) str += "\nNoInlineHard: "s + m_noInlineHardWyp;
if (m_noInlineSoftWyp) str += "\nNoInlineSoft: "s + m_noInlineSoftWyp;
str += "\n";
return str;
}
};
class InlineModCellVertex final : public InlineModEitherVertex {
VL_RTTI_IMPL(InlineModCellVertex, InlineModEitherVertex)
AstCell* const m_cellp; // The cell (instance)
const char* m_doInlineWyp = nullptr; // First reason this instance should be inlined
bool m_flatten = false; // Whether this cell and below already flattened (avoid O(n^2))
public:
InlineModCellVertex(InlineModGraph& graph, AstCell* cellp)
: InlineModEitherVertex{graph}
, m_cellp{cellp} {}
~InlineModCellVertex() override = default;
// ACCESSORS
AstCell* cellp() const { return m_cellp; }
bool doInline() const { return m_doInlineWyp; }
void setDoInline(const char* whyp) {
if (!m_doInlineWyp) m_doInlineWyp = whyp;
}
bool flatten() const { return m_flatten; }
void setFlatten() { m_flatten = true; }
// The module vertx this cell is instantiating
InlineModModuleVertex& instanceOf() const {
UASSERT_OBJ(outSize1(), this, "Cell should have exactly one outgoing edge");
return *outEdges().frontp()->top()->as<InlineModModuleVertex>();
}
// The module vertex this cell is instantiated in
InlineModModuleVertex& instanceIn() const {
UASSERT_OBJ(inSize1(), this, "Cell should have exactly one incoming edge");
return *inEdges().frontp()->fromp()->as<InlineModModuleVertex>();
}
// debug
FileLine* fileline() const override { return m_cellp->fileline(); }
std::string dotColor() const override { return m_doInlineWyp ? "green" : "black"; }
std::string dotShape() const override { return "ellipse"; }
std::string name() const override VL_MT_STABLE {
std::string str = m_cellp->typeName() + " "s + cvtToHex(m_cellp);
str += "\n" + m_cellp->name() + " @ " + fileline()->ascii();
if (m_doInlineWyp) str += "\nDoInline: "s + m_doInlineWyp;
str += "\n";
return str;
}
};
InlineModModuleVertex* InlineModGraph::getInlineModModuleVertexp(AstNodeModule* modp) {
if (!modp->user4p()) modp->user4p(new InlineModModuleVertex{*this, modp});
return modp->user4u().to<InlineModModuleVertex*>();
}
InlineModCellVertex* InlineModGraph::getInlineModCellVertexp(AstCell* cellp) {
if (!cellp->user4p()) cellp->user4p(new InlineModCellVertex{*this, cellp});
return cellp->user4u().to<InlineModCellVertex*>();
}
void InlineModGraph::addEdge(InlineModModuleVertex& parent, InlineModCellVertex& cell) {
UASSERT_OBJ(cell.inEmpty(), &cell, "Cell should have at most one incoming edge");
new V3GraphEdge{this, &parent, &cell, 1, /* cutable: */ false};
}
void InlineModGraph::addEdge(InlineModCellVertex& cell, InlineModModuleVertex& submodule) {
UASSERT_OBJ(cell.outEmpty(), &cell, "Cell should have at most one outgoing edge");
new V3GraphEdge{this, &cell, &submodule, 1, /* cutable: */ false};
}
void InlineModModuleVertex::setFlatten() {
for (V3GraphEdge& edge : outEdges()) {
InlineModCellVertex& cVtx = *edge.top()->as<InlineModCellVertex>();
if (cVtx.flatten()) continue;
cVtx.setFlatten();
InlineModModuleVertex& iVtx = cVtx.instanceOf();
if (!iVtx.noInlineHard() && !iVtx.noInlineSoft()) cVtx.setDoInline("flatten parent");
iVtx.setFlatten();
}
}
//######################################################################
// Visitor that builds the bipartite module instantiation graph
class InlineModGraphBuilder final : public VNVisitor {
// STATE
std::unique_ptr<InlineModGraph> m_graphp{new InlineModGraph}; // The graph being built
InlineModModuleVertex* m_modVtxp = nullptr; // Vertex of module currently being iterated
// VISITORS
void visit(AstNodeModule* nodep) override {
UASSERT_OBJ(!m_modp, nodep, "Unsupported: Nested modules");
VL_RESTORER(m_modp);
m_modp = nodep;
m_allMods.push_back(nodep);
m_modp->user2(CIL_MAYBE);
m_modp->user4(0); // statement count
if (VN_IS(m_modp, Iface)) {
// Inlining an interface means we no longer have a cell handle to resolve to.
// If inlining moves post-scope this can perhaps be relaxed.
cantInline("modIface", true);
}
if (m_modp->modPublic() && (m_modp->isTop() || !v3Global.opt.flatten())) {
cantInline("modPublic", false);
}
// If the instance is a --lib-create library stub instance, and need tracing,
// then don't inline as we need to know its a lib stub for sepecial handling
// in V3TraceDecl. See #7001.
if (m_modp->verilatorLib() && v3Global.opt.trace()) {
cantInline("verilatorLib with --trace", false);
if (nodep == v3Global.rootp()->constPoolp()->modp()) return; // Ignore const pool module
UASSERT_OBJ(!m_modVtxp, nodep, "Unsupported: Nested modules");
// Create the module vertex
InlineModModuleVertex* const vtxp = m_graphp->getInlineModModuleVertexp(nodep);
// Check if the module itself is not inlineable
// Inlining an interface means we no longer have a cell handle to resolve to.
// If inlining moves post-scope this can perhaps be relaxed.
if (VN_IS(nodep, Iface)) vtxp->setNoInlineHard("Interface");
// Never inline packages - TODO: conceptually fine, but why not?
if (VN_IS(nodep, Package)) vtxp->setNoInlineHard("Package");
// A --lib-create library stub instance that needs tracing must not be
// inlined, so we still know it is a lib stub in V3TraceDecl (see #7001)
if (nodep->verilatorLib() && v3Global.opt.trace()) {
vtxp->setNoInlineHard("verilatorLib with --trace");
}
iterateChildren(nodep);
// Don't inline public modules by default
if (nodep->modPublic()) vtxp->setNoInlineSoft("Public module");
// Iterate children
VL_RESTORER(m_modVtxp);
m_modVtxp = vtxp;
iterateChildrenConst(nodep);
}
void visit(AstClass* nodep) override {
// TODO allow inlining of modules that have classes
// (Probably wait for new inliner scheme)
cantInline("class", true);
iterateChildren(nodep);
// TODO allow inlining of modules that contain classes
if (m_modVtxp) m_modVtxp->setNoInlineHard("Contains class");
iterateChildrenConst(nodep); // TODO: this is only needed or FTaskRef cleanup
}
// Cells instantiate modules
void visit(AstCell* nodep) override {
m_moduleState(nodep->modp()).m_cellRefs++;
m_moduleState(m_modp).m_childCells.push_back(nodep);
m_instances[m_modp][nodep->modp()]++;
iterateChildren(nodep);
UASSERT_OBJ(m_modVtxp, nodep, "Cell should be under a module");
// Create the cell vertex
InlineModCellVertex* const vtxp = m_graphp->getInlineModCellVertexp(nodep);
// Add containing-module/instantiated-module edges
m_graphp->addEdge(*m_modVtxp, *vtxp);
m_graphp->addEdge(*vtxp, *m_graphp->getInlineModModuleVertexp(nodep->modp()));
// Iterate children
iterateChildrenConst(nodep);
}
void visit(AstPragma* nodep) override {
if (nodep->pragType() == VPragmaType::INLINE_MODULE) {
if (!m_modp) {
if (!m_modVtxp) {
nodep->v3error("Inline pragma not under a module"); // LCOV_EXCL_LINE
} else if (m_modp->user2() == CIL_MAYBE || m_modp->user2() == CIL_NOTSOFT) {
m_modp->user2(CIL_USER);
} else {
m_modVtxp->setShouldInline("Pragma INLINE_MODULE");
}
// Remove so it does not propagate to upper cell
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
} else if (nodep->pragType() == VPragmaType::NO_INLINE_MODULE) {
if (!m_modp) {
nodep->v3error("Inline pragma not under a module"); // LCOV_EXCL_LINE
} else if (!v3Global.opt.flatten()) {
cantInline("Pragma NO_INLINE_MODULE", false);
}
// Remove so it does not propagate to upper cell
// Remove so don't propagate to upper cell...
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
return;
}
if (nodep->pragType() == VPragmaType::NO_INLINE_MODULE) {
if (!m_modVtxp) {
nodep->v3error("Inline pragma not under a module"); // LCOV_EXCL_LINE
} else {
m_modVtxp->setNoInlineSoft("Pragma NO_INLINE_MODULE");
}
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
return;
}
iterateChildrenConst(nodep);
}
void visit(AstVarXRef* nodep) override {
// Keep varp - V3Const::constifyEdit is called during pinReconnectSimple
// which needs varp to be set. V3LinkDot will re-resolve after inlining.
}
// TODO: Bit nasty to do this here, but historically present, and still necessary
void visit(AstNodeFTaskRef* nodep) override {
if (m_modVtxp) m_modVtxp->sizeInc();
// Remove link. V3LinkDot will reestablish it after inlining.
// MethodCalls not currently supported by inliner, so keep linked
if (!nodep->classOrPackagep() && !VN_IS(nodep, MethodCall)) {
nodep->taskp(nullptr);
VIsCached::clearCacheTree();
}
iterateChildren(nodep);
iterateChildrenConst(nodep);
}
void visit(AstAlways* nodep) override {
if (nodep->keyword() != VAlwaysKwd::CONT_ASSIGN) nodep->user4Inc(); // statement count
iterateChildren(nodep);
}
void visit(AstNodeAssign* nodep) override {
// Don't count assignments, as they'll likely flatten out
// Still need to iterate though to nullify VarXRefs
const int oldcnt = m_modp->user4();
iterateChildren(nodep);
m_modp->user4(oldcnt);
}
void visit(AstNetlist* nodep) override {
// Build ModuleState, user2, and user4 for all modules.
// Also build m_allMods and m_instances.
iterateChildren(nodep);
// Iterate through all modules in bottom-up order.
// Make a final inlining decision for each.
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:
int statements = modp->user4();
for (const auto& pair : m_instances[modp]) {
const AstNodeModule* const childp = pair.first;
if (m_moduleState(childp).m_inlined) { // inlining child
statements += childp->user4() * pair.second;
}
}
modp->user4(statements);
const int allowed = modp->user2();
const int refs = m_moduleState(modp).m_cellRefs;
// Should we automatically inline this module?
// If --flatten is specified, then force everything to be inlined that can be.
// inlineMult = 2000 by default.
// If a mod*#refs is < this # nodes, can inline it
// Packages aren't really "under" anything so they confuse this algorithm
const bool doit = !VN_IS(modp, Package) //
&& allowed != CIL_NOTHARD //
&& allowed != CIL_NOTSOFT //
&& (allowed == CIL_USER //
|| v3Global.opt.flatten() //
|| refs == 1 //
|| statements < INLINE_MODS_SMALLER //
|| v3Global.opt.inlineMult() < 1 //
|| refs * statements < v3Global.opt.inlineMult());
m_moduleState(modp).m_inlined = doit;
UINFO(4, " Inline=" << doit << " Possible=" << allowed << " Refs=" << refs
<< " Stmts=" << statements << " " << modp);
}
}
//--------------------
// Base node
void visit(AstNode* nodep) override {
if (m_modp) m_modp->user4Inc(); // Inc statement count
iterateChildren(nodep);
if (m_modVtxp) m_modVtxp->sizeInc();
iterateChildrenConst(nodep);
}
// CONSTRUCTORS
explicit InlineModGraphBuilder(AstNetlist* nodep) {
// Build the module instantiation graph
iterateConst(nodep);
// Order vertices (any topological order is fine), can't be cyclic at this point
m_graphp->order();
// Check that the first vertex is the top level module (everything, including packages,
// have a corresponding AstCell under the top level at this point).
UASSERT_OBJ(m_graphp->vertices().frontp()->as<InlineModModuleVertex>()->modp()->isTop(),
nodep, "First vertex should be top level module");
#ifdef VL_DEBUG
for (const V3GraphVertex& vtx : m_graphp->vertices()) {
// First vertex is the top levelmodule, we checked above
if (&vtx == m_graphp->vertices().frontp()) continue;
// Otherwise it should have instantiations
UASSERT_OBJ(!vtx.inEmpty(), &vtx, "Should have edges from root");
}
#endif
}
~InlineModGraphBuilder() override = default;
public:
// CONSTRUCTORS
explicit InlineMarkVisitor(AstNode* nodep, ModuleStateUser1Allocator& moduleState)
: m_moduleState{moduleState} {
iterate(nodep);
}
~InlineMarkVisitor() override {
V3Stats::addStat("Optimizations, Inline unsupported", m_statUnsup);
static std::unique_ptr<InlineModGraph> apply(AstNetlist* nodep) {
return std::move(InlineModGraphBuilder{nodep}.m_graphp);
}
};
@ -264,8 +391,12 @@ class InlineRelinkVisitor final : public VNVisitor {
m_pinSubstitutedXRefs; // VarXRefs created by pin substitution in this relink pass.
// Their dotted/inlinedDots already represent the parent's scope
// and must not be rewritten on the immediate visit.
InlineModGraph& m_graph; // The instance graph
AstNodeModule* const m_modp; // The module we are inlining into
// The vertex of the module we are inlining into, for updating the graph
InlineModModuleVertex* const m_mVtxp = m_graph.getInlineModModuleVertexp(m_modp);
const AstCell* const m_cellp; // The cell being inlined
size_t m_nPlaceholders = 0; // Unique identifier sequence number for placeholder variables
// VISITORS
@ -282,6 +413,11 @@ class InlineRelinkVisitor final : public VNVisitor {
void visit(AstCell* nodep) override {
// Cell under the inline cell, need to rename to avoid conflicts
nodep->name(m_cellp->name() + "__DOT__" + nodep->name());
// Need to update graph
nodep->user4p(nullptr); // clone copied user4p, reset to make new vertex
InlineModCellVertex* const vtxp = m_graph.getInlineModCellVertexp(nodep);
m_graph.addEdge(*m_mVtxp, *vtxp);
m_graph.addEdge(*vtxp, *m_graph.getInlineModModuleVertexp(nodep->modp()));
iterateChildren(nodep);
}
void visit(AstClass* nodep) override {
@ -464,8 +600,10 @@ class InlineRelinkVisitor final : public VNVisitor {
public:
// CONSTRUCTORS
InlineRelinkVisitor(AstNodeModule* cloneModp, AstNodeModule* oldModp, AstCell* cellp)
: m_modp{oldModp}
InlineRelinkVisitor(AstNodeModule* cloneModp, AstNodeModule* oldModp, AstCell* cellp,
InlineModGraph& graph)
: m_graph{graph}
, m_modp{oldModp}
, m_cellp{cellp} {
// CellInlines added by V3Begin for generate/named blocks have origModName
// "__BEGIN__"; only those added by prior V3Inline passes carry a real module
@ -607,7 +745,7 @@ void connectPort(AstNodeModule* modp, AstVar* nodep, AstNodeExpr* pinExprp) {
}
// Inline 'cellp' into 'modp'. 'last' indicatest this is tha last instance of the inlined module
void inlineCell(AstNodeModule* modp, AstCell* cellp, bool last) {
void inlineCell(AstNodeModule* modp, AstCell* cellp, bool last, InlineModGraph& graph) {
UINFO(5, " Inline Cell " << cellp);
UINFO(5, " into Module " << modp);
@ -662,8 +800,8 @@ void inlineCell(AstNodeModule* modp, AstCell* cellp, bool last) {
connectPort(modp, newModVarp, pinExprp);
}
// Cleanup var names, etc, to not conflict, relink replaced variables
{ InlineRelinkVisitor{inlinedp, modp, cellp}; }
// Cleanup var names, etc, to not conflict, relink replaced variables, adjust graph
{ InlineRelinkVisitor{inlinedp, modp, cellp, graph}; }
// Move statements from the inlined module into the module we are inlining into
if (AstNode* const stmtsp = inlinedp->stmtsp()) {
modp->addStmtsp(stmtsp->unlinkFrBackWithNext());
@ -675,39 +813,60 @@ void inlineCell(AstNodeModule* modp, AstCell* cellp, bool last) {
}
// Apply all inlining decisions
void process(AstNetlist* netlistp, ModuleStateUser1Allocator& moduleStates) {
void process(AstNetlist* netlistp, InlineModGraph& graph) {
// NODE STATE
// Input:
// AstNodeModule::user1p() // ModuleState instance (via moduleState)
//
// Cleared entire netlist
// AstIfaceRefDType::user1() // Whether the cell pointed to by this
// // AstIfaceRefDType has been inlined
// AstCell::user3p() // AstCell*, the clone
// AstVar::user3p() // AstVar*, the clone clone
// AstVar::user3p() // AstVar*, the clone
// Cleared each cell
// AstVar::user2p() // AstVarRef*/AstConst* This port is connected to (AstPin::expr())
const VNUser3InUse m_user3InUse;
const VNUser1InUse user1InUse;
const VNUser3InUse user3InUse;
// Number of inlined instances, for statistics
VDouble0 m_nInlined;
// We want to inline bottom up. The modules under the netlist are in
// dependency order (top first, leaves last), so find the end of the list.
AstNode* nodep = netlistp->modulesp();
while (nodep->nextp()) nodep = nodep->nextp();
// Gather all cells that need to be inlined (this is in topological order)
std::vector<InlineModCellVertex*> cVtxps;
for (V3GraphVertex& vtx : graph.vertices()) {
InlineModCellVertex* const cVtxp = vtx.cast<InlineModCellVertex>();
if (!cVtxp) continue;
if (!cVtxp->doInline()) continue;
cVtxps.push_back(cVtxp);
}
// Iterate module list backwards (stop when we get back to the Netlist)
while (AstNodeModule* const modp = VN_CAST(nodep, NodeModule)) {
nodep = nodep->backp();
// Inline cells bottom up (leaves into roots)
for (InlineModCellVertex* const cVtxp : vlstd::reverse_view(cVtxps)) {
// Pick up parts before deleting
InlineModModuleVertex& mVtx = cVtxp->instanceIn();
InlineModModuleVertex* const iVtxp = &cVtxp->instanceOf();
AstCell* const cellp = cVtxp->cellp();
const bool last = iVtxp->inSize1();
UASSERT_OBJ(!iVtxp->noInlineHard(), cellp, "Should not be inlining if not possible");
// Consider each cell inside the current module for inlining
for (AstCell* const cellp : moduleStates(modp).m_childCells) {
ModuleState& childState = moduleStates(cellp->modp());
if (!childState.m_inlined) continue;
++m_nInlined;
inlineCell(modp, cellp, --childState.m_cellRefs == 0);
// Update
++m_nInlined;
mVtx.sizeInc(iVtxp->size()); // For debug dump only
// Delete the cell we are inlining
VL_DO_DANGLING(cVtxp->unlinkDelete(&graph), cVtxp);
// Delete the module we are inlining if this is the last instance
if (last) {
while (!iVtxp->outEmpty()) {
InlineModCellVertex* const tVtxp
= iVtxp->outEdges().frontp()->top()->as<InlineModCellVertex>();
// Bottom up ordering ensures this
UASSERT_OBJ(!tVtxp->doInline(), tVtxp, "Should have been inlined");
VL_DO_DANGLING(tVtxp->unlinkDelete(&graph), tVtxp);
}
VL_DO_DANGLING(iVtxp->unlinkDelete(&graph), iVtxp);
}
// Do it
inlineCell(mVtx.modp(), cellp, last, graph);
if (dumpGraphLevel() >= 9) graph.dumpDotFilePrefixed("inlinemod-cell");
}
V3Stats::addStat("Optimizations, Inlined instances", m_nInlined);
@ -729,25 +888,65 @@ void process(AstNetlist* netlistp, ModuleStateUser1Allocator& moduleStates) {
void V3Inline::inlineAll(AstNetlist* nodep) {
UINFO(2, __FUNCTION__ << ":");
{
const VNUser1InUse m_inuser1; // output of InlineMarkVisitor, input to InlineVisitor.
ModuleStateUser1Allocator moduleState; // AstUser1Allocator
// Build the bipartite module instantiation graph
std::unique_ptr<InlineModGraph> graphp = InlineModGraphBuilder::apply(nodep);
if (dumpGraphLevel() >= 6) graphp->dumpDotFilePrefixed("inlinemod-graph");
// Scoped to clean up temp userN's
{ InlineMarkVisitor{nodep, moduleState}; }
// Inline the modles we decided to inline
ModuleInliner::process(nodep, moduleState);
// Check inlined modules have been removed during traversal. Otherwise we might have blown
// up Verilator memory consumption.
for (AstNodeModule* modp = v3Global.rootp()->modulesp(); modp;
modp = VN_AS(modp->nextp(), NodeModule)) {
UASSERT_OBJ(!moduleState(modp).m_inlined, modp,
"Inlined module should have been deleted when the last instance "
"referencing it was inlined");
// Decide which instances to inline
const size_t designSize
= graphp->vertices().frontp()->as<InlineModModuleVertex>()->flattenedSize();
for (V3GraphVertex& vtx : graphp->vertices()) {
if (InlineModModuleVertex* const mVtxp = vtx.cast<InlineModModuleVertex>()) {
// If this module is less than 10% of the design, flatten this module
if (mVtxp->flattenedSize() * 10 < designSize) mVtxp->setFlatten();
// Don't inline if can't inline
if (mVtxp->noInlineHard()) continue;
// Don't inline if soft off
if (mVtxp->noInlineSoft()) continue;
// If all instances of this module combined are less than 20% of the design, inline all
size_t totalSize = mVtxp->flattenedSize() * mVtxp->instanceCount();
if (totalSize * 5 < designSize) {
for (V3GraphEdge& edge : mVtxp->inEdges()) {
InlineModCellVertex* const cVtxp = edge.fromp()->as<InlineModCellVertex>();
cVtxp->setDoInline("< 20% of design");
}
}
// No more decisions based on module vertex
continue;
}
// The instantiation
InlineModCellVertex& cVtx = *vtx.as<InlineModCellVertex>();
// The module instantiated by this cell
InlineModModuleVertex& mVtx = cVtx.instanceOf();
// Don't inline if can't inline, duh!
if (mVtx.noInlineHard()) continue;
// If it should be inlined, inlined it
if (mVtx.shouldInline()) cVtx.setDoInline("should inline");
// If --flatten, inline it
if (v3Global.opt.flatten()) cVtx.setDoInline("--flatten");
// Don't inline for other reasons if soft off
if (mVtx.noInlineSoft()) continue;
// If instatiated in exactly one static site, inline it
if (mVtx.inSize1()) cVtx.setDoInline("Single static instance");
// If small, inline it
if (mVtx.size() < INLINE_MODS_SMALLER) cVtx.setDoInline("Small");
// If inlineMult is 0, inline it
if (v3Global.opt.inlineMult() < 1) cVtx.setDoInline("inlineMult < 1");
// If it would yield less than the given number of ops, inline it
const size_t inlinedSize = mVtx.inEdges().size() * mVtx.size();
const size_t limit = v3Global.opt.inlineMult();
if (inlinedSize < limit) cVtx.setDoInline("inlinedSize < inlineMult");
}
if (dumpGraphLevel() >= 6) graphp->dumpDotFilePrefixed("inlinemod-decision");
// Inline the modles we decided to inline
ModuleInliner::process(nodep, *graphp);
if (dumpGraphLevel() >= 6) graphp->dumpDotFilePrefixed("inlinemod-inlined");
V3Global::dumpCheckGlobalTree("inline", 0, dumpTreeEitherLevel() >= 3);
}

View File

@ -1,33 +1,33 @@
%Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:26:19: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_then_u.state_q': assigned value 3 is not present in the declared enum
26 | S0: state_d = sel ? 2'd3 : S1;
%Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:274:19: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_wide_direct_u.state_q': assigned value 40'hffffffffff is not present in the declared enum
274 | S0: state_d = 40'hffff_ffff_ff;
| ^
... For warning description see https://verilator.org/warn/COVERIGN?v=latest
... Use "/* verilator lint_off COVERIGN */" and lint_on around source to disable this message.
%Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:53:19: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_else_u.state_q': assigned value 3 is not present in the declared enum
53 | S0: state_d = sel ? S1 : 2'd3;
| ^
%Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:79:19: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_direct_u.state_q': assigned value 3 is not present in the declared enum
79 | S0: state_d = 2'd3;
| ^
%Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:126:15: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_reset_u.state_q': assigned value 3 is not present in the declared enum
126 | state_q <= 2'd3;
| ^~
%Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:150:7: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_source_u.state_q': case item value 3 is not present in the declared enum
150 | 2'd3: state_d = S0;
| ^~~~
%Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:175:5: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_if_source_u.state_q': case item value 3 is not present in the declared enum
175 | if (state_q == 2'd3) state_d = S0;
| ^~
%Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:199:32: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_if_direct_target_u.state_q': assigned value 3 is not present in the declared enum
199 | if (state_q == S0) state_d = 2'd3;
%Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:249:32: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_if_else_target_u.state_q': assigned value 3 is not present in the declared enum
249 | if (state_q == S0) state_d = sel ? S1 : 2'd3;
| ^
%Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:224:32: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_if_then_target_u.state_q': assigned value 3 is not present in the declared enum
224 | if (state_q == S0) state_d = sel ? 2'd3 : S1;
| ^
%Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:249:32: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_if_else_target_u.state_q': assigned value 3 is not present in the declared enum
249 | if (state_q == S0) state_d = sel ? S1 : 2'd3;
%Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:199:32: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_if_direct_target_u.state_q': assigned value 3 is not present in the declared enum
199 | if (state_q == S0) state_d = 2'd3;
| ^
%Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:274:19: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_wide_direct_u.state_q': assigned value 40'hffffffffff is not present in the declared enum
274 | S0: state_d = 40'hffff_ffff_ff;
%Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:175:5: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_if_source_u.state_q': case item value 3 is not present in the declared enum
175 | if (state_q == 2'd3) state_d = S0;
| ^~
%Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:150:7: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_source_u.state_q': case item value 3 is not present in the declared enum
150 | 2'd3: state_d = S0;
| ^~~~
%Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:126:15: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_reset_u.state_q': assigned value 3 is not present in the declared enum
126 | state_q <= 2'd3;
| ^~
%Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:79:19: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_direct_u.state_q': assigned value 3 is not present in the declared enum
79 | S0: state_d = 2'd3;
| ^
%Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:53:19: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_else_u.state_q': assigned value 3 is not present in the declared enum
53 | S0: state_d = sel ? S1 : 2'd3;
| ^
%Warning-COVERIGN: t/t_cover_fsm_if_unknown_enum_multi_bad.v:26:19: Ignoring unsupported: FSM coverage on enum state variable 't.unknown_then_u.state_q': assigned value 3 is not present in the declared enum
26 | S0: state_d = sel ? 2'd3 : S1;
| ^
%Error: Exiting due to

View File

@ -1,12 +1,12 @@
%Warning-COVERIGN: t/t_cover_fsm_plain_always_warn_multi_bad.v:25:5: Ignoring unsupported: FSM coverage on non-clocked always blocks requires a combinational sensitivity list or always_comb
25 | case (state_q)
%Warning-COVERIGN: t/t_cover_fsm_plain_always_warn_multi_bad.v:86:5: Ignoring unsupported: FSM coverage on non-clocked always blocks requires a combinational sensitivity list or always_comb
86 | case (state_q)
| ^~~~
... For warning description see https://verilator.org/warn/COVERIGN?v=latest
... Use "/* verilator lint_off COVERIGN */" and lint_on around source to disable this message.
%Warning-COVERIGN: t/t_cover_fsm_plain_always_warn_multi_bad.v:55:5: Ignoring unsupported: FSM coverage on non-clocked always blocks requires a combinational sensitivity list or always_comb
55 | case (state_d)
| ^~~~
%Warning-COVERIGN: t/t_cover_fsm_plain_always_warn_multi_bad.v:86:5: Ignoring unsupported: FSM coverage on non-clocked always blocks requires a combinational sensitivity list or always_comb
86 | case (state_q)
%Warning-COVERIGN: t/t_cover_fsm_plain_always_warn_multi_bad.v:25:5: Ignoring unsupported: FSM coverage on non-clocked always blocks requires a combinational sensitivity list or always_comb
25 | case (state_q)
| ^~~~
%Error: Exiting due to

View File

@ -10,12 +10,12 @@
| ^
... For warning description see https://verilator.org/warn/WIDTHTRUNC?v=latest
... Use "/* verilator lint_off WIDTHTRUNC */" and lint_on around source to disable this message.
%Error: t/t_dpi_2exparg_bad.v:21:8: Duplicate declaration of DPI function with different signature: 'dpix_twice'
21 | task dpix_twice(input int i, output [63:0] o);
| ^~~~~~~~~~
: ... New signature: void dpix_twice (int, svLogicVecVal* /* logic[63:0] */ )
t/t_dpi_2exparg_bad.v:12:8: ... Original signature: void dpix_twice (int, svLogicVecVal* /* logic[2:0] */ )
%Error: t/t_dpi_2exparg_bad.v:12:8: Duplicate declaration of DPI function with different signature: 'dpix_twice'
12 | task dpix_twice(input int i, output [2:0] o);
| ^~~~~~~~~~
: ... New signature: void dpix_twice (int, svLogicVecVal* /* logic[2:0] */ )
t/t_dpi_2exparg_bad.v:21:8: ... Original signature: void dpix_twice (int, svLogicVecVal* /* logic[63:0] */ )
21 | task dpix_twice(input int i, output [63:0] o);
| ^~~~~~~~~~
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error: Exiting due to

View File

@ -1,29 +1,3 @@
%Warning-FSMMULTI: t/t_fsmmulti_combo_multi_warn_bad.v:36:21: FSM coverage: multiple supported transition candidates found in the same combinational always block. Only the first candidate will be instrumented.
36 | B0: state_b_d = B1;
| ^
t/t_fsmmulti_combo_multi_warn_bad.v:32:21: ... Location of first supported candidate for 't.same_u.state_a_q'
32 | A0: state_a_d = A1;
| ^
... For warning description see https://verilator.org/warn/FSMMULTI?v=latest
... Use "/* verilator lint_off FSMMULTI */" and lint_on around source to disable this message.
%Warning-FSMMULTI: t/t_fsmmulti_combo_multi_warn_bad.v:73:19: FSM coverage: multiple supported transition candidates found for the same FSM in combinational always blocks. Only the first candidate will be instrumented.
73 | S0: state_d = S1;
| ^
t/t_fsmmulti_combo_multi_warn_bad.v:65:19: ... Location of first supported candidate for 't.split_u.state_q'
65 | S0: state_d = S1;
| ^
%Warning-FSMMULTI: t/t_fsmmulti_combo_multi_warn_bad.v:107:5: FSM coverage: multiple supported transition candidates found in the same combinational always block. Only the first candidate will be instrumented.
107 | if (state_b_q == B0) state_b_d = B1;
| ^~
t/t_fsmmulti_combo_multi_warn_bad.v:105:5: ... Location of first supported candidate for 't.same_if_u.state_a_q'
105 | if (state_a_q == A0) state_a_d = A1;
| ^~
%Warning-FSMMULTI: t/t_fsmmulti_combo_multi_warn_bad.v:140:5: FSM coverage: multiple supported transition candidates found for the same FSM in combinational always blocks. Only the first candidate will be instrumented.
140 | if (state_q == S0) state_d = S1;
| ^~
t/t_fsmmulti_combo_multi_warn_bad.v:134:5: ... Location of first supported candidate for 't.split_if_u.state_q'
134 | if (state_q == S0) state_d = S1;
| ^~
%Warning-COVERIGN: t/t_fsmmulti_combo_multi_warn_bad.v:165:5: Ignoring unsupported: FSM coverage on multiple supported if-chain statements found in the same combinational always block. Only the first candidate will be instrumented.
165 | if (state_q == S1) state_d = S0;
| ^~
@ -32,4 +6,30 @@
| ^~
... For warning description see https://verilator.org/warn/COVERIGN?v=latest
... Use "/* verilator lint_off COVERIGN */" and lint_on around source to disable this message.
%Warning-FSMMULTI: t/t_fsmmulti_combo_multi_warn_bad.v:140:5: FSM coverage: multiple supported transition candidates found for the same FSM in combinational always blocks. Only the first candidate will be instrumented.
140 | if (state_q == S0) state_d = S1;
| ^~
t/t_fsmmulti_combo_multi_warn_bad.v:134:5: ... Location of first supported candidate for 't.split_if_u.state_q'
134 | if (state_q == S0) state_d = S1;
| ^~
... For warning description see https://verilator.org/warn/FSMMULTI?v=latest
... Use "/* verilator lint_off FSMMULTI */" and lint_on around source to disable this message.
%Warning-FSMMULTI: t/t_fsmmulti_combo_multi_warn_bad.v:107:5: FSM coverage: multiple supported transition candidates found in the same combinational always block. Only the first candidate will be instrumented.
107 | if (state_b_q == B0) state_b_d = B1;
| ^~
t/t_fsmmulti_combo_multi_warn_bad.v:105:5: ... Location of first supported candidate for 't.same_if_u.state_a_q'
105 | if (state_a_q == A0) state_a_d = A1;
| ^~
%Warning-FSMMULTI: t/t_fsmmulti_combo_multi_warn_bad.v:73:19: FSM coverage: multiple supported transition candidates found for the same FSM in combinational always blocks. Only the first candidate will be instrumented.
73 | S0: state_d = S1;
| ^
t/t_fsmmulti_combo_multi_warn_bad.v:65:19: ... Location of first supported candidate for 't.split_u.state_q'
65 | S0: state_d = S1;
| ^
%Warning-FSMMULTI: t/t_fsmmulti_combo_multi_warn_bad.v:36:21: FSM coverage: multiple supported transition candidates found in the same combinational always block. Only the first candidate will be instrumented.
36 | B0: state_b_d = B1;
| ^
t/t_fsmmulti_combo_multi_warn_bad.v:32:21: ... Location of first supported candidate for 't.same_u.state_a_q'
32 | A0: state_a_d = A1;
| ^
%Error: Exiting due to

View File

@ -1,12 +1,12 @@
created tag with scope = top.t.tag
created tag with scope = top.t.b.gen[0].tag
created tag with scope = top.t.b.gen[1].tag
created tag with scope = top.t.b.gen[0].tag
created tag with scope = top.t.tag
mod a has scope = top.t
mod a has tag = top.t.tag
mod b has scope = top.t.b
mod b has tag = top.t.tag
mod c has scope = top.t.b.gen[0].c
mod c has tag = top.t.b.gen[0].tag
mod c has scope = top.t.b.gen[1].c
mod c has tag = top.t.b.gen[1].tag
mod c has scope = top.t.b.gen[0].c
mod c has tag = top.t.b.gen[0].tag
*-* All Finished *-*

View File

@ -1,9 +1,9 @@
top.t.u_sub1.unnamedblk1 1..1 i=1
top.t.SUB_PIPE[0].u_sub.unnamedblk1 1..0 i=1
top.t.SUB_PIPE[0].u_sub.unnamedblk1 1..0 i=0
top.t.u_sub0.unnamedblk1 1..0 i=1
top.t.u_sub0.unnamedblk1 1..0 i=0
top.t.SUB_PIPE[-1].u_sub.unnamedblk1 1..-1 i=1
top.t.SUB_PIPE[-1].u_sub.unnamedblk1 1..-1 i=0
top.t.SUB_PIPE[-1].u_sub.unnamedblk1 1..-1 i=-1
top.t.SUB_PIPE[0].u_sub.unnamedblk1 1..0 i=1
top.t.SUB_PIPE[0].u_sub.unnamedblk1 1..0 i=0
top.t.u_sub1.unnamedblk1 1..1 i=1
*-* All Finished *-*

View File

@ -20,11 +20,11 @@ test.compile(
if test.vlt_all:
test.file_grep(
out_filename,
r'{"type":"VAR","name":"t.u.u0.u0.z1",.*"loc":"\w,70:[^"]*",.*"origName":"z1",.*"dtypeName":"logic"'
r'{"type":"VAR","name":"t.u.u1.u0.z1",.*"loc":"\w,70:[^"]*",.*"origName":"z1",.*"dtypeName":"logic"'
)
test.file_grep(
out_filename,
r'{"type":"VAR","name":"t.u.u0.u1.z1",.*"loc":"\w,70:[^"]*",.*"origName":"z1",.*"dtypeName":"logic"'
r'{"type":"VAR","name":"t.u.u1.u1.z1",.*"loc":"\w,70:[^"]*",.*"origName":"z1",.*"dtypeName":"logic"'
)
test.file_grep(
out_filename,

View File

@ -24,20 +24,20 @@
"valuep": [
{"type":"CONST","name":"2'h2","addr":"(Z)","loc":"d,25:43,25:44","dtypep":"(T)"}
],"attrsp": []},
{"type":"VAR","name":"t.cell1.WIDTH","addr":"(AB)","loc":"d,48:15,48:20","dtypep":"(BB)","origName":"WIDTH","verilogName":"WIDTH","direction":"NONE","isConst":true,"lifetime":"VSTATICI","varType":"GPARAM","dtypeName":"logic","isGParam":true,"isParam":true,"hasUserInit":true,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],
{"type":"VAR","name":"t.cell2.clk","addr":"(AB)","loc":"d,62:11,62:14","dtypep":"(J)","origName":"clk","verilogName":"clk","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"t.cell2.d","addr":"(BB)","loc":"d,63:17,63:18","dtypep":"(H)","origName":"d","verilogName":"d","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"t.cell2.q","addr":"(CB)","loc":"d,64:23,64:24","dtypep":"(H)","origName":"q","verilogName":"q","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"WIRE","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"t.cell1.WIDTH","addr":"(DB)","loc":"d,48:15,48:20","dtypep":"(EB)","origName":"WIDTH","verilogName":"WIDTH","direction":"NONE","isConst":true,"lifetime":"VSTATICI","varType":"GPARAM","dtypeName":"logic","isGParam":true,"isParam":true,"hasUserInit":true,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],
"valuep": [
{"type":"CONST","name":"32'sh4","addr":"(CB)","loc":"d,32:14,32:15","dtypep":"(DB)"}
{"type":"CONST","name":"32'sh4","addr":"(FB)","loc":"d,32:14,32:15","dtypep":"(GB)"}
],"attrsp": []},
{"type":"VAR","name":"t.cell1.clk","addr":"(EB)","loc":"d,50:11,50:14","dtypep":"(J)","origName":"clk","verilogName":"clk","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"t.cell1.d","addr":"(FB)","loc":"d,51:23,51:24","dtypep":"(H)","origName":"d","verilogName":"d","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"t.cell1.q","addr":"(GB)","loc":"d,52:30,52:31","dtypep":"(H)","origName":"q","verilogName":"q","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"t.cell1.IGNORED","addr":"(HB)","loc":"d,55:14,55:21","dtypep":"(BB)","origName":"IGNORED","verilogName":"IGNORED","direction":"NONE","isConst":true,"lifetime":"VSTATICI","varType":"LPARAM","dtypeName":"logic","isParam":true,"hasUserInit":true,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],
{"type":"VAR","name":"t.cell1.clk","addr":"(HB)","loc":"d,50:11,50:14","dtypep":"(J)","origName":"clk","verilogName":"clk","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"t.cell1.d","addr":"(IB)","loc":"d,51:23,51:24","dtypep":"(H)","origName":"d","verilogName":"d","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"t.cell1.q","addr":"(JB)","loc":"d,52:30,52:31","dtypep":"(H)","origName":"q","verilogName":"q","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"t.cell1.IGNORED","addr":"(KB)","loc":"d,55:14,55:21","dtypep":"(EB)","origName":"IGNORED","verilogName":"IGNORED","direction":"NONE","isConst":true,"lifetime":"VSTATICI","varType":"LPARAM","dtypeName":"logic","isParam":true,"hasUserInit":true,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],
"valuep": [
{"type":"CONST","name":"32'sh1","addr":"(IB)","loc":"d,55:24,55:25","dtypep":"(DB)"}
{"type":"CONST","name":"32'sh1","addr":"(LB)","loc":"d,55:24,55:25","dtypep":"(GB)"}
],"attrsp": []},
{"type":"VAR","name":"t.cell2.clk","addr":"(JB)","loc":"d,62:11,62:14","dtypep":"(J)","origName":"clk","verilogName":"clk","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"t.cell2.d","addr":"(KB)","loc":"d,63:17,63:18","dtypep":"(H)","origName":"d","verilogName":"d","direction":"NONE","lifetime":"VSTATICI","varType":"PORT","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"VAR","name":"t.cell2.q","addr":"(LB)","loc":"d,64:23,64:24","dtypep":"(H)","origName":"q","verilogName":"q","direction":"NONE","icoMaybeWritten":true,"lifetime":"VSTATICI","varType":"WIRE","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []},
{"type":"TOPSCOPE","name":"","addr":"(E)","loc":"d,7:8,7:9","senTreesp": [],
"scopep": [
{"type":"SCOPE","name":"TOP","addr":"(MB)","loc":"d,7:8,7:9","aboveScopep":"UNLINKED","aboveCellp":"UNLINKED","modp":"(F)",
@ -85,74 +85,74 @@
{"type":"VARSCOPE","name":"t.S_IDLE","addr":"(JC)","loc":"d,23:26,23:32","dtypep":"(T)","isTrace":true,"scopep":"(MB)","varp":"(S)"},
{"type":"VARSCOPE","name":"t.S_FETCH","addr":"(KC)","loc":"d,24:26,24:33","dtypep":"(T)","isTrace":true,"scopep":"(MB)","varp":"(W)"},
{"type":"VARSCOPE","name":"t.S_EXEC","addr":"(LC)","loc":"d,25:26,25:32","dtypep":"(T)","isTrace":true,"scopep":"(MB)","varp":"(Y)"},
{"type":"VARSCOPE","name":"t.cell1.WIDTH","addr":"(MC)","loc":"d,48:15,48:20","dtypep":"(BB)","isTrace":true,"scopep":"(MB)","varp":"(AB)"},
{"type":"VARSCOPE","name":"t.cell1.clk","addr":"(NC)","loc":"d,50:11,50:14","dtypep":"(J)","isTrace":true,"scopep":"(MB)","varp":"(EB)"},
{"type":"ALWAYS","name":"","addr":"(OC)","loc":"d,50:11,50:14","keyword":"cont_assign","sentreep": [],
{"type":"VARSCOPE","name":"t.cell2.clk","addr":"(MC)","loc":"d,62:11,62:14","dtypep":"(J)","isTrace":true,"scopep":"(MB)","varp":"(AB)"},
{"type":"ALWAYS","name":"","addr":"(NC)","loc":"d,62:11,62:14","keyword":"cont_assign","sentreep": [],
"stmtsp": [
{"type":"ASSIGNW","name":"","addr":"(PC)","loc":"d,50:11,50:14","dtypep":"(J)",
{"type":"ASSIGNW","name":"","addr":"(OC)","loc":"d,62:11,62:14","dtypep":"(J)",
"rhsp": [
{"type":"VARREF","name":"clk","addr":"(QC)","loc":"d,50:11,50:14","dtypep":"(J)","access":"RD","varp":"(I)","varScopep":"(OB)","classOrPackagep":"UNLINKED"}
{"type":"VARREF","name":"clk","addr":"(PC)","loc":"d,62:11,62:14","dtypep":"(J)","access":"RD","varp":"(I)","varScopep":"(OB)","classOrPackagep":"UNLINKED"}
],
"lhsp": [
{"type":"VARREF","name":"t.cell1.clk","addr":"(RC)","loc":"d,50:11,50:14","dtypep":"(J)","access":"WR","varp":"(EB)","varScopep":"(NC)","classOrPackagep":"UNLINKED"}
{"type":"VARREF","name":"t.cell2.clk","addr":"(QC)","loc":"d,62:11,62:14","dtypep":"(J)","access":"WR","varp":"(AB)","varScopep":"(MC)","classOrPackagep":"UNLINKED"}
],"timingControlp": [],"strengthSpecp": []}
]},
{"type":"VARSCOPE","name":"t.cell1.d","addr":"(SC)","loc":"d,51:23,51:24","dtypep":"(H)","isTrace":true,"scopep":"(MB)","varp":"(FB)"},
{"type":"ALWAYS","name":"","addr":"(TC)","loc":"d,51:23,51:24","keyword":"cont_assign","sentreep": [],
{"type":"VARSCOPE","name":"t.cell2.d","addr":"(RC)","loc":"d,63:17,63:18","dtypep":"(H)","isTrace":true,"scopep":"(MB)","varp":"(BB)"},
{"type":"ALWAYS","name":"","addr":"(SC)","loc":"d,63:17,63:18","keyword":"cont_assign","sentreep": [],
"stmtsp": [
{"type":"ASSIGNW","name":"","addr":"(UC)","loc":"d,51:23,51:24","dtypep":"(H)",
{"type":"ASSIGNW","name":"","addr":"(TC)","loc":"d,63:17,63:18","dtypep":"(H)",
"rhsp": [
{"type":"VARREF","name":"d","addr":"(VC)","loc":"d,51:23,51:24","dtypep":"(H)","access":"RD","varp":"(K)","varScopep":"(PB)","classOrPackagep":"UNLINKED"}
{"type":"VARREF","name":"t.between","addr":"(UC)","loc":"d,63:17,63:18","dtypep":"(H)","access":"RD","varp":"(O)","varScopep":"(FC)","classOrPackagep":"UNLINKED"}
],
"lhsp": [
{"type":"VARREF","name":"t.cell1.d","addr":"(WC)","loc":"d,51:23,51:24","dtypep":"(H)","access":"WR","varp":"(FB)","varScopep":"(SC)","classOrPackagep":"UNLINKED"}
{"type":"VARREF","name":"t.cell2.d","addr":"(VC)","loc":"d,63:17,63:18","dtypep":"(H)","access":"WR","varp":"(BB)","varScopep":"(RC)","classOrPackagep":"UNLINKED"}
],"timingControlp": [],"strengthSpecp": []}
]},
{"type":"VARSCOPE","name":"t.cell1.q","addr":"(XC)","loc":"d,52:30,52:31","dtypep":"(H)","isTrace":true,"scopep":"(MB)","varp":"(GB)"},
{"type":"ALWAYS","name":"","addr":"(YC)","loc":"d,52:30,52:31","keyword":"cont_assign","sentreep": [],
{"type":"VARSCOPE","name":"t.cell2.q","addr":"(WC)","loc":"d,64:23,64:24","dtypep":"(H)","isTrace":true,"scopep":"(MB)","varp":"(CB)"},
{"type":"ALWAYS","name":"","addr":"(XC)","loc":"d,64:23,64:24","keyword":"cont_assign","sentreep": [],
"stmtsp": [
{"type":"ASSIGNW","name":"","addr":"(ZC)","loc":"d,52:30,52:31","dtypep":"(H)",
{"type":"ASSIGNW","name":"","addr":"(YC)","loc":"d,64:23,64:24","dtypep":"(H)",
"rhsp": [
{"type":"VARREF","name":"t.between","addr":"(AD)","loc":"d,52:30,52:31","dtypep":"(H)","access":"RD","varp":"(O)","varScopep":"(FC)","classOrPackagep":"UNLINKED"}
{"type":"VARREF","name":"q","addr":"(ZC)","loc":"d,64:23,64:24","dtypep":"(H)","access":"RD","varp":"(G)","varScopep":"(NB)","classOrPackagep":"UNLINKED"}
],
"lhsp": [
{"type":"VARREF","name":"t.cell1.q","addr":"(BD)","loc":"d,52:30,52:31","dtypep":"(H)","access":"WR","varp":"(GB)","varScopep":"(XC)","classOrPackagep":"UNLINKED"}
{"type":"VARREF","name":"t.cell2.q","addr":"(AD)","loc":"d,64:23,64:24","dtypep":"(H)","access":"WR","varp":"(CB)","varScopep":"(WC)","classOrPackagep":"UNLINKED"}
],"timingControlp": [],"strengthSpecp": []}
]},
{"type":"VARSCOPE","name":"t.cell1.IGNORED","addr":"(CD)","loc":"d,55:14,55:21","dtypep":"(BB)","isTrace":true,"scopep":"(MB)","varp":"(HB)"},
{"type":"VARSCOPE","name":"t.cell2.clk","addr":"(DD)","loc":"d,62:11,62:14","dtypep":"(J)","isTrace":true,"scopep":"(MB)","varp":"(JB)"},
{"type":"ALWAYS","name":"","addr":"(ED)","loc":"d,62:11,62:14","keyword":"cont_assign","sentreep": [],
{"type":"VARSCOPE","name":"t.cell1.WIDTH","addr":"(BD)","loc":"d,48:15,48:20","dtypep":"(EB)","isTrace":true,"scopep":"(MB)","varp":"(DB)"},
{"type":"VARSCOPE","name":"t.cell1.clk","addr":"(CD)","loc":"d,50:11,50:14","dtypep":"(J)","isTrace":true,"scopep":"(MB)","varp":"(HB)"},
{"type":"ALWAYS","name":"","addr":"(DD)","loc":"d,50:11,50:14","keyword":"cont_assign","sentreep": [],
"stmtsp": [
{"type":"ASSIGNW","name":"","addr":"(FD)","loc":"d,62:11,62:14","dtypep":"(J)",
{"type":"ASSIGNW","name":"","addr":"(ED)","loc":"d,50:11,50:14","dtypep":"(J)",
"rhsp": [
{"type":"VARREF","name":"clk","addr":"(GD)","loc":"d,62:11,62:14","dtypep":"(J)","access":"RD","varp":"(I)","varScopep":"(OB)","classOrPackagep":"UNLINKED"}
{"type":"VARREF","name":"clk","addr":"(FD)","loc":"d,50:11,50:14","dtypep":"(J)","access":"RD","varp":"(I)","varScopep":"(OB)","classOrPackagep":"UNLINKED"}
],
"lhsp": [
{"type":"VARREF","name":"t.cell2.clk","addr":"(HD)","loc":"d,62:11,62:14","dtypep":"(J)","access":"WR","varp":"(JB)","varScopep":"(DD)","classOrPackagep":"UNLINKED"}
{"type":"VARREF","name":"t.cell1.clk","addr":"(GD)","loc":"d,50:11,50:14","dtypep":"(J)","access":"WR","varp":"(HB)","varScopep":"(CD)","classOrPackagep":"UNLINKED"}
],"timingControlp": [],"strengthSpecp": []}
]},
{"type":"VARSCOPE","name":"t.cell2.d","addr":"(ID)","loc":"d,63:17,63:18","dtypep":"(H)","isTrace":true,"scopep":"(MB)","varp":"(KB)"},
{"type":"ALWAYS","name":"","addr":"(JD)","loc":"d,63:17,63:18","keyword":"cont_assign","sentreep": [],
{"type":"VARSCOPE","name":"t.cell1.d","addr":"(HD)","loc":"d,51:23,51:24","dtypep":"(H)","isTrace":true,"scopep":"(MB)","varp":"(IB)"},
{"type":"ALWAYS","name":"","addr":"(ID)","loc":"d,51:23,51:24","keyword":"cont_assign","sentreep": [],
"stmtsp": [
{"type":"ASSIGNW","name":"","addr":"(KD)","loc":"d,63:17,63:18","dtypep":"(H)",
{"type":"ASSIGNW","name":"","addr":"(JD)","loc":"d,51:23,51:24","dtypep":"(H)",
"rhsp": [
{"type":"VARREF","name":"t.between","addr":"(LD)","loc":"d,63:17,63:18","dtypep":"(H)","access":"RD","varp":"(O)","varScopep":"(FC)","classOrPackagep":"UNLINKED"}
{"type":"VARREF","name":"d","addr":"(KD)","loc":"d,51:23,51:24","dtypep":"(H)","access":"RD","varp":"(K)","varScopep":"(PB)","classOrPackagep":"UNLINKED"}
],
"lhsp": [
{"type":"VARREF","name":"t.cell2.d","addr":"(MD)","loc":"d,63:17,63:18","dtypep":"(H)","access":"WR","varp":"(KB)","varScopep":"(ID)","classOrPackagep":"UNLINKED"}
{"type":"VARREF","name":"t.cell1.d","addr":"(LD)","loc":"d,51:23,51:24","dtypep":"(H)","access":"WR","varp":"(IB)","varScopep":"(HD)","classOrPackagep":"UNLINKED"}
],"timingControlp": [],"strengthSpecp": []}
]},
{"type":"VARSCOPE","name":"t.cell2.q","addr":"(ND)","loc":"d,64:23,64:24","dtypep":"(H)","isTrace":true,"scopep":"(MB)","varp":"(LB)"},
{"type":"ALWAYS","name":"","addr":"(OD)","loc":"d,64:23,64:24","keyword":"cont_assign","sentreep": [],
{"type":"VARSCOPE","name":"t.cell1.q","addr":"(MD)","loc":"d,52:30,52:31","dtypep":"(H)","isTrace":true,"scopep":"(MB)","varp":"(JB)"},
{"type":"ALWAYS","name":"","addr":"(ND)","loc":"d,52:30,52:31","keyword":"cont_assign","sentreep": [],
"stmtsp": [
{"type":"ASSIGNW","name":"","addr":"(PD)","loc":"d,64:23,64:24","dtypep":"(H)",
{"type":"ASSIGNW","name":"","addr":"(OD)","loc":"d,52:30,52:31","dtypep":"(H)",
"rhsp": [
{"type":"VARREF","name":"q","addr":"(QD)","loc":"d,64:23,64:24","dtypep":"(H)","access":"RD","varp":"(G)","varScopep":"(NB)","classOrPackagep":"UNLINKED"}
{"type":"VARREF","name":"t.between","addr":"(PD)","loc":"d,52:30,52:31","dtypep":"(H)","access":"RD","varp":"(O)","varScopep":"(FC)","classOrPackagep":"UNLINKED"}
],
"lhsp": [
{"type":"VARREF","name":"t.cell2.q","addr":"(RD)","loc":"d,64:23,64:24","dtypep":"(H)","access":"WR","varp":"(LB)","varScopep":"(ND)","classOrPackagep":"UNLINKED"}
{"type":"VARREF","name":"t.cell1.q","addr":"(QD)","loc":"d,52:30,52:31","dtypep":"(H)","access":"WR","varp":"(JB)","varScopep":"(MD)","classOrPackagep":"UNLINKED"}
],"timingControlp": [],"strengthSpecp": []}
]}
]},
{"type":"VARSCOPE","name":"t.cell1.IGNORED","addr":"(RD)","loc":"d,55:14,55:21","dtypep":"(EB)","isTrace":true,"scopep":"(MB)","varp":"(KB)"}
],
"blocksp": [
{"type":"ALWAYS","name":"","addr":"(SD)","loc":"d,27:23,27:24","keyword":"cont_assign","sentreep": [],
@ -221,34 +221,34 @@
{"type":"VARREF","name":"t.anonymous_expr","addr":"(RE)","loc":"d,29:10,29:24","dtypep":"(J)","access":"WR","varp":"(R)","varScopep":"(IC)","classOrPackagep":"UNLINKED"}
],"timingControlp": [],"strengthSpecp": []}
]},
{"type":"ALWAYS","name":"","addr":"(SE)","loc":"d,57:3,57:9","keyword":"always",
{"type":"ALWAYS","name":"","addr":"(SE)","loc":"d,67:12,67:13","keyword":"cont_assign","sentreep": [],
"stmtsp": [
{"type":"ASSIGNW","name":"","addr":"(TE)","loc":"d,67:12,67:13","dtypep":"(H)",
"rhsp": [
{"type":"VARREF","name":"t.between","addr":"(UE)","loc":"d,67:14,67:15","dtypep":"(H)","access":"RD","varp":"(O)","varScopep":"(FC)","classOrPackagep":"UNLINKED"}
],
"lhsp": [
{"type":"VARREF","name":"q","addr":"(VE)","loc":"d,67:10,67:11","dtypep":"(H)","access":"WR","varp":"(G)","varScopep":"(NB)","classOrPackagep":"UNLINKED"}
],"timingControlp": [],"strengthSpecp": []}
]},
{"type":"ALWAYS","name":"","addr":"(WE)","loc":"d,57:3,57:9","keyword":"always",
"sentreep": [
{"type":"SENTREE","name":"","addr":"(TE)","loc":"d,57:10,57:11",
{"type":"SENTREE","name":"","addr":"(XE)","loc":"d,57:10,57:11",
"sensesp": [
{"type":"SENITEM","name":"","addr":"(UE)","loc":"d,57:12,57:19","edgeType":"POS",
{"type":"SENITEM","name":"","addr":"(YE)","loc":"d,57:12,57:19","edgeType":"POS",
"sensp": [
{"type":"VARREF","name":"clk","addr":"(VE)","loc":"d,57:20,57:23","dtypep":"(J)","access":"RD","varp":"(I)","varScopep":"(OB)","classOrPackagep":"UNLINKED"}
{"type":"VARREF","name":"clk","addr":"(ZE)","loc":"d,57:20,57:23","dtypep":"(J)","access":"RD","varp":"(I)","varScopep":"(OB)","classOrPackagep":"UNLINKED"}
],"condp": []}
]}
],
"stmtsp": [
{"type":"ASSIGNDLY","name":"","addr":"(WE)","loc":"d,57:27,57:29","dtypep":"(H)",
{"type":"ASSIGNDLY","name":"","addr":"(AF)","loc":"d,57:27,57:29","dtypep":"(H)",
"rhsp": [
{"type":"VARREF","name":"d","addr":"(XE)","loc":"d,57:30,57:31","dtypep":"(H)","access":"RD","varp":"(K)","varScopep":"(PB)","classOrPackagep":"UNLINKED"}
{"type":"VARREF","name":"d","addr":"(BF)","loc":"d,57:30,57:31","dtypep":"(H)","access":"RD","varp":"(K)","varScopep":"(PB)","classOrPackagep":"UNLINKED"}
],
"lhsp": [
{"type":"VARREF","name":"t.between","addr":"(YE)","loc":"d,57:25,57:26","dtypep":"(H)","access":"WR","varp":"(O)","varScopep":"(FC)","classOrPackagep":"UNLINKED"}
{"type":"VARREF","name":"t.between","addr":"(CF)","loc":"d,57:25,57:26","dtypep":"(H)","access":"WR","varp":"(O)","varScopep":"(FC)","classOrPackagep":"UNLINKED"}
],"timingControlp": []}
]},
{"type":"ALWAYS","name":"","addr":"(ZE)","loc":"d,67:12,67:13","keyword":"cont_assign","sentreep": [],
"stmtsp": [
{"type":"ASSIGNW","name":"","addr":"(AF)","loc":"d,67:12,67:13","dtypep":"(H)",
"rhsp": [
{"type":"VARREF","name":"t.between","addr":"(BF)","loc":"d,67:14,67:15","dtypep":"(H)","access":"RD","varp":"(O)","varScopep":"(FC)","classOrPackagep":"UNLINKED"}
],
"lhsp": [
{"type":"VARREF","name":"q","addr":"(CF)","loc":"d,67:10,67:11","dtypep":"(H)","access":"WR","varp":"(G)","varScopep":"(NB)","classOrPackagep":"UNLINKED"}
],"timingControlp": [],"strengthSpecp": []}
]}
],"inlinesp": []}
]}
@ -260,11 +260,11 @@
{"type":"BASICDTYPE","name":"bit","addr":"(V)","loc":"d,23:35,23:40","dtypep":"(V)","keyword":"bit","range":"1:0","generic":true,"rangep": []},
{"type":"BASICDTYPE","name":"logic","addr":"(J)","loc":"d,27:32,27:34","dtypep":"(J)","keyword":"logic","generic":true,"rangep": []},
{"type":"BASICDTYPE","name":"logic","addr":"(T)","loc":"d,23:14,23:19","dtypep":"(T)","keyword":"logic","range":"1:0","generic":true,"rangep": []},
{"type":"BASICDTYPE","name":"logic","addr":"(BB)","loc":"d,48:15,48:20","dtypep":"(BB)","keyword":"logic","range":"31:0","generic":true,"signed":true,"rangep": []},
{"type":"BASICDTYPE","name":"logic","addr":"(EB)","loc":"d,48:15,48:20","dtypep":"(EB)","keyword":"logic","range":"31:0","generic":true,"signed":true,"rangep": []},
{"type":"BASICDTYPE","name":"logic","addr":"(H)","loc":"d,16:15,16:16","dtypep":"(H)","keyword":"logic","range":"3:0","generic":true,"rangep": []},
{"type":"BASICDTYPE","name":"logic","addr":"(AE)","loc":"d,27:26,27:27","dtypep":"(AE)","keyword":"logic","range":"1:0","generic":true,"signed":true,"rangep": []},
{"type":"BASICDTYPE","name":"bit","addr":"(VD)","loc":"d,27:32,27:34","dtypep":"(VD)","keyword":"bit","generic":true,"rangep": []},
{"type":"BASICDTYPE","name":"bit","addr":"(DB)","loc":"d,29:48,29:49","dtypep":"(DB)","keyword":"bit","range":"31:0","generic":true,"signed":true,"rangep": []}
{"type":"BASICDTYPE","name":"bit","addr":"(GB)","loc":"d,29:48,29:49","dtypep":"(GB)","keyword":"bit","range":"31:0","generic":true,"signed":true,"rangep": []}
]},
{"type":"CONSTPOOL","name":"","addr":"(D)","loc":"a,0:0,0:0",
"modulep": [

View File

@ -21,12 +21,6 @@
%Warning-UNUSEDLOOP: t/t_lint_unusedloop_removed_bad.v:280:5: Loop is not used and will be optimized out
280 | while (m_2_ticked);
| ^~~~~
%Warning-UNUSEDLOOP: t/t_lint_unusedloop_removed_bad.v:114:5: Loop condition is always false
114 | while(always_zero < 0) begin
| ^~~~~
%Warning-UNUSEDLOOP: t/t_lint_unusedloop_removed_bad.v:171:5: Loop condition is always false
171 | while(always_false) begin
| ^~~~~
%Warning-UNUSEDLOOP: t/t_lint_unusedloop_removed_bad.v:181:5: Loop condition is always false
181 | while(always_zero) begin
| ^~~~~
@ -36,4 +30,10 @@
%Warning-UNUSEDLOOP: t/t_lint_unusedloop_removed_bad.v:190:5: Loop condition is always false
190 | for (int i = 0; i < always_zero; i++)
| ^~~
%Warning-UNUSEDLOOP: t/t_lint_unusedloop_removed_bad.v:171:5: Loop condition is always false
171 | while(always_false) begin
| ^~~~~
%Warning-UNUSEDLOOP: t/t_lint_unusedloop_removed_bad.v:114:5: Loop condition is always false
114 | while(always_zero < 0) begin
| ^~~~~
%Error: Exiting due to

View File

@ -18,7 +18,7 @@ test.compile(verilator_flags2=["--no-json-edit-nums", "--stats"])
if test.vlt_all:
test.file_grep(
out_filename,
r'{"type":"VAR","name":"t.f0.clock_gate.clken_latched","addr":"[^"]*","loc":"\w,44:[^"]*","dtypep":"\(\w+\)",.*"origName":"clken_latched",.*"isLatched":true,.*"dtypeName":"logic"'
r'{"type":"VAR","name":"t.f1.clock_gate.clken_latched","addr":"[^"]*","loc":"\w,44:[^"]*","dtypep":"\(\w+\)",.*"origName":"clken_latched",.*"isLatched":true,.*"dtypeName":"logic"'
)
test.file_grep(test.stats, r'Optimizations, Gate sigs deduped\s+(\d+)', 2)

View File

@ -4,8 +4,8 @@
... For warning description see https://verilator.org/warn/UNOPTFLAT?v=latest
... Use "/* verilator lint_off UNOPTFLAT */" and lint_on around source to disable this message.
t/t_unoptflat_simple_3.v:16:14: Example path: t.x
t/t_unoptflat_simple_3.v:58:18: Example path: ASSIGNW
t/t_unoptflat_simple_3.v:56:21: Example path: t.__Vcellout__test1i__xvecout
t/t_unoptflat_simple_3.v:21:8: Example path: ASSIGNW
t/t_unoptflat_simple_3.v:76:18: Example path: ASSIGNW
t/t_unoptflat_simple_3.v:74:21: Example path: t.__Vcellout__test2i__xvecout
t/t_unoptflat_simple_3.v:27:8: Example path: ASSIGNW
t/t_unoptflat_simple_3.v:16:14: Example path: t.x
%Error: Exiting due to

View File

@ -3,8 +3,8 @@ x_assigned (initial) = 0x00000000
uninitialized2 = 0xdf5768de
big = 0x355d75711c3bf0ca3e65805db585c43beae34b336b9dbe44a2d040cbe101a665
random_init = 0x5fa24450
top.t.the_sub_yes_inline_1 no_init 0x842cd8b1033a58
top.t.the_sub_yes_inline_2 no_init 0xa36c65459f4b9f46
top.t.the_sub_yes_inline_1 no_init 0x842cd8b1033a58
top.t.the_sub_no_inline_1 no_init 0x42d55205d10c58f8
top.t.the_sub_no_inline_2 no_init 0xac98037e5042d96d
rand = 0x5fa24450

View File

@ -3,8 +3,8 @@ x_assigned (initial) = 0x00000000
uninitialized2 = 0xdf5768de
big = 0x355d75711c3bf0ca3e65805db585c43beae34b336b9dbe44a2d040cbe101a665
random_init = 0x5fa24450
top.t.the_sub_yes_inline_1 no_init 0x842cd8b1033a58
top.t.the_sub_yes_inline_2 no_init 0xa36c65459f4b9f46
top.t.the_sub_yes_inline_1 no_init 0x842cd8b1033a58
top.t.the_sub_no_inline_1 no_init 0x42d55205d10c58f8
top.t.the_sub_no_inline_2 no_init 0xac98037e5042d96d
rand = 0x5fa24450

View File

@ -3,8 +3,8 @@ x_assigned (initial) = 0x00000000
uninitialized2 = 0xdf5768de
big = 0x355d75711c3bf0ca3e65805db585c43beae34b336b9dbe44a2d040cbe101a665
random_init = 0x5fa24450
top.t.the_sub_yes_inline_1 no_init 0x842cd8b1033a58
top.t.the_sub_yes_inline_2 no_init 0xa36c65459f4b9f46
top.t.the_sub_yes_inline_1 no_init 0x842cd8b1033a58
top.t.the_sub_no_inline_1 no_init 0x42d55205d10c58f8
top.t.the_sub_no_inline_2 no_init 0xac98037e5042d96d
rand = 0x5fa24450

View File

@ -3,8 +3,8 @@ x_assigned (initial) = 0x00000000
uninitialized2 = 0xdf5768de
big = 0x355d75711c3bf0ca3e65805db585c43beae34b336b9dbe44a2d040cbe101a665
random_init = 0x5fa24450
top.t.the_sub_yes_inline_1 no_init 0x842cd8b1033a58
top.t.the_sub_yes_inline_2 no_init 0xa36c65459f4b9f46
top.t.the_sub_yes_inline_1 no_init 0x842cd8b1033a58
top.t.the_sub_no_inline_1 no_init 0x42d55205d10c58f8
top.t.the_sub_no_inline_2 no_init 0xac98037e5042d96d
rand = 0x5fa24450

View File

@ -3,8 +3,8 @@ x_assigned (initial) = 0x00000000
uninitialized2 = 0x00000000
big = 0x0000000000000000000000000000000000000000000000000000000000000000
random_init = 0x5fa24450
top.t.the_sub_yes_inline_1 no_init 0x0
top.t.the_sub_yes_inline_2 no_init 0x0
top.t.the_sub_yes_inline_1 no_init 0x0
top.t.the_sub_no_inline_1 no_init 0x0
top.t.the_sub_no_inline_2 no_init 0x0
rand = 0x5fa24450

View File

@ -3,8 +3,8 @@ x_assigned (initial) = 0x00000000
uninitialized2 = 0xdf5768de
big = 0x355d75711c3bf0ca3e65805db585c43beae34b336b9dbe44a2d040cbe101a665
random_init = 0x5fa24450
top.t.the_sub_yes_inline_1 no_init 0x842cd8b1033a58
top.t.the_sub_yes_inline_2 no_init 0xa36c65459f4b9f46
top.t.the_sub_yes_inline_1 no_init 0x842cd8b1033a58
top.t.the_sub_no_inline_1 no_init 0x42d55205d10c58f8
top.t.the_sub_no_inline_2 no_init 0xac98037e5042d96d
rand = 0x24800459

View File

@ -3,8 +3,8 @@ x_assigned (initial) = 0x00000000
uninitialized2 = 0xdf5768de
big = 0x355d75711c3bf0ca3e65805db585c43beae34b336b9dbe44a2d040cbe101a665
random_init = 0x5fa24450
top.t.the_sub_yes_inline_1 no_init 0x842cd8b1033a58
top.t.the_sub_yes_inline_2 no_init 0xa36c65459f4b9f46
top.t.the_sub_yes_inline_1 no_init 0x842cd8b1033a58
top.t.the_sub_no_inline_1 no_init 0x42d55205d10c58f8
top.t.the_sub_no_inline_2 no_init 0xac98037e5042d96d
rand = 0x24800459

View File

@ -3,8 +3,8 @@ x_assigned (initial) = 0x00000000
uninitialized2 = 0xdf5768de
big = 0x355d75711c3bf0ca3e65805db585c43beae34b336b9dbe44a2d040cbe101a665
random_init = 0x5fa24450
top.t.the_sub_yes_inline_1 no_init 0x842cd8b1033a58
top.t.the_sub_yes_inline_2 no_init 0xa36c65459f4b9f46
top.t.the_sub_yes_inline_1 no_init 0x842cd8b1033a58
top.t.the_sub_no_inline_1 no_init 0x42d55205d10c58f8
top.t.the_sub_no_inline_2 no_init 0xac98037e5042d96d
rand = 0x24800459

View File

@ -3,8 +3,8 @@ x_assigned (initial) = 0x00000000
uninitialized2 = 0xdf5768de
big = 0x355d75711c3bf0ca3e65805db585c43beae34b336b9dbe44a2d040cbe101a665
random_init = 0x5fa24450
top.t.the_sub_yes_inline_1 no_init 0x842cd8b1033a58
top.t.the_sub_yes_inline_2 no_init 0xa36c65459f4b9f46
top.t.the_sub_yes_inline_1 no_init 0x842cd8b1033a58
top.t.the_sub_no_inline_1 no_init 0x42d55205d10c58f8
top.t.the_sub_no_inline_2 no_init 0xac98037e5042d96d
rand = 0x24800459

View File

@ -3,8 +3,8 @@ x_assigned (initial) = 0x00000000
uninitialized2 = 0x00000000
big = 0x0000000000000000000000000000000000000000000000000000000000000000
random_init = 0x5fa24450
top.t.the_sub_yes_inline_1 no_init 0x0
top.t.the_sub_yes_inline_2 no_init 0x0
top.t.the_sub_yes_inline_1 no_init 0x0
top.t.the_sub_no_inline_1 no_init 0x0
top.t.the_sub_no_inline_2 no_init 0x0
rand = 0x24800459