Internals: Refactor `systemc_* section handling (#6280)
This commit is contained in:
parent
cefcf836fd
commit
0c712d7c60
|
|
@ -1604,6 +1604,37 @@ inline std::ostream& operator<<(std::ostream& os, const VStrength& rhs) {
|
|||
return os << rhs.ascii();
|
||||
}
|
||||
|
||||
// ######################################################################
|
||||
// VSystemCSectionType - Represents the type of a `systemc_* block (Verilator specific extension)
|
||||
|
||||
class VSystemCSectionType final {
|
||||
public:
|
||||
enum en : uint8_t {
|
||||
CTOR, // `systemc_ctor
|
||||
DTOR, // `systemc_dtor
|
||||
HDR, // `systemc_header
|
||||
HDR_POST, // `systemc_header_post
|
||||
IMP, // `systemc_implementation
|
||||
IMP_HDR, // `systemc_imp_header
|
||||
INT // `systemc_interface
|
||||
};
|
||||
enum en m_e;
|
||||
const char* ascii() const {
|
||||
static const char* const names[] = {"`systemc_ctor", //
|
||||
"`systemc_dtor", //
|
||||
"`systemc_header", //
|
||||
"`systemc_header_post", //
|
||||
"`systemc_implementation", //
|
||||
"`systemc_imp_header", //
|
||||
"`systemc_interface"};
|
||||
return names[m_e];
|
||||
}
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
constexpr VSystemCSectionType(en _e)
|
||||
: m_e{_e} {}
|
||||
constexpr operator en() const { return m_e; }
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
||||
class VTracePrefixType final {
|
||||
|
|
|
|||
|
|
@ -1643,6 +1643,29 @@ public:
|
|||
void dump(std::ostream& str) const override;
|
||||
void dumpJson(std::ostream& str) const override;
|
||||
};
|
||||
class AstSystemCSection final : public AstNode {
|
||||
// Verilator specific "`systemc_* block". This is a "module item"
|
||||
// containing arbitrary text that is emitted to the C++ output in various
|
||||
// locations depending on the sectionType.
|
||||
const VSystemCSectionType m_sectionType; // The section type
|
||||
const std::string m_text; // The text content
|
||||
|
||||
public:
|
||||
AstSystemCSection(FileLine* fl, VSystemCSectionType sectionType, const std::string& text)
|
||||
: ASTGEN_SUPER_SystemCSection(fl)
|
||||
, m_sectionType{sectionType}
|
||||
, m_text{text} {
|
||||
v3Global.setHasSystemCSections();
|
||||
}
|
||||
ASTGEN_MEMBERS_AstSystemCSection;
|
||||
VSystemCSectionType sectionType() const { return m_sectionType; }
|
||||
const std::string& text() const { return m_text; }
|
||||
void dump(std::ostream&) const override;
|
||||
void dumpJson(std::ostream&) const override;
|
||||
bool sameNode(const AstNode*) const override { return false; }
|
||||
bool isPure() override { return false; }
|
||||
bool isOutputter() override { return true; }
|
||||
};
|
||||
class AstTopScope final : public AstNode {
|
||||
// A singleton, held under the top level AstModule. Holds the top level
|
||||
// AstScope, and after V3ActiveTop, the global list of AstSenTrees (list of
|
||||
|
|
@ -2808,64 +2831,6 @@ public:
|
|||
bool sameNode(const AstNode* /*samep*/) const override { return true; }
|
||||
};
|
||||
|
||||
// === AstNodeText ===
|
||||
class AstScCtor final : public AstNodeText {
|
||||
public:
|
||||
AstScCtor(FileLine* fl, const string& textp)
|
||||
: ASTGEN_SUPER_ScCtor(fl, textp) {}
|
||||
ASTGEN_MEMBERS_AstScCtor;
|
||||
bool isPure() override { return false; } // SPECIAL: User may order w/other sigs
|
||||
bool isOutputter() override { return true; }
|
||||
};
|
||||
class AstScDtor final : public AstNodeText {
|
||||
public:
|
||||
AstScDtor(FileLine* fl, const string& textp)
|
||||
: ASTGEN_SUPER_ScDtor(fl, textp) {}
|
||||
ASTGEN_MEMBERS_AstScDtor;
|
||||
bool isPure() override { return false; } // SPECIAL: User may order w/other sigs
|
||||
bool isOutputter() override { return true; }
|
||||
};
|
||||
class AstScHdr final : public AstNodeText {
|
||||
public:
|
||||
AstScHdr(FileLine* fl, const string& textp)
|
||||
: ASTGEN_SUPER_ScHdr(fl, textp) {}
|
||||
ASTGEN_MEMBERS_AstScHdr;
|
||||
bool isPure() override { return false; } // SPECIAL: User may order w/other sigs
|
||||
bool isOutputter() override { return true; }
|
||||
};
|
||||
class AstScHdrPost final : public AstNodeText {
|
||||
public:
|
||||
AstScHdrPost(FileLine* fl, const string& textp)
|
||||
: ASTGEN_SUPER_ScHdrPost(fl, textp) {}
|
||||
ASTGEN_MEMBERS_AstScHdrPost;
|
||||
bool isPure() override { return false; } // SPECIAL: User may order w/other sigs
|
||||
bool isOutputter() override { return true; }
|
||||
};
|
||||
class AstScImp final : public AstNodeText {
|
||||
public:
|
||||
AstScImp(FileLine* fl, const string& textp)
|
||||
: ASTGEN_SUPER_ScImp(fl, textp) {}
|
||||
ASTGEN_MEMBERS_AstScImp;
|
||||
bool isPure() override { return false; } // SPECIAL: User may order w/other sigs
|
||||
bool isOutputter() override { return true; }
|
||||
};
|
||||
class AstScImpHdr final : public AstNodeText {
|
||||
public:
|
||||
AstScImpHdr(FileLine* fl, const string& textp)
|
||||
: ASTGEN_SUPER_ScImpHdr(fl, textp) {}
|
||||
ASTGEN_MEMBERS_AstScImpHdr;
|
||||
bool isPure() override { return false; } // SPECIAL: User may order w/other sigs
|
||||
bool isOutputter() override { return true; }
|
||||
};
|
||||
class AstScInt final : public AstNodeText {
|
||||
public:
|
||||
AstScInt(FileLine* fl, const string& textp)
|
||||
: ASTGEN_SUPER_ScInt(fl, textp) {}
|
||||
ASTGEN_MEMBERS_AstScInt;
|
||||
bool isPure() override { return false; } // SPECIAL: User may order w/other sigs
|
||||
bool isOutputter() override { return true; }
|
||||
};
|
||||
|
||||
// === AstNodeSimpleText ===
|
||||
class AstText final : public AstNodeSimpleText {
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -2532,6 +2532,14 @@ void AstSliceSel::dumpJson(std::ostream& str) const {
|
|||
if (declRange().ranged()) dumpJsonStr(str, "declRange", cvtToStr(declRange()));
|
||||
dumpJsonGen(str);
|
||||
}
|
||||
void AstSystemCSection::dump(std::ostream& str) const {
|
||||
this->AstNode::dump(str);
|
||||
str << " sectionType=" << sectionType().ascii();
|
||||
}
|
||||
void AstSystemCSection::dumpJson(std::ostream& str) const {
|
||||
dumpJsonStr(str, "sectionType", sectionType().ascii());
|
||||
dumpJsonGen(str);
|
||||
}
|
||||
void AstMTaskBody::dump(std::ostream& str) const {
|
||||
this->AstNode::dump(str);
|
||||
str << " ";
|
||||
|
|
|
|||
|
|
@ -138,8 +138,8 @@ class CCtorsVisitor final : public VNVisitor {
|
|||
V3CCtorsBuilder* m_varResetp = nullptr; // Builder of _ctor_var_reset
|
||||
|
||||
// METHODS
|
||||
static void insertSc(AstCFunc* cfuncp, const AstNodeModule* modp, VNType type) {
|
||||
auto textAndFileline = EmitCBaseVisitorConst::textSection(modp, type);
|
||||
static void insertSc(AstCFunc* cfuncp, const AstNodeModule* modp, VSystemCSectionType type) {
|
||||
auto textAndFileline = EmitCBaseVisitorConst::scSection(modp, type);
|
||||
if (!textAndFileline.first.empty()) {
|
||||
AstTextBlock* const newp
|
||||
= new AstTextBlock{textAndFileline.second, textAndFileline.first, false, false};
|
||||
|
|
@ -177,7 +177,7 @@ class CCtorsVisitor final : public VNVisitor {
|
|||
// If can be referred to by base pointer, need virtual delete
|
||||
funcp->isVirtual(classp->isExtended());
|
||||
funcp->slow(false);
|
||||
insertSc(funcp, classp, VNType::ScDtor);
|
||||
insertSc(funcp, classp, VSystemCSectionType::DTOR);
|
||||
classp->addStmtsp(funcp);
|
||||
}
|
||||
}
|
||||
|
|
@ -188,7 +188,7 @@ class CCtorsVisitor final : public VNVisitor {
|
|||
m_varResetp = nullptr;
|
||||
m_cfuncp = nodep;
|
||||
iterateChildren(nodep);
|
||||
if (nodep->name() == "new") insertSc(nodep, m_modp, VNType::ScCtor);
|
||||
if (nodep->name() == "new") insertSc(nodep, m_modp, VSystemCSectionType::CTOR);
|
||||
}
|
||||
void visit(AstVar* nodep) override {
|
||||
if (nodep->needsCReset()) {
|
||||
|
|
|
|||
|
|
@ -281,26 +281,28 @@ void EmitCBaseVisitorConst::emitModCUse(const AstNodeModule* modp, VUseType useT
|
|||
if (nl) puts("\n");
|
||||
}
|
||||
|
||||
std::pair<string, FileLine*> EmitCBaseVisitorConst::textSection(const AstNodeModule* modp,
|
||||
VNType type) {
|
||||
if (!v3Global.hasSCTextSections()) return std::make_pair("", nullptr);
|
||||
std::pair<string, FileLine*> EmitCBaseVisitorConst::scSection(const AstNodeModule* modp,
|
||||
VSystemCSectionType type) {
|
||||
if (!v3Global.hasSystemCSections()) return std::make_pair("", nullptr);
|
||||
string text;
|
||||
FileLine* fl = nullptr;
|
||||
int last_line = -999;
|
||||
for (AstNode* nodep = modp->stmtsp(); nodep; nodep = nodep->nextp()) {
|
||||
if (nodep->type() != type) continue;
|
||||
if (const AstNodeText* const textp = VN_CAST(nodep, NodeText)) {
|
||||
if (text.empty()) {
|
||||
fl = textp->fileline();
|
||||
text += "\n";
|
||||
if (v3Global.opt.decoration())
|
||||
text += "\n//*** Below code from `systemc in Verilog file\n";
|
||||
AstSystemCSection* const ssp = VN_CAST(nodep, SystemCSection);
|
||||
if (!ssp) continue;
|
||||
if (ssp->sectionType() != type) continue;
|
||||
if (text.empty()) {
|
||||
fl = ssp->fileline();
|
||||
text += "\n";
|
||||
if (v3Global.opt.decoration()) {
|
||||
text += "\n//*** Below code from `systemc in Verilog file\n";
|
||||
}
|
||||
if (last_line + 1 != nodep->fileline()->lineno() && v3Global.opt.decoration())
|
||||
text += "// From `systemc at " + nodep->fileline()->ascii() + "\n";
|
||||
last_line = textp->fileline()->lineno();
|
||||
text += textp->text();
|
||||
}
|
||||
if (last_line + 1 != nodep->fileline()->lineno() && v3Global.opt.decoration()) {
|
||||
text += "// From `systemc at " + nodep->fileline()->ascii() + "\n";
|
||||
}
|
||||
last_line = ssp->fileline()->lineno();
|
||||
text += ssp->text();
|
||||
}
|
||||
if (!text.empty()) {
|
||||
if (v3Global.opt.decoration()) text += "//*** Above code from `systemc in Verilog file\n";
|
||||
|
|
@ -315,9 +317,10 @@ std::pair<string, FileLine*> EmitCBaseVisitorConst::textSection(const AstNodeMod
|
|||
return std::make_pair(text, fl);
|
||||
}
|
||||
|
||||
void EmitCBaseVisitorConst::emitTextSection(const AstNodeModule* modp, VNType type) {
|
||||
void EmitCBaseVisitorConst::emitSystemCSection(const AstNodeModule* modp,
|
||||
VSystemCSectionType type) {
|
||||
// Short circuit if nothing to do. This can save a lot of time on large designs as this
|
||||
// function needs to traverse the entire module linearly.
|
||||
auto textAndFileline = textSection(modp, type);
|
||||
auto textAndFileline = scSection(modp, type);
|
||||
if (!textAndFileline.first.empty()) ofp()->putsNoTracking(textAndFileline.first);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -158,8 +158,9 @@ public:
|
|||
}
|
||||
}
|
||||
void emitModCUse(const AstNodeModule* modp, VUseType useType);
|
||||
void emitTextSection(const AstNodeModule* modp, VNType type);
|
||||
static std::pair<string, FileLine*> textSection(const AstNodeModule* modp, VNType type);
|
||||
void emitSystemCSection(const AstNodeModule* modp, VSystemCSectionType type);
|
||||
static std::pair<string, FileLine*> scSection(const AstNodeModule* modp,
|
||||
VSystemCSectionType type);
|
||||
|
||||
// CONSTRUCTORS
|
||||
EmitCBaseVisitorConst() = default;
|
||||
|
|
|
|||
|
|
@ -564,7 +564,7 @@ class EmitCHeader final : public EmitCConstInit {
|
|||
puts("\nclass " + EmitCUtil::symClassName() + ";\n");
|
||||
|
||||
// From `systemc_header
|
||||
emitTextSection(modp, VNType::ScHdr);
|
||||
emitSystemCSection(modp, VSystemCSectionType::HDR);
|
||||
|
||||
emitStructs(modp);
|
||||
|
||||
|
|
@ -607,7 +607,7 @@ class EmitCHeader final : public EmitCConstInit {
|
|||
emitFuncDecls(modp, /* inClassBody: */ true);
|
||||
|
||||
// From `systemc_interface
|
||||
emitTextSection(modp, VNType::ScInt);
|
||||
emitSystemCSection(modp, VSystemCSectionType::INT);
|
||||
|
||||
// Close class body
|
||||
puts("};\n");
|
||||
|
|
@ -616,7 +616,7 @@ class EmitCHeader final : public EmitCConstInit {
|
|||
// Emit out of class function declarations
|
||||
puts("\n");
|
||||
emitFuncDecls(modp, /* inClassBody: */ false);
|
||||
emitTextSection(modp, VNType::ScHdrPost);
|
||||
emitSystemCSection(modp, VSystemCSectionType::HDR_POST);
|
||||
}
|
||||
|
||||
explicit EmitCHeader(const AstNodeModule* modp) {
|
||||
|
|
|
|||
|
|
@ -200,7 +200,7 @@ class EmitCImp final : EmitCFunc {
|
|||
puts("#include \"" + EmitCUtil::pchClassName() + ".h\"\n");
|
||||
for (const string& name : headers) puts("#include \"" + name + ".h\"\n");
|
||||
|
||||
emitTextSection(m_modp, VNType::ScImpHdr);
|
||||
emitSystemCSection(m_modp, VSystemCSectionType::IMP_HDR);
|
||||
}
|
||||
|
||||
void emitStaticVarDefns(const AstNodeModule* modp) {
|
||||
|
|
@ -286,7 +286,7 @@ class EmitCImp final : EmitCFunc {
|
|||
|
||||
putsDecoration(modp, "// Reset structure values\n");
|
||||
puts(modName + "__" + protect("_ctor_var_reset") + "(this);\n");
|
||||
emitTextSection(modp, VNType::ScCtor);
|
||||
emitSystemCSection(modp, VSystemCSectionType::CTOR);
|
||||
|
||||
puts("}\n");
|
||||
}
|
||||
|
|
@ -393,7 +393,7 @@ class EmitCImp final : EmitCFunc {
|
|||
puts("\n");
|
||||
putns(modp, EmitCUtil::prefixNameProtect(modp) + "::~" + EmitCUtil::prefixNameProtect(modp)
|
||||
+ "() {\n");
|
||||
emitTextSection(modp, VNType::ScDtor);
|
||||
emitSystemCSection(modp, VSystemCSectionType::DTOR);
|
||||
puts("}\n");
|
||||
splitSizeInc(10);
|
||||
}
|
||||
|
|
@ -487,9 +487,13 @@ class EmitCImp final : EmitCFunc {
|
|||
if (!modp) return false;
|
||||
// We always need the slow file
|
||||
if (m_slow) return true;
|
||||
// The fast file is only required when we have ScImp nodes
|
||||
for (const AstNode* nodep = modp->stmtsp(); nodep; nodep = nodep->nextp()) {
|
||||
if (VN_IS(nodep, ScImp)) return true;
|
||||
// The fast file is only required when we have `systemc_implementation nodes
|
||||
if (v3Global.hasSystemCSections()) {
|
||||
for (const AstNode* nodep = modp->stmtsp(); nodep; nodep = nodep->nextp()) {
|
||||
if (const AstSystemCSection* const ssp = VN_CAST(nodep, SystemCSection)) {
|
||||
if (ssp->sectionType() == VSystemCSectionType::IMP) return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -507,7 +511,7 @@ class EmitCImp final : EmitCFunc {
|
|||
emitSavableImp(modp);
|
||||
} else {
|
||||
// From `systemc_implementation
|
||||
emitTextSection(modp, VNType::ScImp);
|
||||
emitSystemCSection(modp, VSystemCSectionType::IMP);
|
||||
}
|
||||
}
|
||||
void emitCommonImp(const AstNodeModule* modp) {
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ class V3Global final {
|
|||
bool m_usesStdPackage = false; // Design uses the std package
|
||||
bool m_usesTiming = false; // Design uses timing constructs
|
||||
bool m_hasForceableSignals = false; // Need to apply V3Force pass
|
||||
bool m_hasSCTextSections = false; // Has `systemc_* sections that need to be emitted
|
||||
bool m_hasSystemCSections = false; // Has AstSystemCSection that need to be emitted
|
||||
bool m_useParallelBuild = false; // Use parallel build for model
|
||||
bool m_useRandomizeMethods = false; // Need to define randomize() class methods
|
||||
uint64_t m_currentHierBlockCost = 0; // Total cost of this hier block, used for scheduling
|
||||
|
|
@ -197,8 +197,8 @@ public:
|
|||
void setUsesTiming() { m_usesTiming = true; }
|
||||
bool hasForceableSignals() const { return m_hasForceableSignals; }
|
||||
void setHasForceableSignals() { m_hasForceableSignals = true; }
|
||||
bool hasSCTextSections() const VL_MT_SAFE { return m_hasSCTextSections; }
|
||||
void setHasSCTextSections() { m_hasSCTextSections = true; }
|
||||
bool hasSystemCSections() const VL_MT_SAFE { return m_hasSystemCSections; }
|
||||
void setHasSystemCSections() { m_hasSystemCSections = true; }
|
||||
V3HierGraph* hierGraphp() const { return m_hierGraphp; }
|
||||
void hierGraphp(V3HierGraph* graphp) { m_hierGraphp = graphp; }
|
||||
bool useParallelBuild() const { return m_useParallelBuild; }
|
||||
|
|
|
|||
|
|
@ -469,20 +469,15 @@ class LinkResolveVisitor final : public VNVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
void visit(AstScCtor* nodep) override {
|
||||
// Constructor info means the module must remain public
|
||||
m_modp->modPublic(true);
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
void visit(AstScDtor* nodep) override {
|
||||
// Destructor info means the module must remain public
|
||||
m_modp->modPublic(true);
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
void visit(AstScInt* nodep) override {
|
||||
// Special class info means the module must remain public
|
||||
m_modp->modPublic(true);
|
||||
iterateChildren(nodep);
|
||||
void visit(AstSystemCSection* nodep) override {
|
||||
switch (nodep->sectionType()) {
|
||||
// Constructor, desctructor or special class info means the module must remain public
|
||||
case VSystemCSectionType::CTOR:
|
||||
case VSystemCSectionType::DTOR:
|
||||
case VSystemCSectionType::INT: m_modp->modPublic(true); break;
|
||||
default: break;
|
||||
}
|
||||
// Has no children
|
||||
}
|
||||
|
||||
void visit(AstIfaceRefDType* nodep) override {
|
||||
|
|
|
|||
|
|
@ -2575,13 +2575,13 @@ non_port_module_item<nodep>: // ==IEEE: non_port_module_item
|
|||
;
|
||||
|
||||
vlScBlock<nodep>: // Verilator-specific `systemc_* blocks
|
||||
yaSCHDR { $$ = new AstScHdr{$<fl>1, *$1}; v3Global.setHasSCTextSections(); }
|
||||
| yaSCHDRP { $$ = new AstScHdrPost{$<fl>1, *$1}; v3Global.setHasSCTextSections(); }
|
||||
| yaSCINT { $$ = new AstScInt{$<fl>1, *$1}; v3Global.setHasSCTextSections(); }
|
||||
| yaSCIMP { $$ = new AstScImp{$<fl>1, *$1}; v3Global.setHasSCTextSections(); }
|
||||
| yaSCIMPH { $$ = new AstScImpHdr{$<fl>1, *$1}; v3Global.setHasSCTextSections(); }
|
||||
| yaSCCTOR { $$ = new AstScCtor{$<fl>1, *$1}; v3Global.setHasSCTextSections(); }
|
||||
| yaSCDTOR { $$ = new AstScDtor{$<fl>1, *$1}; v3Global.setHasSCTextSections(); }
|
||||
yaSCHDR { $$ = new AstSystemCSection{$<fl>1, VSystemCSectionType::HDR, *$1}; }
|
||||
| yaSCHDRP { $$ = new AstSystemCSection{$<fl>1, VSystemCSectionType::HDR_POST, *$1}; }
|
||||
| yaSCINT { $$ = new AstSystemCSection{$<fl>1, VSystemCSectionType::INT, *$1}; }
|
||||
| yaSCIMP { $$ = new AstSystemCSection{$<fl>1, VSystemCSectionType::IMP, *$1}; }
|
||||
| yaSCIMPH { $$ = new AstSystemCSection{$<fl>1, VSystemCSectionType::IMP_HDR, *$1}; }
|
||||
| yaSCCTOR { $$ = new AstSystemCSection{$<fl>1, VSystemCSectionType::CTOR, *$1}; }
|
||||
| yaSCDTOR { $$ = new AstSystemCSection{$<fl>1, VSystemCSectionType::DTOR, *$1}; }
|
||||
;
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue