Add --emit-accessors (#5182) (#5227)

This commit is contained in:
Ryan Ziegler 2024-07-06 07:12:53 -05:00 committed by GitHub
parent de44ca8df3
commit 947b6fd23f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 111 additions and 0 deletions

View File

@ -357,6 +357,7 @@ detailed descriptions of these arguments.
--dumpi-tree-json <level> Enable dumping Ast .tree.json files at level
--dumpi-<srcfile> <level> Enable dumping everything in source file at level
-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
--exe Link to create executable
--expand-limit <value> Set expand optimization limit

View File

@ -483,6 +483,12 @@ Summary:
See also :vlopt:`--dump-defines`, :vlopt:`-P`, and
: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>
After this number of errors are encountered during Verilator run, exit.

View File

@ -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) {
bool nl = false;
forModCUse(modp, useType, [&](string entry) {

View File

@ -118,6 +118,7 @@ public:
void emitCFuncHeader(const AstCFunc* funcp, const AstNodeModule* modp, bool withScope);
void emitCFuncDecl(const AstCFunc* funcp, const AstNodeModule* modp, bool cLinkage = false);
void emitVarDecl(const AstVar* nodep, bool asRef = false);
void emitVarAccessors(const AstVar* nodep);
template <typename F>
static void forModCUse(const AstNodeModule* modp, VUseType useType, F action) {
for (AstNode* itemp = modp->stmtsp(); itemp; itemp = itemp->nextp()) {

View File

@ -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");
// Cells instantiated by the top level (for access to /* verilator public */)

View File

@ -65,6 +65,10 @@ class NameVisitor final : public VNVisitorConst {
nodep->name(newname);
nodep->editCountInc();
} 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 {
renameKeywordCheck(nodep);
}

View File

@ -1240,6 +1240,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc,
if (flag) m_std = false;
m_preprocOnly = flag;
});
DECL_OPTION("-emit-accessors", OnOff, &m_emitAccessors);
DECL_OPTION("-error-limit", CbVal, static_cast<void (*)(int)>(&V3Error::errorLimit));
DECL_OPTION("-exe", OnOff, &m_exe);
DECL_OPTION("-expand-limit", CbVal,

View File

@ -250,6 +250,7 @@ private:
bool m_decoration = true; // main switch: --decoration
bool m_decorationNodes = false; // main switch: --decoration=nodes
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_flatten = false; // main switch: --flatten
bool m_hierarchical = false; // main switch: --hierarchical
@ -499,6 +500,7 @@ public:
bool dumpTreeDot() const {
return m_dumpLevel.count("tree-dot") && m_dumpLevel.at("tree-dot");
}
bool emitAccessors() const { return m_emitAccessors; }
bool exe() const { return m_exe; }
bool flatten() const { return m_flatten; }
bool gmake() const { return m_gmake; }

View 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);
}

View 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;

View 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