parent
3c28b72897
commit
a730daabef
|
@ -377,6 +377,7 @@ detailed descriptions of these arguments.
|
|||
--get-supported <feature> Get if feature is supported
|
||||
--help Show this help
|
||||
--hierarchical Enable hierarchical Verilation
|
||||
--hierarchical-params-file <name> Internal option that specifies parameters file for hier blocks
|
||||
-I<dir> Directory to search for includes
|
||||
--if-depth <value> Tune IFDEPTH warning
|
||||
+incdir+<dir> Directory to search for includes
|
||||
|
|
|
@ -723,6 +723,12 @@ Summary:
|
|||
:option:`/*verilator&32;hier_block*/` metacomment is ignored. See
|
||||
:ref:`Hierarchical Verilation`.
|
||||
|
||||
.. option:: --hierarchical-params-file <filename>
|
||||
|
||||
Internal flag inserted during V3HierBlock phase, specifies name of hierarchical
|
||||
parameters file for de-parametrized modules with :option:`/*verilator&32;hier_block*/`
|
||||
metacomment. See :ref:`Hierarchical Verilation`.
|
||||
|
||||
.. option:: -I<dir>
|
||||
|
||||
See :vlopt:`-y`.
|
||||
|
@ -1996,6 +2002,13 @@ The grammar of configuration commands is as follows:
|
|||
that the setting is ignored unless the :vlopt:`--hierarchical` option is
|
||||
specified. See :ref:`Hierarchical Verilation`.
|
||||
|
||||
.. option:: hier_params -module "<modulename>"
|
||||
|
||||
Specifies that the module contains parameters a :vlopt:`--hierarchical` block. This option
|
||||
is used internally to specify parameters for deparametrized hier block instances.
|
||||
This option should not be used directly.
|
||||
See :ref:`Hierarchical Verilation`.
|
||||
|
||||
.. option:: inline -module "<modulename>"
|
||||
|
||||
Specifies the module may be inlined into any modules that use this
|
||||
|
|
|
@ -48,12 +48,6 @@ For --cc/--sc, it creates:
|
|||
- Make include file for compiling (from --make gmake)
|
||||
* - *{prefix}*\ _classes.mk
|
||||
- Make include file with class names (from --make gmake)
|
||||
* - *{prefix}*\ _hier.mk
|
||||
- Make file for hierarchy blocks (from --make gmake)
|
||||
* - *{prefix}*\ __hierMkArgs.f
|
||||
- Arguments for hierarchical Verilation (from --make gmake)
|
||||
* - *{prefix}*\ __hierCMakeArgs.f
|
||||
- Arguments for hierarchical Verilation (from --make cmake)
|
||||
* - *{prefix}*\ .h
|
||||
- Model header
|
||||
* - *{prefix}*\ .cpp
|
||||
|
@ -95,16 +89,24 @@ For --cc/--sc, it creates:
|
|||
* - *{prefix}{each_verilog_module}{__DepSet_hash__n}*\ .cpp
|
||||
- Additional lower C++ files (hashed to reduce build times)
|
||||
|
||||
For --hierarchy mode, it creates:
|
||||
For --hierarchical mode, it creates:
|
||||
|
||||
.. list-table::
|
||||
|
||||
* - V\ *{hier_block}*\ /
|
||||
- Directory to Verilate each hierarchy block (from --hierarchy)
|
||||
- Directory to Verilate each hierarchical block (from --hierarchical)
|
||||
* - *{prefix}*\ __hierVer.d
|
||||
- Make dependencies of the top module (from --hierarchy)
|
||||
- Make dependencies of the top module (from --hierarchical)
|
||||
* - *{prefix}*\ _hier.mk
|
||||
- Make file for hierarchical blocks (from --make gmake)
|
||||
* - *{prefix}*\ __hierCMakeArgs.f
|
||||
- Arguments for hierarchical Verilation (from --make cmake)
|
||||
* - *{prefix}*\ __hierMkArgs.f
|
||||
- Arguments for hierarchical Verilation (from --make gmake)
|
||||
* - *{prefix}*\ __hierParameters.v
|
||||
- Module parameters for hierarchical blocks
|
||||
* - *{prefix}*\ __hier.dir
|
||||
- Directory to store .dot, .vpp, .tree of top module (from --hierarchy)
|
||||
- Directory to store .dot, .vpp, .tree of top module (from --hierarchical)
|
||||
|
||||
In specific debug and other modes, it also creates:
|
||||
|
||||
|
|
|
@ -330,6 +330,7 @@ public:
|
|||
ILLEGAL,
|
||||
COVERAGE_BLOCK_OFF,
|
||||
HIER_BLOCK,
|
||||
HIER_PARAMS,
|
||||
INLINE_MODULE,
|
||||
NO_INLINE_MODULE,
|
||||
NO_INLINE_TASK,
|
||||
|
|
|
@ -238,6 +238,7 @@ class AstNodeModule VL_NOT_FINAL : public AstNode {
|
|||
bool m_hasGParam : 1; // Has global parameter (for link)
|
||||
bool m_hasParameterList : 1; // Has #() for parameter declaration
|
||||
bool m_hierBlock : 1; // Hierarchical Block marked by HIER_BLOCK pragma
|
||||
bool m_hierParams : 1; // Block containing params for parametrized hier blocks
|
||||
bool m_internal : 1; // Internally created
|
||||
bool m_recursive : 1; // Recursive module
|
||||
bool m_recursiveClone : 1; // If recursive, what module it clones, otherwise nullptr
|
||||
|
@ -253,6 +254,7 @@ protected:
|
|||
, m_hasGParam{false}
|
||||
, m_hasParameterList{false}
|
||||
, m_hierBlock{false}
|
||||
, m_hierParams{false}
|
||||
, m_internal{false}
|
||||
, m_recursive{false}
|
||||
, m_recursiveClone{false} {}
|
||||
|
@ -286,6 +288,8 @@ public:
|
|||
void hasParameterList(bool flag) { m_hasParameterList = flag; }
|
||||
bool hierBlock() const { return m_hierBlock; }
|
||||
void hierBlock(bool flag) { m_hierBlock = flag; }
|
||||
bool hierParams() const { return m_hierParams; }
|
||||
void hierParams(bool flag) { m_hierParams = flag; }
|
||||
bool internal() const { return m_internal; }
|
||||
void internal(bool flag) { m_internal = flag; }
|
||||
bool recursive() const { return m_recursive; }
|
||||
|
|
|
@ -200,6 +200,9 @@ public:
|
|||
modp->addStmtsp(nodep);
|
||||
}
|
||||
for (const auto& itr : m_modPragmas) {
|
||||
// Catch hier param modules to mark their attributes before they are
|
||||
// flagged dead in LinkDot.
|
||||
if (itr == VPragmaType::HIER_PARAMS) modp->hierParams(true);
|
||||
AstNode* const nodep = new AstPragma{modp->fileline(), itr};
|
||||
modp->addStmtsp(nodep);
|
||||
}
|
||||
|
|
|
@ -602,7 +602,7 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public EmitCBaseVisitorConst {
|
|||
}
|
||||
void visit(AstTypedef* nodep) override {
|
||||
putfs(nodep, "typedef ");
|
||||
iterateAndNextConstNull(nodep->dtypep());
|
||||
iterateAndNextConstNull(nodep->subDTypep());
|
||||
puts(" ");
|
||||
puts(nodep->prettyName());
|
||||
puts(";\n");
|
||||
|
@ -630,7 +630,13 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public EmitCBaseVisitorConst {
|
|||
iterateConst(nodep->subDTypep());
|
||||
iterateAndNextConstNull(nodep->rangep());
|
||||
}
|
||||
void visit(AstRefDType* nodep) override { iterateConst(nodep->skipRefp()); }
|
||||
void visit(AstRefDType* nodep) override {
|
||||
if (nodep->subDTypep()) {
|
||||
iterateConst(nodep->skipRefp());
|
||||
} else {
|
||||
puts("\n???? // "s + nodep->prettyTypeName() + " -> UNLINKED\n");
|
||||
}
|
||||
}
|
||||
void visit(AstNodeUOrStructDType* nodep) override {
|
||||
puts(nodep->verilogKwd() + " ");
|
||||
if (nodep->packed()) puts("packed ");
|
||||
|
|
|
@ -79,6 +79,13 @@ void V3Global::readFiles() {
|
|||
"Cannot find file containing library module: ");
|
||||
}
|
||||
|
||||
// Read hierarchical type parameter file
|
||||
const string filename = v3Global.opt.hierParamFile();
|
||||
if (!filename.empty()) {
|
||||
parser.parseFile(new FileLine{FileLine::commandLineFilename()}, filename, false,
|
||||
"Cannot open file containing hierarchical parameter declarations: ");
|
||||
}
|
||||
|
||||
// v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("parse.tree"));
|
||||
V3Error::abortIfErrors();
|
||||
|
||||
|
|
|
@ -38,29 +38,36 @@
|
|||
// Here is more detailed internal process.
|
||||
// 1) Parser adds VPragmaType::HIER_BLOCK of AstPragma to modules
|
||||
// that are marked with /*verilator hier_block*/ metacomment in Verilator run a).
|
||||
// 2) AstModule with HIER_BLOCK pragma is marked modp->hier_block(true)
|
||||
// 2) If module type parameters are present, V3Config marks hier param modules
|
||||
// (marked with hier_params verilator config pragma) as modp->hierParams(true).
|
||||
// This is done in run b), de-parametrized modules are mapped with their params one-to-one.
|
||||
// 3) AstModule with HIER_BLOCK pragma is marked modp->hierBlock(true)
|
||||
// in V3LinkResolve.cpp during run a).
|
||||
// 3) In V3LinkCells.cpp, the following things are done during run b) and c).
|
||||
// 3-1) Delete the upper modules of the hierarchical block because the top module in run b) is
|
||||
// 4) In V3LinkCells.cpp, the following things are done during run b) and c).
|
||||
// 4-1) Delete the upper modules of the hierarchical block because the top module in run b) is
|
||||
// hierarchical block, not the top module of run c).
|
||||
// 3-2) If the top module of the run b) or c) instantiates other hierarchical blocks that is
|
||||
// 4-2) If the top module of the run b) or c) instantiates other hierarchical blocks that is
|
||||
// parameterized,
|
||||
// module and task names are renamed to the original name to be compatible with the
|
||||
// hier module to be called.
|
||||
//
|
||||
// Parameterized modules have unique name by V3Param.cpp. The unique name contains '__' and
|
||||
// Verilator encodes '__' when loading such symbols.
|
||||
// 4) V3LinkDot.cpp checks dotted access across hierarchical block boundary.
|
||||
// 5) In V3Dead.cpp, some parameters of parameterized modules are protected not to be deleted even
|
||||
// 5) In V3LinkDot.cpp,
|
||||
// 5-1) Dotted access across hierarchical block boundary is checked. Currently hierarchical
|
||||
// block references are not supported.
|
||||
// 5-2) If present, parameters in hier params module replace parameter values of de-parametrized
|
||||
// module in run b).
|
||||
// 6) In V3Dead.cpp, some parameters of parameterized modules are protected not to be deleted even
|
||||
// if the parameter is not referred. This protection is necessary to match step 6) below.
|
||||
// 6) In V3Param.cpp, use --lib-create wrapper of the parameterized module made in b) and c).
|
||||
// 7) In V3Param.cpp, use --lib-create wrapper of the parameterized module made in b) and c).
|
||||
// If a hierarchical block is a parameterized module and instantiated in multiple locations,
|
||||
// all parameters must exactly match.
|
||||
// 7) In V3HierBlock.cpp, relationship among hierarchical blocks are checked in run a).
|
||||
// 8) In V3HierBlock.cpp, relationships among hierarchical blocks are checked in run a).
|
||||
// (which block uses other blocks..)
|
||||
// 8) In V3EmitMk.cpp, ${prefix}_hier.mk is created in run a).
|
||||
// 9) In V3EmitMk.cpp, ${prefix}_hier.mk is created in run a).
|
||||
//
|
||||
// There are two hidden command options.
|
||||
// There are three hidden command options:
|
||||
// --hierarchical-child is added to Verilator run b).
|
||||
// --hierarchical-block module_name,mangled_name,name0,value0,name1,value1,...
|
||||
// module_name :The original modulename
|
||||
|
@ -70,12 +77,18 @@
|
|||
// value :Overridden value of the parameter
|
||||
//
|
||||
// Used for b) and c).
|
||||
// This options is repeated for all instantiating hierarchical blocks.
|
||||
// These options are repeated for all instantiated hierarchical blocks.
|
||||
// --hierarchical-params-file filename
|
||||
// filename :Name of a hierarchical parameters file
|
||||
//
|
||||
// Added in a), used for b).
|
||||
// Each de-parametrized module version has exactly one hier params file specified.
|
||||
|
||||
#include "V3PchAstNoMT.h" // VL_MT_DISABLED_CODE_UNIT
|
||||
|
||||
#include "V3HierBlock.h"
|
||||
|
||||
#include "V3EmitV.h"
|
||||
#include "V3File.h"
|
||||
#include "V3Os.h"
|
||||
#include "V3Stats.h"
|
||||
|
@ -93,6 +106,10 @@ static string V3HierCommandArgsFilename(const string& prefix, bool forCMake) {
|
|||
+ (forCMake ? "__hierCMakeArgs.f" : "__hierMkArgs.f");
|
||||
}
|
||||
|
||||
static string V3HierParametersFileName(const string& prefix) {
|
||||
return v3Global.opt.makeDir() + "/" + prefix + "__hierParameters.v";
|
||||
}
|
||||
|
||||
static void V3HierWriteCommonInputs(const V3HierBlock* hblockp, std::ostream* of, bool forCMake) {
|
||||
string topModuleFile;
|
||||
if (hblockp) topModuleFile = hblockp->vFileIfNecessary();
|
||||
|
@ -107,7 +124,8 @@ static void V3HierWriteCommonInputs(const V3HierBlock* hblockp, std::ostream* of
|
|||
|
||||
//######################################################################
|
||||
|
||||
V3HierBlock::StrGParams V3HierBlock::stringifyParams(const GParams& gparams, bool forGOption) {
|
||||
V3HierBlock::StrGParams V3HierBlock::stringifyParams(const V3HierBlockParams::GParams& gparams,
|
||||
bool forGOption) {
|
||||
StrGParams strParams;
|
||||
for (const auto& gparam : gparams) {
|
||||
if (const AstConst* const constp = VN_CAST(gparam->valuep(), Const)) {
|
||||
|
@ -159,17 +177,21 @@ V3StringList V3HierBlock::commandArgs(bool forCMake) const {
|
|||
opts.push_back(" --protect-key " + v3Global.opt.protectKeyDefaulted());
|
||||
opts.push_back(" --hierarchical-child " + cvtToStr(v3Global.opt.threads()));
|
||||
|
||||
const StrGParams gparamsStr = stringifyParams(gparams(), true);
|
||||
for (StrGParams::const_iterator paramIt = gparamsStr.begin(); paramIt != gparamsStr.end();
|
||||
++paramIt) {
|
||||
opts.push_back("-G" + paramIt->first + "=" + paramIt->second + "");
|
||||
const StrGParams gparamsStr = stringifyParams(params().gparams(), true);
|
||||
for (const StrGParam& param : gparamsStr) {
|
||||
const string name = param.first;
|
||||
const string value = param.second;
|
||||
opts.push_back("-G" + name + "=" + value + "");
|
||||
}
|
||||
if (!params().gTypeParams().empty())
|
||||
opts.push_back(" --hierarchical-params-file " + typeParametersFilename());
|
||||
|
||||
return opts;
|
||||
}
|
||||
|
||||
V3StringList V3HierBlock::hierBlockArgs() const {
|
||||
V3StringList opts;
|
||||
const StrGParams gparamsStr = stringifyParams(gparams(), false);
|
||||
const StrGParams gparamsStr = stringifyParams(params().gparams(), false);
|
||||
opts.push_back("--hierarchical-block ");
|
||||
string s = modp()->origName(); // origName
|
||||
s += "," + modp()->name(); // mangledName
|
||||
|
@ -238,6 +260,29 @@ string V3HierBlock::commandArgsFilename(bool forCMake) const {
|
|||
return V3HierCommandArgsFilename(hierPrefix(), forCMake);
|
||||
}
|
||||
|
||||
string V3HierBlock::typeParametersFilename() const {
|
||||
return V3HierParametersFileName(hierPrefix());
|
||||
}
|
||||
|
||||
void V3HierBlock::writeParametersFile() const {
|
||||
if (m_params.gTypeParams().empty()) return;
|
||||
|
||||
VHashSha256 hash{"type params"};
|
||||
const string moduleName = "Vhsh" + hash.digestSymbol();
|
||||
const std::unique_ptr<std::ofstream> of{V3File::new_ofstream(typeParametersFilename())};
|
||||
*of << "module " << moduleName << ";\n";
|
||||
for (const AstParamTypeDType* const gparam : m_params.gTypeParams()) {
|
||||
AstTypedef* tdefp
|
||||
= new AstTypedef(new FileLine{FileLine::builtInFilename()}, gparam->name(), nullptr,
|
||||
VFlagChildDType{}, gparam->skipRefp()->cloneTreePure(true));
|
||||
V3EmitV::verilogForTree(tdefp, *of);
|
||||
VL_DO_DANGLING(tdefp->deleteTree(), tdefp);
|
||||
}
|
||||
*of << "endmodule\n\n";
|
||||
*of << "`verilator_config\n";
|
||||
*of << "hier_params -module \"" << moduleName << "\"\n";
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
// Collect how hierarchical blocks are used
|
||||
class HierBlockUsageCollectVisitor final : public VNVisitorConst {
|
||||
|
@ -251,7 +296,7 @@ class HierBlockUsageCollectVisitor final : public VNVisitorConst {
|
|||
AstModule* m_modp = nullptr; // The current module
|
||||
AstModule* m_hierBlockp = nullptr; // The nearest parent module that is a hierarchical block
|
||||
ModuleSet m_referred; // Modules that have hier_block pragma
|
||||
V3HierBlock::GParams m_gparams; // list of variables that is VVarType::GPARAM
|
||||
V3HierBlockParams m_params;
|
||||
|
||||
void visit(AstModule* nodep) override {
|
||||
// Don't visit twice
|
||||
|
@ -262,23 +307,23 @@ class HierBlockUsageCollectVisitor final : public VNVisitorConst {
|
|||
VL_RESTORER(m_modp);
|
||||
AstModule* const prevHierBlockp = m_hierBlockp;
|
||||
ModuleSet prevReferred;
|
||||
V3HierBlock::GParams prevGParams;
|
||||
V3HierBlockParams previousParams;
|
||||
m_modp = nodep;
|
||||
if (nodep->hierBlock()) {
|
||||
m_hierBlockp = nodep;
|
||||
prevReferred.swap(m_referred);
|
||||
}
|
||||
prevGParams.swap(m_gparams);
|
||||
previousParams.swap(m_params);
|
||||
|
||||
iterateChildrenConst(nodep);
|
||||
|
||||
if (nodep->hierBlock()) {
|
||||
m_planp->add(nodep, m_gparams);
|
||||
m_planp->add(nodep, m_params);
|
||||
for (const AstModule* modp : m_referred) m_planp->registerUsage(nodep, modp);
|
||||
m_hierBlockp = prevHierBlockp;
|
||||
m_referred = prevReferred;
|
||||
}
|
||||
m_gparams = prevGParams;
|
||||
m_params.swap(previousParams);
|
||||
}
|
||||
void visit(AstCell* nodep) override {
|
||||
// Visit used module here to know that the module is hier_block or not.
|
||||
|
@ -294,10 +339,13 @@ class HierBlockUsageCollectVisitor final : public VNVisitorConst {
|
|||
if (m_modp && m_modp->hierBlock() && nodep->isIfaceRef() && !nodep->isIfaceParent()) {
|
||||
nodep->v3error("Modport cannot be used at the hierarchical block boundary");
|
||||
}
|
||||
if (nodep->isGParam() && nodep->overriddenParam()) m_gparams.push_back(nodep);
|
||||
if (nodep->isGParam() && nodep->overriddenParam()) m_params.add(nodep);
|
||||
}
|
||||
|
||||
void visit(AstParamTypeDType* nodep) override { m_params.add(nodep); }
|
||||
|
||||
void visit(AstNodeExpr*) override {} // Accelerate
|
||||
void visit(AstConstPool*) override {} // Accelerate
|
||||
void visit(AstNode* nodep) override { iterateChildrenConst(nodep); }
|
||||
|
||||
public:
|
||||
|
@ -309,11 +357,12 @@ public:
|
|||
|
||||
//######################################################################
|
||||
|
||||
void V3HierBlockPlan::add(const AstNodeModule* modp, const std::vector<AstVar*>& gparams) {
|
||||
void V3HierBlockPlan::add(const AstNodeModule* modp, const V3HierBlockParams& params) {
|
||||
const auto pair = m_blocks.emplace(modp, nullptr);
|
||||
if (pair.second) {
|
||||
V3HierBlock* hblockp = new V3HierBlock{modp, gparams};
|
||||
UINFO(3, "Add " << modp->prettyNameQ() << " with " << gparams.size() << " parameters"
|
||||
V3HierBlock* hblockp = new V3HierBlock{modp, params};
|
||||
UINFO(3, "Add " << modp->prettyNameQ() << " with " << params.gparams().size()
|
||||
<< " parameters and " << params.gTypeParams().size() << " type parameters"
|
||||
<< std::endl);
|
||||
pair.first->second = hblockp;
|
||||
}
|
||||
|
@ -434,3 +483,7 @@ void V3HierBlockPlan::writeCommandArgsFiles(bool forCMake) const {
|
|||
string V3HierBlockPlan::topCommandArgsFilename(bool forCMake) {
|
||||
return V3HierCommandArgsFilename(v3Global.opt.prefix(), forCMake);
|
||||
}
|
||||
|
||||
void V3HierBlockPlan::writeParametersFiles() const {
|
||||
for (const auto& block : *this) { block.second->writeParametersFile(); }
|
||||
}
|
||||
|
|
|
@ -32,19 +32,44 @@
|
|||
|
||||
class AstNetlist;
|
||||
class AstNodeModule;
|
||||
class AstParamTypeDType;
|
||||
class AstVar;
|
||||
|
||||
//######################################################################
|
||||
|
||||
class V3HierBlock final {
|
||||
class V3HierBlockParams final {
|
||||
public:
|
||||
using GParams = std::vector<AstVar*>;
|
||||
using GTypeParams = std::vector<AstParamTypeDType*>;
|
||||
|
||||
private:
|
||||
GParams m_params;
|
||||
GTypeParams m_typeParams;
|
||||
|
||||
public:
|
||||
void add(AstVar* param) { m_params.push_back(param); }
|
||||
void add(AstParamTypeDType* param) { m_typeParams.push_back(param); }
|
||||
|
||||
const GParams& gparams() const { return m_params; };
|
||||
const GTypeParams& gTypeParams() const { return m_typeParams; };
|
||||
GParams& gparams() { return m_params; };
|
||||
GTypeParams& gTypeParams() { return m_typeParams; };
|
||||
|
||||
void swap(V3HierBlockParams& other) {
|
||||
m_params.swap(other.m_params);
|
||||
m_typeParams.swap(other.m_typeParams);
|
||||
}
|
||||
};
|
||||
|
||||
class V3HierBlock final {
|
||||
public:
|
||||
using HierBlockSet = std::unordered_set<V3HierBlock*>;
|
||||
|
||||
private:
|
||||
// TYPES
|
||||
// Parameter name, stringified value
|
||||
using StrGParams = std::vector<std::pair<std::string, std::string>>;
|
||||
using StrGParam = std::pair<string, string>;
|
||||
using StrGParams = std::vector<StrGParam>;
|
||||
|
||||
// MEMBERS
|
||||
const AstNodeModule* const m_modp; // Hierarchical block module
|
||||
|
@ -53,16 +78,18 @@ private:
|
|||
// Hierarchical blocks that this block directly or indirectly instantiates
|
||||
HierBlockSet m_children;
|
||||
// Parameters that are overridden by #(.param(value)) syntax.
|
||||
const GParams m_gparams;
|
||||
const V3HierBlockParams m_params;
|
||||
|
||||
// METHODS
|
||||
VL_UNCOPYABLE(V3HierBlock);
|
||||
static StrGParams stringifyParams(const GParams& gparams, bool forGOption) VL_MT_DISABLED;
|
||||
static StrGParams stringifyParams(const V3HierBlockParams::GParams& params,
|
||||
bool forGOption) VL_MT_DISABLED;
|
||||
|
||||
public:
|
||||
V3HierBlock(const AstNodeModule* modp, const GParams& gparams)
|
||||
V3HierBlock(const AstNodeModule* modp, const V3HierBlockParams& params)
|
||||
: m_modp{modp}
|
||||
, m_gparams{gparams} {}
|
||||
, m_params{params} {}
|
||||
|
||||
~V3HierBlock() VL_MT_DISABLED;
|
||||
|
||||
void addParent(V3HierBlock* parentp) { m_parents.insert(parentp); }
|
||||
|
@ -70,7 +97,7 @@ public:
|
|||
bool hasChild() const { return !m_children.empty(); }
|
||||
const HierBlockSet& parents() const { return m_parents; }
|
||||
const HierBlockSet& children() const { return m_children; }
|
||||
const GParams& gparams() const { return m_gparams; }
|
||||
const V3HierBlockParams& params() const { return m_params; }
|
||||
const AstNodeModule* modp() const { return m_modp; }
|
||||
|
||||
// For emitting Makefile and CMakeLists.txt
|
||||
|
@ -87,7 +114,9 @@ public:
|
|||
string vFileIfNecessary() const VL_MT_DISABLED;
|
||||
// Write command line arguments to .f file for this hierarchical block
|
||||
void writeCommandArgsFile(bool forCMake) const VL_MT_DISABLED;
|
||||
void writeParametersFile() const VL_MT_DISABLED;
|
||||
string commandArgsFilename(bool forCMake) const VL_MT_DISABLED;
|
||||
string typeParametersFilename() const VL_MT_DISABLED;
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
@ -105,7 +134,7 @@ public:
|
|||
using const_iterator = HierMap::const_iterator;
|
||||
using HierVector = std::vector<const V3HierBlock*>;
|
||||
|
||||
void add(const AstNodeModule* modp, const std::vector<AstVar*>& gparams) VL_MT_DISABLED;
|
||||
void add(const AstNodeModule* modp, const V3HierBlockParams& params) VL_MT_DISABLED;
|
||||
void registerUsage(const AstNodeModule* parentp, const AstNodeModule* childp) VL_MT_DISABLED;
|
||||
|
||||
const_iterator begin() const { return m_blocks.begin(); }
|
||||
|
@ -118,6 +147,7 @@ public:
|
|||
|
||||
// Write command line arguments to .f files for child Verilation run
|
||||
void writeCommandArgsFiles(bool forCMake) const VL_MT_DISABLED;
|
||||
void writeParametersFiles() const VL_MT_DISABLED;
|
||||
static string topCommandArgsFilename(bool forCMake) VL_MT_DISABLED;
|
||||
|
||||
static void createPlan(AstNetlist* nodep) VL_MT_DISABLED;
|
||||
|
|
|
@ -751,6 +751,8 @@ class LinkDotFindVisitor final : public VNVisitor {
|
|||
AstClocking* m_clockingp = nullptr; // Current clocking block
|
||||
VSymEnt* m_modSymp = nullptr; // Symbol Entry for current module
|
||||
VSymEnt* m_curSymp = nullptr; // Symbol Entry for current table, where to lookup/insert
|
||||
string
|
||||
m_hierParamsName; // Name of module with hierarchical type parameters, empty when not used
|
||||
string m_scope; // Scope text
|
||||
const AstNodeBlock* m_blockp = nullptr; // Current Begin/end block
|
||||
const AstNodeFTask* m_ftaskp = nullptr; // Current function/task
|
||||
|
@ -919,9 +921,22 @@ class LinkDotFindVisitor final : public VNVisitor {
|
|||
iterateChildren(nodep);
|
||||
nodep->user4(true);
|
||||
} else { // !doit
|
||||
// Will be optimized away later
|
||||
// Can't remove now, as our backwards iterator will throw up
|
||||
UINFO(5, "Module not under any CELL or top - dead module: " << nodep << endl);
|
||||
if (nodep->hierParams()) {
|
||||
UINFO(1, "Found module with hier type parameters" << endl);
|
||||
m_hierParamsName = nodep->name();
|
||||
for (const AstNode* node = nodep->op2p(); node; node = node->nextp()) {
|
||||
if (const AstTypedef* const tdef = VN_CAST(node, Typedef)) {
|
||||
UINFO(1, "Inserting hier type parameter typedef: " << tdef << endl);
|
||||
VSymEnt* const upperSymp = m_curSymp ? m_curSymp : m_statep->rootEntp();
|
||||
m_curSymp = m_modSymp = m_statep->insertBlock(upperSymp, nodep->name(),
|
||||
nodep, m_classOrPackagep);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Will be optimized away later
|
||||
// Can't remove now, as our backwards iterator will throw up
|
||||
UINFO(5, "Module not under any CELL or top - dead module: " << nodep << endl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1367,6 +1382,29 @@ class LinkDotFindVisitor final : public VNVisitor {
|
|||
}
|
||||
void visit(AstParamTypeDType* nodep) override {
|
||||
UASSERT_OBJ(m_curSymp, nodep, "Parameter type not under module/package/$unit");
|
||||
|
||||
// Replace missing param types with provided hierarchical type params.
|
||||
if (!m_hierParamsName.empty()) {
|
||||
if (const VSymEnt* const typedefEntp = m_curSymp->findIdFallback(m_hierParamsName)) {
|
||||
const AstModule* modp = VN_CAST(typedefEntp->nodep(), Module);
|
||||
|
||||
for (const AstNode* node = modp ? modp->stmtsp() : nullptr; node;
|
||||
node = node->nextp()) {
|
||||
const AstTypedef* tdefp = VN_CAST(node, Typedef);
|
||||
|
||||
if (tdefp && tdefp->name() == nodep->name() && m_statep->forPrimary()) {
|
||||
UINFO(8, "Replacing type of" << nodep << endl
|
||||
<< " with " << tdefp << endl);
|
||||
AstNodeDType* const newType = tdefp->childDTypep();
|
||||
AstNodeDType* const oldType = nodep->childDTypep();
|
||||
|
||||
oldType->replaceWith(newType->cloneTree(false));
|
||||
oldType->deleteTree();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
iterateChildren(nodep);
|
||||
m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_classOrPackagep);
|
||||
if (m_statep->forPrimary() && nodep->isGParam()) {
|
||||
|
@ -1615,7 +1653,7 @@ class LinkDotParamVisitor final : public VNVisitor {
|
|||
void visit(AstConstPool*) override {}
|
||||
void visit(AstNodeModule* nodep) override {
|
||||
UINFO(5, " " << nodep << endl);
|
||||
if (nodep->dead() || !nodep->user4()) {
|
||||
if ((nodep->dead() || !nodep->user4()) && !nodep->hierParams()) {
|
||||
UINFO(4, "Mark dead module " << nodep << endl);
|
||||
UASSERT_OBJ(m_statep->forPrearray(), nodep,
|
||||
"Dead module persisted past where should have removed");
|
||||
|
|
|
@ -864,8 +864,11 @@ void V3Options::notify() VL_MT_DISABLED {
|
|||
cmdfl->v3error(
|
||||
"--hierarchical must not be set with --hierarchical-child or --hierarchical-block");
|
||||
}
|
||||
if (m_hierChild && m_hierBlocks.empty()) {
|
||||
cmdfl->v3error("--hierarchical-block must be set when --hierarchical-child is set");
|
||||
if (m_hierChild) {
|
||||
if (m_hierBlocks.empty()) {
|
||||
cmdfl->v3error("--hierarchical-block must be set when --hierarchical-child is set");
|
||||
}
|
||||
m_main = false;
|
||||
}
|
||||
|
||||
if (protectIds()) {
|
||||
|
@ -1326,6 +1329,8 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc,
|
|||
m_hierBlocks.emplace(opt.mangledName(), opt);
|
||||
});
|
||||
DECL_OPTION("-hierarchical-child", Set, &m_hierChild);
|
||||
DECL_OPTION("-hierarchical-params-file", CbVal,
|
||||
[this](const char* optp) { m_hierParamsFile = optp; });
|
||||
|
||||
DECL_OPTION("-I", CbPartialMatch,
|
||||
[this, &optdir](const char* optp) { addIncDirUser(parseFileArg(optdir, optp)); });
|
||||
|
|
|
@ -346,6 +346,7 @@ private:
|
|||
string m_buildDepBin; // main switch: --build-dep-bin {filename}
|
||||
string m_exeName; // main switch: -o {name}
|
||||
string m_flags; // main switch: -f {name}
|
||||
string m_hierParamsFile; // main switch: --hierarchical-params-file
|
||||
string m_l2Name; // main switch: --l2name; "" for top-module's name
|
||||
string m_libCreate; // main switch: --lib-create {lib_name}
|
||||
string m_mainTopName; // main switch: --main-top-name
|
||||
|
@ -600,6 +601,7 @@ public:
|
|||
int compLimitParens() const { return m_compLimitParens; }
|
||||
|
||||
string exeName() const { return m_exeName != "" ? m_exeName : prefix(); }
|
||||
string hierParamFile() const { return m_hierParamsFile; }
|
||||
string l2Name() const { return m_l2Name; }
|
||||
string libCreate() const { return m_libCreate; }
|
||||
string libCreateName(bool shared) {
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
|
||||
#include "V3Case.h"
|
||||
#include "V3Const.h"
|
||||
#include "V3EmitV.h"
|
||||
#include "V3Hasher.h"
|
||||
#include "V3Os.h"
|
||||
#include "V3Parse.h"
|
||||
|
@ -90,7 +91,9 @@ class ParameterizedHierBlocks final {
|
|||
|
||||
public:
|
||||
ParameterizedHierBlocks(const V3HierBlockOptSet& hierOpts, AstNetlist* nodep)
|
||||
: m_hierSubRun(!v3Global.opt.hierBlocks().empty() || v3Global.opt.hierChild()) {
|
||||
: m_hierSubRun((!v3Global.opt.hierBlocks().empty() || v3Global.opt.hierChild())
|
||||
// Exclude consolidation
|
||||
&& !v3Global.opt.hierParamFile().empty()) {
|
||||
for (const auto& hierOpt : hierOpts) {
|
||||
m_hierBlockOptsByOrigName.emplace(hierOpt.second.origName(), &hierOpt.second);
|
||||
const V3HierarchicalBlockOption::ParamStrMap& params = hierOpt.second.params();
|
||||
|
@ -146,8 +149,6 @@ public:
|
|||
UASSERT(params.size() == hierIt->second->params().size(), "not match");
|
||||
for (AstPin* pinp = firstPinp; pinp; pinp = VN_AS(pinp->nextp(), Pin)) {
|
||||
if (!pinp->exprp()) continue;
|
||||
UASSERT_OBJ(!pinp->modPTypep(), pinp,
|
||||
"module with type parameter must not be a hierarchical block");
|
||||
if (const AstVar* const modvarp = pinp->modVarp()) {
|
||||
AstConst* const constp = VN_AS(pinp->exprp(), Const);
|
||||
UASSERT_OBJ(constp, pinp,
|
||||
|
@ -275,7 +276,7 @@ class ParamProcessor final {
|
|||
// Database to get lib-create wrapper that matches parameters in hierarchical Verilation
|
||||
ParameterizedHierBlocks m_hierBlocks;
|
||||
// Default parameter values key:parameter name, value:default value (can be nullptr)
|
||||
using DefaultValueMap = std::map<std::string, AstConst*>;
|
||||
using DefaultValueMap = std::map<std::string, AstNode*>;
|
||||
// Default parameter values of hierarchical blocks
|
||||
std::map<AstNodeModule*, DefaultValueMap> m_defaultParameterValues;
|
||||
VNDeleter m_deleter; // Used to delay deletion of nodes
|
||||
|
@ -457,7 +458,7 @@ class ParamProcessor final {
|
|||
}
|
||||
// Check if parameter setting during instantiation is simple enough for hierarchical Verilation
|
||||
void checkSupportedParam(AstNodeModule* modp, AstPin* pinp) const {
|
||||
// InitArray and AstParamTypeDType are not supported because that can not be set via -G
|
||||
// InitArray is not supported because that can not be set via -G
|
||||
// option.
|
||||
if (pinp->modVarp()) {
|
||||
bool supported = false;
|
||||
|
@ -465,13 +466,11 @@ class ParamProcessor final {
|
|||
supported = !constp->isOpaque();
|
||||
}
|
||||
if (!supported) {
|
||||
pinp->v3error(AstNode::prettyNameQ(modp->origName())
|
||||
<< " has hier_block metacomment, hierarchical Verilation"
|
||||
<< " supports only integer/floating point/string parameters");
|
||||
pinp->v3error(
|
||||
AstNode::prettyNameQ(modp->origName())
|
||||
<< " has hier_block metacomment, hierarchical Verilation"
|
||||
<< " supports only integer/floating point/string and type param parameters");
|
||||
}
|
||||
} else {
|
||||
pinp->v3error(AstNode::prettyNameQ(modp->origName())
|
||||
<< " has hier_block metacomment, but 'parameter type' is not supported");
|
||||
}
|
||||
}
|
||||
bool moduleExists(const string& modName) const {
|
||||
|
@ -487,16 +486,18 @@ class ParamProcessor final {
|
|||
// - Hash the long name to get valid Verilog symbol
|
||||
UASSERT_OBJ(modp->hierBlock(), modp, "should be used for hierarchical block");
|
||||
|
||||
std::map<string, AstConst*> pins;
|
||||
for (AstPin* pinp = paramPinsp; pinp; pinp = VN_AS(pinp->nextp(), Pin)) {
|
||||
std::map<string, AstNode*> pins;
|
||||
|
||||
AstPin* pinp = paramPinsp;
|
||||
while (pinp) {
|
||||
checkSupportedParam(modp, pinp);
|
||||
if (const AstVar* const varp = pinp->modVarp()) {
|
||||
if (!pinp->exprp()) continue;
|
||||
if (varp->isGParam()) {
|
||||
AstConst* const constp = VN_CAST(pinp->exprp(), Const);
|
||||
pins.emplace(varp->name(), constp);
|
||||
}
|
||||
if (varp->isGParam()) { pins.emplace(varp->name(), pinp->exprp()); }
|
||||
} else if (VN_IS(pinp->exprp(), BasicDType) || VN_IS(pinp->exprp(), NodeDType)) {
|
||||
pins.emplace(pinp->name(), pinp->exprp());
|
||||
}
|
||||
pinp = VN_AS(pinp->nextp(), Pin);
|
||||
}
|
||||
|
||||
const auto pair = m_defaultParameterValues.emplace(
|
||||
|
@ -513,6 +514,8 @@ class ParamProcessor final {
|
|||
// nullptr means that the parameter is using some default value.
|
||||
params.emplace(varp->name(), constp);
|
||||
}
|
||||
} else if (const AstParamTypeDType* const p = VN_CAST(stmtp, ParamTypeDType)) {
|
||||
params.emplace(p->name(), p->skipRefp());
|
||||
}
|
||||
}
|
||||
pair.first->second = std::move(params);
|
||||
|
@ -523,13 +526,23 @@ class ParamProcessor final {
|
|||
string longname = modp->origName();
|
||||
for (auto&& defaultValue : paramsIt->second) {
|
||||
const auto pinIt = pins.find(defaultValue.first);
|
||||
const AstConst* const constp
|
||||
= pinIt == pins.end() ? defaultValue.second : pinIt->second;
|
||||
// If the pin does not have a value assigned, use the default one.
|
||||
const AstNode* const node = pinIt == pins.end() ? defaultValue.second : pinIt->second;
|
||||
// This longname is not valid as verilog symbol, but ok, because it will be hashed
|
||||
longname += "_" + defaultValue.first + "=";
|
||||
// constp can be nullptr
|
||||
if (constp) longname += constp->num().ascii(false);
|
||||
|
||||
if (const AstConst* const p = VN_CAST(node, Const)) {
|
||||
// Treat modules parametrized with the same values but with different type as the
|
||||
// same.
|
||||
longname += p->num().ascii(false);
|
||||
} else if (node) {
|
||||
std::stringstream type;
|
||||
V3EmitV::verilogForTree(node, type);
|
||||
longname += type.str();
|
||||
}
|
||||
}
|
||||
UINFO(9, " module params longname: " << longname << endl);
|
||||
|
||||
const auto iter = m_longMap.find(longname);
|
||||
if (iter != m_longMap.end()) return iter->second; // Already calculated
|
||||
|
|
|
@ -744,6 +744,7 @@ static void verilate(const string& argString) {
|
|||
v3Global.hierPlanp()->writeCommandArgsFiles(true);
|
||||
V3EmitCMake::emit();
|
||||
}
|
||||
v3Global.hierPlanp()->writeParametersFiles();
|
||||
}
|
||||
if (v3Global.opt.makeDepend().isTrue()) {
|
||||
string filename = v3Global.opt.makeDir() + "/" + v3Global.opt.prefix();
|
||||
|
|
|
@ -114,6 +114,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
|||
"forceable" { FL; return yVLT_FORCEABLE; }
|
||||
"full_case" { FL; return yVLT_FULL_CASE; }
|
||||
"hier_block" { FL; return yVLT_HIER_BLOCK; }
|
||||
"hier_params" { FL; return yVLT_HIER_PARAMS; }
|
||||
"inline" { FL; return yVLT_INLINE; }
|
||||
"isolate_assignments" { FL; return yVLT_ISOLATE_ASSIGNMENTS; }
|
||||
"lint_off" { FL; return yVLT_LINT_OFF; }
|
||||
|
|
|
@ -473,6 +473,7 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"})
|
|||
%token<fl> yVLT_FORCEABLE "forceable"
|
||||
%token<fl> yVLT_FULL_CASE "full_case"
|
||||
%token<fl> yVLT_HIER_BLOCK "hier_block"
|
||||
%token<fl> yVLT_HIER_PARAMS "hier_params"
|
||||
%token<fl> yVLT_INLINE "inline"
|
||||
%token<fl> yVLT_ISOLATE_ASSIGNMENTS "isolate_assignments"
|
||||
%token<fl> yVLT_LINT_OFF "lint_off"
|
||||
|
@ -7497,6 +7498,8 @@ vltItem:
|
|||
{ V3Config::addCaseFull(*$3, $5->toUInt()); }
|
||||
| yVLT_HIER_BLOCK vltDModuleE
|
||||
{ V3Config::addModulePragma(*$2, VPragmaType::HIER_BLOCK); }
|
||||
| yVLT_HIER_PARAMS vltDModuleE
|
||||
{ V3Config::addModulePragma(*$2, VPragmaType::HIER_PARAMS); }
|
||||
| yVLT_PARALLEL_CASE yVLT_D_FILE yaSTRING
|
||||
{ V3Config::addCaseParallel(*$3, 0); }
|
||||
| yVLT_PARALLEL_CASE yVLT_D_FILE yaSTRING yVLT_D_LINES yaINTNUM
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
%Error: t/t_hier_block0_bad.v:21:11: 'sub0' has hier_block metacomment, hierarchical Verilation supports only integer/floating point/string parameters
|
||||
%Error: t/t_hier_block0_bad.v:21:11: 'sub0' has hier_block metacomment, hierarchical Verilation supports only integer/floating point/string and type param parameters
|
||||
: ... note: In instance 't'
|
||||
21 | sub0 #(UNPACKED) i_sub0(.clk(clk), .in(8'(count)), .out(out0));
|
||||
| ^~~~~~~~
|
||||
%Error: t/t_hier_block0_bad.v:23:12: 'sub1' has hier_block metacomment, but 'parameter type' is not supported
|
||||
: ... note: In instance 't'
|
||||
23 | sub1 #(.T(logic[7:0])) i_sub1(.in(out0), .out(out1));
|
||||
| ^
|
||||
%Error: t/t_hier_block0_bad.v:27:42: Cannot access inside hierarchical block
|
||||
27 | $display("%d %d %d", count, i_sub0.ff, out1);
|
||||
%Error: t/t_hier_block0_bad.v:26:42: Cannot access inside hierarchical block
|
||||
26 | $display("%d %d %d", count, i_sub0.ff, out1);
|
||||
| ^~
|
||||
%Error: Exiting due to
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2020 by Yutetsu TAKATSUKASA
|
||||
// without warranty, 2020-2024 by Yutetsu TAKATSUKASA and Antmicro.
|
||||
// SPDX-License-Identifier: Unlicense
|
||||
|
||||
`define HIER_BLOCK /*verilator hier_block*/
|
||||
|
@ -19,7 +19,6 @@ module t (/*AUTOARG*/
|
|||
// unpacked array cannot be passed to hierarchical block
|
||||
localparam logic UNPACKED[0:1] = '{1'b1, 1'b0};
|
||||
sub0 #(UNPACKED) i_sub0(.clk(clk), .in(8'(count)), .out(out0));
|
||||
// Passing type parameter is not supported
|
||||
sub1 #(.T(logic[7:0])) i_sub1(.in(out0), .out(out1));
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,24 @@
|
|||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2024 by Wilson Snyder. 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(
|
||||
verilator_flags2 => ['--hierarchical']
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
);
|
||||
|
||||
file_grep($Self->{obj_dir} . "/VTest_1/Test_1.sv", /^module\s+(\S+)\s+/, "Test");
|
||||
|
||||
ok(1);
|
||||
1;
|
|
@ -0,0 +1,35 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2024 by Antmicro.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t(
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
logic [31:0] in1;
|
||||
logic [31:0] out1;
|
||||
|
||||
assign in1 = 0;
|
||||
|
||||
Test #(.TYPE_t(logic[31:0])) test(.out (out1), .in (in1));
|
||||
|
||||
always @ (posedge clk) begin
|
||||
if (out1 !== ~in1) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module Test
|
||||
#(parameter type TYPE_t = logic [4:0])
|
||||
(
|
||||
output TYPE_t out,
|
||||
input TYPE_t in
|
||||
);
|
||||
/*verilator hier_block*/
|
||||
|
||||
assign out = ~ in;
|
||||
endmodule
|
|
@ -0,0 +1,21 @@
|
|||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2024 by Wilson Snyder. 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(
|
||||
verilator_flags2 => ['--hierarchical']
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
);
|
||||
ok(1);
|
||||
1;
|
|
@ -0,0 +1,35 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2024 by Antmicro.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t(
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
logic [31:0] in1;
|
||||
logic [31:0] out1;
|
||||
|
||||
assign in1 = 0;
|
||||
|
||||
Test #(.TYPE_IN(logic[31:0]), .TYPE_OUT(logic[31:0])) test(.out (out1), .in (in1));
|
||||
|
||||
always @ (posedge clk) begin
|
||||
if (out1 !== ~in1) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module Test
|
||||
#(parameter type TYPE_IN = logic [4:0], parameter type TYPE_OUT = logic [7:0])
|
||||
(
|
||||
output TYPE_IN out,
|
||||
input TYPE_OUT in
|
||||
);
|
||||
/*verilator hier_block*/
|
||||
|
||||
assign out = ~ in;
|
||||
endmodule
|
|
@ -0,0 +1,21 @@
|
|||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2024 by Wilson Snyder. 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(
|
||||
verilator_flags2 => ['--hierarchical']
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
);
|
||||
ok(1);
|
||||
1;
|
|
@ -0,0 +1,42 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2024 by Antmicro.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t(
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
logic [21:0] in1;
|
||||
logic [21:0] out1;
|
||||
|
||||
assign in1 = 0;
|
||||
|
||||
Test #(.TYPE_t(logic[21:0])) test(.out (out1), .in (in1));
|
||||
|
||||
logic [63:0] in2;
|
||||
logic [63:0] out2;
|
||||
|
||||
assign in2 = 0;
|
||||
Test #(.TYPE_t(logic[63:0])) test2(.out (out2), .in (in2));
|
||||
|
||||
always @ (posedge clk) begin
|
||||
if (out1 !== ~in1) $stop;
|
||||
if (out2 !== ~in2) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module Test
|
||||
#(parameter type TYPE_t = logic [4:0])
|
||||
(
|
||||
output TYPE_t out,
|
||||
input TYPE_t in
|
||||
);
|
||||
/*verilator hier_block*/
|
||||
|
||||
assign out = ~ in;
|
||||
endmodule
|
|
@ -0,0 +1,22 @@
|
|||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2024 by Wilson Snyder. 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(
|
||||
verilator_flags2 => ['--hierarchical'],
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
|
@ -0,0 +1,53 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2024 by Antmicro.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t(
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
logic [2:0] in1;
|
||||
logic [2:0] out1;
|
||||
|
||||
assign in1 = 0;
|
||||
|
||||
Test #(.TYPE_t(logic[2:0])) test(.out (out1), .in (in1));
|
||||
|
||||
logic [3:0] in2;
|
||||
logic [3:0] out2;
|
||||
|
||||
assign in2 = 0;
|
||||
Test #(.TYPE_t(logic[3:0])) test2(.out (out2), .in (in2));
|
||||
|
||||
always @ (posedge clk) begin
|
||||
if (out1 !== ~in1) $stop;
|
||||
if (out2 !== ~in2) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module Test
|
||||
#(parameter type TYPE_t = logic [5:0])
|
||||
(
|
||||
output TYPE_t out,
|
||||
input TYPE_t in
|
||||
);
|
||||
/*verilator hier_block*/
|
||||
|
||||
SubTest #(.TYPE_t(TYPE_t)) subTest(.out(out), .in(in));
|
||||
endmodule
|
||||
|
||||
module SubTest
|
||||
#(parameter type TYPE_t = logic [8:0])
|
||||
(
|
||||
output TYPE_t out,
|
||||
input TYPE_t in
|
||||
);
|
||||
/*verilator hier_block*/
|
||||
|
||||
assign out = ~ in;
|
||||
endmodule
|
|
@ -0,0 +1,12 @@
|
|||
%Error: Cannot open file containing hierarchical parameter declarations: '/does-not-exist'
|
||||
... Looked in:
|
||||
t//does-not-exist
|
||||
t//does-not-exist.v
|
||||
t//does-not-exist.sv
|
||||
/does-not-exist
|
||||
/does-not-exist.v
|
||||
/does-not-exist.sv
|
||||
obj_vlt/t_hier_block_type_param_notfound_bad//does-not-exist
|
||||
obj_vlt/t_hier_block_type_param_notfound_bad//does-not-exist.v
|
||||
obj_vlt/t_hier_block_type_param_notfound_bad//does-not-exist.sv
|
||||
%Error: Exiting due to
|
|
@ -0,0 +1,21 @@
|
|||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2024 by Wilson Snyder. 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(vlt => 1);
|
||||
top_filename("t/t_hier_block_type_param.v");
|
||||
|
||||
compile (
|
||||
verilator_flags2 => ["--hierarchical-params-file", "/does-not-exist"],
|
||||
fails => 1,
|
||||
expect_filename => $Self->{golden_filename},
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
|
@ -0,0 +1,43 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2024 by Antmicro.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t(
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
logic [21:0] in1;
|
||||
logic [21:0] out1;
|
||||
|
||||
assign in1 = 0;
|
||||
typedef logic[21:0] PARAM_T;
|
||||
Test #(.TYPE_t(PARAM_T)) test(.out (out1), .in (in1));
|
||||
|
||||
logic [63:0] in2;
|
||||
logic [63:0] out2;
|
||||
|
||||
assign in2 = 0;
|
||||
typedef logic[63:0] PARAM2_T;
|
||||
Test #(.TYPE_t(PARAM2_T)) test2(.out (out2), .in (in2));
|
||||
|
||||
always @ (posedge clk) begin
|
||||
if (out1 !== ~in1) $stop;
|
||||
if (out2 !== ~in2) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module Test
|
||||
#(parameter type TYPE_t = logic [4:0])
|
||||
(
|
||||
output TYPE_t out,
|
||||
input TYPE_t in
|
||||
);
|
||||
/*verilator hier_block*/
|
||||
|
||||
assign out = ~ in;
|
||||
endmodule
|
|
@ -0,0 +1,23 @@
|
|||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003-2024 by Wilson Snyder. 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);
|
||||
top_filename("t/t_typedef_param.v");
|
||||
|
||||
compile(
|
||||
verilator_flags2 => ["--hierarchical"]
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
|
@ -80,6 +80,7 @@ module TestNonAnsi (/*AUTOARG*/
|
|||
// Inputs
|
||||
clk, in
|
||||
);
|
||||
/*verilator hier_block*/
|
||||
parameter type p_t = shortint;
|
||||
|
||||
input clk;
|
||||
|
@ -97,7 +98,8 @@ module TestAnsi
|
|||
input clk,
|
||||
input p_t in,
|
||||
output p_t out
|
||||
);
|
||||
);
|
||||
/*verilator hier_block*/
|
||||
always @(posedge clk) begin
|
||||
out <= ~in;
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue