Add --protect-ids to obscure information in objects, bug1521.
This commit is contained in:
parent
ed1e5fb509
commit
91f1acd85f
2
Changes
2
Changes
|
|
@ -6,6 +6,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
|
||||||
|
|
||||||
*** Examples have been renamed.
|
*** Examples have been renamed.
|
||||||
|
|
||||||
|
*** Add --protect-ids to obscure information in objects, bug1521. [Todd Strader]
|
||||||
|
|
||||||
|
|
||||||
* Verilator 4.020 2019-10-06
|
* Verilator 4.020 2019-10-06
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -352,6 +352,8 @@ detailed descriptions in L</"VERILATION ARGUMENTS"> for more information.
|
||||||
--prefix <topname> Name of top level class
|
--prefix <topname> Name of top level class
|
||||||
--prof-cfuncs Name functions for profiling
|
--prof-cfuncs Name functions for profiling
|
||||||
--prof-threads Enable generating gantt chart data for threads
|
--prof-threads Enable generating gantt chart data for threads
|
||||||
|
--protect-key <key> Key for symbol protection
|
||||||
|
--protect-ids Hash identifier names for obscurity
|
||||||
--private Debugging; see docs
|
--private Debugging; see docs
|
||||||
--public Debugging; see docs
|
--public Debugging; see docs
|
||||||
--public-flat-rw Mark all variables, etc as public_flat_rw
|
--public-flat-rw Mark all variables, etc as public_flat_rw
|
||||||
|
|
@ -1153,6 +1155,42 @@ When profiling is enabled, the runtime will emit a blurb of profiling data
|
||||||
in non-human-friendly form. The C<verilator_gantt> script will transform
|
in non-human-friendly form. The C<verilator_gantt> script will transform
|
||||||
this into a nicer visual format and produce some related statistics.
|
this into a nicer visual format and produce some related statistics.
|
||||||
|
|
||||||
|
=item --protect-key I<key>
|
||||||
|
|
||||||
|
Specifies the private key for --protect-ids. For best security this key
|
||||||
|
should be 16 or more random bytes, a reasonable medium-security choice is
|
||||||
|
the output of uuidgen. Typically, a key would be created by the user once
|
||||||
|
for a given protected design library, then every Verilator run for
|
||||||
|
subsequent versions of that library would be passed the same
|
||||||
|
--protect-key. Thus, if the input Verilog is similar between library
|
||||||
|
versions (Verilator runs), the Verilated code will likewise be mostly
|
||||||
|
similar.
|
||||||
|
|
||||||
|
If --protect-key is not specified and a key is needed, Verilator will
|
||||||
|
generate a new key for every Verilator run. As the key is not saved, this
|
||||||
|
is best for security, but means every Verilator run will give vastly
|
||||||
|
different output even for identical input, perhaps harming compile times
|
||||||
|
(and certainly thrashing any I<ccache>).
|
||||||
|
|
||||||
|
=item --protect-ids
|
||||||
|
|
||||||
|
Hash any private identifiers (variable, module, and assertion block names
|
||||||
|
that are not on the top level) into hashed random-looking identifiers,
|
||||||
|
resulting after compilation in protected library binaries that expose less
|
||||||
|
design information. This hashing uses the provided or default
|
||||||
|
--protect-key, see important details there.
|
||||||
|
|
||||||
|
Verilator will also create a {prefix}__idmap.xml file which contains the
|
||||||
|
mapping from the hashed identifiers back to the original identifiers. This
|
||||||
|
idmap file is to be kept private, and is to assist mapping any runtime
|
||||||
|
design assertions, coverage, or trace information, which will report the
|
||||||
|
hashed identifiers, back to the original design's identifier names.
|
||||||
|
|
||||||
|
Using DPI imports/exports is allowed and generally relatively safe in terms
|
||||||
|
of information disclosed, which is limited to the DPI function prototyptes.
|
||||||
|
Use of the VPI is not recommended as many design details may be exposed,
|
||||||
|
and an INSECURE warning will be issued.
|
||||||
|
|
||||||
=item --private
|
=item --private
|
||||||
|
|
||||||
Opposite of --public. Is the default; this option exists for backwards
|
Opposite of --public. Is the default; this option exists for backwards
|
||||||
|
|
@ -1910,6 +1948,7 @@ In certain debug and other modes, it also creates:
|
||||||
{prefix}__Trace{__n}.cpp // Wave file generation code (--trace)
|
{prefix}__Trace{__n}.cpp // Wave file generation code (--trace)
|
||||||
{prefix}__cdc.txt // Clock Domain Crossing checks (--cdc)
|
{prefix}__cdc.txt // Clock Domain Crossing checks (--cdc)
|
||||||
{prefix}__stats.txt // Statistics (--stats)
|
{prefix}__stats.txt // Statistics (--stats)
|
||||||
|
{prefix}__idmap.txt // Symbol demangling (--protect-ids)
|
||||||
|
|
||||||
It also creates internal files that can be mostly ignored:
|
It also creates internal files that can be mostly ignored:
|
||||||
|
|
||||||
|
|
@ -3714,6 +3753,16 @@ non-delayed assignment. See also the COMBDLY warning.
|
||||||
Ignoring this warning may make Verilator simulations differ from other
|
Ignoring this warning may make Verilator simulations differ from other
|
||||||
simulators.
|
simulators.
|
||||||
|
|
||||||
|
=item INSECURE
|
||||||
|
|
||||||
|
Warns that the combination of options selected may be defeating the attempt
|
||||||
|
to protect/obscure identifiers or hide information in the model. Correct
|
||||||
|
the options provided, or inspect the output code to see if the information
|
||||||
|
exposed is acceptable.
|
||||||
|
|
||||||
|
Ignoring this warning will only suppress the lint check, it will simulate
|
||||||
|
correctly.
|
||||||
|
|
||||||
=item LITENDIAN
|
=item LITENDIAN
|
||||||
|
|
||||||
Warns that a packed vector is declared with little endian bit numbering
|
Warns that a packed vector is declared with little endian bit numbering
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,7 @@ void AstNode::init() {
|
||||||
// Attributes
|
// Attributes
|
||||||
m_didWidth = false;
|
m_didWidth = false;
|
||||||
m_doingWidth = false;
|
m_doingWidth = false;
|
||||||
|
m_protect = true;
|
||||||
m_user1u = VNUser(0);
|
m_user1u = VNUser(0);
|
||||||
m_user1Cnt = 0;
|
m_user1Cnt = 0;
|
||||||
m_user2u = VNUser(0);
|
m_user2u = VNUser(0);
|
||||||
|
|
@ -133,6 +134,10 @@ string AstNode::encodeNumber(vlsint64_t num) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string AstNode::nameProtect() const {
|
||||||
|
return VIdProtect::protectIf(name(), protect());
|
||||||
|
}
|
||||||
|
|
||||||
string AstNode::shortName() const {
|
string AstNode::shortName() const {
|
||||||
string pretty = name();
|
string pretty = name();
|
||||||
string::size_type pos;
|
string::size_type pos;
|
||||||
|
|
|
||||||
|
|
@ -1165,6 +1165,7 @@ class AstNode {
|
||||||
// Attributes
|
// Attributes
|
||||||
bool m_didWidth:1; // Did V3Width computation
|
bool m_didWidth:1; // Did V3Width computation
|
||||||
bool m_doingWidth:1; // Inside V3Width
|
bool m_doingWidth:1; // Inside V3Width
|
||||||
|
bool m_protect:1; // Protect name if protection is on
|
||||||
// // Space for more bools here
|
// // Space for more bools here
|
||||||
|
|
||||||
// This member ordering both allows 64 bit alignment and puts associated data together
|
// This member ordering both allows 64 bit alignment and puts associated data together
|
||||||
|
|
@ -1278,6 +1279,7 @@ public:
|
||||||
virtual void tag(const string& text) {}
|
virtual void tag(const string& text) {}
|
||||||
virtual string tag() const { return ""; }
|
virtual string tag() const { return ""; }
|
||||||
virtual string verilogKwd() const { return ""; }
|
virtual string verilogKwd() const { return ""; }
|
||||||
|
string nameProtect() const; // Name with --protect-id applied
|
||||||
string shortName() const; // Name with __PVT__ removed for concatenating scopes
|
string shortName() const; // Name with __PVT__ removed for concatenating scopes
|
||||||
static string dedotName(const string& namein); // Name with dots removed
|
static string dedotName(const string& namein); // Name with dots removed
|
||||||
static string prettyName(const string& namein); // Name for printing out to the user
|
static string prettyName(const string& namein); // Name for printing out to the user
|
||||||
|
|
@ -1297,8 +1299,10 @@ public:
|
||||||
void didWidth(bool flag) { m_didWidth = flag; }
|
void didWidth(bool flag) { m_didWidth = flag; }
|
||||||
bool didWidth() const { return m_didWidth; }
|
bool didWidth() const { return m_didWidth; }
|
||||||
bool didWidthAndSet() { if (didWidth()) return true; didWidth(true); return false; }
|
bool didWidthAndSet() { if (didWidth()) return true; didWidth(true); return false; }
|
||||||
void doingWidth(bool flag) { m_doingWidth = flag; }
|
|
||||||
bool doingWidth() const { return m_doingWidth; }
|
bool doingWidth() const { return m_doingWidth; }
|
||||||
|
void doingWidth(bool flag) { m_doingWidth = flag; }
|
||||||
|
bool protect() const { return m_protect; }
|
||||||
|
void protect(bool flag) { m_protect = flag; }
|
||||||
|
|
||||||
//TODO stomp these width functions out, and call via dtypep() instead
|
//TODO stomp these width functions out, and call via dtypep() instead
|
||||||
int width() const;
|
int width() const;
|
||||||
|
|
@ -1845,6 +1849,7 @@ public:
|
||||||
AstVarScope* varScopep() const { return m_varScopep; }
|
AstVarScope* varScopep() const { return m_varScopep; }
|
||||||
void varScopep(AstVarScope* varscp) { m_varScopep = varscp; }
|
void varScopep(AstVarScope* varscp) { m_varScopep = varscp; }
|
||||||
string hiername() const { return m_hiername; }
|
string hiername() const { return m_hiername; }
|
||||||
|
string hiernameProtect() const;
|
||||||
void hiername(const string& hn) { m_hiername = hn; }
|
void hiername(const string& hn) { m_hiername = hn; }
|
||||||
bool hierThis() const { return m_hierThis; }
|
bool hierThis() const { return m_hierThis; }
|
||||||
void hierThis(bool flag) { m_hierThis = flag; }
|
void hierThis(bool flag) { m_hierThis = flag; }
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,10 @@ void AstNodeVarRef::cloneRelink() {
|
||||||
if (m_varp && m_varp->clonep()) { m_varp = m_varp->clonep(); }
|
if (m_varp && m_varp->clonep()) { m_varp = m_varp->clonep(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string AstNodeVarRef::hiernameProtect() const {
|
||||||
|
return VIdProtect::protectWordsIf(hiername(), protect());
|
||||||
|
}
|
||||||
|
|
||||||
int AstNodeSel::bitConst() const {
|
int AstNodeSel::bitConst() const {
|
||||||
AstConst* constp = VN_CAST(bitp(), Const);
|
AstConst* constp = VN_CAST(bitp(), Const);
|
||||||
return (constp ? constp->toSInt() : 0);
|
return (constp ? constp->toSInt() : 0);
|
||||||
|
|
@ -269,7 +273,7 @@ string AstVar::vlArgType(bool named, bool forReturn, bool forFunc) const {
|
||||||
oname += "&";
|
oname += "&";
|
||||||
mayparen = true;
|
mayparen = true;
|
||||||
}
|
}
|
||||||
if (named) oname += " "+name();
|
if (named) oname += " "+VIdProtect::protectIf(name(), protect());
|
||||||
|
|
||||||
string oarray;
|
string oarray;
|
||||||
if (isDpiOpenArray() || direction().isRefOrConstRef()) {
|
if (isDpiOpenArray() || direction().isRefOrConstRef()) {
|
||||||
|
|
@ -594,6 +598,10 @@ AstNode* AstArraySel::baseFromp(AstNode* nodep) { ///< What is the base variabl
|
||||||
return nodep;
|
return nodep;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string AstCCall::hiernameProtect() const {
|
||||||
|
return VIdProtect::protectWordsIf(hiername(), protect());
|
||||||
|
}
|
||||||
|
|
||||||
const char* AstScope::broken() const {
|
const char* AstScope::broken() const {
|
||||||
BROKEN_RTN(m_aboveScopep && !m_aboveScopep->brokeExists());
|
BROKEN_RTN(m_aboveScopep && !m_aboveScopep->brokeExists());
|
||||||
BROKEN_RTN(m_aboveCellp && !m_aboveCellp->brokeExists());
|
BROKEN_RTN(m_aboveCellp && !m_aboveCellp->brokeExists());
|
||||||
|
|
|
||||||
|
|
@ -6094,6 +6094,7 @@ public:
|
||||||
AstCFunc* funcp() const { return m_funcp; }
|
AstCFunc* funcp() const { return m_funcp; }
|
||||||
string hiername() const { return m_hiername; }
|
string hiername() const { return m_hiername; }
|
||||||
void hiername(const string& hn) { m_hiername = hn; }
|
void hiername(const string& hn) { m_hiername = hn; }
|
||||||
|
string hiernameProtect() const;
|
||||||
void argTypes(const string& str) { m_argTypes = str; }
|
void argTypes(const string& str) { m_argTypes = str; }
|
||||||
string argTypes() const { return m_argTypes; }
|
string argTypes() const { return m_argTypes; }
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -226,6 +226,7 @@ private:
|
||||||
funcp->slow(true);
|
funcp->slow(true);
|
||||||
funcp->isStatic(false);
|
funcp->isStatic(false);
|
||||||
funcp->entryPoint(true);
|
funcp->entryPoint(true);
|
||||||
|
funcp->protect(false);
|
||||||
funcp->addInitsp(new AstCStmt
|
funcp->addInitsp(new AstCStmt
|
||||||
(nodep->fileline(),
|
(nodep->fileline(),
|
||||||
EmitCBaseVisitor::symClassVar()+" = this->__VlSymsp;\n"));
|
EmitCBaseVisitor::symClassVar()+" = this->__VlSymsp;\n"));
|
||||||
|
|
|
||||||
198
src/V3EmitC.cpp
198
src/V3EmitC.cpp
|
|
@ -128,12 +128,12 @@ public:
|
||||||
if (const AstEnumDType* adtypep
|
if (const AstEnumDType* adtypep
|
||||||
= VN_CAST(nodep->dtypep()->skipRefToEnump(), EnumDType)) {
|
= VN_CAST(nodep->dtypep()->skipRefToEnump(), EnumDType)) {
|
||||||
if (adtypep->width()>64) {
|
if (adtypep->width()>64) {
|
||||||
putsDecoration("// enum "+nodep->name()+" // Ignored: Too wide for C++\n");
|
putsDecoration("// enum "+nodep->nameProtect()+" // Ignored: Too wide for C++\n");
|
||||||
} else {
|
} else {
|
||||||
puts("enum "+nodep->name()+" {\n");
|
puts("enum "+nodep->name()+" {\n");
|
||||||
for (AstEnumItem* itemp = adtypep->itemsp();
|
for (AstEnumItem* itemp = adtypep->itemsp();
|
||||||
itemp; itemp = VN_CAST(itemp->nextp(), EnumItem)) {
|
itemp; itemp = VN_CAST(itemp->nextp(), EnumItem)) {
|
||||||
puts(itemp->name());
|
puts(itemp->nameProtect());
|
||||||
puts(" = ");
|
puts(" = ");
|
||||||
iterateAndNextNull(itemp->valuep());
|
iterateAndNextNull(itemp->valuep());
|
||||||
if (VN_IS(itemp->nextp(), EnumItem)) puts(",");
|
if (VN_IS(itemp->nextp(), EnumItem)) puts(",");
|
||||||
|
|
@ -214,8 +214,8 @@ public:
|
||||||
virtual void visit(AstAlwaysPublic*) {
|
virtual void visit(AstAlwaysPublic*) {
|
||||||
}
|
}
|
||||||
virtual void visit(AstCCall* nodep) {
|
virtual void visit(AstCCall* nodep) {
|
||||||
puts(nodep->hiername());
|
puts(nodep->hiernameProtect());
|
||||||
puts(nodep->funcp()->name());
|
puts(nodep->funcp()->nameProtect());
|
||||||
puts("(");
|
puts("(");
|
||||||
puts(nodep->argTypes());
|
puts(nodep->argTypes());
|
||||||
bool comma = (nodep->argTypes() != "");
|
bool comma = (nodep->argTypes() != "");
|
||||||
|
|
@ -237,8 +237,14 @@ public:
|
||||||
}
|
}
|
||||||
virtual void visit(AstComment* nodep) {
|
virtual void visit(AstComment* nodep) {
|
||||||
string at;
|
string at;
|
||||||
if (nodep->showAt()) at = " at "+nodep->fileline()->ascii();
|
if (nodep->showAt()) {
|
||||||
|
at = " at "+nodep->fileline()->ascii();
|
||||||
|
// If protecting, passthru less information about the design
|
||||||
|
if (!v3Global.opt.protectIds()) return;
|
||||||
|
}
|
||||||
|
if (!(nodep->protect() && v3Global.opt.protectIds())) {
|
||||||
putsDecoration(string("// ")+nodep->name()+at+"\n");
|
putsDecoration(string("// ")+nodep->name()+at+"\n");
|
||||||
|
}
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
}
|
}
|
||||||
virtual void visit(AstCoverDecl* nodep) {
|
virtual void visit(AstCoverDecl* nodep) {
|
||||||
|
|
@ -251,12 +257,13 @@ public:
|
||||||
// hierarchies itself, and if verilator_cov also did it, you'd end up
|
// hierarchies itself, and if verilator_cov also did it, you'd end up
|
||||||
// with (number-of-instant) times too many counts in this bin.
|
// with (number-of-instant) times too many counts in this bin.
|
||||||
puts(", first"); // Enable, passed from __Vconfigure parameter
|
puts(", first"); // Enable, passed from __Vconfigure parameter
|
||||||
puts(", "); putsQuoted(nodep->fileline()->filename());
|
puts(", "); putsQuoted(protect(nodep->fileline()->filename()));
|
||||||
puts(", "); puts(cvtToStr(nodep->fileline()->lineno()));
|
puts(", "); puts(cvtToStr(nodep->fileline()->lineno()));
|
||||||
puts(", "); puts(cvtToStr(nodep->column()));
|
puts(", "); puts(cvtToStr(nodep->column()));
|
||||||
puts(", "); putsQuoted((nodep->hier()!=""?".":"")+nodep->hier());
|
puts(", "); putsQuoted((!nodep->hier().empty() ? "." : "")
|
||||||
puts(", "); putsQuoted(nodep->page());
|
+protectWordsIf(nodep->hier(), nodep->protect()));
|
||||||
puts(", "); putsQuoted(nodep->comment());
|
puts(", "); putsQuoted(protectWordsIf(nodep->page(), nodep->protect()));
|
||||||
|
puts(", "); putsQuoted(protectWordsIf(nodep->comment(), nodep->protect()));
|
||||||
puts(");\n");
|
puts(");\n");
|
||||||
}
|
}
|
||||||
virtual void visit(AstCoverInc* nodep) {
|
virtual void visit(AstCoverInc* nodep) {
|
||||||
|
|
@ -280,7 +287,7 @@ public:
|
||||||
if (!nodep->dpiExport()) {
|
if (!nodep->dpiExport()) {
|
||||||
// this is where the DPI import context scope is set
|
// this is where the DPI import context scope is set
|
||||||
string scope = nodep->scopeDpiName();
|
string scope = nodep->scopeDpiName();
|
||||||
putbs("(&(vlSymsp->__Vscope_"+scope+"))");
|
putbs("(&(vlSymsp->"+protect("__Vscope_"+scope)+"))");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstSFormat* nodep) {
|
virtual void visit(AstSFormat* nodep) {
|
||||||
|
|
@ -520,14 +527,14 @@ public:
|
||||||
}
|
}
|
||||||
virtual void visit(AstStop* nodep) {
|
virtual void visit(AstStop* nodep) {
|
||||||
puts("VL_STOP_MT(");
|
puts("VL_STOP_MT(");
|
||||||
putsQuoted(nodep->fileline()->filename());
|
putsQuoted(protect(nodep->fileline()->filename()));
|
||||||
puts(",");
|
puts(",");
|
||||||
puts(cvtToStr(nodep->fileline()->lineno()));
|
puts(cvtToStr(nodep->fileline()->lineno()));
|
||||||
puts(",\"\");\n");
|
puts(",\"\");\n");
|
||||||
}
|
}
|
||||||
virtual void visit(AstFinish* nodep) {
|
virtual void visit(AstFinish* nodep) {
|
||||||
puts("VL_FINISH_MT(");
|
puts("VL_FINISH_MT(");
|
||||||
putsQuoted(nodep->fileline()->filename());
|
putsQuoted(protect(nodep->fileline()->filename()));
|
||||||
puts(",");
|
puts(",");
|
||||||
puts(cvtToStr(nodep->fileline()->lineno()));
|
puts(cvtToStr(nodep->fileline()->lineno()));
|
||||||
puts(",\"\");\n");
|
puts(",\"\");\n");
|
||||||
|
|
@ -555,13 +562,13 @@ public:
|
||||||
iterateAndNextNull(nodep->bodysp());
|
iterateAndNextNull(nodep->bodysp());
|
||||||
}
|
}
|
||||||
virtual void visit(AstUCStmt* nodep) {
|
virtual void visit(AstUCStmt* nodep) {
|
||||||
putsDecoration("// $c statement at "+nodep->fileline()->ascii()+"\n");
|
putsDecoration(ifNoProtect("// $c statement at "+nodep->fileline()->ascii()+"\n"));
|
||||||
iterateAndNextNull(nodep->bodysp());
|
iterateAndNextNull(nodep->bodysp());
|
||||||
puts("\n");
|
puts("\n");
|
||||||
}
|
}
|
||||||
virtual void visit(AstUCFunc* nodep) {
|
virtual void visit(AstUCFunc* nodep) {
|
||||||
puts("\n");
|
puts("\n");
|
||||||
putsDecoration("// $c function at "+nodep->fileline()->ascii()+"\n");
|
putsDecoration(ifNoProtect("// $c function at "+nodep->fileline()->ascii()+"\n"));
|
||||||
iterateAndNextNull(nodep->bodysp());
|
iterateAndNextNull(nodep->bodysp());
|
||||||
puts("\n");
|
puts("\n");
|
||||||
}
|
}
|
||||||
|
|
@ -701,8 +708,8 @@ public:
|
||||||
}
|
}
|
||||||
// Terminals
|
// Terminals
|
||||||
virtual void visit(AstVarRef* nodep) {
|
virtual void visit(AstVarRef* nodep) {
|
||||||
puts(nodep->hiername());
|
puts(nodep->hiernameProtect());
|
||||||
puts(nodep->varp()->name());
|
puts(nodep->varp()->nameProtect());
|
||||||
}
|
}
|
||||||
void emitCvtPackStr(AstNode* nodep) {
|
void emitCvtPackStr(AstNode* nodep) {
|
||||||
if (const AstConst* constp = VN_CAST(nodep, Const)) {
|
if (const AstConst* constp = VN_CAST(nodep, Const)) {
|
||||||
|
|
@ -756,8 +763,8 @@ public:
|
||||||
if (!assigntop) {
|
if (!assigntop) {
|
||||||
puts(assignString);
|
puts(assignString);
|
||||||
} else if (VN_IS(assigntop, VarRef)) {
|
} else if (VN_IS(assigntop, VarRef)) {
|
||||||
puts(assigntop->hiername());
|
puts(assigntop->hiernameProtect());
|
||||||
puts(assigntop->varp()->name());
|
puts(assigntop->varp()->nameProtect());
|
||||||
} else {
|
} else {
|
||||||
iterateAndNextNull(assigntop);
|
iterateAndNextNull(assigntop);
|
||||||
}
|
}
|
||||||
|
|
@ -779,8 +786,8 @@ public:
|
||||||
if (!assigntop) {
|
if (!assigntop) {
|
||||||
puts(assignString);
|
puts(assignString);
|
||||||
} else if (VN_IS(assigntop, VarRef)) {
|
} else if (VN_IS(assigntop, VarRef)) {
|
||||||
puts(assigntop->hiername());
|
puts(assigntop->hiernameProtect());
|
||||||
puts(assigntop->varp()->name());
|
puts(assigntop->varp()->nameProtect());
|
||||||
} else {
|
} else {
|
||||||
iterateAndNextNull(assigntop);
|
iterateAndNextNull(assigntop);
|
||||||
}
|
}
|
||||||
|
|
@ -1090,7 +1097,7 @@ class EmitCImp : EmitCStmts {
|
||||||
ExecMTask* mtp = nodep->execMTaskp();
|
ExecMTask* mtp = nodep->execMTaskp();
|
||||||
puts("\n");
|
puts("\n");
|
||||||
puts("void ");
|
puts("void ");
|
||||||
puts(modClassName(m_modp)+"::"+mtp->cFuncName());
|
puts(modClassName(m_modp)+"::"+protect(mtp->cFuncName()));
|
||||||
puts("(bool even_cycle, void* symtab) {\n");
|
puts("(bool even_cycle, void* symtab) {\n");
|
||||||
|
|
||||||
// Declare and set vlSymsp
|
// Declare and set vlSymsp
|
||||||
|
|
@ -1119,13 +1126,13 @@ class EmitCImp : EmitCStmts {
|
||||||
if (nodep->ifdef()!="") puts("#ifdef "+nodep->ifdef()+"\n");
|
if (nodep->ifdef()!="") puts("#ifdef "+nodep->ifdef()+"\n");
|
||||||
if (nodep->isInline()) puts("VL_INLINE_OPT ");
|
if (nodep->isInline()) puts("VL_INLINE_OPT ");
|
||||||
puts(nodep->rtnTypeVoid()); puts(" ");
|
puts(nodep->rtnTypeVoid()); puts(" ");
|
||||||
puts(modClassName(m_modp)+"::"+nodep->name()
|
puts(modClassName(m_modp)+"::"+nodep->nameProtect()
|
||||||
+"("+cFuncArgs(nodep)+") {\n");
|
+"("+cFuncArgs(nodep)+") {\n");
|
||||||
|
|
||||||
// "+" in the debug indicates a print from the model
|
// "+" in the debug indicates a print from the model
|
||||||
puts("VL_DEBUG_IF(VL_DBG_MSGF(\"+ ");
|
puts("VL_DEBUG_IF(VL_DBG_MSGF(\"+ ");
|
||||||
for (int i=0; i<m_modp->level(); ++i) { puts(" "); }
|
for (int i=0; i<m_modp->level(); ++i) { puts(" "); }
|
||||||
puts(modClassName(m_modp)+"::"+nodep->name()
|
puts(modClassName(m_modp)+"::"+nodep->nameProtect()
|
||||||
+"\\n\"); );\n");
|
+"\\n\"); );\n");
|
||||||
|
|
||||||
// Declare and set vlTOPp
|
// Declare and set vlTOPp
|
||||||
|
|
@ -1172,8 +1179,8 @@ class EmitCImp : EmitCStmts {
|
||||||
doubleOrDetect(changep, gotOne);
|
doubleOrDetect(changep, gotOne);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (gotOne) {
|
if (gotOne) puts(");\n");
|
||||||
puts(");\n");
|
if (gotOne && !v3Global.opt.protectIds()) {
|
||||||
//puts("VL_DEBUG_IF( if (__req) cout<<\"- CLOCKREQ );");
|
//puts("VL_DEBUG_IF( if (__req) cout<<\"- CLOCKREQ );");
|
||||||
for (std::vector<AstChangeDet*>::iterator it = m_blkChangeDetVec.begin();
|
for (std::vector<AstChangeDet*>::iterator it = m_blkChangeDetVec.begin();
|
||||||
it != m_blkChangeDetVec.end(); ++it) {
|
it != m_blkChangeDetVec.end(); ++it) {
|
||||||
|
|
@ -1232,14 +1239,14 @@ class EmitCImp : EmitCStmts {
|
||||||
if (runInline) {
|
if (runInline) {
|
||||||
// The thread calling eval() will run this mtask inline,
|
// The thread calling eval() will run this mtask inline,
|
||||||
// along with its packed successors.
|
// along with its packed successors.
|
||||||
puts(execMTasks[i]->cFuncName()
|
puts(protect(execMTasks[i]->cFuncName())
|
||||||
+ "(vlTOPp->__Vm_even_cycle, vlSymsp);\n");
|
+ "(vlTOPp->__Vm_even_cycle, vlSymsp);\n");
|
||||||
puts("Verilated::mtaskId(0);\n");
|
puts("Verilated::mtaskId(0);\n");
|
||||||
} else {
|
} else {
|
||||||
// The other N-1 go to the thread pool.
|
// The other N-1 go to the thread pool.
|
||||||
puts("vlTOPp->__Vm_threadPoolp->workerp("
|
puts("vlTOPp->__Vm_threadPoolp->workerp("
|
||||||
+ cvtToStr(i)+")->addTask("
|
+ cvtToStr(i)+")->addTask("
|
||||||
+ execMTasks[i]->cFuncName()
|
+ protect(execMTasks[i]->cFuncName())
|
||||||
+ ", vlTOPp->__Vm_even_cycle, vlSymsp);\n");
|
+ ", vlTOPp->__Vm_even_cycle, vlSymsp);\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1307,7 +1314,7 @@ void EmitCStmts::emitVarDecl(const AstVar* nodep, const string& prefixIfImp) {
|
||||||
puts(nodep->scType());
|
puts(nodep->scType());
|
||||||
puts("> ");
|
puts("> ");
|
||||||
}
|
}
|
||||||
puts(nodep->name());
|
puts(nodep->nameProtect());
|
||||||
emitDeclArrayBrackets(nodep);
|
emitDeclArrayBrackets(nodep);
|
||||||
puts(";\n");
|
puts(";\n");
|
||||||
} else if (basicp && basicp->isOpaque()) {
|
} else if (basicp && basicp->isOpaque()) {
|
||||||
|
|
@ -1326,7 +1333,7 @@ void EmitCStmts::emitVarDecl(const AstVar* nodep, const string& prefixIfImp) {
|
||||||
else if (nodep->widthMin() <= 16) puts("16");
|
else if (nodep->widthMin() <= 16) puts("16");
|
||||||
else if (nodep->isWide()) puts("W");
|
else if (nodep->isWide()) puts("W");
|
||||||
|
|
||||||
puts("("+nodep->name());
|
puts("("+nodep->nameProtect());
|
||||||
emitDeclArrayBrackets(nodep);
|
emitDeclArrayBrackets(nodep);
|
||||||
// If it's a packed struct/array then nodep->width is the whole
|
// If it's a packed struct/array then nodep->width is the whole
|
||||||
// thing, msb/lsb is just lowest dimension
|
// thing, msb/lsb is just lowest dimension
|
||||||
|
|
@ -1357,7 +1364,7 @@ void EmitCStmts::emitVarDecl(const AstVar* nodep, const string& prefixIfImp) {
|
||||||
puts("SIGW(");
|
puts("SIGW(");
|
||||||
}
|
}
|
||||||
if (prefixIfImp!="") { puts(prefixIfImp); puts("::"); }
|
if (prefixIfImp!="") { puts(prefixIfImp); puts("::"); }
|
||||||
puts(nodep->name());
|
puts(nodep->nameProtect());
|
||||||
emitDeclArrayBrackets(nodep);
|
emitDeclArrayBrackets(nodep);
|
||||||
// If it's a packed struct/array then nodep->width is the whole
|
// If it's a packed struct/array then nodep->width is the whole
|
||||||
// thing, msb/lsb is just lowest dimension
|
// thing, msb/lsb is just lowest dimension
|
||||||
|
|
@ -1387,12 +1394,12 @@ void EmitCStmts::emitVarCtors(bool* firstp) {
|
||||||
bool isArray = !VN_CAST(varp->dtypeSkipRefp(), BasicDType);
|
bool isArray = !VN_CAST(varp->dtypeSkipRefp(), BasicDType);
|
||||||
if (isArray) {
|
if (isArray) {
|
||||||
puts("// Skipping array: ");
|
puts("// Skipping array: ");
|
||||||
puts(varp->name());
|
puts(varp->nameProtect());
|
||||||
puts("\n");
|
puts("\n");
|
||||||
} else {
|
} else {
|
||||||
emitCtorSep(firstp);
|
emitCtorSep(firstp);
|
||||||
puts(varp->name());
|
puts(varp->nameProtect());
|
||||||
puts("("); putsQuoted(varp->name()); puts(")");
|
puts("("); putsQuoted(varp->nameProtect()); puts(")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
puts("\n#endif\n");
|
puts("\n#endif\n");
|
||||||
|
|
@ -1456,8 +1463,8 @@ void EmitCStmts::emitOpName(AstNode* nodep, const string& format,
|
||||||
UASSERT_OBJ(m_wideTempRefp, nodep,
|
UASSERT_OBJ(m_wideTempRefp, nodep,
|
||||||
"Wide Op w/ no temp, perhaps missing op in V3EmitC?");
|
"Wide Op w/ no temp, perhaps missing op in V3EmitC?");
|
||||||
COMMA;
|
COMMA;
|
||||||
puts(m_wideTempRefp->hiername());
|
puts(m_wideTempRefp->hiernameProtect());
|
||||||
puts(m_wideTempRefp->varp()->name());
|
puts(m_wideTempRefp->varp()->nameProtect());
|
||||||
m_wideTempRefp = NULL;
|
m_wideTempRefp = NULL;
|
||||||
needComma = true;
|
needComma = true;
|
||||||
}
|
}
|
||||||
|
|
@ -1727,7 +1734,7 @@ void EmitCImp::emitVarReset(AstVar* varp) {
|
||||||
UASSERT_OBJ(varp->valuep(), varp, "No init for a param?");
|
UASSERT_OBJ(varp->valuep(), varp, "No init for a param?");
|
||||||
// If a simple CONST value we initialize it using an enum
|
// If a simple CONST value we initialize it using an enum
|
||||||
// If an ARRAYINIT we initialize it using an initial block similar to a signal
|
// If an ARRAYINIT we initialize it using an initial block similar to a signal
|
||||||
//puts("// parameter "+varp->name()+" = "+varp->valuep()->name()+"\n");
|
//puts("// parameter "+varp->nameProtect()+" = "+varp->valuep()->name()+"\n");
|
||||||
}
|
}
|
||||||
else if (AstInitArray* initarp = VN_CAST(varp->valuep(), InitArray)) {
|
else if (AstInitArray* initarp = VN_CAST(varp->valuep(), InitArray)) {
|
||||||
if (AstUnpackArrayDType* arrayp = VN_CAST(varp->dtypeSkipRefp(), UnpackArrayDType)) {
|
if (AstUnpackArrayDType* arrayp = VN_CAST(varp->dtypeSkipRefp(), UnpackArrayDType)) {
|
||||||
|
|
@ -1736,7 +1743,8 @@ void EmitCImp::emitVarReset(AstVar* varp) {
|
||||||
puts("{ int __Vi=0;");
|
puts("{ int __Vi=0;");
|
||||||
puts(" for (; __Vi<"+cvtToStr(arrayp->elementsConst()));
|
puts(" for (; __Vi<"+cvtToStr(arrayp->elementsConst()));
|
||||||
puts("; ++__Vi) {\n");
|
puts("; ++__Vi) {\n");
|
||||||
emitSetVarConstant(varp->name()+"[__Vi]", VN_CAST(initarp->defaultp(), Const));
|
emitSetVarConstant(varp->nameProtect()+"[__Vi]",
|
||||||
|
VN_CAST(initarp->defaultp(), Const));
|
||||||
puts("}}\n");
|
puts("}}\n");
|
||||||
}
|
}
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
|
|
@ -1744,7 +1752,8 @@ void EmitCImp::emitVarReset(AstVar* varp) {
|
||||||
int index = initarp->posIndex(pos);
|
int index = initarp->posIndex(pos);
|
||||||
UASSERT_OBJ(initarp->defaultp() || index==pos, initarp,
|
UASSERT_OBJ(initarp->defaultp() || index==pos, initarp,
|
||||||
"Not enough values in array initialization");
|
"Not enough values in array initialization");
|
||||||
emitSetVarConstant(varp->name()+"["+cvtToStr(index)+"]", VN_CAST(itemp, Const));
|
emitSetVarConstant(varp->nameProtect()
|
||||||
|
+"["+cvtToStr(index)+"]", VN_CAST(itemp, Const));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
varp->v3fatalSrc("InitArray under non-arrayed var");
|
varp->v3fatalSrc("InitArray under non-arrayed var");
|
||||||
|
|
@ -1780,11 +1789,11 @@ void EmitCImp::emitVarReset(AstVar* varp) {
|
||||||
else puts("VL_RAND_RESET_W(");
|
else puts("VL_RAND_RESET_W(");
|
||||||
puts(cvtToStr(varp->widthMin()));
|
puts(cvtToStr(varp->widthMin()));
|
||||||
puts(",");
|
puts(",");
|
||||||
puts(varp->name());
|
puts(varp->nameProtect());
|
||||||
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
|
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
|
||||||
puts(");\n");
|
puts(");\n");
|
||||||
} else {
|
} else {
|
||||||
puts(varp->name());
|
puts(varp->nameProtect());
|
||||||
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
|
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
|
||||||
// If --x-initial-edge is set, we want to force an initial
|
// If --x-initial-edge is set, we want to force an initial
|
||||||
// edge on uninitialized clocks (from 'X' to whatever the
|
// edge on uninitialized clocks (from 'X' to whatever the
|
||||||
|
|
@ -1868,7 +1877,7 @@ void EmitCImp::emitCtorImp(AstNodeModule* modp) {
|
||||||
puts("\n");
|
puts("\n");
|
||||||
}
|
}
|
||||||
putsDecoration("// Reset structure values\n");
|
putsDecoration("// Reset structure values\n");
|
||||||
puts("_ctor_var_reset();\n");
|
puts(protect("_ctor_var_reset")+"();\n");
|
||||||
emitTextSection(AstType::atScCtor);
|
emitTextSection(AstType::atScCtor);
|
||||||
|
|
||||||
if (modp->isTop() && v3Global.opt.mtasks()) {
|
if (modp->isTop() && v3Global.opt.mtasks()) {
|
||||||
|
|
@ -1907,11 +1916,12 @@ void EmitCImp::emitCtorImp(AstNodeModule* modp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitCImp::emitConfigureImp(AstNodeModule* modp) {
|
void EmitCImp::emitConfigureImp(AstNodeModule* modp) {
|
||||||
puts("\nvoid "+modClassName(modp)+"::__Vconfigure("+symClassName()+"* vlSymsp, bool first) {\n");
|
puts("\nvoid "+modClassName(modp)+"::"+protect("__Vconfigure")
|
||||||
|
+"("+symClassName()+"* vlSymsp, bool first) {\n");
|
||||||
puts( "if (0 && first) {} // Prevent unused\n");
|
puts( "if (0 && first) {} // Prevent unused\n");
|
||||||
puts( "this->__VlSymsp = vlSymsp;\n"); // First, as later stuff needs it.
|
puts( "this->__VlSymsp = vlSymsp;\n"); // First, as later stuff needs it.
|
||||||
if (v3Global.opt.coverage() ) {
|
if (v3Global.opt.coverage() ) {
|
||||||
puts("this->_configure_coverage(vlSymsp, first);\n");
|
puts(protect("_configure_coverage")+"(vlSymsp, first);\n");
|
||||||
}
|
}
|
||||||
puts("}\n");
|
puts("}\n");
|
||||||
splitSizeInc(10);
|
splitSizeInc(10);
|
||||||
|
|
@ -1962,7 +1972,7 @@ void EmitCImp::emitSavableImp(AstNodeModule* modp) {
|
||||||
string funcname = de ? "__Vdeserialize" : "__Vserialize";
|
string funcname = de ? "__Vdeserialize" : "__Vserialize";
|
||||||
string op = de ? ">>" : "<<";
|
string op = de ? ">>" : "<<";
|
||||||
// NOLINTNEXTLINE(performance-inefficient-string-concatenation)
|
// NOLINTNEXTLINE(performance-inefficient-string-concatenation)
|
||||||
puts("void "+modClassName(modp)+"::"+funcname+"("+classname+"& os) {\n");
|
puts("void "+modClassName(modp)+"::"+protect(funcname)+"("+classname+"& os) {\n");
|
||||||
// Place a computed checksum to insure proper structure save/restore formatting
|
// Place a computed checksum to insure proper structure save/restore formatting
|
||||||
// OK if this hash includes some things we won't dump, since
|
// OK if this hash includes some things we won't dump, since
|
||||||
// just looking for loading the wrong model
|
// just looking for loading the wrong model
|
||||||
|
|
@ -2019,7 +2029,7 @@ void EmitCImp::emitSavableImp(AstNodeModule* modp) {
|
||||||
puts(" for (; "+ivar+"<"+cvtToStr(elementp->widthWords()));
|
puts(" for (; "+ivar+"<"+cvtToStr(elementp->widthWords()));
|
||||||
puts("; ++"+ivar+") {\n");
|
puts("; ++"+ivar+") {\n");
|
||||||
}
|
}
|
||||||
puts("os"+op+varp->name());
|
puts("os"+op+varp->nameProtect());
|
||||||
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
|
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
|
||||||
puts(";\n");
|
puts(";\n");
|
||||||
for (int v=0; v<vects; ++v) puts( "}}\n");
|
for (int v=0; v<vects; ++v) puts( "}}\n");
|
||||||
|
|
@ -2028,7 +2038,7 @@ void EmitCImp::emitSavableImp(AstNodeModule* modp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (modp->isTop()) { // Save the children
|
if (modp->isTop()) { // Save the children
|
||||||
puts( "__VlSymsp->"+funcname+"(os);\n");
|
puts( "__VlSymsp->"+protect(funcname)+"(os);\n");
|
||||||
}
|
}
|
||||||
puts("}\n");
|
puts("}\n");
|
||||||
}
|
}
|
||||||
|
|
@ -2051,10 +2061,8 @@ void EmitCImp::emitTextSection(AstType type) {
|
||||||
if (last_line < 0) {
|
if (last_line < 0) {
|
||||||
puts("\n//*** Below code from `systemc in Verilog file\n");
|
puts("\n//*** Below code from `systemc in Verilog file\n");
|
||||||
}
|
}
|
||||||
ofp()->putsNoTracking("//#line "+cvtToStr(nodep->fileline()->lineno())
|
putsDecoration(ifNoProtect("// From `systemc at "
|
||||||
+" ");
|
+nodep->fileline()->ascii()+"\n"));
|
||||||
ofp()->putsQuoted(nodep->fileline()->filename());
|
|
||||||
ofp()->putsNoTracking("\n");
|
|
||||||
last_line = nodep->fileline()->lineno();
|
last_line = nodep->fileline()->lineno();
|
||||||
}
|
}
|
||||||
ofp()->putsNoTracking(textp->text());
|
ofp()->putsNoTracking(textp->text());
|
||||||
|
|
@ -2075,7 +2083,7 @@ void EmitCImp::emitCellCtors(AstNodeModule* modp) {
|
||||||
}
|
}
|
||||||
for (AstNode* nodep = modp->stmtsp(); nodep; nodep = nodep->nextp()) {
|
for (AstNode* nodep = modp->stmtsp(); nodep; nodep = nodep->nextp()) {
|
||||||
if (AstCell* cellp = VN_CAST(nodep, Cell)) {
|
if (AstCell* cellp = VN_CAST(nodep, Cell)) {
|
||||||
puts("VL_CELL("+cellp->name()+", "+modClassName(cellp->modp())+");\n");
|
puts("VL_CELL("+cellp->nameProtect()+", "+modClassName(cellp->modp())+");\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2105,7 +2113,7 @@ void EmitCImp::emitSensitives() {
|
||||||
puts(" for (; "+ivar+"<="+cvtToStr(arrayp->msb()));
|
puts(" for (; "+ivar+"<="+cvtToStr(arrayp->msb()));
|
||||||
puts("; ++"+ivar+") {\n");
|
puts("; ++"+ivar+") {\n");
|
||||||
}
|
}
|
||||||
puts("sensitive << "+varp->name());
|
puts("sensitive << "+varp->nameProtect());
|
||||||
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
|
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
|
||||||
puts(";\n");
|
puts(";\n");
|
||||||
for (int v=0; v<vects; ++v) puts( "}}\n");
|
for (int v=0; v<vects; ++v) puts( "}}\n");
|
||||||
|
|
@ -2128,13 +2136,13 @@ void EmitCImp::emitSettleLoop(const std::string& eval_call, bool initial) {
|
||||||
puts( "// Note you must run make with OPT=-DVL_DEBUG for debug prints.\n");
|
puts( "// Note you must run make with OPT=-DVL_DEBUG for debug prints.\n");
|
||||||
puts( "int __Vsaved_debug = Verilated::debug();\n");
|
puts( "int __Vsaved_debug = Verilated::debug();\n");
|
||||||
puts( "Verilated::debug(1);\n");
|
puts( "Verilated::debug(1);\n");
|
||||||
puts( "__Vchange = _change_request(vlSymsp);\n");
|
puts( "__Vchange = "+protect("_change_request")+"(vlSymsp);\n");
|
||||||
puts( "Verilated::debug(__Vsaved_debug);\n");
|
puts( "Verilated::debug(__Vsaved_debug);\n");
|
||||||
puts( "VL_FATAL_MT(__FILE__,__LINE__,__FILE__,\"Verilated model didn't ");
|
puts( "VL_FATAL_MT(__FILE__,__LINE__,__FILE__,\"Verilated model didn't ");
|
||||||
if (initial) puts("DC ");
|
if (initial) puts("DC ");
|
||||||
puts( "converge\");\n");
|
puts( "converge\");\n");
|
||||||
puts( "} else {\n");
|
puts( "} else {\n");
|
||||||
puts( "__Vchange = _change_request(vlSymsp);\n");
|
puts( "__Vchange = "+protect("_change_request")+"(vlSymsp);\n");
|
||||||
puts( "}\n");
|
puts( "}\n");
|
||||||
puts("} while (VL_UNLIKELY(__Vchange));\n");
|
puts("} while (VL_UNLIKELY(__Vchange));\n");
|
||||||
}
|
}
|
||||||
|
|
@ -2146,10 +2154,11 @@ void EmitCImp::emitWrapEval(AstNodeModule* modp) {
|
||||||
puts(EmitCBaseVisitor::symTopAssign()+"\n");
|
puts(EmitCBaseVisitor::symTopAssign()+"\n");
|
||||||
puts("#ifdef VL_DEBUG\n");
|
puts("#ifdef VL_DEBUG\n");
|
||||||
putsDecoration("// Debug assertions\n");
|
putsDecoration("// Debug assertions\n");
|
||||||
puts("_eval_debug_assertions();\n");
|
puts(protect("_eval_debug_assertions")+"();\n");
|
||||||
puts("#endif // VL_DEBUG\n");
|
puts("#endif // VL_DEBUG\n");
|
||||||
putsDecoration("// Initialize\n");
|
putsDecoration("// Initialize\n");
|
||||||
puts("if (VL_UNLIKELY(!vlSymsp->__Vm_didInit)) _eval_initial_loop(vlSymsp);\n");
|
puts("if (VL_UNLIKELY(!vlSymsp->__Vm_didInit)) "
|
||||||
|
+protect("_eval_initial_loop")+"(vlSymsp);\n");
|
||||||
if (v3Global.opt.inhibitSim()) {
|
if (v3Global.opt.inhibitSim()) {
|
||||||
puts("if (VL_UNLIKELY(__Vm_inhibitSim)) return;\n");
|
puts("if (VL_UNLIKELY(__Vm_inhibitSim)) return;\n");
|
||||||
}
|
}
|
||||||
|
|
@ -2201,7 +2210,7 @@ void EmitCImp::emitWrapEval(AstNodeModule* modp) {
|
||||||
emitSettleLoop(
|
emitSettleLoop(
|
||||||
(string("VL_DEBUG_IF(VL_DBG_MSGF(\"+ Clock loop\\n\"););\n")
|
(string("VL_DEBUG_IF(VL_DBG_MSGF(\"+ Clock loop\\n\"););\n")
|
||||||
+ (v3Global.opt.trace() ? "vlSymsp->__Vm_activity = true;\n" : "")
|
+ (v3Global.opt.trace() ? "vlSymsp->__Vm_activity = true;\n" : "")
|
||||||
+ "_eval(vlSymsp);"), false);
|
+ protect("_eval")+"(vlSymsp);"), false);
|
||||||
if (v3Global.opt.threads() == 1) {
|
if (v3Global.opt.threads() == 1) {
|
||||||
puts("Verilated::endOfThreadMTask(vlSymsp->__Vm_evalMsgQp);\n");
|
puts("Verilated::endOfThreadMTask(vlSymsp->__Vm_evalMsgQp);\n");
|
||||||
}
|
}
|
||||||
|
|
@ -2212,14 +2221,15 @@ void EmitCImp::emitWrapEval(AstNodeModule* modp) {
|
||||||
splitSizeInc(10);
|
splitSizeInc(10);
|
||||||
|
|
||||||
//
|
//
|
||||||
puts("\nvoid "+modClassName(modp)+"::_eval_initial_loop("+EmitCBaseVisitor::symClassVar()+") {\n");
|
puts("\nvoid "+modClassName(modp)+"::"+protect("_eval_initial_loop")
|
||||||
|
+"("+EmitCBaseVisitor::symClassVar()+") {\n");
|
||||||
puts("vlSymsp->__Vm_didInit = true;\n");
|
puts("vlSymsp->__Vm_didInit = true;\n");
|
||||||
puts("_eval_initial(vlSymsp);\n");
|
puts(protect("_eval_initial")+"(vlSymsp);\n");
|
||||||
if (v3Global.opt.trace()) {
|
if (v3Global.opt.trace()) {
|
||||||
puts("vlSymsp->__Vm_activity = true;\n");
|
puts("vlSymsp->__Vm_activity = true;\n");
|
||||||
}
|
}
|
||||||
emitSettleLoop((string("_eval_settle(vlSymsp);\n")
|
emitSettleLoop((protect("_eval_settle")+"(vlSymsp);\n"
|
||||||
+"_eval(vlSymsp);"), true);
|
+protect("_eval")+"(vlSymsp);"), true);
|
||||||
puts("}\n");
|
puts("}\n");
|
||||||
splitSizeInc(10);
|
splitSizeInc(10);
|
||||||
}
|
}
|
||||||
|
|
@ -2428,7 +2438,8 @@ void EmitCImp::emitIntFuncDecls(AstNodeModule* modp) {
|
||||||
if (funcp->ifdef()!="") puts("#ifdef "+funcp->ifdef()+"\n");
|
if (funcp->ifdef()!="") puts("#ifdef "+funcp->ifdef()+"\n");
|
||||||
if (funcp->isStatic().trueU()) puts("static ");
|
if (funcp->isStatic().trueU()) puts("static ");
|
||||||
puts(funcp->rtnTypeVoid()); puts(" ");
|
puts(funcp->rtnTypeVoid()); puts(" ");
|
||||||
puts(funcp->name()); puts("("+cFuncArgs(funcp)+")");
|
puts(funcp->nameProtect());
|
||||||
|
puts("("+cFuncArgs(funcp)+")");
|
||||||
if (funcp->slow()) puts(" VL_ATTR_COLD");
|
if (funcp->slow()) puts(" VL_ATTR_COLD");
|
||||||
puts(";\n");
|
puts(";\n");
|
||||||
if (funcp->ifdef()!="") puts("#endif // "+funcp->ifdef()+"\n");
|
if (funcp->ifdef()!="") puts("#endif // "+funcp->ifdef()+"\n");
|
||||||
|
|
@ -2446,7 +2457,7 @@ void EmitCImp::emitIntFuncDecls(AstNodeModule* modp) {
|
||||||
if (mtp->threadRoot()) {
|
if (mtp->threadRoot()) {
|
||||||
// Emit function declaration for this mtask
|
// Emit function declaration for this mtask
|
||||||
ofp()->putsPrivate(true);
|
ofp()->putsPrivate(true);
|
||||||
puts("static void "); puts(mtp->cFuncName());
|
puts("static void "); puts(protect(mtp->cFuncName()));
|
||||||
puts("(bool even_cycle, void* symtab);\n");
|
puts("(bool even_cycle, void* symtab);\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2558,7 +2569,7 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
|
||||||
if (modp->isTop()) puts("// Public to allow access to /*verilator_public*/ items;\n");
|
if (modp->isTop()) puts("// Public to allow access to /*verilator_public*/ items;\n");
|
||||||
if (modp->isTop()) puts("// otherwise the application code can consider these internals.\n");
|
if (modp->isTop()) puts("// otherwise the application code can consider these internals.\n");
|
||||||
}
|
}
|
||||||
puts(modClassName(cellp->modp())+"* "+cellp->name()+";\n");
|
puts(modClassName(cellp->modp())+"* "+cellp->nameProtect()+";\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2604,16 +2615,16 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
|
||||||
// These should be static const values, however microsloth VC++ doesn't
|
// These should be static const values, however microsloth VC++ doesn't
|
||||||
// support them. They also cause problems with GDB under GCC2.95.
|
// support them. They also cause problems with GDB under GCC2.95.
|
||||||
if (varp->isWide()) { // Unsupported for output
|
if (varp->isWide()) { // Unsupported for output
|
||||||
putsDecoration("// enum WData "+varp->name()+" //wide");
|
putsDecoration("// enum WData "+varp->nameProtect()+" //wide");
|
||||||
} else if (!VN_IS(varp->valuep(), Const)) { // Unsupported for output
|
} else if (!VN_IS(varp->valuep(), Const)) { // Unsupported for output
|
||||||
//putsDecoration("// enum ..... "+varp->name()
|
//putsDecoration("// enum ..... "+varp->nameProtect()
|
||||||
// +"not simple value, see variable above instead");
|
// +"not simple value, see variable above instead");
|
||||||
} else if (VN_IS(varp->dtypep(), BasicDType)
|
} else if (VN_IS(varp->dtypep(), BasicDType)
|
||||||
&& VN_CAST(varp->dtypep(), BasicDType)->isOpaque()) { // Can't put out e.g. doubles
|
&& VN_CAST(varp->dtypep(), BasicDType)->isOpaque()) { // Can't put out e.g. doubles
|
||||||
} else {
|
} else {
|
||||||
puts("enum ");
|
puts("enum ");
|
||||||
puts(varp->isQuad()?"_QData":"_IData");
|
puts(varp->isQuad()?"_QData":"_IData");
|
||||||
puts(""+varp->name()+" { "+varp->name()+" = ");
|
puts(""+varp->nameProtect()+" { "+varp->nameProtect()+" = ");
|
||||||
iterateAndNextNull(varp->valuep());
|
iterateAndNextNull(varp->valuep());
|
||||||
puts("};");
|
puts("};");
|
||||||
}
|
}
|
||||||
|
|
@ -2672,27 +2683,28 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
|
||||||
puts("\n// INTERNAL METHODS\n");
|
puts("\n// INTERNAL METHODS\n");
|
||||||
if (modp->isTop()) {
|
if (modp->isTop()) {
|
||||||
ofp()->putsPrivate(true); // private:
|
ofp()->putsPrivate(true); // private:
|
||||||
puts("static void _eval_initial_loop("+EmitCBaseVisitor::symClassVar()+");\n");
|
puts("static void "+protect("_eval_initial_loop")
|
||||||
|
+"("+EmitCBaseVisitor::symClassVar()+");\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
ofp()->putsPrivate(false); // public:
|
ofp()->putsPrivate(false); // public:
|
||||||
puts("void __Vconfigure("+symClassName()+"* symsp, bool first);\n");
|
puts("void "+protect("__Vconfigure")+"("+symClassName()+"* symsp, bool first);\n");
|
||||||
|
|
||||||
emitIntFuncDecls(modp);
|
emitIntFuncDecls(modp);
|
||||||
|
|
||||||
if (v3Global.opt.trace()) {
|
if (v3Global.opt.trace()) {
|
||||||
ofp()->putsPrivate(false); // public:
|
ofp()->putsPrivate(false); // public:
|
||||||
puts("static void traceInit("+v3Global.opt.traceClassBase()
|
puts("static void "+protect("traceInit")+"("+v3Global.opt.traceClassBase()
|
||||||
+"* vcdp, void* userthis, uint32_t code);\n");
|
+"* vcdp, void* userthis, uint32_t code);\n");
|
||||||
puts("static void traceFull("+v3Global.opt.traceClassBase()
|
puts("static void "+protect("traceFull")+"("+v3Global.opt.traceClassBase()
|
||||||
+"* vcdp, void* userthis, uint32_t code);\n");
|
+"* vcdp, void* userthis, uint32_t code);\n");
|
||||||
puts("static void traceChg("+v3Global.opt.traceClassBase()
|
puts("static void "+protect("traceChg")+"("+v3Global.opt.traceClassBase()
|
||||||
+"* vcdp, void* userthis, uint32_t code);\n");
|
+"* vcdp, void* userthis, uint32_t code);\n");
|
||||||
}
|
}
|
||||||
if (v3Global.opt.savable()) {
|
if (v3Global.opt.savable()) {
|
||||||
ofp()->putsPrivate(false); // public:
|
ofp()->putsPrivate(false); // public:
|
||||||
puts("void __Vserialize(VerilatedSerialize& os);\n");
|
puts("void "+protect("__Vserialize")+"(VerilatedSerialize& os);\n");
|
||||||
puts("void __Vdeserialize(VerilatedDeserialize& os);\n");
|
puts("void "+protect("__Vdeserialize")+"(VerilatedDeserialize& os);\n");
|
||||||
puts("\n");
|
puts("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2703,10 +2715,10 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
|
||||||
if (v3Global.opt.savable() && modp->isTop()) {
|
if (v3Global.opt.savable() && modp->isTop()) {
|
||||||
puts("inline VerilatedSerialize& operator<<(VerilatedSerialize& os, "
|
puts("inline VerilatedSerialize& operator<<(VerilatedSerialize& os, "
|
||||||
+modClassName(modp)+"& rhs) {\n"
|
+modClassName(modp)+"& rhs) {\n"
|
||||||
"Verilated::quiesce(); rhs.__Vserialize(os); return os; }\n");
|
"Verilated::quiesce(); rhs."+protect("__Vserialize")+"(os); return os; }\n");
|
||||||
puts("inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, "
|
puts("inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, "
|
||||||
+modClassName(modp)+"& rhs) {\n"
|
+modClassName(modp)+"& rhs) {\n"
|
||||||
"Verilated::quiesce(); rhs.__Vdeserialize(os); return os; }\n");
|
"Verilated::quiesce(); rhs."+protect("__Vdeserialize")+"(os); return os; }\n");
|
||||||
puts("\n");
|
puts("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2838,8 +2850,8 @@ class EmitCTrace : EmitCStmts {
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
void newOutCFile(int filenum) {
|
void newOutCFile(int filenum) {
|
||||||
string filename = (v3Global.opt.makeDir()+"/"+ topClassName()
|
string filename = (v3Global.opt.makeDir()+"/"
|
||||||
+"__Trace");
|
+topClassName()+"_"+protect("_Trace"));
|
||||||
if (filenum) filename += "__"+cvtToStr(filenum);
|
if (filenum) filename += "__"+cvtToStr(filenum);
|
||||||
filename += (m_slow ? "__Slow":"");
|
filename += (m_slow ? "__Slow":"");
|
||||||
filename += ".cpp";
|
filename += ".cpp";
|
||||||
|
|
@ -2868,13 +2880,13 @@ class EmitCTrace : EmitCStmts {
|
||||||
puts("void "+topClassName()+"::trace(");
|
puts("void "+topClassName()+"::trace(");
|
||||||
puts(v3Global.opt.traceClassBase()+"C* tfp, int, int) {\n");
|
puts(v3Global.opt.traceClassBase()+"C* tfp, int, int) {\n");
|
||||||
puts( "tfp->spTrace()->addCallback("
|
puts( "tfp->spTrace()->addCallback("
|
||||||
"&"+topClassName()+"::traceInit"
|
"&"+topClassName()+"::"+protect("traceInit")
|
||||||
+", &"+topClassName()+"::traceFull"
|
+", &"+topClassName()+"::"+protect("traceFull")
|
||||||
+", &"+topClassName()+"::traceChg, this);\n");
|
+", &"+topClassName()+"::"+protect("traceChg")+", this);\n");
|
||||||
puts("}\n");
|
puts("}\n");
|
||||||
splitSizeInc(10);
|
splitSizeInc(10);
|
||||||
|
|
||||||
puts("void "+topClassName()+"::traceInit("
|
puts("void "+topClassName()+"::"+protect("traceInit")+"("
|
||||||
+v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code) {\n");
|
+v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code) {\n");
|
||||||
putsDecoration("// Callback from vcd->open()\n");
|
putsDecoration("// Callback from vcd->open()\n");
|
||||||
puts(topClassName()+"* t = ("+topClassName()+"*)userthis;\n");
|
puts(topClassName()+"* t = ("+topClassName()+"*)userthis;\n");
|
||||||
|
|
@ -2883,17 +2895,17 @@ class EmitCTrace : EmitCStmts {
|
||||||
puts( "VL_FATAL_MT(__FILE__,__LINE__,__FILE__,\"Turning on wave traces requires Verilated::traceEverOn(true) call before time 0.\");\n");
|
puts( "VL_FATAL_MT(__FILE__,__LINE__,__FILE__,\"Turning on wave traces requires Verilated::traceEverOn(true) call before time 0.\");\n");
|
||||||
puts("}\n");
|
puts("}\n");
|
||||||
puts("vcdp->scopeEscape(' ');\n");
|
puts("vcdp->scopeEscape(' ');\n");
|
||||||
puts("t->traceInitThis(vlSymsp, vcdp, code);\n");
|
puts("t->"+protect("traceInitThis")+"(vlSymsp, vcdp, code);\n");
|
||||||
puts("vcdp->scopeEscape('.');\n"); // Restore so later traced files won't break
|
puts("vcdp->scopeEscape('.');\n"); // Restore so later traced files won't break
|
||||||
puts("}\n");
|
puts("}\n");
|
||||||
splitSizeInc(10);
|
splitSizeInc(10);
|
||||||
|
|
||||||
puts("void "+topClassName()+"::traceFull("
|
puts("void "+topClassName()+"::"+protect("traceFull")+"("
|
||||||
+v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code) {\n");
|
+v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code) {\n");
|
||||||
putsDecoration("// Callback from vcd->dump()\n");
|
putsDecoration("// Callback from vcd->dump()\n");
|
||||||
puts(topClassName()+"* t = ("+topClassName()+"*)userthis;\n");
|
puts(topClassName()+"* t = ("+topClassName()+"*)userthis;\n");
|
||||||
puts(EmitCBaseVisitor::symClassVar()+" = t->__VlSymsp; // Setup global symbol table\n");
|
puts(EmitCBaseVisitor::symClassVar()+" = t->__VlSymsp; // Setup global symbol table\n");
|
||||||
puts("t->traceFullThis(vlSymsp, vcdp, code);\n");
|
puts("t->"+protect("traceFullThis")+"(vlSymsp, vcdp, code);\n");
|
||||||
puts("}\n");
|
puts("}\n");
|
||||||
splitSizeInc(10);
|
splitSizeInc(10);
|
||||||
|
|
||||||
|
|
@ -2903,13 +2915,13 @@ class EmitCTrace : EmitCStmts {
|
||||||
void emitTraceFast() {
|
void emitTraceFast() {
|
||||||
puts("\n//======================\n\n");
|
puts("\n//======================\n\n");
|
||||||
|
|
||||||
puts("void "+topClassName()+"::traceChg("
|
puts("void "+topClassName()+"::"+protect("traceChg")+"("
|
||||||
+v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code) {\n");
|
+v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code) {\n");
|
||||||
putsDecoration("// Callback from vcd->dump()\n");
|
putsDecoration("// Callback from vcd->dump()\n");
|
||||||
puts(topClassName()+"* t = ("+topClassName()+"*)userthis;\n");
|
puts(topClassName()+"* t = ("+topClassName()+"*)userthis;\n");
|
||||||
puts(EmitCBaseVisitor::symClassVar()+" = t->__VlSymsp; // Setup global symbol table\n");
|
puts(EmitCBaseVisitor::symClassVar()+" = t->__VlSymsp; // Setup global symbol table\n");
|
||||||
puts("if (vlSymsp->getClearActivity()) {\n");
|
puts("if (vlSymsp->getClearActivity()) {\n");
|
||||||
puts("t->traceChgThis(vlSymsp, vcdp, code);\n");
|
puts("t->"+protect("traceChgThis")+"(vlSymsp, vcdp, code);\n");
|
||||||
puts("}\n");
|
puts("}\n");
|
||||||
puts("}\n");
|
puts("}\n");
|
||||||
splitSizeInc(10);
|
splitSizeInc(10);
|
||||||
|
|
@ -2954,7 +2966,7 @@ class EmitCTrace : EmitCStmts {
|
||||||
puts("(c+"+cvtToStr(nodep->code()));
|
puts("(c+"+cvtToStr(nodep->code()));
|
||||||
if (nodep->arrayRange().ranged()) puts("+i*"+cvtToStr(nodep->widthWords()));
|
if (nodep->arrayRange().ranged()) puts("+i*"+cvtToStr(nodep->widthWords()));
|
||||||
puts(",");
|
puts(",");
|
||||||
putsQuoted(nodep->showname());
|
putsQuoted(VIdProtect::protectWordsIf(nodep->showname(), nodep->protect()));
|
||||||
// Direction
|
// Direction
|
||||||
if (v3Global.opt.traceFormat().fstFlavor()) {
|
if (v3Global.opt.traceFormat().fstFlavor()) {
|
||||||
puts(","+cvtToStr(enumNum));
|
puts(","+cvtToStr(enumNum));
|
||||||
|
|
@ -3033,7 +3045,7 @@ class EmitCTrace : EmitCStmts {
|
||||||
enump->user1(enumNum);
|
enump->user1(enumNum);
|
||||||
int nvals = 0;
|
int nvals = 0;
|
||||||
puts("{\n");
|
puts("{\n");
|
||||||
puts("const char* __VenumItemNames[]\n");
|
puts("const char* "+protect("__VenumItemNames")+"[]\n");
|
||||||
puts("= {");
|
puts("= {");
|
||||||
for (AstEnumItem* itemp = enump->itemsp(); itemp;
|
for (AstEnumItem* itemp = enump->itemsp(); itemp;
|
||||||
itemp = VN_CAST(itemp->nextp(), EnumItem)) {
|
itemp = VN_CAST(itemp->nextp(), EnumItem)) {
|
||||||
|
|
@ -3042,7 +3054,7 @@ class EmitCTrace : EmitCStmts {
|
||||||
}
|
}
|
||||||
puts("};\n");
|
puts("};\n");
|
||||||
nvals = 0;
|
nvals = 0;
|
||||||
puts("const char* __VenumItemValues[]\n");
|
puts("const char* "+protect("__VenumItemValues")+"[]\n");
|
||||||
puts("= {");
|
puts("= {");
|
||||||
for (AstEnumItem* itemp = enump->itemsp(); itemp;
|
for (AstEnumItem* itemp = enump->itemsp(); itemp;
|
||||||
itemp = VN_CAST(itemp->nextp(), EnumItem)) {
|
itemp = VN_CAST(itemp->nextp(), EnumItem)) {
|
||||||
|
|
@ -3055,7 +3067,9 @@ class EmitCTrace : EmitCStmts {
|
||||||
+", \""+enump->prettyName()+"\", "
|
+", \""+enump->prettyName()+"\", "
|
||||||
+cvtToStr(nvals)
|
+cvtToStr(nvals)
|
||||||
+", "+cvtToStr(enump->widthMin())
|
+", "+cvtToStr(enump->widthMin())
|
||||||
+", __VenumItemNames, __VenumItemValues);\n");
|
+", "+protect("__VenumItemNames")
|
||||||
|
+", "+protect("__VenumItemValues")
|
||||||
|
+");\n");
|
||||||
puts("}\n");
|
puts("}\n");
|
||||||
}
|
}
|
||||||
return enumNum;
|
return enumNum;
|
||||||
|
|
@ -3146,7 +3160,7 @@ class EmitCTrace : EmitCStmts {
|
||||||
|
|
||||||
puts("\n");
|
puts("\n");
|
||||||
puts(nodep->rtnTypeVoid()); puts(" ");
|
puts(nodep->rtnTypeVoid()); puts(" ");
|
||||||
puts(topClassName()+"::"+nodep->name()
|
puts(topClassName()+"::"+nodep->nameProtect()
|
||||||
+"("+cFuncArgs(nodep)+") {\n");
|
+"("+cFuncArgs(nodep)+") {\n");
|
||||||
|
|
||||||
if (nodep->symProlog()) puts(EmitCBaseVisitor::symTopAssign()+"\n");
|
if (nodep->symProlog()) puts(EmitCBaseVisitor::symTopAssign()+"\n");
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,13 @@ public:
|
||||||
void putsDecoration(const string& str) { if (v3Global.opt.decoration()) puts(str); }
|
void putsDecoration(const string& str) { if (v3Global.opt.decoration()) puts(str); }
|
||||||
void putsQuoted(const string& str) { ofp()->putsQuoted(str); }
|
void putsQuoted(const string& str) { ofp()->putsQuoted(str); }
|
||||||
bool optSystemC() { return v3Global.opt.systemC(); }
|
bool optSystemC() { return v3Global.opt.systemC(); }
|
||||||
static string symClassName() { return v3Global.opt.prefix()+"__Syms"; }
|
static string protect(const string& name) { return VIdProtect::protectIf(name, true); }
|
||||||
|
static string protectIf(const string& name, bool doIt) {
|
||||||
|
return VIdProtect::protectIf(name, doIt); }
|
||||||
|
static string protectWordsIf(const string& name, bool doIt) {
|
||||||
|
return VIdProtect::protectWordsIf(name, doIt); }
|
||||||
|
static string ifNoProtect(const string& in) { return v3Global.opt.protectIds() ? "" : in; }
|
||||||
|
static string symClassName() { return v3Global.opt.prefix()+"_"+protect("_Syms"); }
|
||||||
static string symClassVar() { return symClassName()+"* __restrict vlSymsp"; }
|
static string symClassVar() { return symClassName()+"* __restrict vlSymsp"; }
|
||||||
static string symTopAssign() {
|
static string symTopAssign() {
|
||||||
return v3Global.opt.prefix()+"* __restrict vlTOPp VL_ATTR_UNUSED = vlSymsp->TOPp;"; }
|
return v3Global.opt.prefix()+"* __restrict vlTOPp VL_ATTR_UNUSED = vlSymsp->TOPp;"; }
|
||||||
|
|
@ -54,7 +60,7 @@ public:
|
||||||
if (modp->isTop()) {
|
if (modp->isTop()) {
|
||||||
return v3Global.opt.prefix();
|
return v3Global.opt.prefix();
|
||||||
} else {
|
} else {
|
||||||
return v3Global.opt.modPrefix() + "_" + modp->name();
|
return v3Global.opt.modPrefix()+"_"+protect(modp->name());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static string topClassName() { // Return name of top wrapper module
|
static string topClassName() { // Return name of top wrapper module
|
||||||
|
|
|
||||||
|
|
@ -405,7 +405,7 @@ void EmitCSyms::emitSymHdr() {
|
||||||
for (ScopeFuncs::iterator it = m_scopeFuncs.begin(); it != m_scopeFuncs.end(); ++it) {
|
for (ScopeFuncs::iterator it = m_scopeFuncs.begin(); it != m_scopeFuncs.end(); ++it) {
|
||||||
AstCFunc* funcp = it->second.m_funcp;
|
AstCFunc* funcp = it->second.m_funcp;
|
||||||
if (funcp->dpiExport()) {
|
if (funcp->dpiExport()) {
|
||||||
string cbtype = v3Global.opt.prefix()+"__Vcb_"+funcp->cname()+"_t";
|
string cbtype = protect(v3Global.opt.prefix()+"__Vcb_"+funcp->cname()+"_t");
|
||||||
types["typedef void (*"+cbtype+") ("+cFuncArgs(funcp)+");\n"] = 1;
|
types["typedef void (*"+cbtype+") ("+cFuncArgs(funcp)+");\n"] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -430,11 +430,11 @@ void EmitCSyms::emitSymHdr() {
|
||||||
AstScope* scopep = it->first; AstNodeModule* modp = it->second;
|
AstScope* scopep = it->first; AstNodeModule* modp = it->second;
|
||||||
if (modp->isTop()) {
|
if (modp->isTop()) {
|
||||||
ofp()->printf("%-30s ", (modClassName(modp)+"*").c_str());
|
ofp()->printf("%-30s ", (modClassName(modp)+"*").c_str());
|
||||||
puts(scopep->nameDotless()+"p;\n");
|
puts(protectIf(scopep->nameDotless()+"p", scopep->protect())+";\n");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ofp()->printf("%-30s ", (modClassName(modp)+"").c_str());
|
ofp()->printf("%-30s ", (modClassName(modp)+"").c_str());
|
||||||
puts(scopep->nameDotless()+";\n");
|
puts(protectIf(scopep->nameDotless(), scopep->protect())+";\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -446,7 +446,7 @@ void EmitCSyms::emitSymHdr() {
|
||||||
if (!m_scopeNames.empty()) { // Scope names
|
if (!m_scopeNames.empty()) { // Scope names
|
||||||
puts("\n// SCOPE NAMES\n");
|
puts("\n// SCOPE NAMES\n");
|
||||||
for (ScopeNames::iterator it = m_scopeNames.begin(); it != m_scopeNames.end(); ++it) {
|
for (ScopeNames::iterator it = m_scopeNames.begin(); it != m_scopeNames.end(); ++it) {
|
||||||
puts("VerilatedScope __Vscope_"+it->second.m_symName+";\n");
|
puts("VerilatedScope "+protect("__Vscope_"+it->second.m_symName)+";\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -476,8 +476,8 @@ void EmitCSyms::emitSymHdr() {
|
||||||
puts("inline bool getClearActivity() { bool r=__Vm_activity; __Vm_activity=false; return r; }\n");
|
puts("inline bool getClearActivity() { bool r=__Vm_activity; __Vm_activity=false; return r; }\n");
|
||||||
}
|
}
|
||||||
if (v3Global.opt.savable() ) {
|
if (v3Global.opt.savable() ) {
|
||||||
puts("void __Vserialize(VerilatedSerialize& os);\n");
|
puts("void "+protect("__Vserialize")+"(VerilatedSerialize& os);\n");
|
||||||
puts("void __Vdeserialize(VerilatedDeserialize& os);\n");
|
puts("void "+protect("__Vdeserialize")+"(VerilatedDeserialize& os);\n");
|
||||||
}
|
}
|
||||||
puts("\n");
|
puts("\n");
|
||||||
puts("} VL_ATTR_ALIGNED(64);\n");
|
puts("} VL_ATTR_ALIGNED(64);\n");
|
||||||
|
|
@ -558,7 +558,7 @@ void EmitCSyms::emitSymImp() {
|
||||||
string funcname = de ? "__Vdeserialize" : "__Vserialize";
|
string funcname = de ? "__Vdeserialize" : "__Vserialize";
|
||||||
string op = de ? ">>" : "<<";
|
string op = de ? ">>" : "<<";
|
||||||
// NOLINTNEXTLINE(performance-inefficient-string-concatenation)
|
// NOLINTNEXTLINE(performance-inefficient-string-concatenation)
|
||||||
puts("void "+symClassName()+"::"+funcname+"("+classname+"& os) {\n");
|
puts("void "+symClassName()+"::"+protect(funcname)+"("+classname+"& os) {\n");
|
||||||
puts( "// LOCAL STATE\n");
|
puts( "// LOCAL STATE\n");
|
||||||
// __Vm_namep presumably already correct
|
// __Vm_namep presumably already correct
|
||||||
if (v3Global.opt.trace()) {
|
if (v3Global.opt.trace()) {
|
||||||
|
|
@ -570,7 +570,8 @@ void EmitCSyms::emitSymImp() {
|
||||||
it != m_scopes.end(); ++it) {
|
it != m_scopes.end(); ++it) {
|
||||||
AstScope* scopep = it->first; AstNodeModule* modp = it->second;
|
AstScope* scopep = it->first; AstNodeModule* modp = it->second;
|
||||||
if (!modp->isTop()) {
|
if (!modp->isTop()) {
|
||||||
puts( scopep->nameDotless()+"."+funcname+"(os);\n");
|
puts(protectIf(scopep->nameDotless(), scopep->protect())
|
||||||
|
+"."+protect(funcname)+"(os);\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
puts("}\n");
|
puts("}\n");
|
||||||
|
|
@ -593,10 +594,10 @@ void EmitCSyms::emitSymImp() {
|
||||||
AstScope* scopep = it->first; AstNodeModule* modp = it->second;
|
AstScope* scopep = it->first; AstNodeModule* modp = it->second;
|
||||||
if (modp->isTop()) {
|
if (modp->isTop()) {
|
||||||
} else {
|
} else {
|
||||||
puts(string(" ")+comma+" "+scopep->nameDotless());
|
puts(string(" ")+comma+" "+protect(scopep->nameDotless()));
|
||||||
puts("(Verilated::catName(topp->name(),");
|
puts("(Verilated::catName(topp->name(),");
|
||||||
// The "." is added by catName
|
// The "." is added by catName
|
||||||
putsQuoted(scopep->prettyName());
|
putsQuoted(protectWordsIf(scopep->prettyName(), scopep->protect()));
|
||||||
puts("))\n");
|
puts("))\n");
|
||||||
comma = ',';
|
comma = ',';
|
||||||
++m_numStmts;
|
++m_numStmts;
|
||||||
|
|
@ -617,15 +618,16 @@ void EmitCSyms::emitSymImp() {
|
||||||
arrow.replace(pos, 1, "->");
|
arrow.replace(pos, 1, "->");
|
||||||
}
|
}
|
||||||
if (arrow.substr(0, 5) == "TOP->") arrow.replace(0, 5, "TOPp->");
|
if (arrow.substr(0, 5) == "TOP->") arrow.replace(0, 5, "TOPp->");
|
||||||
ofp()->printf("%-30s ", arrow.c_str());
|
string arrowProt = protectWordsIf(arrow, scopep->protect());
|
||||||
|
ofp()->printf("%-30s ", arrowProt.c_str());
|
||||||
puts(" = &");
|
puts(" = &");
|
||||||
puts(scopep->nameDotless()+";\n");
|
puts(protectIf(scopep->nameDotless(), scopep->protect())+";\n");
|
||||||
++m_numStmts;
|
++m_numStmts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
puts("// Setup each module's pointer back to symbol table (for public functions)\n");
|
puts("// Setup each module's pointer back to symbol table (for public functions)\n");
|
||||||
puts("TOPp->__Vconfigure(this, true);\n");
|
puts("TOPp->"+protect("__Vconfigure")+"(this, true);\n");
|
||||||
for (std::vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end(); ++it) {
|
for (std::vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end(); ++it) {
|
||||||
AstScope* scopep = it->first; AstNodeModule* modp = it->second;
|
AstScope* scopep = it->first; AstNodeModule* modp = it->second;
|
||||||
if (!modp->isTop()) {
|
if (!modp->isTop()) {
|
||||||
|
|
@ -633,7 +635,8 @@ void EmitCSyms::emitSymImp() {
|
||||||
// first is used by AstCoverDecl's call to __vlCoverInsert
|
// first is used by AstCoverDecl's call to __vlCoverInsert
|
||||||
bool first = !modp->user1();
|
bool first = !modp->user1();
|
||||||
modp->user1(true);
|
modp->user1(true);
|
||||||
puts(scopep->nameDotless()+".__Vconfigure(this, "
|
puts(protectIf(scopep->nameDotless(), scopep->protect())
|
||||||
|
+"."+protect("__Vconfigure")+"(this, "
|
||||||
+(first?"true":"false")
|
+(first?"true":"false")
|
||||||
+");\n");
|
+");\n");
|
||||||
++m_numStmts;
|
++m_numStmts;
|
||||||
|
|
@ -644,10 +647,11 @@ void EmitCSyms::emitSymImp() {
|
||||||
puts("// Setup scopes\n");
|
puts("// Setup scopes\n");
|
||||||
for (ScopeNames::iterator it = m_scopeNames.begin(); it != m_scopeNames.end(); ++it) {
|
for (ScopeNames::iterator it = m_scopeNames.begin(); it != m_scopeNames.end(); ++it) {
|
||||||
checkSplit(false);
|
checkSplit(false);
|
||||||
puts("__Vscope_"+it->second.m_symName+".configure(this,name(),");
|
puts(protect("__Vscope_"+it->second.m_symName)
|
||||||
putsQuoted(it->second.m_prettyName);
|
+".configure(this, name(), ");
|
||||||
|
putsQuoted(protectWordsIf(it->second.m_prettyName, true));
|
||||||
puts(", ");
|
puts(", ");
|
||||||
putsQuoted(scopeDecodeIdentifier(it->second.m_prettyName));
|
putsQuoted(protect(scopeDecodeIdentifier(it->second.m_prettyName)));
|
||||||
puts(", VerilatedScope::"+it->second.m_type+");\n");
|
puts(", VerilatedScope::"+it->second.m_type+");\n");
|
||||||
++m_numStmts;
|
++m_numStmts;
|
||||||
}
|
}
|
||||||
|
|
@ -661,7 +665,7 @@ void EmitCSyms::emitSymImp() {
|
||||||
if (it->first == "TOP") continue;
|
if (it->first == "TOP") continue;
|
||||||
name = name.replace(0, 4, ""); // Remove the "TOP."
|
name = name.replace(0, 4, ""); // Remove the "TOP."
|
||||||
if ((name.find(".") == string::npos) && (it->second.m_type == "SCOPE_MODULE")) {
|
if ((name.find(".") == string::npos) && (it->second.m_type == "SCOPE_MODULE")) {
|
||||||
puts("__Vhier.add(0, &__Vscope_" + it->second.m_symName + ");\n");
|
puts("__Vhier.add(0, &"+protect("__Vscope_"+it->second.m_symName)+");\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -676,8 +680,8 @@ void EmitCSyms::emitSymImp() {
|
||||||
UASSERT(from != m_scopeNames.end(), fromname+" not in m_scopeNames");
|
UASSERT(from != m_scopeNames.end(), fromname+" not in m_scopeNames");
|
||||||
UASSERT(to != m_scopeNames.end(), toname+" not in m_scopeNames");
|
UASSERT(to != m_scopeNames.end(), toname+" not in m_scopeNames");
|
||||||
puts("__Vhier.add(");
|
puts("__Vhier.add(");
|
||||||
puts("&__Vscope_"+from->second.m_symName+", ");
|
puts("&"+protect("__Vscope_"+from->second.m_symName)+", ");
|
||||||
puts("&__Vscope_"+to->second.m_symName+");\n");
|
puts("&"+protect("__Vscope_"+to->second.m_symName)+");\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
puts("\n");
|
puts("\n");
|
||||||
|
|
@ -695,12 +699,12 @@ void EmitCSyms::emitSymImp() {
|
||||||
AstNodeModule* modp = it->second.m_modp;
|
AstNodeModule* modp = it->second.m_modp;
|
||||||
if (funcp->dpiExport()) {
|
if (funcp->dpiExport()) {
|
||||||
checkSplit(true);
|
checkSplit(true);
|
||||||
puts("__Vscope_"+scopep->scopeSymName()+".exportInsert(__Vfinal,");
|
puts(protect("__Vscope_"+scopep->scopeSymName())+".exportInsert(__Vfinal, ");
|
||||||
putsQuoted(funcp->cname());
|
putsQuoted(funcp->cname()); // Not protected - user asked for import/export
|
||||||
puts(", (void*)(&");
|
puts(", (void*)(&");
|
||||||
puts(modClassName(modp));
|
puts(modClassName(modp));
|
||||||
puts("::");
|
puts("::");
|
||||||
puts(funcp->name());
|
puts(funcp->nameProtect());
|
||||||
puts("));\n");
|
puts("));\n");
|
||||||
++m_numStmts;
|
++m_numStmts;
|
||||||
}
|
}
|
||||||
|
|
@ -738,17 +742,17 @@ void EmitCSyms::emitSymImp() {
|
||||||
if (pdim>1 || udim>1) {
|
if (pdim>1 || udim>1) {
|
||||||
puts("//UNSUP "); // VerilatedImp can't deal with >2d or packed arrays
|
puts("//UNSUP "); // VerilatedImp can't deal with >2d or packed arrays
|
||||||
}
|
}
|
||||||
puts("__Vscope_"+it->second.m_scopeName+".varInsert(__Vfinal,");
|
puts(protect("__Vscope_"+it->second.m_scopeName)+".varInsert(__Vfinal,");
|
||||||
putsQuoted(it->second.m_varBasePretty);
|
putsQuoted(protect(it->second.m_varBasePretty));
|
||||||
puts(", &(");
|
puts(", &(");
|
||||||
if (modp->isTop()) {
|
if (modp->isTop()) {
|
||||||
puts(scopep->nameDotless());
|
puts(protectIf(scopep->nameDotless()+"p", scopep->protect()));
|
||||||
puts("p->");
|
puts("->");
|
||||||
} else {
|
} else {
|
||||||
puts(scopep->nameDotless());
|
puts(protectIf(scopep->nameDotless(), scopep->protect()));
|
||||||
puts(".");
|
puts(".");
|
||||||
}
|
}
|
||||||
puts(varp->name());
|
puts(varp->nameProtect());
|
||||||
puts("), ");
|
puts("), ");
|
||||||
puts(varp->vlEnumType()); // VLVT_UINT32 etc
|
puts(varp->vlEnumType()); // VLVT_UINT32 etc
|
||||||
puts(",");
|
puts(",");
|
||||||
|
|
@ -796,13 +800,15 @@ void EmitCSyms::emitDpiHdr() {
|
||||||
AstCFunc* nodep = *it;
|
AstCFunc* nodep = *it;
|
||||||
if (nodep->dpiExportWrapper()) {
|
if (nodep->dpiExportWrapper()) {
|
||||||
if (!firstExp++) puts("\n// DPI EXPORTS\n");
|
if (!firstExp++) puts("\n// DPI EXPORTS\n");
|
||||||
puts("// DPI export at "+nodep->fileline()->ascii()+"\n");
|
puts("// DPI export"+ifNoProtect(" at "+nodep->fileline()->ascii())+"\n");
|
||||||
puts("extern "+nodep->rtnTypeVoid()+" "+nodep->name()+"("+cFuncArgs(nodep)+");\n");
|
puts("extern "+nodep->rtnTypeVoid()+" "+nodep->nameProtect()
|
||||||
|
+"("+cFuncArgs(nodep)+");\n");
|
||||||
}
|
}
|
||||||
else if (nodep->dpiImport()) {
|
else if (nodep->dpiImport()) {
|
||||||
if (!firstImp++) puts("\n// DPI IMPORTS\n");
|
if (!firstImp++) puts("\n// DPI IMPORTS\n");
|
||||||
puts("// DPI import at "+nodep->fileline()->ascii()+"\n");
|
puts("// DPI import"+ifNoProtect(" at "+nodep->fileline()->ascii())+"\n");
|
||||||
puts("extern "+nodep->rtnTypeVoid()+" "+nodep->name()+"("+cFuncArgs(nodep)+");\n");
|
puts("extern "+nodep->rtnTypeVoid()+" "+nodep->nameProtect()
|
||||||
|
+"("+cFuncArgs(nodep)+");\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -846,7 +852,7 @@ void EmitCSyms::emitDpiImp() {
|
||||||
puts("#ifndef _VL_DPIDECL_"+nodep->name()+"\n");
|
puts("#ifndef _VL_DPIDECL_"+nodep->name()+"\n");
|
||||||
puts("#define _VL_DPIDECL_"+nodep->name()+"\n");
|
puts("#define _VL_DPIDECL_"+nodep->name()+"\n");
|
||||||
puts(nodep->rtnTypeVoid()+" "+nodep->name()+"("+cFuncArgs(nodep)+") {\n");
|
puts(nodep->rtnTypeVoid()+" "+nodep->name()+"("+cFuncArgs(nodep)+") {\n");
|
||||||
puts("// DPI Export at "+nodep->fileline()->ascii()+"\n");
|
puts("// DPI export"+ifNoProtect(" at "+nodep->fileline()->ascii())+"\n");
|
||||||
puts("return "+topClassName()+"::"+nodep->name()+"(");
|
puts("return "+topClassName()+"::"+nodep->name()+"(");
|
||||||
string args;
|
string args;
|
||||||
for (AstNode* stmtp = nodep->argsp(); stmtp; stmtp=stmtp->nextp()) {
|
for (AstNode* stmtp = nodep->argsp(); stmtp; stmtp=stmtp->nextp()) {
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,7 @@ public:
|
||||||
INCABSPATH, // Include has absolute path
|
INCABSPATH, // Include has absolute path
|
||||||
INFINITELOOP, // Infinite loop
|
INFINITELOOP, // Infinite loop
|
||||||
INITIALDLY, // Initial delayed statement
|
INITIALDLY, // Initial delayed statement
|
||||||
|
INSECURE, // Insecure options
|
||||||
LITENDIAN, // Little bit endian vector
|
LITENDIAN, // Little bit endian vector
|
||||||
MODDUP, // Duplicate module
|
MODDUP, // Duplicate module
|
||||||
MULTIDRIVEN, // Driven from multiple blocks
|
MULTIDRIVEN, // Driven from multiple blocks
|
||||||
|
|
@ -145,7 +146,7 @@ public:
|
||||||
"ENDLABEL", "GENCLK",
|
"ENDLABEL", "GENCLK",
|
||||||
"IFDEPTH", "IGNOREDRETURN",
|
"IFDEPTH", "IGNOREDRETURN",
|
||||||
"IMPERFECTSCH", "IMPLICIT", "IMPORTSTAR", "IMPURE",
|
"IMPERFECTSCH", "IMPLICIT", "IMPORTSTAR", "IMPURE",
|
||||||
"INCABSPATH", "INFINITELOOP", "INITIALDLY",
|
"INCABSPATH", "INFINITELOOP", "INITIALDLY", "INSECURE",
|
||||||
"LITENDIAN", "MODDUP",
|
"LITENDIAN", "MODDUP",
|
||||||
"MULTIDRIVEN", "MULTITOP",
|
"MULTIDRIVEN", "MULTITOP",
|
||||||
"PINMISSING", "PINNOCONNECT", "PINCONNECTEMPTY", "PROCASSWIRE",
|
"PINMISSING", "PINNOCONNECT", "PINCONNECTEMPTY", "PROCASSWIRE",
|
||||||
|
|
|
||||||
121
src/V3File.cpp
121
src/V3File.cpp
|
|
@ -917,3 +917,124 @@ void V3OutFile::putsForceIncs() {
|
||||||
puts("#include \""+*it+"\"\n");
|
puts("#include \""+*it+"\"\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
// VIdProtect
|
||||||
|
|
||||||
|
class VIdProtectImp {
|
||||||
|
// MEMBERS
|
||||||
|
typedef std::map<string,string> IdMap;
|
||||||
|
IdMap m_nameMap; // Map of old name into new name
|
||||||
|
typedef vl_unordered_set<std::string> IdSet;
|
||||||
|
IdSet m_newIdSet; // Which new names exist
|
||||||
|
protected:
|
||||||
|
// CONSTRUCTORS
|
||||||
|
friend class VIdProtect;
|
||||||
|
static VIdProtectImp& singleton() { static VIdProtectImp s; return s; }
|
||||||
|
public:
|
||||||
|
VIdProtectImp() {
|
||||||
|
passthru("this");
|
||||||
|
passthru("TOPp");
|
||||||
|
passthru("vlTOPp");
|
||||||
|
passthru("vlSymsp");
|
||||||
|
}
|
||||||
|
~VIdProtectImp() {}
|
||||||
|
// METHODS
|
||||||
|
string passthru(const string& old) {
|
||||||
|
if (!v3Global.opt.protectIds()) return old;
|
||||||
|
IdMap::iterator it = m_nameMap.find(old);
|
||||||
|
if (it != m_nameMap.end()) {
|
||||||
|
// No way to go back and correct the older crypt name
|
||||||
|
UASSERT(old == it->second, "Passthru request for '"
|
||||||
|
+old+"' after already --protect-ids of it.");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_nameMap.insert(make_pair(old, old));
|
||||||
|
m_newIdSet.insert(old);
|
||||||
|
}
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
string protectIf(const string& old, bool doIt) {
|
||||||
|
if (!v3Global.opt.protectIds() || old.empty() || !doIt) return old;
|
||||||
|
IdMap::iterator it = m_nameMap.find(old);
|
||||||
|
if (it != m_nameMap.end()) return it->second;
|
||||||
|
else {
|
||||||
|
string out;
|
||||||
|
if (v3Global.opt.debugProtect()) {
|
||||||
|
// This lets us see the symbol being protected to debug cases
|
||||||
|
// where e.g. the definition is protect() but reference is
|
||||||
|
// missing a protect()
|
||||||
|
out = "PS"+old;
|
||||||
|
} else {
|
||||||
|
VHashSha256 digest (v3Global.opt.protectKeyDefaulted());
|
||||||
|
digest.insert(old);
|
||||||
|
// Add "PS" prefix (Protect Symbols) as cannot start symbol with number
|
||||||
|
out = "PS"+digest.digestSymbol();
|
||||||
|
// See if we can shrink the digest symbol to something smaller
|
||||||
|
for (size_t len = 6; len < out.size() - 3; len += 3) {
|
||||||
|
string tryout = out.substr(0, len);
|
||||||
|
if (m_newIdSet.find(tryout) == m_newIdSet.end()) {
|
||||||
|
out = tryout;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_nameMap.insert(make_pair(old, out));
|
||||||
|
m_newIdSet.insert(out);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
string protectWordsIf(const string& old, bool doIt) {
|
||||||
|
// Split at " " (for traces), "." (for scopes), or "->" (for scopes)
|
||||||
|
if (!(doIt && v3Global.opt.protectIds())) return old;
|
||||||
|
string out;
|
||||||
|
string::size_type start = 0;
|
||||||
|
// space, ., ->
|
||||||
|
while (1) {
|
||||||
|
// When C++11, use find_if and lambda
|
||||||
|
string::size_type pos = string::npos;
|
||||||
|
string separator = "";
|
||||||
|
trySep(old, start, " ", pos/*ref*/, separator/*ref*/);
|
||||||
|
trySep(old, start, ".", pos/*ref*/, separator/*ref*/);
|
||||||
|
trySep(old, start, "->", pos/*ref*/, separator/*ref*/);
|
||||||
|
if (pos == string::npos) break;
|
||||||
|
out += protectIf(old.substr(start, pos-start), true) + separator;
|
||||||
|
start = pos + separator.length();
|
||||||
|
}
|
||||||
|
out += protectIf(old.substr(start), true);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
void writeMapFile(const string& filename) const {
|
||||||
|
V3OutXmlFile of (filename);
|
||||||
|
of.putsHeader();
|
||||||
|
of.puts("<!-- DESCR" "IPTION: Verilator output: XML representation of netlist -->\n");
|
||||||
|
of.puts("<verilator_id_map>\n");
|
||||||
|
{
|
||||||
|
for (IdMap::const_iterator it = m_nameMap.begin(); it != m_nameMap.end(); ++it) {
|
||||||
|
of.puts("<map from=\""+it->second+"\" to=\""+it->first+"\"/>\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
of.puts("</verilator_id_map>\n");
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
void trySep(const string& old, string::size_type start, const string& trySep,
|
||||||
|
string::size_type& posr, string& separatorr) {
|
||||||
|
string::size_type trypos = old.find(trySep, start);
|
||||||
|
if (trypos != string::npos) {
|
||||||
|
if (posr == string::npos || (posr > trypos)) {
|
||||||
|
posr = trypos;
|
||||||
|
separatorr = trySep;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
string VIdProtect::protectIf(const string& old, bool doIt) {
|
||||||
|
return VIdProtectImp::singleton().protectIf(old, doIt);
|
||||||
|
}
|
||||||
|
string VIdProtect::protectWordsIf(const string& old, bool doIt) {
|
||||||
|
return VIdProtectImp::singleton().protectWordsIf(old, doIt);
|
||||||
|
}
|
||||||
|
void VIdProtect::writeMapFile(const string& filename) {
|
||||||
|
VIdProtectImp::singleton().writeMapFile(filename);
|
||||||
|
}
|
||||||
|
|
|
||||||
20
src/V3File.h
20
src/V3File.h
|
|
@ -182,9 +182,6 @@ private:
|
||||||
virtual void putcOutput(char chr) { fputc(chr, m_fp); }
|
virtual void putcOutput(char chr) { fputc(chr, m_fp); }
|
||||||
};
|
};
|
||||||
|
|
||||||
//######################################################################
|
|
||||||
// V3OutCFile: A class for abstracting out SystemC/C++ details
|
|
||||||
|
|
||||||
class V3OutCFile : public V3OutFile {
|
class V3OutCFile : public V3OutFile {
|
||||||
int m_private;
|
int m_private;
|
||||||
public:
|
public:
|
||||||
|
|
@ -250,4 +247,21 @@ public:
|
||||||
void puts(const string& strg) { putsNoTracking(strg); }
|
void puts(const string& strg) { putsNoTracking(strg); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
// VIdProtect: Hash identifier names in output files to protect them
|
||||||
|
|
||||||
|
class VIdProtectImp;
|
||||||
|
|
||||||
|
class VIdProtect {
|
||||||
|
public:
|
||||||
|
// METHODS
|
||||||
|
// Rename to a new encoded string (unless earlier passthru'ed)
|
||||||
|
static string protect(const string& old) { return protectIf(old, true); }
|
||||||
|
static string protectIf(const string& old, bool doIt=true);
|
||||||
|
// Rename words to a new encoded string
|
||||||
|
static string protectWordsIf(const string& old, bool doIt=true);
|
||||||
|
// Write map of renames to output file
|
||||||
|
static void writeMapFile(const string& filename);
|
||||||
|
};
|
||||||
|
|
||||||
#endif // Guard
|
#endif // Guard
|
||||||
|
|
|
||||||
|
|
@ -112,6 +112,7 @@ void V3LinkLevel::wrapTop(AstNetlist* rootp) {
|
||||||
newmodp->addNext(oldmodp);
|
newmodp->addNext(oldmodp);
|
||||||
newmodp->level(1);
|
newmodp->level(1);
|
||||||
newmodp->modPublic(true);
|
newmodp->modPublic(true);
|
||||||
|
newmodp->protect(false);
|
||||||
rootp->addModulep(newmodp);
|
rootp->addModulep(newmodp);
|
||||||
|
|
||||||
// TODO the module creation above could be done after linkcells, but
|
// TODO the module creation above could be done after linkcells, but
|
||||||
|
|
@ -192,6 +193,7 @@ void V3LinkLevel::wrapTopCell(AstNetlist* rootp) {
|
||||||
|
|
||||||
AstVar* varp = oldvarp->cloneTree(false);
|
AstVar* varp = oldvarp->cloneTree(false);
|
||||||
varp->name(name);
|
varp->name(name);
|
||||||
|
varp->protect(false);
|
||||||
newmodp->addStmtp(varp);
|
newmodp->addStmtp(varp);
|
||||||
varp->sigPublic(true); // User needs to be able to get to it...
|
varp->sigPublic(true); // User needs to be able to get to it...
|
||||||
if (oldvarp->isIO()) {
|
if (oldvarp->isIO()) {
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
#include "V3Global.h"
|
#include "V3Global.h"
|
||||||
#include "V3Name.h"
|
#include "V3Name.h"
|
||||||
#include "V3Ast.h"
|
#include "V3Ast.h"
|
||||||
|
#include "V3File.h"
|
||||||
#include "V3LanguageWords.h"
|
#include "V3LanguageWords.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
|
||||||
|
|
@ -534,6 +534,25 @@ void V3Options::notify() {
|
||||||
&& !cdc()) {
|
&& !cdc()) {
|
||||||
v3fatal("verilator: Need --cc, --sc, --cdc, --lint-only, --xml_only or --E option");
|
v3fatal("verilator: Need --cc, --sc, --cdc, --lint-only, --xml_only or --E option");
|
||||||
}
|
}
|
||||||
|
if (protectIds()) {
|
||||||
|
FileLine* cmdfl = new FileLine(FileLine::commandLineFilename());
|
||||||
|
if (allPublic()) {
|
||||||
|
// We always call protect() on names, we don't check if public or not
|
||||||
|
// Hence any external references wouldn't be able to find the refed public object.
|
||||||
|
cmdfl->v3error("Unsupported: Using --protect-ids with --public\n"
|
||||||
|
+V3Error::warnMore()+"... Suggest remove --public.");
|
||||||
|
}
|
||||||
|
if (trace()) {
|
||||||
|
cmdfl->v3warn(INSECURE,
|
||||||
|
"Using --protect-ids with --trace may expose private design details\n"
|
||||||
|
+V3Error::warnMore()+"... Suggest remove --trace.");
|
||||||
|
}
|
||||||
|
if (vpi()) {
|
||||||
|
cmdfl->v3warn(INSECURE,
|
||||||
|
"Using --protect-ids with --vpi may expose private design details\n"
|
||||||
|
+V3Error::warnMore()+"... Suggest remove --vpi.");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
|
|
@ -545,6 +564,16 @@ string V3Options::version() {
|
||||||
return ver;
|
return ver;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string V3Options::protectKeyDefaulted() {
|
||||||
|
if (m_protectKey.empty()) {
|
||||||
|
// Create a key with a human-readable symbol-like name.
|
||||||
|
// This conversion drops ~2 bits of entropy out of 256, shouldn't matter.
|
||||||
|
VHashSha256 digest (V3Os::trueRandom(32));
|
||||||
|
m_protectKey = digest.digestSymbol();
|
||||||
|
}
|
||||||
|
return m_protectKey;
|
||||||
|
}
|
||||||
|
|
||||||
void V3Options::throwSigsegv() {
|
void V3Options::throwSigsegv() {
|
||||||
#if !(defined(VL_CPPCHECK) || defined(__clang_analyzer__))
|
#if !(defined(VL_CPPCHECK) || defined(__clang_analyzer__))
|
||||||
char* zp=NULL; *zp=0; // Intentional core dump, ignore warnings here
|
char* zp=NULL; *zp=0; // Intentional core dump, ignore warnings here
|
||||||
|
|
@ -687,6 +716,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
||||||
else if ( onoff (sw, "-debug-leak", flag/*ref*/)) { m_debugLeak = flag; }
|
else if ( onoff (sw, "-debug-leak", flag/*ref*/)) { m_debugLeak = flag; }
|
||||||
else if ( onoff (sw, "-debug-nondeterminism", flag/*ref*/)){ m_debugNondeterminism = flag; }
|
else if ( onoff (sw, "-debug-nondeterminism", flag/*ref*/)){ m_debugNondeterminism = flag; }
|
||||||
else if ( onoff (sw, "-debug-partition", flag/*ref*/)){ m_debugPartition = flag; } // Undocumented
|
else if ( onoff (sw, "-debug-partition", flag/*ref*/)){ m_debugPartition = flag; } // Undocumented
|
||||||
|
else if ( onoff (sw, "-debug-protect", flag/*ref*/)){ m_debugProtect = flag; } // Undocumented
|
||||||
else if ( onoff (sw, "-debug-self-test", flag/*ref*/)){ m_debugSelfTest = flag; } // Undocumented
|
else if ( onoff (sw, "-debug-self-test", flag/*ref*/)){ m_debugSelfTest = flag; } // Undocumented
|
||||||
else if (!strcmp(sw, "-debug-sigsegv")) { throwSigsegv(); } // Undocumented, see also --debug-abort
|
else if (!strcmp(sw, "-debug-sigsegv")) { throwSigsegv(); } // Undocumented, see also --debug-abort
|
||||||
else if (!strcmp(sw, "-debug-fatalsrc")) { v3fatalSrc("--debug-fatal-src"); } // Undocumented, see also --debug-abort
|
else if (!strcmp(sw, "-debug-fatalsrc")) { v3fatalSrc("--debug-fatal-src"); } // Undocumented, see also --debug-abort
|
||||||
|
|
@ -709,6 +739,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
||||||
else if ( onoff (sw, "-prof-cfuncs", flag/*ref*/)) { m_profCFuncs = flag; }
|
else if ( onoff (sw, "-prof-cfuncs", flag/*ref*/)) { m_profCFuncs = flag; }
|
||||||
else if ( onoff (sw, "-profile-cfuncs", flag/*ref*/)) { m_profCFuncs = flag; } // Undocumented, for backward compat
|
else if ( onoff (sw, "-profile-cfuncs", flag/*ref*/)) { m_profCFuncs = flag; } // Undocumented, for backward compat
|
||||||
else if ( onoff (sw, "-prof-threads", flag/*ref*/)) { m_profThreads = flag; }
|
else if ( onoff (sw, "-prof-threads", flag/*ref*/)) { m_profThreads = flag; }
|
||||||
|
else if ( onoff (sw, "-protect-ids", flag/*ref*/)) { m_protectIds = flag; }
|
||||||
else if ( onoff (sw, "-public", flag/*ref*/)) { m_public = flag; }
|
else if ( onoff (sw, "-public", flag/*ref*/)) { m_public = flag; }
|
||||||
else if ( onoff (sw, "-public-flat-rw", flag/*ref*/) ) { m_publicFlatRW = flag; v3Global.dpi(true); }
|
else if ( onoff (sw, "-public-flat-rw", flag/*ref*/) ) { m_publicFlatRW = flag; v3Global.dpi(true); }
|
||||||
else if (!strncmp(sw, "-pvalue+", strlen("-pvalue+"))) { addParameter(string(sw+strlen("-pvalue+")), false); }
|
else if (!strncmp(sw, "-pvalue+", strlen("-pvalue+"))) { addParameter(string(sw+strlen("-pvalue+")), false); }
|
||||||
|
|
@ -1056,6 +1087,9 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
||||||
shift; m_prefix = argv[i];
|
shift; m_prefix = argv[i];
|
||||||
if (m_modPrefix=="") m_modPrefix = m_prefix;
|
if (m_modPrefix=="") m_modPrefix = m_prefix;
|
||||||
}
|
}
|
||||||
|
else if (!strcmp(sw, "-protect-key") && (i+1)<argc) {
|
||||||
|
shift; m_protectKey = argv[i];
|
||||||
|
}
|
||||||
else if (!strcmp(sw, "-no-threads")) { m_threads = 0; } // Undocumented until functional
|
else if (!strcmp(sw, "-no-threads")) { m_threads = 0; } // Undocumented until functional
|
||||||
else if (!strcmp(sw, "-threads") && (i+1)<argc) { // Undocumented until functional
|
else if (!strcmp(sw, "-threads") && (i+1)<argc) { // Undocumented until functional
|
||||||
shift; m_threads = atoi(argv[i]);
|
shift; m_threads = atoi(argv[i]);
|
||||||
|
|
@ -1290,6 +1324,7 @@ V3Options::V3Options() {
|
||||||
m_debugLeak = true;
|
m_debugLeak = true;
|
||||||
m_debugNondeterminism = false;
|
m_debugNondeterminism = false;
|
||||||
m_debugPartition = false;
|
m_debugPartition = false;
|
||||||
|
m_debugProtect = false;
|
||||||
m_debugSelfTest = false;
|
m_debugSelfTest = false;
|
||||||
m_decoration = true;
|
m_decoration = true;
|
||||||
m_dpiHdrOnly = false;
|
m_dpiHdrOnly = false;
|
||||||
|
|
@ -1309,6 +1344,7 @@ V3Options::V3Options() {
|
||||||
m_ppComments = false;
|
m_ppComments = false;
|
||||||
m_profCFuncs = false;
|
m_profCFuncs = false;
|
||||||
m_profThreads = false;
|
m_profThreads = false;
|
||||||
|
m_protectIds = false;
|
||||||
m_preprocOnly = false;
|
m_preprocOnly = false;
|
||||||
m_preprocNoLine = false;
|
m_preprocNoLine = false;
|
||||||
m_public = false;
|
m_public = false;
|
||||||
|
|
|
||||||
|
|
@ -118,6 +118,7 @@ class V3Options {
|
||||||
bool m_debugLeak; // main switch: --debug-leak
|
bool m_debugLeak; // main switch: --debug-leak
|
||||||
bool m_debugNondeterminism; // main switch: --debug-nondeterminism
|
bool m_debugNondeterminism; // main switch: --debug-nondeterminism
|
||||||
bool m_debugPartition; // main switch: --debug-partition
|
bool m_debugPartition; // main switch: --debug-partition
|
||||||
|
bool m_debugProtect; // main switch: --debug-protect
|
||||||
bool m_debugSelfTest; // main switch: --debug-self-test
|
bool m_debugSelfTest; // main switch: --debug-self-test
|
||||||
bool m_decoration; // main switch: --decoration
|
bool m_decoration; // main switch: --decoration
|
||||||
bool m_dpiHdrOnly; // main switch: --dpi-hdr-only
|
bool m_dpiHdrOnly; // main switch: --dpi-hdr-only
|
||||||
|
|
@ -134,6 +135,7 @@ class V3Options {
|
||||||
bool m_ppComments; // main switch: --pp-comments
|
bool m_ppComments; // main switch: --pp-comments
|
||||||
bool m_profCFuncs; // main switch: --prof-cfuncs
|
bool m_profCFuncs; // main switch: --prof-cfuncs
|
||||||
bool m_profThreads; // main switch: --prof-threads
|
bool m_profThreads; // main switch: --prof-threads
|
||||||
|
bool m_protectIds; // main switch: --protect-ids
|
||||||
bool m_public; // main switch: --public
|
bool m_public; // main switch: --public
|
||||||
bool m_publicFlatRW; // main switch: --public-flat-rw
|
bool m_publicFlatRW; // main switch: --public-flat-rw
|
||||||
bool m_relativeCFuncs; // main switch: --relative-cfuncs
|
bool m_relativeCFuncs; // main switch: --relative-cfuncs
|
||||||
|
|
@ -188,6 +190,7 @@ class V3Options {
|
||||||
string m_modPrefix; // main switch: --mod-prefix
|
string m_modPrefix; // main switch: --mod-prefix
|
||||||
string m_pipeFilter; // main switch: --pipe-filter
|
string m_pipeFilter; // main switch: --pipe-filter
|
||||||
string m_prefix; // main switch: --prefix
|
string m_prefix; // main switch: --prefix
|
||||||
|
string m_protectKey; // main switch: --protect-key
|
||||||
string m_topModule; // main switch: --top-module
|
string m_topModule; // main switch: --top-module
|
||||||
string m_unusedRegexp; // main switch: --unused-regexp
|
string m_unusedRegexp; // main switch: --unused-regexp
|
||||||
string m_xAssign; // main switch: --x-assign
|
string m_xAssign; // main switch: --x-assign
|
||||||
|
|
@ -288,6 +291,7 @@ class V3Options {
|
||||||
bool debugLeak() const { return m_debugLeak; }
|
bool debugLeak() const { return m_debugLeak; }
|
||||||
bool debugNondeterminism() const { return m_debugNondeterminism; }
|
bool debugNondeterminism() const { return m_debugNondeterminism; }
|
||||||
bool debugPartition() const { return m_debugPartition; }
|
bool debugPartition() const { return m_debugPartition; }
|
||||||
|
bool debugProtect() const { return m_debugProtect; }
|
||||||
bool debugSelfTest() const { return m_debugSelfTest; }
|
bool debugSelfTest() const { return m_debugSelfTest; }
|
||||||
bool decoration() const { return m_decoration; }
|
bool decoration() const { return m_decoration; }
|
||||||
bool dpiHdrOnly() const { return m_dpiHdrOnly; }
|
bool dpiHdrOnly() const { return m_dpiHdrOnly; }
|
||||||
|
|
@ -310,6 +314,7 @@ class V3Options {
|
||||||
bool ppComments() const { return m_ppComments; }
|
bool ppComments() const { return m_ppComments; }
|
||||||
bool profCFuncs() const { return m_profCFuncs; }
|
bool profCFuncs() const { return m_profCFuncs; }
|
||||||
bool profThreads() const { return m_profThreads; }
|
bool profThreads() const { return m_profThreads; }
|
||||||
|
bool protectIds() const { return m_protectIds; }
|
||||||
bool allPublic() const { return m_public; }
|
bool allPublic() const { return m_public; }
|
||||||
bool publicFlatRW() const { return m_publicFlatRW; }
|
bool publicFlatRW() const { return m_publicFlatRW; }
|
||||||
bool lintOnly() const { return m_lintOnly; }
|
bool lintOnly() const { return m_lintOnly; }
|
||||||
|
|
@ -351,6 +356,8 @@ class V3Options {
|
||||||
string modPrefix() const { return m_modPrefix; }
|
string modPrefix() const { return m_modPrefix; }
|
||||||
string pipeFilter() const { return m_pipeFilter; }
|
string pipeFilter() const { return m_pipeFilter; }
|
||||||
string prefix() const { return m_prefix; }
|
string prefix() const { return m_prefix; }
|
||||||
|
string protectKey() const { return m_protectKey; }
|
||||||
|
string protectKeyDefaulted(); // Set default key if not set by user
|
||||||
string topModule() const { return m_topModule; }
|
string topModule() const { return m_topModule; }
|
||||||
string unusedRegexp() const { return m_unusedRegexp; }
|
string unusedRegexp() const { return m_unusedRegexp; }
|
||||||
string xAssign() const { return m_xAssign; }
|
string xAssign() const { return m_xAssign; }
|
||||||
|
|
|
||||||
13
src/V3Os.cpp
13
src/V3Os.cpp
|
|
@ -31,6 +31,7 @@
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <fstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
@ -218,6 +219,18 @@ vluint64_t V3Os::rand64(vluint64_t* statep) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string V3Os::trueRandom(size_t size) {
|
||||||
|
string data; data.reserve(size);
|
||||||
|
std::ifstream is ("/dev/urandom", std::ios::in | std::ios::binary);
|
||||||
|
char bytes[size];
|
||||||
|
if (!is.read(bytes, size)) {
|
||||||
|
v3fatal("Could not open /dev/urandom, no source of randomness. Try specifing a key instead.");
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
data.append(bytes, size);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// METHODS (performance)
|
// METHODS (performance)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@ public:
|
||||||
|
|
||||||
// METHODS (random)
|
// METHODS (random)
|
||||||
static vluint64_t rand64(vluint64_t* statep);
|
static vluint64_t rand64(vluint64_t* statep);
|
||||||
|
static string trueRandom(size_t size);
|
||||||
|
|
||||||
// METHODS (performance)
|
// METHODS (performance)
|
||||||
static uint64_t timeUsecs(); ///< Return wall time since epoch in microseconds, or 0 if not implemented
|
static uint64_t timeUsecs(); ///< Return wall time since epoch in microseconds, or 0 if not implemented
|
||||||
|
|
|
||||||
|
|
@ -711,6 +711,7 @@ private:
|
||||||
dpip->entryPoint(true);
|
dpip->entryPoint(true);
|
||||||
dpip->isStatic(true);
|
dpip->isStatic(true);
|
||||||
dpip->dpiExportWrapper(true);
|
dpip->dpiExportWrapper(true);
|
||||||
|
dpip->protect(false);
|
||||||
dpip->cname(nodep->cname());
|
dpip->cname(nodep->cname());
|
||||||
// Add DPI reference to top, since it's a global function
|
// Add DPI reference to top, since it's a global function
|
||||||
m_topScopep->scopep()->addActivep(dpip);
|
m_topScopep->scopep()->addActivep(dpip);
|
||||||
|
|
@ -733,7 +734,8 @@ private:
|
||||||
// If the find fails, it will throw an error
|
// If the find fails, it will throw an error
|
||||||
stmt += "const VerilatedScope* __Vscopep = Verilated::dpiScope();\n";
|
stmt += "const VerilatedScope* __Vscopep = Verilated::dpiScope();\n";
|
||||||
// If dpiScope is fails and is null; the exportFind function throws and error
|
// If dpiScope is fails and is null; the exportFind function throws and error
|
||||||
string cbtype = v3Global.opt.prefix()+"__Vcb_"+nodep->cname()+"_t";
|
string cbtype = VIdProtect::protect(v3Global.opt.prefix()
|
||||||
|
+"__Vcb_"+nodep->cname()+"_t");
|
||||||
stmt += cbtype+" __Vcb = ("+cbtype+")(VerilatedScope::exportFind(__Vscopep, __Vfuncnum));\n"; // Can't use static_cast
|
stmt += cbtype+" __Vcb = ("+cbtype+")(VerilatedScope::exportFind(__Vscopep, __Vfuncnum));\n"; // Can't use static_cast
|
||||||
// If __Vcb is null the exportFind function throws and error
|
// If __Vcb is null the exportFind function throws and error
|
||||||
dpip->addStmtsp(new AstCStmt(nodep->fileline(), stmt));
|
dpip->addStmtsp(new AstCStmt(nodep->fileline(), stmt));
|
||||||
|
|
@ -741,7 +743,8 @@ private:
|
||||||
|
|
||||||
// Convert input/inout DPI arguments to Internal types
|
// Convert input/inout DPI arguments to Internal types
|
||||||
string args;
|
string args;
|
||||||
args += "("+v3Global.opt.prefix()+"__Syms*)(__Vscopep->symsp())"; // Upcast w/o overhead
|
args += ("("+EmitCBaseVisitor::symClassName()
|
||||||
|
+"*)(__Vscopep->symsp())"); // Upcast w/o overhead
|
||||||
AstNode* argnodesp = NULL;
|
AstNode* argnodesp = NULL;
|
||||||
for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp=stmtp->nextp()) {
|
for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp=stmtp->nextp()) {
|
||||||
if (AstVar* portp = VN_CAST(stmtp, Var)) {
|
if (AstVar* portp = VN_CAST(stmtp, Var)) {
|
||||||
|
|
@ -755,6 +758,9 @@ private:
|
||||||
args = "";
|
args = "";
|
||||||
}
|
}
|
||||||
AstVarScope* outvscp = createFuncVar(dpip, portp->name()+"__Vcvt", portp);
|
AstVarScope* outvscp = createFuncVar(dpip, portp->name()+"__Vcvt", portp);
|
||||||
|
// No information exposure; is already visible in import/export func template
|
||||||
|
outvscp->varp()->protect(false);
|
||||||
|
portp->protect(false);
|
||||||
AstVarRef* refp = new AstVarRef(portp->fileline(), outvscp,
|
AstVarRef* refp = new AstVarRef(portp->fileline(), outvscp,
|
||||||
portp->isWritable());
|
portp->isWritable());
|
||||||
argnodesp = argnodesp->addNextNull(refp);
|
argnodesp = argnodesp->addNextNull(refp);
|
||||||
|
|
@ -775,6 +781,8 @@ private:
|
||||||
args="";
|
args="";
|
||||||
}
|
}
|
||||||
AstVarScope* outvscp = createFuncVar(dpip, portp->name()+"__Vcvt", portp);
|
AstVarScope* outvscp = createFuncVar(dpip, portp->name()+"__Vcvt", portp);
|
||||||
|
// No information exposure; is already visible in import/export func template
|
||||||
|
outvscp->varp()->protect(false);
|
||||||
AstVarRef* refp = new AstVarRef(portp->fileline(), outvscp, portp->isWritable());
|
AstVarRef* refp = new AstVarRef(portp->fileline(), outvscp, portp->isWritable());
|
||||||
argnodesp = argnodesp->addNextNull(refp);
|
argnodesp = argnodesp->addNextNull(refp);
|
||||||
}
|
}
|
||||||
|
|
@ -826,6 +834,7 @@ private:
|
||||||
dpip->entryPoint(false);
|
dpip->entryPoint(false);
|
||||||
dpip->funcPublic(true);
|
dpip->funcPublic(true);
|
||||||
dpip->isStatic(false);
|
dpip->isStatic(false);
|
||||||
|
dpip->protect(false);
|
||||||
dpip->pure(nodep->pure());
|
dpip->pure(nodep->pure());
|
||||||
dpip->dpiImport(true);
|
dpip->dpiImport(true);
|
||||||
// Add DPI reference to top, since it's a global function
|
// Add DPI reference to top, since it's a global function
|
||||||
|
|
@ -952,6 +961,7 @@ private:
|
||||||
// Convert output/inout arguments back to internal type
|
// Convert output/inout arguments back to internal type
|
||||||
for (AstNode* stmtp = cfuncp->argsp(); stmtp; stmtp=stmtp->nextp()) {
|
for (AstNode* stmtp = cfuncp->argsp(); stmtp; stmtp=stmtp->nextp()) {
|
||||||
if (AstVar* portp = VN_CAST(stmtp, Var)) {
|
if (AstVar* portp = VN_CAST(stmtp, Var)) {
|
||||||
|
portp->protect(false); // No additional exposure - already part of shown proto
|
||||||
if (portp->isIO() && (portp->isWritable() || portp->isFuncReturn())
|
if (portp->isIO() && (portp->isWritable() || portp->isFuncReturn())
|
||||||
&& !portp->isDpiOpenArray()) {
|
&& !portp->isDpiOpenArray()) {
|
||||||
AstVarScope* portvscp = VN_CAST(portp->user2p(), VarScope); // Remembered when we created it earlier
|
AstVarScope* portvscp = VN_CAST(portp->user2p(), VarScope); // Remembered when we created it earlier
|
||||||
|
|
@ -984,6 +994,7 @@ private:
|
||||||
rtnvarp = portp;
|
rtnvarp = portp;
|
||||||
rtnvarp->funcLocal(true);
|
rtnvarp->funcLocal(true);
|
||||||
rtnvarp->name(rtnvarp->name()+"__Vfuncrtn"); // Avoid conflict with DPI function name
|
rtnvarp->name(rtnvarp->name()+"__Vfuncrtn"); // Avoid conflict with DPI function name
|
||||||
|
if (nodep->dpiImport() || nodep->dpiExport()) rtnvarp->protect(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nodep->dpiImport()) {
|
if (nodep->dpiImport()) {
|
||||||
|
|
@ -1245,6 +1256,11 @@ private:
|
||||||
if (nodep->dpiImport()) modes++;
|
if (nodep->dpiImport()) modes++;
|
||||||
if (nodep->dpiExport()) modes++;
|
if (nodep->dpiExport()) modes++;
|
||||||
if (nodep->taskPublic()) modes++;
|
if (nodep->taskPublic()) modes++;
|
||||||
|
if (v3Global.opt.protectIds() && nodep->taskPublic()) {
|
||||||
|
// We always call protect() on names, we don't check if public or not
|
||||||
|
// Hence any external references wouldn't be able to find the refed public object.
|
||||||
|
nodep->v3error("Unsupported: Using --protect-ids with public function");
|
||||||
|
}
|
||||||
if (modes > 1) nodep->v3error("Cannot mix DPI import, DPI export and/or public on same function: "
|
if (modes > 1) nodep->v3error("Cannot mix DPI import, DPI export and/or public on same function: "
|
||||||
<<nodep->prettyNameQ());
|
<<nodep->prettyNameQ());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -643,6 +643,9 @@ int main(int argc, char** argv, char** env) {
|
||||||
V3File::writeTimes(v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()
|
V3File::writeTimes(v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()
|
||||||
+"__verFiles.dat", argString);
|
+"__verFiles.dat", argString);
|
||||||
}
|
}
|
||||||
|
if (v3Global.opt.protectIds()) {
|
||||||
|
VIdProtect::writeMapFile(v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"__idmap.xml");
|
||||||
|
}
|
||||||
|
|
||||||
// Final writing shouldn't throw warnings, but...
|
// Final writing shouldn't throw warnings, but...
|
||||||
V3Error::abortIfWarnings();
|
V3Error::abortIfWarnings();
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,9 @@ static void checkResult(bool p, const char *msg_fail) {
|
||||||
// Main function instantiates the model and steps through the test.
|
// Main function instantiates the model and steps through the test.
|
||||||
int main() {
|
int main() {
|
||||||
Vt_dpi_accessors *dut = new Vt_dpi_accessors ("dut");
|
Vt_dpi_accessors *dut = new Vt_dpi_accessors ("dut");
|
||||||
svSetScope(svGetScopeFromName("dut.t"));
|
svScope scope = svGetScopeFromName("dut.t");
|
||||||
|
if (!scope) vl_fatal(__FILE__, __LINE__, "dut", "No svGetScopeFromName result");
|
||||||
|
svSetScope(scope);
|
||||||
|
|
||||||
// evaluate the model with no signal changes to get the initial blocks
|
// evaluate the model with no signal changes to get the initial blocks
|
||||||
// executed.
|
// executed.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2003 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.
|
||||||
|
|
||||||
|
scenarios(vlt_all => 1);
|
||||||
|
|
||||||
|
# Use --debug-protect to assist debug
|
||||||
|
|
||||||
|
# This test makes randomly named .cpp/.h files, which tend to collect, so remove them first
|
||||||
|
foreach my $filename (glob ("$Self->{obj_dir}/*_PS*.cpp"
|
||||||
|
." $Self->{obj_dir}/*_PS*.h"
|
||||||
|
." $Self->{obj_dir}/*.d" )) {
|
||||||
|
print "rm $filename\n" if $Self->{verbose};
|
||||||
|
unlink $filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
compile(
|
||||||
|
verilator_flags2 => ["--protect-ids",
|
||||||
|
"--trace",
|
||||||
|
"--coverage",
|
||||||
|
"-Wno-INSECURE",
|
||||||
|
"t/t_protect_ids_c.cpp"],
|
||||||
|
);
|
||||||
|
|
||||||
|
execute(
|
||||||
|
check_finished => 1,
|
||||||
|
);
|
||||||
|
|
||||||
|
# 'to="PS"' indicates means we probably mis-protected something already protected
|
||||||
|
# Use --debug-protect to assist debugging these
|
||||||
|
file_grep_not("$Self->{obj_dir}/$Self->{VM_PREFIX}__idmap.xml", qr/to="PS/);
|
||||||
|
|
||||||
|
if ($Self->{vlt_all}) {
|
||||||
|
# Check for secret in any outputs
|
||||||
|
my $any;
|
||||||
|
foreach my $filename (glob $Self->{obj_dir}."/*.[ch]*") {
|
||||||
|
if ($filename =~ /secret/) {
|
||||||
|
$Self->error("Secret found in a filename: ".$filename);
|
||||||
|
}
|
||||||
|
file_grep_not($filename, qr/secret/);
|
||||||
|
$any = 1;
|
||||||
|
}
|
||||||
|
$any or $Self->error("No outputs found");
|
||||||
|
}
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2019 by Wilson Snyder.
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/
|
||||||
|
// Inputs
|
||||||
|
clk
|
||||||
|
);
|
||||||
|
input clk;
|
||||||
|
|
||||||
|
secret_sub secret_inst (.*);
|
||||||
|
secret_other secret_inst2 (.*);
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module secret_sub
|
||||||
|
(
|
||||||
|
input clk);
|
||||||
|
|
||||||
|
// verilator no_inline_module
|
||||||
|
|
||||||
|
integer secret_cyc;
|
||||||
|
real secret_cyc_r;
|
||||||
|
integer secret_o;
|
||||||
|
real secret_r;
|
||||||
|
|
||||||
|
export "DPI-C" task dpix_a_task;
|
||||||
|
task dpix_a_task(input int i, output int o); o = i + 1; endtask
|
||||||
|
import "DPI-C" context task dpii_a_task(input int i, output int o);
|
||||||
|
|
||||||
|
export "DPI-C" function dpix_a_func;
|
||||||
|
function int dpix_a_func(input int i); return i + 2; endfunction
|
||||||
|
import "DPI-C" context function int dpii_a_func(input int i);
|
||||||
|
|
||||||
|
// Test loop
|
||||||
|
always @ (posedge clk) begin
|
||||||
|
secret_cyc_r = $itor(secret_cyc)/10.0 - 5.0;
|
||||||
|
secret_cyc <= dpii_a_func(secret_cyc);
|
||||||
|
secret_r += 1.0 + $cos(secret_cyc_r);
|
||||||
|
dpix_a_task(secret_cyc, secret_o);
|
||||||
|
if (secret_cyc==90) begin
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module secret_other
|
||||||
|
(
|
||||||
|
input clk);
|
||||||
|
|
||||||
|
integer secret_cyc;
|
||||||
|
|
||||||
|
always @ (posedge clk) begin
|
||||||
|
secret_cyc <= secret_cyc + 1;
|
||||||
|
if (secret_cyc==99) begin
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
%Error: Unsupported: Using --protect-ids with --public
|
||||||
|
... Suggest remove --public.
|
||||||
|
%Warning-INSECURE: Using --protect-ids with --trace may expose private design details
|
||||||
|
... Suggest remove --trace.
|
||||||
|
... Use "/* verilator lint_off INSECURE */" and lint_on around source to disable this message.
|
||||||
|
%Warning-INSECURE: Using --protect-ids with --vpi may expose private design details
|
||||||
|
... Suggest remove --vpi.
|
||||||
|
%Error: Exiting due to
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2003 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.
|
||||||
|
|
||||||
|
scenarios(vlt => 1);
|
||||||
|
|
||||||
|
compile(
|
||||||
|
verilator_flags2 => ["--protect-ids",
|
||||||
|
"--trace",
|
||||||
|
"--public",
|
||||||
|
"--vpi",
|
||||||
|
],
|
||||||
|
fails => 1,
|
||||||
|
expect_filename => $Self->{golden_filename},
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2019 by Wilson Snyder.
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/);
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||||
|
//*************************************************************************
|
||||||
|
//
|
||||||
|
// Copyright 2009-2009 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.
|
||||||
|
//
|
||||||
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
//*************************************************************************
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
#include "svdpi.h"
|
||||||
|
|
||||||
|
//======================================================================
|
||||||
|
|
||||||
|
#if defined(VERILATOR)
|
||||||
|
# ifdef T_PROTECT_IDS_KEY
|
||||||
|
# include "Vt_protect_ids_key__Dpi.h"
|
||||||
|
# else
|
||||||
|
# include "Vt_protect_ids__Dpi.h"
|
||||||
|
# endif
|
||||||
|
#elif defined(VCS)
|
||||||
|
# include "../vc_hdrs.h"
|
||||||
|
#elif defined(CADENCE)
|
||||||
|
# define NEED_EXTERNS
|
||||||
|
#else
|
||||||
|
# error "Unknown simulator for DPI test"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef NEED_EXTERNS
|
||||||
|
# error "Not supported"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//======================================================================
|
||||||
|
|
||||||
|
int dpii_a_func(int i) {
|
||||||
|
int o = dpix_a_func(i);
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dpii_a_task(int i, int* op) {
|
||||||
|
int o = 0;
|
||||||
|
(void)dpix_a_task(i, op);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
<?xml version="1.0" ?>
|
||||||
|
<!-- DESCRIPTION: Verilator output: XML representation of netlist -->
|
||||||
|
<verilator_id_map>
|
||||||
|
<map from="PSbKTb" to="TOP__t__DOT__secret_inst"/>
|
||||||
|
<map from="TOPp" to="TOPp"/>
|
||||||
|
<map from="PSbvpV" to="Vt_protect_ids_key__Vcb_dpix_a_func_t"/>
|
||||||
|
<map from="PSkBNa" to="Vt_protect_ids_key__Vcb_dpix_a_task_t"/>
|
||||||
|
<map from="PS49FI" to="_Syms"/>
|
||||||
|
<map from="PSA0ET" to="__PVT__secret_cyc"/>
|
||||||
|
<map from="PS7KZL" to="__PVT__secret_cyc_r"/>
|
||||||
|
<map from="PShnzQ" to="__PVT__secret_r"/>
|
||||||
|
<map from="PS39wi" to="__PVT__t__DOT__secret_inst"/>
|
||||||
|
<map from="PSgHnb" to="__Vclklast__TOP__clk"/>
|
||||||
|
<map from="PSTDrn" to="__Vconfigure"/>
|
||||||
|
<map from="PSAer0" to="__Vdly__secret_cyc"/>
|
||||||
|
<map from="PSswQ3" to="__Vdly__t__DOT__secret_inst2__DOT__secret_cyc"/>
|
||||||
|
<map from="PSH9UL" to="__Vdpiexp_dpix_a_func_TOP__t__DOT__secret_inst"/>
|
||||||
|
<map from="PSabB6" to="__Vdpiexp_dpix_a_task_TOP__t__DOT__secret_inst"/>
|
||||||
|
<map from="PS8F1t" to="__Vdpiimwrap_dpii_a_func_TOP__t__DOT__secret_inst"/>
|
||||||
|
<map from="PSBPcq" to="__Vdpiimwrap_dpii_a_task_TOP__t__DOT__secret_inst"/>
|
||||||
|
<map from="PSY85C" to="__Vfunc_dpii_a_func__0__Vfuncout"/>
|
||||||
|
<map from="PSUcyn" to="__Vscope_t__secret_inst"/>
|
||||||
|
<map from="PS27AG" to="__Vtask_dpix_a_task__1__i"/>
|
||||||
|
<map from="PSgcfL" to="_change_request"/>
|
||||||
|
<map from="PSNQUa" to="_ctor_var_reset"/>
|
||||||
|
<map from="PSeP2H" to="_eval"/>
|
||||||
|
<map from="PS8Ytd" to="_eval_debug_assertions"/>
|
||||||
|
<map from="PSGiE1" to="_eval_initial"/>
|
||||||
|
<map from="PSCvUR" to="_eval_initial_loop"/>
|
||||||
|
<map from="PSrrKr" to="_eval_settle"/>
|
||||||
|
<map from="PSVBHr" to="_sequent__TOP__1"/>
|
||||||
|
<map from="PSJVjb" to="_sequent__TOP__t__DOT__secret_inst__1"/>
|
||||||
|
<map from="PSnkZP" to="clk"/>
|
||||||
|
<map from="PSLGUV" to="secret_inst"/>
|
||||||
|
<map from="PSCwHq" to="secret_sub"/>
|
||||||
|
<map from="PSwmbl" to="t"/>
|
||||||
|
<map from="PS4YQ7" to="t/t_protect_ids.v"/>
|
||||||
|
<map from="PSkXXg" to="t__DOT__secret_inst2__DOT__secret_cyc"/>
|
||||||
|
<map from="this" to="this"/>
|
||||||
|
<map from="vlSymsp" to="vlSymsp"/>
|
||||||
|
<map from="vlTOPp" to="vlTOPp"/>
|
||||||
|
</verilator_id_map>
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2003 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.
|
||||||
|
|
||||||
|
scenarios(vlt => 1);
|
||||||
|
|
||||||
|
top_filename("t/t_protect_ids.v");
|
||||||
|
|
||||||
|
compile(
|
||||||
|
verilator_flags2 => ["--protect-ids --protect-key MY_KEY",
|
||||||
|
"t/t_protect_ids_c.cpp"],
|
||||||
|
);
|
||||||
|
|
||||||
|
execute(
|
||||||
|
check_finished => 1,
|
||||||
|
);
|
||||||
|
|
||||||
|
# Since using a named key, we can check for always identical map
|
||||||
|
files_identical("$Self->{obj_dir}/$Self->{VM_PREFIX}__idmap.xml", $Self->{golden_filename});
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
Loading…
Reference in New Issue