Support `systemc_interface and related inside `class`.
This commit is contained in:
parent
6edf2f80a2
commit
b4ef6ce860
1
Changes
1
Changes
|
|
@ -20,6 +20,7 @@ Verilator 5.035 devel
|
||||||
**Other:**
|
**Other:**
|
||||||
|
|
||||||
* Support force/release with a variable reference (#5721) (#5810). [Bartłomiej Chmiel, Antmicro Ltd.]
|
* Support force/release with a variable reference (#5721) (#5810). [Bartłomiej Chmiel, Antmicro Ltd.]
|
||||||
|
* Support `systemc_interface and related inside `class`.
|
||||||
* Add multi-thread hierarchical simulation (#2583) (#5871). [Bartłomiej Chmiel, Antmicro Ltd.]
|
* Add multi-thread hierarchical simulation (#2583) (#5871). [Bartłomiej Chmiel, Antmicro Ltd.]
|
||||||
* Add check for `let` misused in statement context (#5733).
|
* Add check for `let` misused in statement context (#5733).
|
||||||
* Add used language to `--preproc-resolve` output (#5795). [Kamil Rakoczy, Antmicro Ltd.]
|
* Add used language to `--preproc-resolve` output (#5795). [Kamil Rakoczy, Antmicro Ltd.]
|
||||||
|
|
|
||||||
|
|
@ -107,48 +107,60 @@ or "`ifdef`"'s may break other tools.
|
||||||
Take the remaining text up to the next :option:`\`verilog` or
|
Take the remaining text up to the next :option:`\`verilog` or
|
||||||
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
|
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
|
||||||
verbatim into the output .h file's header. Must be placed as a module
|
verbatim into the output .h file's header. Must be placed as a module
|
||||||
item, e.g., directly inside a module/endmodule pair. Despite the name of
|
or class item, e.g., directly inside a module/endmodule or
|
||||||
this macro, this also works in pure C++ code.
|
class/endclass pair. Despite the name of this macro, this also works in
|
||||||
|
pure C++ code.
|
||||||
|
|
||||||
|
.. option:: `systemc_class_name
|
||||||
|
|
||||||
|
Inside one of the :option:`\`systemc_... <\`systemc_header>` text
|
||||||
|
blocks, replaced with the C++ class name generated for the given
|
||||||
|
containing SystemVerilog class or module. Currently this is replaced
|
||||||
|
blindly, ignoring quoting or other escapes; this behavior may change in
|
||||||
|
the future. This attribute is indented only to be used internally in
|
||||||
|
`verilated_std.sv`.
|
||||||
|
|
||||||
.. option:: `systemc_ctor
|
.. option:: `systemc_ctor
|
||||||
|
|
||||||
Take the remaining text up to the next :option:`\`verilog` or
|
Take the remaining text up to the next :option:`\`verilog` or
|
||||||
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
|
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
|
||||||
verbatim into the C++ class constructor. Must be placed as a module
|
verbatim into the C++ class constructor. Must be placed as a module or
|
||||||
item, e.g., directly inside a module/endmodule pair. Despite the name of
|
class item, e.g., directly inside a module/endmodule or class/endclass
|
||||||
this macro, this also works in pure C++ code.
|
pair. Despite the name of this macro, this also works in pure C++ code.
|
||||||
|
|
||||||
.. option:: `systemc_dtor
|
.. option:: `systemc_dtor
|
||||||
|
|
||||||
Take the remaining text up to the next :option:`\`verilog` or
|
Take the remaining text up to the next :option:`\`verilog` or
|
||||||
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
|
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
|
||||||
verbatim into the C++ class destructor. Must be placed as a module
|
verbatim into the C++ class destructor. Must be placed as a module or
|
||||||
item, e.g., directly inside a module/endmodule pair. Despite the name of
|
class item, e.g., directly inside a module/endmodule or class/endclass
|
||||||
this macro, this also works in pure C++ code.
|
pair. Despite the name of this macro, this also works in pure C++ code.
|
||||||
|
|
||||||
.. option:: `systemc_interface
|
.. option:: `systemc_interface
|
||||||
|
|
||||||
Take the remaining text up to the next :option:`\`verilog` or
|
Take the remaining text up to the next :option:`\`verilog` or
|
||||||
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
|
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
|
||||||
verbatim into the C++ class interface. Must be placed as a module item,
|
verbatim into the C++ class interface. Must be placed as a module or
|
||||||
e.g., directly inside a module/endmodule pair. Despite the name of this
|
class item, e.g., directly inside a module/endmodule or class/endclass
|
||||||
macro, this also works in pure C++ code.
|
pair. Despite the name of this macro, this also works in pure C++ code.
|
||||||
|
|
||||||
.. option:: `systemc_imp_header
|
.. option:: `systemc_imp_header
|
||||||
|
|
||||||
Take the remaining text up to the next :option:`\`verilog` or
|
Take the remaining text up to the next :option:`\`verilog` or
|
||||||
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
|
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
|
||||||
verbatim into the header of all files for this C++ class implementation.
|
verbatim into the header of all files for this C++ class implementation.
|
||||||
Must be placed as a module item, e.g., directly inside a module/endmodule
|
Must be placed as a module or class item, e.g., directly inside a
|
||||||
pair. Despite the name of this macro, this also works in pure C++ code.
|
module/endmodule or class/endclass pair. Despite the name of this macro,
|
||||||
|
this also works in pure C++ code.
|
||||||
|
|
||||||
.. option:: `systemc_implementation
|
.. option:: `systemc_implementation
|
||||||
|
|
||||||
Take the remaining text up to the next :option:`\`verilog` or
|
Take the remaining text up to the next :option:`\`verilog` or
|
||||||
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
|
:option:`\`systemc_... <\`systemc_header>` mode switch and place it
|
||||||
verbatim into a single file of the C++ class implementation. Must be
|
verbatim into a single file of the C++ class implementation. Must be
|
||||||
placed as a module item, e.g., directly inside a module/endmodule
|
placed as a module or class item, e.g., directly inside a
|
||||||
pair. Despite the name of this macro, this also works in pure C++ code.
|
module/endmodule or class/endclass pair. Despite the name of this macro,
|
||||||
|
this also works in pure C++ code.
|
||||||
|
|
||||||
If you will be reading or writing any Verilog variables in the C++
|
If you will be reading or writing any Verilog variables in the C++
|
||||||
functions, the Verilog signals must be declared with a
|
functions, the Verilog signals must be declared with a
|
||||||
|
|
|
||||||
|
|
@ -137,7 +137,17 @@ class CCtorsVisitor final : public VNVisitor {
|
||||||
AstCFunc* m_cfuncp = nullptr; // Current function
|
AstCFunc* m_cfuncp = nullptr; // Current function
|
||||||
V3CCtorsBuilder* m_varResetp = nullptr; // Builder of _ctor_var_reset
|
V3CCtorsBuilder* m_varResetp = nullptr; // Builder of _ctor_var_reset
|
||||||
|
|
||||||
// VISITs
|
// METHODS
|
||||||
|
static void insertSc(AstCFunc* cfuncp, const AstNodeModule* modp, VNType type) {
|
||||||
|
auto textAndFileline = EmitCBaseVisitorConst::textSection(modp, type);
|
||||||
|
if (!textAndFileline.first.empty()) {
|
||||||
|
AstTextBlock* const newp
|
||||||
|
= new AstTextBlock{textAndFileline.second, textAndFileline.first, false, false};
|
||||||
|
cfuncp->addStmtsp(newp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// VISITORS
|
||||||
void visit(AstNodeModule* nodep) override {
|
void visit(AstNodeModule* nodep) override {
|
||||||
VL_RESTORER(m_modp);
|
VL_RESTORER(m_modp);
|
||||||
VL_RESTORER(m_varResetp);
|
VL_RESTORER(m_varResetp);
|
||||||
|
|
@ -167,6 +177,7 @@ class CCtorsVisitor final : public VNVisitor {
|
||||||
// If can be referred to by base pointer, need virtual delete
|
// If can be referred to by base pointer, need virtual delete
|
||||||
funcp->isVirtual(classp->isExtended());
|
funcp->isVirtual(classp->isExtended());
|
||||||
funcp->slow(false);
|
funcp->slow(false);
|
||||||
|
insertSc(funcp, classp, VNType::atScDtor);
|
||||||
classp->addStmtsp(funcp);
|
classp->addStmtsp(funcp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -177,6 +188,7 @@ class CCtorsVisitor final : public VNVisitor {
|
||||||
m_varResetp = nullptr;
|
m_varResetp = nullptr;
|
||||||
m_cfuncp = nodep;
|
m_cfuncp = nodep;
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
|
if (nodep->name() == "new") insertSc(nodep, m_modp, VNType::atScCtor);
|
||||||
}
|
}
|
||||||
void visit(AstVar* nodep) override {
|
void visit(AstVar* nodep) override {
|
||||||
if (nodep->needsCReset()) {
|
if (nodep->needsCReset()) {
|
||||||
|
|
|
||||||
|
|
@ -285,27 +285,43 @@ void EmitCBaseVisitorConst::emitModCUse(const AstNodeModule* modp, VUseType useT
|
||||||
if (nl) puts("\n");
|
if (nl) puts("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<string, FileLine*> EmitCBaseVisitorConst::textSection(const AstNodeModule* modp,
|
||||||
|
VNType type) {
|
||||||
|
if (!v3Global.hasSCTextSections()) 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";
|
||||||
|
}
|
||||||
|
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 (!text.empty()) {
|
||||||
|
if (v3Global.opt.decoration()) text += "//*** Above code from `systemc in Verilog file\n";
|
||||||
|
text += "\n";
|
||||||
|
// Substitute `systemc_class_name
|
||||||
|
string::size_type pos;
|
||||||
|
while ((pos = text.find("`systemc_class_name")) != string::npos) {
|
||||||
|
text.replace(pos, std::strlen("`systemc_class_name"),
|
||||||
|
EmitCBase::prefixNameProtect(modp));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return std::make_pair(text, fl);
|
||||||
|
}
|
||||||
|
|
||||||
void EmitCBaseVisitorConst::emitTextSection(const AstNodeModule* modp, VNType type) {
|
void EmitCBaseVisitorConst::emitTextSection(const AstNodeModule* modp, VNType type) {
|
||||||
// Short circuit if nothing to do. This can save a lot of time on large designs as this
|
// 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.
|
// function needs to traverse the entire module linearly.
|
||||||
if (!v3Global.hasSCTextSections()) return;
|
auto textAndFileline = textSection(modp, type);
|
||||||
|
if (!textAndFileline.first.empty()) ofp()->putsNoTracking(textAndFileline.first);
|
||||||
int last_line = -999;
|
|
||||||
for (AstNode* nodep = modp->stmtsp(); nodep; nodep = nodep->nextp()) {
|
|
||||||
if (const AstNodeText* const textp = VN_CAST(nodep, NodeText)) {
|
|
||||||
if (nodep->type() == type) {
|
|
||||||
if (last_line != nodep->fileline()->lineno()) {
|
|
||||||
if (last_line < 0) {
|
|
||||||
putns(nodep, "\n//*** Below code from `systemc in Verilog file\n");
|
|
||||||
}
|
|
||||||
putsDecoration(nodep, ifNoProtect("// From `systemc at "
|
|
||||||
+ nodep->fileline()->ascii() + "\n"));
|
|
||||||
last_line = nodep->fileline()->lineno();
|
|
||||||
}
|
|
||||||
ofp()->putsNoTracking(textp->text());
|
|
||||||
last_line++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (last_line > 0) puts("//*** Above code from `systemc in Verilog file\n\n");
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -164,6 +164,7 @@ public:
|
||||||
}
|
}
|
||||||
void emitModCUse(const AstNodeModule* modp, VUseType useType);
|
void emitModCUse(const AstNodeModule* modp, VUseType useType);
|
||||||
void emitTextSection(const AstNodeModule* modp, VNType type);
|
void emitTextSection(const AstNodeModule* modp, VNType type);
|
||||||
|
static std::pair<string, FileLine*> textSection(const AstNodeModule* modp, VNType type);
|
||||||
|
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
EmitCBaseVisitorConst() = default;
|
EmitCBaseVisitorConst() = default;
|
||||||
|
|
|
||||||
|
|
@ -162,7 +162,7 @@ class LinkCellsVisitor final : public VNVisitor {
|
||||||
return modp;
|
return modp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// VISITs
|
// VISITORS
|
||||||
void visit(AstNetlist* nodep) override {
|
void visit(AstNetlist* nodep) override {
|
||||||
readModNames();
|
readModNames();
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
|
|
|
||||||
|
|
@ -846,7 +846,7 @@ class LinkDotFindVisitor final : public VNVisitor {
|
||||||
return hierBlocks.find(name) != hierBlocks.end();
|
return hierBlocks.find(name) != hierBlocks.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
// VISITs
|
// VISITORS
|
||||||
void visit(AstNetlist* nodep) override {
|
void visit(AstNetlist* nodep) override {
|
||||||
// Process $unit or other packages
|
// Process $unit or other packages
|
||||||
// Not needed - dotted references not allowed from inside packages
|
// Not needed - dotted references not allowed from inside packages
|
||||||
|
|
@ -1791,7 +1791,7 @@ class LinkDotParamVisitor final : public VNVisitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// VISITs
|
// VISITORS
|
||||||
void visit(AstTypeTable*) override {}
|
void visit(AstTypeTable*) override {}
|
||||||
void visit(AstConstPool*) override {}
|
void visit(AstConstPool*) override {}
|
||||||
void visit(AstNodeModule* nodep) override {
|
void visit(AstNodeModule* nodep) override {
|
||||||
|
|
@ -1967,7 +1967,7 @@ class LinkDotScopeVisitor final : public VNVisitor {
|
||||||
const AstScope* m_scopep = nullptr; // The current scope
|
const AstScope* m_scopep = nullptr; // The current scope
|
||||||
VSymEnt* m_modSymp = nullptr; // Symbol entry for current module
|
VSymEnt* m_modSymp = nullptr; // Symbol entry for current module
|
||||||
|
|
||||||
// VISITs
|
// VISITORS
|
||||||
void visit(AstNetlist* nodep) override {
|
void visit(AstNetlist* nodep) override {
|
||||||
// Recurse..., backward as must do packages before using packages
|
// Recurse..., backward as must do packages before using packages
|
||||||
iterateChildrenBackwardsConst(nodep);
|
iterateChildrenBackwardsConst(nodep);
|
||||||
|
|
@ -2131,7 +2131,7 @@ class LinkDotIfaceVisitor final : public VNVisitor {
|
||||||
LinkDotState* const m_statep; // State to pass between visitors, including symbol table
|
LinkDotState* const m_statep; // State to pass between visitors, including symbol table
|
||||||
VSymEnt* m_curSymp; // Symbol Entry for current table, where to lookup/insert
|
VSymEnt* m_curSymp; // Symbol Entry for current table, where to lookup/insert
|
||||||
|
|
||||||
// VISITs
|
// VISITORS
|
||||||
void visit(AstModport* nodep) override {
|
void visit(AstModport* nodep) override {
|
||||||
// Modport: Remember its name for later resolution
|
// Modport: Remember its name for later resolution
|
||||||
UINFO(5, " fiv: " << nodep << endl);
|
UINFO(5, " fiv: " << nodep << endl);
|
||||||
|
|
@ -2543,7 +2543,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||||
return result + " ";
|
return result + " ";
|
||||||
}
|
}
|
||||||
|
|
||||||
// VISITs
|
// VISITORS
|
||||||
void visit(AstNetlist* nodep) override {
|
void visit(AstNetlist* nodep) override {
|
||||||
// Recurse..., backward as must do packages before using packages
|
// Recurse..., backward as must do packages before using packages
|
||||||
iterateChildrenBackwardsConst(nodep);
|
iterateChildrenBackwardsConst(nodep);
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ class LinkLValueVisitor final : public VNVisitor {
|
||||||
bool m_inInitialStatic = false; // Set if inside AstInitialStatic
|
bool m_inInitialStatic = false; // Set if inside AstInitialStatic
|
||||||
VAccess m_setRefLvalue; // Set VarRefs to lvalues for pin assignments
|
VAccess m_setRefLvalue; // Set VarRefs to lvalues for pin assignments
|
||||||
|
|
||||||
// VISITs
|
// VISITORS
|
||||||
// Result handing
|
// Result handing
|
||||||
void visit(AstNodeVarRef* nodep) override {
|
void visit(AstNodeVarRef* nodep) override {
|
||||||
// VarRef: LValue its reference
|
// VarRef: LValue its reference
|
||||||
|
|
|
||||||
|
|
@ -175,7 +175,7 @@ class LinkParseVisitor final : public VNVisitor {
|
||||||
<< nodep->warnContextSecondary());
|
<< nodep->warnContextSecondary());
|
||||||
}
|
}
|
||||||
|
|
||||||
// VISITs
|
// VISITORS
|
||||||
void visit(AstNodeFTask* nodep) override {
|
void visit(AstNodeFTask* nodep) override {
|
||||||
if (!nodep->user1SetOnce()) { // Process only once.
|
if (!nodep->user1SetOnce()) { // Process only once.
|
||||||
// Mark class methods
|
// Mark class methods
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ class LinkResolveVisitor final : public VNVisitor {
|
||||||
bool m_underGenFor = false; // Under GenFor
|
bool m_underGenFor = false; // Under GenFor
|
||||||
bool m_underGenerate = false; // Under GenFor/GenIf
|
bool m_underGenerate = false; // Under GenFor/GenIf
|
||||||
|
|
||||||
// VISITs
|
// VISITORS
|
||||||
// TODO: Most of these visitors are here for historical reasons.
|
// TODO: Most of these visitors are here for historical reasons.
|
||||||
// TODO: ExpectDescriptor can move to data type resolution, and the rest
|
// TODO: ExpectDescriptor can move to data type resolution, and the rest
|
||||||
// TODO: could move to V3LinkParse to get them out of the way of elaboration
|
// TODO: could move to V3LinkParse to get them out of the way of elaboration
|
||||||
|
|
@ -531,7 +531,7 @@ class LinkBotupVisitor final : public VNVisitorConst {
|
||||||
// STATE
|
// STATE
|
||||||
AstNodeModule* m_modp = nullptr; // Current module
|
AstNodeModule* m_modp = nullptr; // Current module
|
||||||
|
|
||||||
// VISITs
|
// VISITORS
|
||||||
void visit(AstNetlist* nodep) override {
|
void visit(AstNetlist* nodep) override {
|
||||||
// Iterate modules backwards, in bottom-up order.
|
// Iterate modules backwards, in bottom-up order.
|
||||||
iterateChildrenBackwardsConst(nodep);
|
iterateChildrenBackwardsConst(nodep);
|
||||||
|
|
|
||||||
|
|
@ -2729,18 +2729,23 @@ non_port_module_item<nodep>: // ==IEEE: non_port_module_item
|
||||||
{ $$ = nullptr; BBUNSUP(CRELINE(), "Unsupported: interface decls within module decls"); }
|
{ $$ = nullptr; BBUNSUP(CRELINE(), "Unsupported: interface decls within module decls"); }
|
||||||
| timeunits_declaration { $$ = $1; }
|
| timeunits_declaration { $$ = $1; }
|
||||||
// // Verilator specific
|
// // Verilator specific
|
||||||
| yaSCHDR { $$ = new AstScHdr{$<fl>1, *$1}; v3Global.setHasSCTextSections(); }
|
| vlScBlock { $$ = $1; }
|
||||||
| 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(); }
|
|
||||||
| yVL_HIER_BLOCK { $$ = new AstPragma{$1, VPragmaType::HIER_BLOCK}; }
|
| yVL_HIER_BLOCK { $$ = new AstPragma{$1, VPragmaType::HIER_BLOCK}; }
|
||||||
| yVL_INLINE_MODULE { $$ = new AstPragma{$1, VPragmaType::INLINE_MODULE}; }
|
| yVL_INLINE_MODULE { $$ = new AstPragma{$1, VPragmaType::INLINE_MODULE}; }
|
||||||
| yVL_NO_INLINE_MODULE { $$ = new AstPragma{$1, VPragmaType::NO_INLINE_MODULE}; }
|
| yVL_NO_INLINE_MODULE { $$ = new AstPragma{$1, VPragmaType::NO_INLINE_MODULE}; }
|
||||||
| yVL_PUBLIC_MODULE { $$ = new AstPragma{$1, VPragmaType::PUBLIC_MODULE}; v3Global.dpi(true); }
|
| yVL_PUBLIC_MODULE { $$ = new AstPragma{$1, VPragmaType::PUBLIC_MODULE}; v3Global.dpi(true); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
vlScBlock<nodep>: // Verilator-specific `systemc_* blocks
|
||||||
|
yaSCHDR { $$ = new AstScHdr{$<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(); }
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
module_or_generate_item<nodep>: // ==IEEE: module_or_generate_item
|
module_or_generate_item<nodep>: // ==IEEE: module_or_generate_item
|
||||||
// // IEEE: parameter_override
|
// // IEEE: parameter_override
|
||||||
yDEFPARAM list_of_defparam_assignments ';' { $$ = $2; }
|
yDEFPARAM list_of_defparam_assignments ';' { $$ = $2; }
|
||||||
|
|
@ -7372,6 +7377,8 @@ class_item<nodep>: // ==IEEE: class_item
|
||||||
// // local_parameter_declaration under parameter_declaration
|
// // local_parameter_declaration under parameter_declaration
|
||||||
| parameter_declaration ';' { $$ = $1; }
|
| parameter_declaration ';' { $$ = $1; }
|
||||||
| ';' { $$ = nullptr; }
|
| ';' { $$ = nullptr; }
|
||||||
|
// // Verilator specific
|
||||||
|
| vlScBlock { $$ = $1; }
|
||||||
//
|
//
|
||||||
| error ';' { $$ = nullptr; }
|
| error ';' { $$ = nullptr; }
|
||||||
;
|
;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# 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
|
||||||
|
|
||||||
|
import vltest_bootstrap
|
||||||
|
|
||||||
|
test.scenarios('vlt')
|
||||||
|
|
||||||
|
test.compile()
|
||||||
|
|
||||||
|
test.execute()
|
||||||
|
|
||||||
|
test.passes()
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2003-2007 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
// Although strange, Verilog defines are expanded inside the C blocks
|
||||||
|
// (as the `systemc_* directives are opaque to the preprocessor)
|
||||||
|
`define finished "*-* All Finished *-*\n"
|
||||||
|
|
||||||
|
class Cls;
|
||||||
|
`ifdef verilator
|
||||||
|
`systemc_header
|
||||||
|
#define DID_INT_HEADER 1
|
||||||
|
`systemc_interface
|
||||||
|
#ifndef DID_INT_HEADER
|
||||||
|
#error "`systemc_header didn't work"
|
||||||
|
#endif
|
||||||
|
bool m_did_ctor;
|
||||||
|
uint32_t my_function() {
|
||||||
|
if (!m_did_ctor) vl_fatal(__FILE__, __LINE__, __FILE__, "`systemc_ctor didn't work");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
static void my_imp_function();
|
||||||
|
|
||||||
|
`systemc_imp_header
|
||||||
|
#define DID_IMP_HEADER 1
|
||||||
|
`systemc_implementation
|
||||||
|
|
||||||
|
void `systemc_class_name::my_imp_function() { }
|
||||||
|
|
||||||
|
`systemc_ctor // Works, but using a $c inside a `function new` might be cleaner
|
||||||
|
m_did_ctor = 1;
|
||||||
|
`systemc_dtor
|
||||||
|
printf("In systemc_dtor\n");
|
||||||
|
printf(`finished);
|
||||||
|
`verilog
|
||||||
|
|
||||||
|
`endif // verilator
|
||||||
|
|
||||||
|
endclass
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/);
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
Cls c;
|
||||||
|
c = new;
|
||||||
|
i = $c(c, "->my_function()");
|
||||||
|
$c(c, "->my_imp_function();");
|
||||||
|
c = null; // Causes destruction and All Finished
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
Loading…
Reference in New Issue