Internals: Make the constant pool a regular package (#8512)

The constant pool is now an ordinary package, created with the netlist
and instantiated under $root like any other package, and most special
handling has been removed, including AstConstPool. Lookups go through
V3ConstPool, which has a singleton instance owned by V3Global. Static
methods on V3Common form the public interfce to add/find constant pool
entries.

With that, the constant pool is usable at any stage during compilation,
so enum and dimension tables created by V3Width, and enum value tables
created by V3Randomize now also live in the constant pool instead of
$unit, so identical tables are shared.

Associative array constants are handled separately from unpacked
tables, which used to be broken but unused.

Emitted constant pool variables use direct initialization, and
`constinit` with C++20 where the type allows it. This ensures we don't
change a run-time in a way that would result in unintended code size
increase.

-fno-merge-const-pool, which was introduced years ago but never prompted
a bug report is deprecated and has no effect.

This is also prep for future work.
This commit is contained in:
Geza Lore
2026-09-27 13:25:41 +01:00
committed by GitHub
parent d234caafc1
commit 348b9b6209
68 changed files with 1239 additions and 930 deletions
+10 -13
View File
@@ -38,6 +38,7 @@
#include "V3Case.h"
#include "V3ConstPool.h"
#include "V3Stats.h"
VL_DEFINE_DEBUG_FUNCTIONS;
@@ -738,18 +739,15 @@ class CaseVisitor final : public VNVisitor {
}
}
// Create the table in the constant pool, unless using an inline table
AstVarScope* const tableVscp = [&]() -> AstVarScope* {
if (isTinyTable) return nullptr;
AstVarScope* vscp = v3Global.rootp()->constPoolp()->findConst(tablep, true);
// Create the lookup table reference, in the constant pool unless using an inline table
AstNodeExpr* const tableRefp = [&]() -> AstNodeExpr* {
if (isTinyTable) return tablep;
AstVarRef* const refp = V3ConstPool::findConst(tablep);
VL_DO_DANGLING(tablep->deleteTree(), tablep); // findConst clones
return vscp;
return refp;
}();
// Create the lookup table reference and index
AstNodeExpr* const tableRefp
= tableVscp ? static_cast<AstNodeExpr*>(new AstVarRef{flp, tableVscp, VAccess::READ})
: static_cast<AstNodeExpr*>(tablep);
// Create the lookup index
AstNodeExpr* const caseExprp
= new AstExtend{flp, nodep->exprp()->cloneTreePure(false), 32};
AstNodeExpr* const scalep = new AstConst{flp, entryWidth};
@@ -855,15 +853,14 @@ class CaseVisitor final : public VNVisitor {
}
// Create the tables
AstVarScope* const matchVscp = v3Global.rootp()->constPoolp()->findConst(matchp, true);
AstVarScope* const tableVscp = v3Global.rootp()->constPoolp()->findTable(tablep);
AstVarRef* const matchRefp = V3ConstPool::findConst(matchp);
AstVarRef* const tableRefp = V3ConstPool::findTable(tablep);
VL_DO_DANGLING(matchp->deleteTree(), matchp);
VL_DO_DANGLING(tablep->deleteTree(), tablep);
// AstMatchMasked produces the index of the matching entry
AstNodeExpr* const tableRefp = new AstVarRef{flp, tableVscp, VAccess::READ};
AstNodeExpr* const caseExprp = nodep->exprp()->cloneTreePure(false);
AstMatchMasked* const indexp = new AstMatchMasked{flp, caseExprp, matchVscp};
AstMatchMasked* const indexp = new AstMatchMasked{flp, caseExprp, matchRefp};
AstNodeExpr* const entryp = new AstArraySel{flp, tableRefp, indexp};
return connectDecoderOutputs(nodep, entryp, "__VcaseDecoderOut");