mirror of
https://github.com/verilator/verilator.git
synced 2025-01-01 04:07:34 +00:00
parent
de44ca8df3
commit
947b6fd23f
@ -357,6 +357,7 @@ detailed descriptions of these arguments.
|
|||||||
--dumpi-tree-json <level> Enable dumping Ast .tree.json files at level
|
--dumpi-tree-json <level> Enable dumping Ast .tree.json files at level
|
||||||
--dumpi-<srcfile> <level> Enable dumping everything in source file at level
|
--dumpi-<srcfile> <level> Enable dumping everything in source file at level
|
||||||
-E Preprocess, but do not compile
|
-E Preprocess, but do not compile
|
||||||
|
--emit-accessors Emit getter and setter methods for model top class
|
||||||
--error-limit <value> Abort after this number of errors
|
--error-limit <value> Abort after this number of errors
|
||||||
--exe Link to create executable
|
--exe Link to create executable
|
||||||
--expand-limit <value> Set expand optimization limit
|
--expand-limit <value> Set expand optimization limit
|
||||||
|
@ -483,6 +483,12 @@ Summary:
|
|||||||
See also :vlopt:`--dump-defines`, :vlopt:`-P`, and
|
See also :vlopt:`--dump-defines`, :vlopt:`-P`, and
|
||||||
:vlopt:`--pp-comments` options.
|
:vlopt:`--pp-comments` options.
|
||||||
|
|
||||||
|
.. option:: --emit-accessors
|
||||||
|
|
||||||
|
Emit getter and setter methods for each top-level signal in the
|
||||||
|
model top class. Signals are still available as public members,
|
||||||
|
but with the `__Vm_sig_` prefix.
|
||||||
|
|
||||||
.. option:: --error-limit <value>
|
.. option:: --error-limit <value>
|
||||||
|
|
||||||
After this number of errors are encountered during Verilator run, exit.
|
After this number of errors are encountered during Verilator run, exit.
|
||||||
|
@ -227,6 +227,15 @@ void EmitCBaseVisitorConst::emitVarDecl(const AstVar* nodep, bool asRef) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmitCBaseVisitorConst::emitVarAccessors(const AstVar* nodep) {
|
||||||
|
assert(nodep->name().rfind("__Vm_sig_") == 0 && nodep->isIO());
|
||||||
|
const string privateName = nodep->name();
|
||||||
|
const string publicName = nodep->name().substr(strlen("__Vm_sig_"));
|
||||||
|
|
||||||
|
puts("decltype("s + privateName + ") "s + publicName + "() {return "s + privateName + ";}\n");
|
||||||
|
puts("void "s + publicName + "(decltype(" + privateName + ") v) {"s + privateName + "=v;}\n");
|
||||||
|
}
|
||||||
|
|
||||||
void EmitCBaseVisitorConst::emitModCUse(const AstNodeModule* modp, VUseType useType) {
|
void EmitCBaseVisitorConst::emitModCUse(const AstNodeModule* modp, VUseType useType) {
|
||||||
bool nl = false;
|
bool nl = false;
|
||||||
forModCUse(modp, useType, [&](string entry) {
|
forModCUse(modp, useType, [&](string entry) {
|
||||||
|
@ -118,6 +118,7 @@ public:
|
|||||||
void emitCFuncHeader(const AstCFunc* funcp, const AstNodeModule* modp, bool withScope);
|
void emitCFuncHeader(const AstCFunc* funcp, const AstNodeModule* modp, bool withScope);
|
||||||
void emitCFuncDecl(const AstCFunc* funcp, const AstNodeModule* modp, bool cLinkage = false);
|
void emitCFuncDecl(const AstCFunc* funcp, const AstNodeModule* modp, bool cLinkage = false);
|
||||||
void emitVarDecl(const AstVar* nodep, bool asRef = false);
|
void emitVarDecl(const AstVar* nodep, bool asRef = false);
|
||||||
|
void emitVarAccessors(const AstVar* nodep);
|
||||||
template <typename F>
|
template <typename F>
|
||||||
static void forModCUse(const AstNodeModule* modp, VUseType useType, F action) {
|
static void forModCUse(const AstNodeModule* modp, VUseType useType, F action) {
|
||||||
for (AstNode* itemp = modp->stmtsp(); itemp; itemp = itemp->nextp()) {
|
for (AstNode* itemp = modp->stmtsp(); itemp; itemp = itemp->nextp()) {
|
||||||
|
@ -118,6 +118,17 @@ class EmitCModel final : public EmitCFunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(v3Global.opt.emitAccessors()) {
|
||||||
|
puts("\n// ACCESSORS\n"
|
||||||
|
"// The application code should use these methods to\n"
|
||||||
|
"// propagate new values into/out from the Verilated model\n"
|
||||||
|
"// instead of using signal variables directly.\n");
|
||||||
|
for (const AstNode* nodep = modp->stmtsp(); nodep; nodep = nodep->nextp()) {
|
||||||
|
if (const AstVar* const varp = VN_CAST(nodep, Var)) {
|
||||||
|
if (varp->isPrimaryIO()) emitVarAccessors(varp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (optSystemC() && v3Global.usesTiming()) puts("sc_core::sc_event trigger_eval;\n");
|
if (optSystemC() && v3Global.usesTiming()) puts("sc_core::sc_event trigger_eval;\n");
|
||||||
|
|
||||||
// Cells instantiated by the top level (for access to /* verilator public */)
|
// Cells instantiated by the top level (for access to /* verilator public */)
|
||||||
|
@ -65,6 +65,10 @@ class NameVisitor final : public VNVisitorConst {
|
|||||||
nodep->name(newname);
|
nodep->name(newname);
|
||||||
nodep->editCountInc();
|
nodep->editCountInc();
|
||||||
} else if (VN_IS(nodep, CFunc) && VN_AS(nodep, CFunc)->isConstructor()) {
|
} else if (VN_IS(nodep, CFunc) && VN_AS(nodep, CFunc)->isConstructor()) {
|
||||||
|
} else if (v3Global.opt.emitAccessors() && VN_IS(nodep, Var) && VN_AS(nodep, Var)->isSigPublic()) {
|
||||||
|
const string newname = "__Vm_sig_" + nodep->name();
|
||||||
|
nodep->name(newname);
|
||||||
|
nodep->editCountInc();
|
||||||
} else {
|
} else {
|
||||||
renameKeywordCheck(nodep);
|
renameKeywordCheck(nodep);
|
||||||
}
|
}
|
||||||
|
@ -1240,6 +1240,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc,
|
|||||||
if (flag) m_std = false;
|
if (flag) m_std = false;
|
||||||
m_preprocOnly = flag;
|
m_preprocOnly = flag;
|
||||||
});
|
});
|
||||||
|
DECL_OPTION("-emit-accessors", OnOff, &m_emitAccessors);
|
||||||
DECL_OPTION("-error-limit", CbVal, static_cast<void (*)(int)>(&V3Error::errorLimit));
|
DECL_OPTION("-error-limit", CbVal, static_cast<void (*)(int)>(&V3Error::errorLimit));
|
||||||
DECL_OPTION("-exe", OnOff, &m_exe);
|
DECL_OPTION("-exe", OnOff, &m_exe);
|
||||||
DECL_OPTION("-expand-limit", CbVal,
|
DECL_OPTION("-expand-limit", CbVal,
|
||||||
|
@ -250,6 +250,7 @@ private:
|
|||||||
bool m_decoration = true; // main switch: --decoration
|
bool m_decoration = true; // main switch: --decoration
|
||||||
bool m_decorationNodes = false; // main switch: --decoration=nodes
|
bool m_decorationNodes = false; // main switch: --decoration=nodes
|
||||||
bool m_dpiHdrOnly = false; // main switch: --dpi-hdr-only
|
bool m_dpiHdrOnly = false; // main switch: --dpi-hdr-only
|
||||||
|
bool m_emitAccessors = false; // main switch: --emit-accessors
|
||||||
bool m_exe = false; // main switch: --exe
|
bool m_exe = false; // main switch: --exe
|
||||||
bool m_flatten = false; // main switch: --flatten
|
bool m_flatten = false; // main switch: --flatten
|
||||||
bool m_hierarchical = false; // main switch: --hierarchical
|
bool m_hierarchical = false; // main switch: --hierarchical
|
||||||
@ -499,6 +500,7 @@ public:
|
|||||||
bool dumpTreeDot() const {
|
bool dumpTreeDot() const {
|
||||||
return m_dumpLevel.count("tree-dot") && m_dumpLevel.at("tree-dot");
|
return m_dumpLevel.count("tree-dot") && m_dumpLevel.at("tree-dot");
|
||||||
}
|
}
|
||||||
|
bool emitAccessors() const { return m_emitAccessors; }
|
||||||
bool exe() const { return m_exe; }
|
bool exe() const { return m_exe; }
|
||||||
bool flatten() const { return m_flatten; }
|
bool flatten() const { return m_flatten; }
|
||||||
bool gmake() const { return m_gmake; }
|
bool gmake() const { return m_gmake; }
|
||||||
|
34
test_regress/t/t_emit_accessors.cpp
Normal file
34
test_regress/t/t_emit_accessors.cpp
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
|
//
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2024 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
#include <verilated.h>
|
||||||
|
#include VM_PREFIX_INCLUDE
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
Verilated::debug(0);
|
||||||
|
Verilated::commandArgs(argc, argv);
|
||||||
|
|
||||||
|
VM_PREFIX* topp = new VM_PREFIX;
|
||||||
|
CData small_in1 = 0;
|
||||||
|
CData small_in2 = 1;
|
||||||
|
IData big_in = 0xffffffff;
|
||||||
|
|
||||||
|
topp->in1(small_in1);
|
||||||
|
topp->in2(small_in2);
|
||||||
|
topp->in3(big_in);
|
||||||
|
topp->in4(big_in);
|
||||||
|
|
||||||
|
topp->eval();
|
||||||
|
|
||||||
|
assert(topp->out1() == 0);
|
||||||
|
assert(topp->out2() == 0xffffffff);
|
||||||
|
assert(topp->out3().at(0) == 1);
|
||||||
|
|
||||||
|
topp->final();
|
||||||
|
VL_DO_DANGLING(delete topp, topp);
|
||||||
|
}
|
23
test_regress/t/t_emit_accessors.pl
Executable file
23
test_regress/t/t_emit_accessors.pl
Executable file
@ -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 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);
|
||||||
|
|
||||||
|
compile(
|
||||||
|
make_main => 0,
|
||||||
|
verilator_flags2 => [
|
||||||
|
"--emit-accessors",
|
||||||
|
"--exe",
|
||||||
|
"$Self->{t_dir}/$Self->{name}.cpp"
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
19
test_regress/t/t_emit_accessors.v
Normal file
19
test_regress/t/t_emit_accessors.v
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2024 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
module t_emit_accessors(
|
||||||
|
input bit in1,
|
||||||
|
input bit in2,
|
||||||
|
input logic [31:0] in3,
|
||||||
|
input logic [31:0] in4,
|
||||||
|
output bit out1,
|
||||||
|
output logic [31:0] out2,
|
||||||
|
output logic [77:0] out3
|
||||||
|
);
|
||||||
|
assign out1 = in1 & in2;
|
||||||
|
assign out2 = in3 & in4;
|
||||||
|
assign out3 = 1;
|
||||||
|
endmodule
|
Loading…
Reference in New Issue
Block a user