forked from github/verilator
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.
|
||||
|
||||
*** Add --protect-ids to obscure information in objects, bug1521. [Todd Strader]
|
||||
|
||||
|
||||
* 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
|
||||
--prof-cfuncs Name functions for profiling
|
||||
--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
|
||||
--public Debugging; see docs
|
||||
--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
|
||||
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
|
||||
|
||||
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}__cdc.txt // Clock Domain Crossing checks (--cdc)
|
||||
{prefix}__stats.txt // Statistics (--stats)
|
||||
{prefix}__idmap.txt // Symbol demangling (--protect-ids)
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
Warns that a packed vector is declared with little endian bit numbering
|
||||
|
@ -81,6 +81,7 @@ void AstNode::init() {
|
||||
// Attributes
|
||||
m_didWidth = false;
|
||||
m_doingWidth = false;
|
||||
m_protect = true;
|
||||
m_user1u = VNUser(0);
|
||||
m_user1Cnt = 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 pretty = name();
|
||||
string::size_type pos;
|
||||
|
@ -1165,6 +1165,7 @@ class AstNode {
|
||||
// Attributes
|
||||
bool m_didWidth:1; // Did V3Width computation
|
||||
bool m_doingWidth:1; // Inside V3Width
|
||||
bool m_protect:1; // Protect name if protection is on
|
||||
// // Space for more bools here
|
||||
|
||||
// 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 string tag() 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
|
||||
static string dedotName(const string& namein); // Name with dots removed
|
||||
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; }
|
||||
bool didWidth() const { return m_didWidth; }
|
||||
bool didWidthAndSet() { if (didWidth()) return true; didWidth(true); return false; }
|
||||
void doingWidth(bool flag) { m_doingWidth = flag; }
|
||||
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
|
||||
int width() const;
|
||||
@ -1845,6 +1849,7 @@ public:
|
||||
AstVarScope* varScopep() const { return m_varScopep; }
|
||||
void varScopep(AstVarScope* varscp) { m_varScopep = varscp; }
|
||||
string hiername() const { return m_hiername; }
|
||||
string hiernameProtect() const;
|
||||
void hiername(const string& hn) { m_hiername = hn; }
|
||||
bool hierThis() const { return m_hierThis; }
|
||||
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(); }
|
||||
}
|
||||
|
||||
string AstNodeVarRef::hiernameProtect() const {
|
||||
return VIdProtect::protectWordsIf(hiername(), protect());
|
||||
}
|
||||
|
||||
int AstNodeSel::bitConst() const {
|
||||
AstConst* constp = VN_CAST(bitp(), Const);
|
||||
return (constp ? constp->toSInt() : 0);
|
||||
@ -269,7 +273,7 @@ string AstVar::vlArgType(bool named, bool forReturn, bool forFunc) const {
|
||||
oname += "&";
|
||||
mayparen = true;
|
||||
}
|
||||
if (named) oname += " "+name();
|
||||
if (named) oname += " "+VIdProtect::protectIf(name(), protect());
|
||||
|
||||
string oarray;
|
||||
if (isDpiOpenArray() || direction().isRefOrConstRef()) {
|
||||
@ -594,6 +598,10 @@ AstNode* AstArraySel::baseFromp(AstNode* nodep) { ///< What is the base variabl
|
||||
return nodep;
|
||||
}
|
||||
|
||||
string AstCCall::hiernameProtect() const {
|
||||
return VIdProtect::protectWordsIf(hiername(), protect());
|
||||
}
|
||||
|
||||
const char* AstScope::broken() const {
|
||||
BROKEN_RTN(m_aboveScopep && !m_aboveScopep->brokeExists());
|
||||
BROKEN_RTN(m_aboveCellp && !m_aboveCellp->brokeExists());
|
||||
|
@ -6094,6 +6094,7 @@ public:
|
||||
AstCFunc* funcp() const { return m_funcp; }
|
||||
string hiername() const { return m_hiername; }
|
||||
void hiername(const string& hn) { m_hiername = hn; }
|
||||
string hiernameProtect() const;
|
||||
void argTypes(const string& str) { m_argTypes = str; }
|
||||
string argTypes() const { return m_argTypes; }
|
||||
//
|
||||
|
@ -226,6 +226,7 @@ private:
|
||||
funcp->slow(true);
|
||||
funcp->isStatic(false);
|
||||
funcp->entryPoint(true);
|
||||
funcp->protect(false);
|
||||
funcp->addInitsp(new AstCStmt
|
||||
(nodep->fileline(),
|
||||
EmitCBaseVisitor::symClassVar()+" = this->__VlSymsp;\n"));
|
||||
|
200
src/V3EmitC.cpp
200
src/V3EmitC.cpp
@ -128,12 +128,12 @@ public:
|
||||
if (const AstEnumDType* adtypep
|
||||
= VN_CAST(nodep->dtypep()->skipRefToEnump(), EnumDType)) {
|
||||
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 {
|
||||
puts("enum "+nodep->name()+" {\n");
|
||||
for (AstEnumItem* itemp = adtypep->itemsp();
|
||||
itemp; itemp = VN_CAST(itemp->nextp(), EnumItem)) {
|
||||
puts(itemp->name());
|
||||
puts(itemp->nameProtect());
|
||||
puts(" = ");
|
||||
iterateAndNextNull(itemp->valuep());
|
||||
if (VN_IS(itemp->nextp(), EnumItem)) puts(",");
|
||||
@ -214,8 +214,8 @@ public:
|
||||
virtual void visit(AstAlwaysPublic*) {
|
||||
}
|
||||
virtual void visit(AstCCall* nodep) {
|
||||
puts(nodep->hiername());
|
||||
puts(nodep->funcp()->name());
|
||||
puts(nodep->hiernameProtect());
|
||||
puts(nodep->funcp()->nameProtect());
|
||||
puts("(");
|
||||
puts(nodep->argTypes());
|
||||
bool comma = (nodep->argTypes() != "");
|
||||
@ -237,8 +237,14 @@ public:
|
||||
}
|
||||
virtual void visit(AstComment* nodep) {
|
||||
string at;
|
||||
if (nodep->showAt()) at = " at "+nodep->fileline()->ascii();
|
||||
putsDecoration(string("// ")+nodep->name()+at+"\n");
|
||||
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");
|
||||
}
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstCoverDecl* nodep) {
|
||||
@ -251,12 +257,13 @@ public:
|
||||
// hierarchies itself, and if verilator_cov also did it, you'd end up
|
||||
// with (number-of-instant) times too many counts in this bin.
|
||||
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->column()));
|
||||
puts(", "); putsQuoted((nodep->hier()!=""?".":"")+nodep->hier());
|
||||
puts(", "); putsQuoted(nodep->page());
|
||||
puts(", "); putsQuoted(nodep->comment());
|
||||
puts(", "); putsQuoted((!nodep->hier().empty() ? "." : "")
|
||||
+protectWordsIf(nodep->hier(), nodep->protect()));
|
||||
puts(", "); putsQuoted(protectWordsIf(nodep->page(), nodep->protect()));
|
||||
puts(", "); putsQuoted(protectWordsIf(nodep->comment(), nodep->protect()));
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstCoverInc* nodep) {
|
||||
@ -280,7 +287,7 @@ public:
|
||||
if (!nodep->dpiExport()) {
|
||||
// this is where the DPI import context scope is set
|
||||
string scope = nodep->scopeDpiName();
|
||||
putbs("(&(vlSymsp->__Vscope_"+scope+"))");
|
||||
putbs("(&(vlSymsp->"+protect("__Vscope_"+scope)+"))");
|
||||
}
|
||||
}
|
||||
virtual void visit(AstSFormat* nodep) {
|
||||
@ -520,14 +527,14 @@ public:
|
||||
}
|
||||
virtual void visit(AstStop* nodep) {
|
||||
puts("VL_STOP_MT(");
|
||||
putsQuoted(nodep->fileline()->filename());
|
||||
putsQuoted(protect(nodep->fileline()->filename()));
|
||||
puts(",");
|
||||
puts(cvtToStr(nodep->fileline()->lineno()));
|
||||
puts(",\"\");\n");
|
||||
}
|
||||
virtual void visit(AstFinish* nodep) {
|
||||
puts("VL_FINISH_MT(");
|
||||
putsQuoted(nodep->fileline()->filename());
|
||||
putsQuoted(protect(nodep->fileline()->filename()));
|
||||
puts(",");
|
||||
puts(cvtToStr(nodep->fileline()->lineno()));
|
||||
puts(",\"\");\n");
|
||||
@ -555,13 +562,13 @@ public:
|
||||
iterateAndNextNull(nodep->bodysp());
|
||||
}
|
||||
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());
|
||||
puts("\n");
|
||||
}
|
||||
virtual void visit(AstUCFunc* nodep) {
|
||||
puts("\n");
|
||||
putsDecoration("// $c function at "+nodep->fileline()->ascii()+"\n");
|
||||
putsDecoration(ifNoProtect("// $c function at "+nodep->fileline()->ascii()+"\n"));
|
||||
iterateAndNextNull(nodep->bodysp());
|
||||
puts("\n");
|
||||
}
|
||||
@ -701,8 +708,8 @@ public:
|
||||
}
|
||||
// Terminals
|
||||
virtual void visit(AstVarRef* nodep) {
|
||||
puts(nodep->hiername());
|
||||
puts(nodep->varp()->name());
|
||||
puts(nodep->hiernameProtect());
|
||||
puts(nodep->varp()->nameProtect());
|
||||
}
|
||||
void emitCvtPackStr(AstNode* nodep) {
|
||||
if (const AstConst* constp = VN_CAST(nodep, Const)) {
|
||||
@ -756,8 +763,8 @@ public:
|
||||
if (!assigntop) {
|
||||
puts(assignString);
|
||||
} else if (VN_IS(assigntop, VarRef)) {
|
||||
puts(assigntop->hiername());
|
||||
puts(assigntop->varp()->name());
|
||||
puts(assigntop->hiernameProtect());
|
||||
puts(assigntop->varp()->nameProtect());
|
||||
} else {
|
||||
iterateAndNextNull(assigntop);
|
||||
}
|
||||
@ -779,8 +786,8 @@ public:
|
||||
if (!assigntop) {
|
||||
puts(assignString);
|
||||
} else if (VN_IS(assigntop, VarRef)) {
|
||||
puts(assigntop->hiername());
|
||||
puts(assigntop->varp()->name());
|
||||
puts(assigntop->hiernameProtect());
|
||||
puts(assigntop->varp()->nameProtect());
|
||||
} else {
|
||||
iterateAndNextNull(assigntop);
|
||||
}
|
||||
@ -1090,7 +1097,7 @@ class EmitCImp : EmitCStmts {
|
||||
ExecMTask* mtp = nodep->execMTaskp();
|
||||
puts("\n");
|
||||
puts("void ");
|
||||
puts(modClassName(m_modp)+"::"+mtp->cFuncName());
|
||||
puts(modClassName(m_modp)+"::"+protect(mtp->cFuncName()));
|
||||
puts("(bool even_cycle, void* symtab) {\n");
|
||||
|
||||
// Declare and set vlSymsp
|
||||
@ -1119,13 +1126,13 @@ class EmitCImp : EmitCStmts {
|
||||
if (nodep->ifdef()!="") puts("#ifdef "+nodep->ifdef()+"\n");
|
||||
if (nodep->isInline()) puts("VL_INLINE_OPT ");
|
||||
puts(nodep->rtnTypeVoid()); puts(" ");
|
||||
puts(modClassName(m_modp)+"::"+nodep->name()
|
||||
puts(modClassName(m_modp)+"::"+nodep->nameProtect()
|
||||
+"("+cFuncArgs(nodep)+") {\n");
|
||||
|
||||
// "+" in the debug indicates a print from the model
|
||||
puts("VL_DEBUG_IF(VL_DBG_MSGF(\"+ ");
|
||||
for (int i=0; i<m_modp->level(); ++i) { puts(" "); }
|
||||
puts(modClassName(m_modp)+"::"+nodep->name()
|
||||
puts(modClassName(m_modp)+"::"+nodep->nameProtect()
|
||||
+"\\n\"); );\n");
|
||||
|
||||
// Declare and set vlTOPp
|
||||
@ -1172,8 +1179,8 @@ class EmitCImp : EmitCStmts {
|
||||
doubleOrDetect(changep, gotOne);
|
||||
}
|
||||
}
|
||||
if (gotOne) {
|
||||
puts(");\n");
|
||||
if (gotOne) puts(");\n");
|
||||
if (gotOne && !v3Global.opt.protectIds()) {
|
||||
//puts("VL_DEBUG_IF( if (__req) cout<<\"- CLOCKREQ );");
|
||||
for (std::vector<AstChangeDet*>::iterator it = m_blkChangeDetVec.begin();
|
||||
it != m_blkChangeDetVec.end(); ++it) {
|
||||
@ -1232,14 +1239,14 @@ class EmitCImp : EmitCStmts {
|
||||
if (runInline) {
|
||||
// The thread calling eval() will run this mtask inline,
|
||||
// along with its packed successors.
|
||||
puts(execMTasks[i]->cFuncName()
|
||||
puts(protect(execMTasks[i]->cFuncName())
|
||||
+ "(vlTOPp->__Vm_even_cycle, vlSymsp);\n");
|
||||
puts("Verilated::mtaskId(0);\n");
|
||||
} else {
|
||||
// The other N-1 go to the thread pool.
|
||||
puts("vlTOPp->__Vm_threadPoolp->workerp("
|
||||
+ cvtToStr(i)+")->addTask("
|
||||
+ execMTasks[i]->cFuncName()
|
||||
+ protect(execMTasks[i]->cFuncName())
|
||||
+ ", vlTOPp->__Vm_even_cycle, vlSymsp);\n");
|
||||
}
|
||||
}
|
||||
@ -1307,7 +1314,7 @@ void EmitCStmts::emitVarDecl(const AstVar* nodep, const string& prefixIfImp) {
|
||||
puts(nodep->scType());
|
||||
puts("> ");
|
||||
}
|
||||
puts(nodep->name());
|
||||
puts(nodep->nameProtect());
|
||||
emitDeclArrayBrackets(nodep);
|
||||
puts(";\n");
|
||||
} 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->isWide()) puts("W");
|
||||
|
||||
puts("("+nodep->name());
|
||||
puts("("+nodep->nameProtect());
|
||||
emitDeclArrayBrackets(nodep);
|
||||
// If it's a packed struct/array then nodep->width is the whole
|
||||
// thing, msb/lsb is just lowest dimension
|
||||
@ -1357,7 +1364,7 @@ void EmitCStmts::emitVarDecl(const AstVar* nodep, const string& prefixIfImp) {
|
||||
puts("SIGW(");
|
||||
}
|
||||
if (prefixIfImp!="") { puts(prefixIfImp); puts("::"); }
|
||||
puts(nodep->name());
|
||||
puts(nodep->nameProtect());
|
||||
emitDeclArrayBrackets(nodep);
|
||||
// If it's a packed struct/array then nodep->width is the whole
|
||||
// thing, msb/lsb is just lowest dimension
|
||||
@ -1387,12 +1394,12 @@ void EmitCStmts::emitVarCtors(bool* firstp) {
|
||||
bool isArray = !VN_CAST(varp->dtypeSkipRefp(), BasicDType);
|
||||
if (isArray) {
|
||||
puts("// Skipping array: ");
|
||||
puts(varp->name());
|
||||
puts(varp->nameProtect());
|
||||
puts("\n");
|
||||
} else {
|
||||
emitCtorSep(firstp);
|
||||
puts(varp->name());
|
||||
puts("("); putsQuoted(varp->name()); puts(")");
|
||||
puts(varp->nameProtect());
|
||||
puts("("); putsQuoted(varp->nameProtect()); puts(")");
|
||||
}
|
||||
}
|
||||
puts("\n#endif\n");
|
||||
@ -1456,8 +1463,8 @@ void EmitCStmts::emitOpName(AstNode* nodep, const string& format,
|
||||
UASSERT_OBJ(m_wideTempRefp, nodep,
|
||||
"Wide Op w/ no temp, perhaps missing op in V3EmitC?");
|
||||
COMMA;
|
||||
puts(m_wideTempRefp->hiername());
|
||||
puts(m_wideTempRefp->varp()->name());
|
||||
puts(m_wideTempRefp->hiernameProtect());
|
||||
puts(m_wideTempRefp->varp()->nameProtect());
|
||||
m_wideTempRefp = NULL;
|
||||
needComma = true;
|
||||
}
|
||||
@ -1727,7 +1734,7 @@ void EmitCImp::emitVarReset(AstVar* varp) {
|
||||
UASSERT_OBJ(varp->valuep(), varp, "No init for a param?");
|
||||
// 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
|
||||
//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)) {
|
||||
if (AstUnpackArrayDType* arrayp = VN_CAST(varp->dtypeSkipRefp(), UnpackArrayDType)) {
|
||||
@ -1736,7 +1743,8 @@ void EmitCImp::emitVarReset(AstVar* varp) {
|
||||
puts("{ int __Vi=0;");
|
||||
puts(" for (; __Vi<"+cvtToStr(arrayp->elementsConst()));
|
||||
puts("; ++__Vi) {\n");
|
||||
emitSetVarConstant(varp->name()+"[__Vi]", VN_CAST(initarp->defaultp(), Const));
|
||||
emitSetVarConstant(varp->nameProtect()+"[__Vi]",
|
||||
VN_CAST(initarp->defaultp(), Const));
|
||||
puts("}}\n");
|
||||
}
|
||||
int pos = 0;
|
||||
@ -1744,7 +1752,8 @@ void EmitCImp::emitVarReset(AstVar* varp) {
|
||||
int index = initarp->posIndex(pos);
|
||||
UASSERT_OBJ(initarp->defaultp() || index==pos, initarp,
|
||||
"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 {
|
||||
varp->v3fatalSrc("InitArray under non-arrayed var");
|
||||
@ -1780,11 +1789,11 @@ void EmitCImp::emitVarReset(AstVar* varp) {
|
||||
else puts("VL_RAND_RESET_W(");
|
||||
puts(cvtToStr(varp->widthMin()));
|
||||
puts(",");
|
||||
puts(varp->name());
|
||||
puts(varp->nameProtect());
|
||||
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
|
||||
puts(");\n");
|
||||
} else {
|
||||
puts(varp->name());
|
||||
puts(varp->nameProtect());
|
||||
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
|
||||
// If --x-initial-edge is set, we want to force an initial
|
||||
// edge on uninitialized clocks (from 'X' to whatever the
|
||||
@ -1868,7 +1877,7 @@ void EmitCImp::emitCtorImp(AstNodeModule* modp) {
|
||||
puts("\n");
|
||||
}
|
||||
putsDecoration("// Reset structure values\n");
|
||||
puts("_ctor_var_reset();\n");
|
||||
puts(protect("_ctor_var_reset")+"();\n");
|
||||
emitTextSection(AstType::atScCtor);
|
||||
|
||||
if (modp->isTop() && v3Global.opt.mtasks()) {
|
||||
@ -1907,11 +1916,12 @@ void EmitCImp::emitCtorImp(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( "this->__VlSymsp = vlSymsp;\n"); // First, as later stuff needs it.
|
||||
if (v3Global.opt.coverage() ) {
|
||||
puts("this->_configure_coverage(vlSymsp, first);\n");
|
||||
puts(protect("_configure_coverage")+"(vlSymsp, first);\n");
|
||||
}
|
||||
puts("}\n");
|
||||
splitSizeInc(10);
|
||||
@ -1962,7 +1972,7 @@ void EmitCImp::emitSavableImp(AstNodeModule* modp) {
|
||||
string funcname = de ? "__Vdeserialize" : "__Vserialize";
|
||||
string op = de ? ">>" : "<<";
|
||||
// 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
|
||||
// OK if this hash includes some things we won't dump, since
|
||||
// just looking for loading the wrong model
|
||||
@ -2019,7 +2029,7 @@ void EmitCImp::emitSavableImp(AstNodeModule* modp) {
|
||||
puts(" for (; "+ivar+"<"+cvtToStr(elementp->widthWords()));
|
||||
puts("; ++"+ivar+") {\n");
|
||||
}
|
||||
puts("os"+op+varp->name());
|
||||
puts("os"+op+varp->nameProtect());
|
||||
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(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
|
||||
puts( "__VlSymsp->"+funcname+"(os);\n");
|
||||
puts( "__VlSymsp->"+protect(funcname)+"(os);\n");
|
||||
}
|
||||
puts("}\n");
|
||||
}
|
||||
@ -2051,10 +2061,8 @@ void EmitCImp::emitTextSection(AstType type) {
|
||||
if (last_line < 0) {
|
||||
puts("\n//*** Below code from `systemc in Verilog file\n");
|
||||
}
|
||||
ofp()->putsNoTracking("//#line "+cvtToStr(nodep->fileline()->lineno())
|
||||
+" ");
|
||||
ofp()->putsQuoted(nodep->fileline()->filename());
|
||||
ofp()->putsNoTracking("\n");
|
||||
putsDecoration(ifNoProtect("// From `systemc at "
|
||||
+nodep->fileline()->ascii()+"\n"));
|
||||
last_line = nodep->fileline()->lineno();
|
||||
}
|
||||
ofp()->putsNoTracking(textp->text());
|
||||
@ -2075,7 +2083,7 @@ void EmitCImp::emitCellCtors(AstNodeModule* modp) {
|
||||
}
|
||||
for (AstNode* nodep = modp->stmtsp(); nodep; nodep = nodep->nextp()) {
|
||||
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("; ++"+ivar+") {\n");
|
||||
}
|
||||
puts("sensitive << "+varp->name());
|
||||
puts("sensitive << "+varp->nameProtect());
|
||||
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(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( "int __Vsaved_debug = Verilated::debug();\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( "VL_FATAL_MT(__FILE__,__LINE__,__FILE__,\"Verilated model didn't ");
|
||||
if (initial) puts("DC ");
|
||||
puts( "converge\");\n");
|
||||
puts( "} else {\n");
|
||||
puts( "__Vchange = _change_request(vlSymsp);\n");
|
||||
puts( "__Vchange = "+protect("_change_request")+"(vlSymsp);\n");
|
||||
puts( "}\n");
|
||||
puts("} while (VL_UNLIKELY(__Vchange));\n");
|
||||
}
|
||||
@ -2146,10 +2154,11 @@ void EmitCImp::emitWrapEval(AstNodeModule* modp) {
|
||||
puts(EmitCBaseVisitor::symTopAssign()+"\n");
|
||||
puts("#ifdef VL_DEBUG\n");
|
||||
putsDecoration("// Debug assertions\n");
|
||||
puts("_eval_debug_assertions();\n");
|
||||
puts(protect("_eval_debug_assertions")+"();\n");
|
||||
puts("#endif // VL_DEBUG\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()) {
|
||||
puts("if (VL_UNLIKELY(__Vm_inhibitSim)) return;\n");
|
||||
}
|
||||
@ -2201,7 +2210,7 @@ void EmitCImp::emitWrapEval(AstNodeModule* modp) {
|
||||
emitSettleLoop(
|
||||
(string("VL_DEBUG_IF(VL_DBG_MSGF(\"+ Clock loop\\n\"););\n")
|
||||
+ (v3Global.opt.trace() ? "vlSymsp->__Vm_activity = true;\n" : "")
|
||||
+ "_eval(vlSymsp);"), false);
|
||||
+ protect("_eval")+"(vlSymsp);"), false);
|
||||
if (v3Global.opt.threads() == 1) {
|
||||
puts("Verilated::endOfThreadMTask(vlSymsp->__Vm_evalMsgQp);\n");
|
||||
}
|
||||
@ -2212,14 +2221,15 @@ void EmitCImp::emitWrapEval(AstNodeModule* modp) {
|
||||
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("_eval_initial(vlSymsp);\n");
|
||||
puts(protect("_eval_initial")+"(vlSymsp);\n");
|
||||
if (v3Global.opt.trace()) {
|
||||
puts("vlSymsp->__Vm_activity = true;\n");
|
||||
}
|
||||
emitSettleLoop((string("_eval_settle(vlSymsp);\n")
|
||||
+"_eval(vlSymsp);"), true);
|
||||
emitSettleLoop((protect("_eval_settle")+"(vlSymsp);\n"
|
||||
+protect("_eval")+"(vlSymsp);"), true);
|
||||
puts("}\n");
|
||||
splitSizeInc(10);
|
||||
}
|
||||
@ -2428,7 +2438,8 @@ void EmitCImp::emitIntFuncDecls(AstNodeModule* modp) {
|
||||
if (funcp->ifdef()!="") puts("#ifdef "+funcp->ifdef()+"\n");
|
||||
if (funcp->isStatic().trueU()) puts("static ");
|
||||
puts(funcp->rtnTypeVoid()); puts(" ");
|
||||
puts(funcp->name()); puts("("+cFuncArgs(funcp)+")");
|
||||
puts(funcp->nameProtect());
|
||||
puts("("+cFuncArgs(funcp)+")");
|
||||
if (funcp->slow()) puts(" VL_ATTR_COLD");
|
||||
puts(";\n");
|
||||
if (funcp->ifdef()!="") puts("#endif // "+funcp->ifdef()+"\n");
|
||||
@ -2446,7 +2457,7 @@ void EmitCImp::emitIntFuncDecls(AstNodeModule* modp) {
|
||||
if (mtp->threadRoot()) {
|
||||
// Emit function declaration for this mtask
|
||||
ofp()->putsPrivate(true);
|
||||
puts("static void "); puts(mtp->cFuncName());
|
||||
puts("static void "); puts(protect(mtp->cFuncName()));
|
||||
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("// 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
|
||||
// support them. They also cause problems with GDB under GCC2.95.
|
||||
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
|
||||
//putsDecoration("// enum ..... "+varp->name()
|
||||
//putsDecoration("// enum ..... "+varp->nameProtect()
|
||||
// +"not simple value, see variable above instead");
|
||||
} else if (VN_IS(varp->dtypep(), BasicDType)
|
||||
&& VN_CAST(varp->dtypep(), BasicDType)->isOpaque()) { // Can't put out e.g. doubles
|
||||
} else {
|
||||
puts("enum ");
|
||||
puts(varp->isQuad()?"_QData":"_IData");
|
||||
puts(""+varp->name()+" { "+varp->name()+" = ");
|
||||
puts(""+varp->nameProtect()+" { "+varp->nameProtect()+" = ");
|
||||
iterateAndNextNull(varp->valuep());
|
||||
puts("};");
|
||||
}
|
||||
@ -2672,27 +2683,28 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
|
||||
puts("\n// INTERNAL METHODS\n");
|
||||
if (modp->isTop()) {
|
||||
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:
|
||||
puts("void __Vconfigure("+symClassName()+"* symsp, bool first);\n");
|
||||
puts("void "+protect("__Vconfigure")+"("+symClassName()+"* symsp, bool first);\n");
|
||||
|
||||
emitIntFuncDecls(modp);
|
||||
|
||||
if (v3Global.opt.trace()) {
|
||||
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");
|
||||
puts("static void traceFull("+v3Global.opt.traceClassBase()
|
||||
puts("static void "+protect("traceFull")+"("+v3Global.opt.traceClassBase()
|
||||
+"* 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");
|
||||
}
|
||||
if (v3Global.opt.savable()) {
|
||||
ofp()->putsPrivate(false); // public:
|
||||
puts("void __Vserialize(VerilatedSerialize& os);\n");
|
||||
puts("void __Vdeserialize(VerilatedDeserialize& os);\n");
|
||||
puts("void "+protect("__Vserialize")+"(VerilatedSerialize& os);\n");
|
||||
puts("void "+protect("__Vdeserialize")+"(VerilatedDeserialize& os);\n");
|
||||
puts("\n");
|
||||
}
|
||||
|
||||
@ -2703,10 +2715,10 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
|
||||
if (v3Global.opt.savable() && modp->isTop()) {
|
||||
puts("inline VerilatedSerialize& operator<<(VerilatedSerialize& os, "
|
||||
+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, "
|
||||
+modClassName(modp)+"& rhs) {\n"
|
||||
"Verilated::quiesce(); rhs.__Vdeserialize(os); return os; }\n");
|
||||
"Verilated::quiesce(); rhs."+protect("__Vdeserialize")+"(os); return os; }\n");
|
||||
puts("\n");
|
||||
}
|
||||
|
||||
@ -2838,8 +2850,8 @@ class EmitCTrace : EmitCStmts {
|
||||
|
||||
// METHODS
|
||||
void newOutCFile(int filenum) {
|
||||
string filename = (v3Global.opt.makeDir()+"/"+ topClassName()
|
||||
+"__Trace");
|
||||
string filename = (v3Global.opt.makeDir()+"/"
|
||||
+topClassName()+"_"+protect("_Trace"));
|
||||
if (filenum) filename += "__"+cvtToStr(filenum);
|
||||
filename += (m_slow ? "__Slow":"");
|
||||
filename += ".cpp";
|
||||
@ -2868,13 +2880,13 @@ class EmitCTrace : EmitCStmts {
|
||||
puts("void "+topClassName()+"::trace(");
|
||||
puts(v3Global.opt.traceClassBase()+"C* tfp, int, int) {\n");
|
||||
puts( "tfp->spTrace()->addCallback("
|
||||
"&"+topClassName()+"::traceInit"
|
||||
+", &"+topClassName()+"::traceFull"
|
||||
+", &"+topClassName()+"::traceChg, this);\n");
|
||||
"&"+topClassName()+"::"+protect("traceInit")
|
||||
+", &"+topClassName()+"::"+protect("traceFull")
|
||||
+", &"+topClassName()+"::"+protect("traceChg")+", this);\n");
|
||||
puts("}\n");
|
||||
splitSizeInc(10);
|
||||
|
||||
puts("void "+topClassName()+"::traceInit("
|
||||
puts("void "+topClassName()+"::"+protect("traceInit")+"("
|
||||
+v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code) {\n");
|
||||
putsDecoration("// Callback from vcd->open()\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("}\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("}\n");
|
||||
splitSizeInc(10);
|
||||
|
||||
puts("void "+topClassName()+"::traceFull("
|
||||
puts("void "+topClassName()+"::"+protect("traceFull")+"("
|
||||
+v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code) {\n");
|
||||
putsDecoration("// Callback from vcd->dump()\n");
|
||||
puts(topClassName()+"* t = ("+topClassName()+"*)userthis;\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");
|
||||
splitSizeInc(10);
|
||||
|
||||
@ -2903,13 +2915,13 @@ class EmitCTrace : EmitCStmts {
|
||||
void emitTraceFast() {
|
||||
puts("\n//======================\n\n");
|
||||
|
||||
puts("void "+topClassName()+"::traceChg("
|
||||
puts("void "+topClassName()+"::"+protect("traceChg")+"("
|
||||
+v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code) {\n");
|
||||
putsDecoration("// Callback from vcd->dump()\n");
|
||||
puts(topClassName()+"* t = ("+topClassName()+"*)userthis;\n");
|
||||
puts(EmitCBaseVisitor::symClassVar()+" = t->__VlSymsp; // Setup global symbol table\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");
|
||||
splitSizeInc(10);
|
||||
@ -2954,7 +2966,7 @@ class EmitCTrace : EmitCStmts {
|
||||
puts("(c+"+cvtToStr(nodep->code()));
|
||||
if (nodep->arrayRange().ranged()) puts("+i*"+cvtToStr(nodep->widthWords()));
|
||||
puts(",");
|
||||
putsQuoted(nodep->showname());
|
||||
putsQuoted(VIdProtect::protectWordsIf(nodep->showname(), nodep->protect()));
|
||||
// Direction
|
||||
if (v3Global.opt.traceFormat().fstFlavor()) {
|
||||
puts(","+cvtToStr(enumNum));
|
||||
@ -3033,7 +3045,7 @@ class EmitCTrace : EmitCStmts {
|
||||
enump->user1(enumNum);
|
||||
int nvals = 0;
|
||||
puts("{\n");
|
||||
puts("const char* __VenumItemNames[]\n");
|
||||
puts("const char* "+protect("__VenumItemNames")+"[]\n");
|
||||
puts("= {");
|
||||
for (AstEnumItem* itemp = enump->itemsp(); itemp;
|
||||
itemp = VN_CAST(itemp->nextp(), EnumItem)) {
|
||||
@ -3042,7 +3054,7 @@ class EmitCTrace : EmitCStmts {
|
||||
}
|
||||
puts("};\n");
|
||||
nvals = 0;
|
||||
puts("const char* __VenumItemValues[]\n");
|
||||
puts("const char* "+protect("__VenumItemValues")+"[]\n");
|
||||
puts("= {");
|
||||
for (AstEnumItem* itemp = enump->itemsp(); itemp;
|
||||
itemp = VN_CAST(itemp->nextp(), EnumItem)) {
|
||||
@ -3055,7 +3067,9 @@ class EmitCTrace : EmitCStmts {
|
||||
+", \""+enump->prettyName()+"\", "
|
||||
+cvtToStr(nvals)
|
||||
+", "+cvtToStr(enump->widthMin())
|
||||
+", __VenumItemNames, __VenumItemValues);\n");
|
||||
+", "+protect("__VenumItemNames")
|
||||
+", "+protect("__VenumItemValues")
|
||||
+");\n");
|
||||
puts("}\n");
|
||||
}
|
||||
return enumNum;
|
||||
@ -3146,7 +3160,7 @@ class EmitCTrace : EmitCStmts {
|
||||
|
||||
puts("\n");
|
||||
puts(nodep->rtnTypeVoid()); puts(" ");
|
||||
puts(topClassName()+"::"+nodep->name()
|
||||
puts(topClassName()+"::"+nodep->nameProtect()
|
||||
+"("+cFuncArgs(nodep)+") {\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 putsQuoted(const string& str) { ofp()->putsQuoted(str); }
|
||||
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 symTopAssign() {
|
||||
return v3Global.opt.prefix()+"* __restrict vlTOPp VL_ATTR_UNUSED = vlSymsp->TOPp;"; }
|
||||
@ -54,7 +60,7 @@ public:
|
||||
if (modp->isTop()) {
|
||||
return v3Global.opt.prefix();
|
||||
} else {
|
||||
return v3Global.opt.modPrefix() + "_" + modp->name();
|
||||
return v3Global.opt.modPrefix()+"_"+protect(modp->name());
|
||||
}
|
||||
}
|
||||
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) {
|
||||
AstCFunc* funcp = it->second.m_funcp;
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -430,11 +430,11 @@ void EmitCSyms::emitSymHdr() {
|
||||
AstScope* scopep = it->first; AstNodeModule* modp = it->second;
|
||||
if (modp->isTop()) {
|
||||
ofp()->printf("%-30s ", (modClassName(modp)+"*").c_str());
|
||||
puts(scopep->nameDotless()+"p;\n");
|
||||
puts(protectIf(scopep->nameDotless()+"p", scopep->protect())+";\n");
|
||||
}
|
||||
else {
|
||||
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
|
||||
puts("\n// SCOPE NAMES\n");
|
||||
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");
|
||||
}
|
||||
if (v3Global.opt.savable() ) {
|
||||
puts("void __Vserialize(VerilatedSerialize& os);\n");
|
||||
puts("void __Vdeserialize(VerilatedDeserialize& os);\n");
|
||||
puts("void "+protect("__Vserialize")+"(VerilatedSerialize& os);\n");
|
||||
puts("void "+protect("__Vdeserialize")+"(VerilatedDeserialize& os);\n");
|
||||
}
|
||||
puts("\n");
|
||||
puts("} VL_ATTR_ALIGNED(64);\n");
|
||||
@ -558,7 +558,7 @@ void EmitCSyms::emitSymImp() {
|
||||
string funcname = de ? "__Vdeserialize" : "__Vserialize";
|
||||
string op = de ? ">>" : "<<";
|
||||
// NOLINTNEXTLINE(performance-inefficient-string-concatenation)
|
||||
puts("void "+symClassName()+"::"+funcname+"("+classname+"& os) {\n");
|
||||
puts("void "+symClassName()+"::"+protect(funcname)+"("+classname+"& os) {\n");
|
||||
puts( "// LOCAL STATE\n");
|
||||
// __Vm_namep presumably already correct
|
||||
if (v3Global.opt.trace()) {
|
||||
@ -570,7 +570,8 @@ void EmitCSyms::emitSymImp() {
|
||||
it != m_scopes.end(); ++it) {
|
||||
AstScope* scopep = it->first; AstNodeModule* modp = it->second;
|
||||
if (!modp->isTop()) {
|
||||
puts( scopep->nameDotless()+"."+funcname+"(os);\n");
|
||||
puts(protectIf(scopep->nameDotless(), scopep->protect())
|
||||
+"."+protect(funcname)+"(os);\n");
|
||||
}
|
||||
}
|
||||
puts("}\n");
|
||||
@ -593,10 +594,10 @@ void EmitCSyms::emitSymImp() {
|
||||
AstScope* scopep = it->first; AstNodeModule* modp = it->second;
|
||||
if (modp->isTop()) {
|
||||
} else {
|
||||
puts(string(" ")+comma+" "+scopep->nameDotless());
|
||||
puts(string(" ")+comma+" "+protect(scopep->nameDotless()));
|
||||
puts("(Verilated::catName(topp->name(),");
|
||||
// The "." is added by catName
|
||||
putsQuoted(scopep->prettyName());
|
||||
putsQuoted(protectWordsIf(scopep->prettyName(), scopep->protect()));
|
||||
puts("))\n");
|
||||
comma = ',';
|
||||
++m_numStmts;
|
||||
@ -617,15 +618,16 @@ void EmitCSyms::emitSymImp() {
|
||||
arrow.replace(pos, 1, "->");
|
||||
}
|
||||
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(scopep->nameDotless()+";\n");
|
||||
puts(protectIf(scopep->nameDotless(), scopep->protect())+";\n");
|
||||
++m_numStmts;
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
AstScope* scopep = it->first; AstNodeModule* modp = it->second;
|
||||
if (!modp->isTop()) {
|
||||
@ -633,7 +635,8 @@ void EmitCSyms::emitSymImp() {
|
||||
// first is used by AstCoverDecl's call to __vlCoverInsert
|
||||
bool first = !modp->user1();
|
||||
modp->user1(true);
|
||||
puts(scopep->nameDotless()+".__Vconfigure(this, "
|
||||
puts(protectIf(scopep->nameDotless(), scopep->protect())
|
||||
+"."+protect("__Vconfigure")+"(this, "
|
||||
+(first?"true":"false")
|
||||
+");\n");
|
||||
++m_numStmts;
|
||||
@ -644,10 +647,11 @@ void EmitCSyms::emitSymImp() {
|
||||
puts("// Setup scopes\n");
|
||||
for (ScopeNames::iterator it = m_scopeNames.begin(); it != m_scopeNames.end(); ++it) {
|
||||
checkSplit(false);
|
||||
puts("__Vscope_"+it->second.m_symName+".configure(this,name(),");
|
||||
putsQuoted(it->second.m_prettyName);
|
||||
puts(protect("__Vscope_"+it->second.m_symName)
|
||||
+".configure(this, name(), ");
|
||||
putsQuoted(protectWordsIf(it->second.m_prettyName, true));
|
||||
puts(", ");
|
||||
putsQuoted(scopeDecodeIdentifier(it->second.m_prettyName));
|
||||
putsQuoted(protect(scopeDecodeIdentifier(it->second.m_prettyName)));
|
||||
puts(", VerilatedScope::"+it->second.m_type+");\n");
|
||||
++m_numStmts;
|
||||
}
|
||||
@ -661,7 +665,7 @@ void EmitCSyms::emitSymImp() {
|
||||
if (it->first == "TOP") continue;
|
||||
name = name.replace(0, 4, ""); // Remove the "TOP."
|
||||
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(to != m_scopeNames.end(), toname+" not in m_scopeNames");
|
||||
puts("__Vhier.add(");
|
||||
puts("&__Vscope_"+from->second.m_symName+", ");
|
||||
puts("&__Vscope_"+to->second.m_symName+");\n");
|
||||
puts("&"+protect("__Vscope_"+from->second.m_symName)+", ");
|
||||
puts("&"+protect("__Vscope_"+to->second.m_symName)+");\n");
|
||||
}
|
||||
}
|
||||
puts("\n");
|
||||
@ -695,12 +699,12 @@ void EmitCSyms::emitSymImp() {
|
||||
AstNodeModule* modp = it->second.m_modp;
|
||||
if (funcp->dpiExport()) {
|
||||
checkSplit(true);
|
||||
puts("__Vscope_"+scopep->scopeSymName()+".exportInsert(__Vfinal,");
|
||||
putsQuoted(funcp->cname());
|
||||
puts(protect("__Vscope_"+scopep->scopeSymName())+".exportInsert(__Vfinal, ");
|
||||
putsQuoted(funcp->cname()); // Not protected - user asked for import/export
|
||||
puts(", (void*)(&");
|
||||
puts(modClassName(modp));
|
||||
puts("::");
|
||||
puts(funcp->name());
|
||||
puts(funcp->nameProtect());
|
||||
puts("));\n");
|
||||
++m_numStmts;
|
||||
}
|
||||
@ -738,17 +742,17 @@ void EmitCSyms::emitSymImp() {
|
||||
if (pdim>1 || udim>1) {
|
||||
puts("//UNSUP "); // VerilatedImp can't deal with >2d or packed arrays
|
||||
}
|
||||
puts("__Vscope_"+it->second.m_scopeName+".varInsert(__Vfinal,");
|
||||
putsQuoted(it->second.m_varBasePretty);
|
||||
puts(protect("__Vscope_"+it->second.m_scopeName)+".varInsert(__Vfinal,");
|
||||
putsQuoted(protect(it->second.m_varBasePretty));
|
||||
puts(", &(");
|
||||
if (modp->isTop()) {
|
||||
puts(scopep->nameDotless());
|
||||
puts("p->");
|
||||
puts(protectIf(scopep->nameDotless()+"p", scopep->protect()));
|
||||
puts("->");
|
||||
} else {
|
||||
puts(scopep->nameDotless());
|
||||
puts(protectIf(scopep->nameDotless(), scopep->protect()));
|
||||
puts(".");
|
||||
}
|
||||
puts(varp->name());
|
||||
puts(varp->nameProtect());
|
||||
puts("), ");
|
||||
puts(varp->vlEnumType()); // VLVT_UINT32 etc
|
||||
puts(",");
|
||||
@ -796,13 +800,15 @@ void EmitCSyms::emitDpiHdr() {
|
||||
AstCFunc* nodep = *it;
|
||||
if (nodep->dpiExportWrapper()) {
|
||||
if (!firstExp++) puts("\n// DPI EXPORTS\n");
|
||||
puts("// DPI export at "+nodep->fileline()->ascii()+"\n");
|
||||
puts("extern "+nodep->rtnTypeVoid()+" "+nodep->name()+"("+cFuncArgs(nodep)+");\n");
|
||||
puts("// DPI export"+ifNoProtect(" at "+nodep->fileline()->ascii())+"\n");
|
||||
puts("extern "+nodep->rtnTypeVoid()+" "+nodep->nameProtect()
|
||||
+"("+cFuncArgs(nodep)+");\n");
|
||||
}
|
||||
else if (nodep->dpiImport()) {
|
||||
if (!firstImp++) puts("\n// DPI IMPORTS\n");
|
||||
puts("// DPI import at "+nodep->fileline()->ascii()+"\n");
|
||||
puts("extern "+nodep->rtnTypeVoid()+" "+nodep->name()+"("+cFuncArgs(nodep)+");\n");
|
||||
puts("// DPI import"+ifNoProtect(" at "+nodep->fileline()->ascii())+"\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("#define _VL_DPIDECL_"+nodep->name()+"\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()+"(");
|
||||
string args;
|
||||
for (AstNode* stmtp = nodep->argsp(); stmtp; stmtp=stmtp->nextp()) {
|
||||
|
@ -88,6 +88,7 @@ public:
|
||||
INCABSPATH, // Include has absolute path
|
||||
INFINITELOOP, // Infinite loop
|
||||
INITIALDLY, // Initial delayed statement
|
||||
INSECURE, // Insecure options
|
||||
LITENDIAN, // Little bit endian vector
|
||||
MODDUP, // Duplicate module
|
||||
MULTIDRIVEN, // Driven from multiple blocks
|
||||
@ -145,7 +146,7 @@ public:
|
||||
"ENDLABEL", "GENCLK",
|
||||
"IFDEPTH", "IGNOREDRETURN",
|
||||
"IMPERFECTSCH", "IMPLICIT", "IMPORTSTAR", "IMPURE",
|
||||
"INCABSPATH", "INFINITELOOP", "INITIALDLY",
|
||||
"INCABSPATH", "INFINITELOOP", "INITIALDLY", "INSECURE",
|
||||
"LITENDIAN", "MODDUP",
|
||||
"MULTIDRIVEN", "MULTITOP",
|
||||
"PINMISSING", "PINNOCONNECT", "PINCONNECTEMPTY", "PROCASSWIRE",
|
||||
|
121
src/V3File.cpp
121
src/V3File.cpp
@ -917,3 +917,124 @@ void V3OutFile::putsForceIncs() {
|
||||
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); }
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
// V3OutCFile: A class for abstracting out SystemC/C++ details
|
||||
|
||||
class V3OutCFile : public V3OutFile {
|
||||
int m_private;
|
||||
public:
|
||||
@ -250,4 +247,21 @@ public:
|
||||
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
|
||||
|
@ -112,6 +112,7 @@ void V3LinkLevel::wrapTop(AstNetlist* rootp) {
|
||||
newmodp->addNext(oldmodp);
|
||||
newmodp->level(1);
|
||||
newmodp->modPublic(true);
|
||||
newmodp->protect(false);
|
||||
rootp->addModulep(newmodp);
|
||||
|
||||
// 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);
|
||||
varp->name(name);
|
||||
varp->protect(false);
|
||||
newmodp->addStmtp(varp);
|
||||
varp->sigPublic(true); // User needs to be able to get to it...
|
||||
if (oldvarp->isIO()) {
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "V3Global.h"
|
||||
#include "V3Name.h"
|
||||
#include "V3Ast.h"
|
||||
#include "V3File.h"
|
||||
#include "V3LanguageWords.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
@ -534,6 +534,25 @@ void V3Options::notify() {
|
||||
&& !cdc()) {
|
||||
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;
|
||||
}
|
||||
|
||||
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() {
|
||||
#if !(defined(VL_CPPCHECK) || defined(__clang_analyzer__))
|
||||
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-nondeterminism", flag/*ref*/)){ m_debugNondeterminism = flag; }
|
||||
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 (!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
|
||||
@ -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, "-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, "-protect-ids", flag/*ref*/)) { m_protectIds = 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 (!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];
|
||||
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, "-threads") && (i+1)<argc) { // Undocumented until functional
|
||||
shift; m_threads = atoi(argv[i]);
|
||||
@ -1290,6 +1324,7 @@ V3Options::V3Options() {
|
||||
m_debugLeak = true;
|
||||
m_debugNondeterminism = false;
|
||||
m_debugPartition = false;
|
||||
m_debugProtect = false;
|
||||
m_debugSelfTest = false;
|
||||
m_decoration = true;
|
||||
m_dpiHdrOnly = false;
|
||||
@ -1309,6 +1344,7 @@ V3Options::V3Options() {
|
||||
m_ppComments = false;
|
||||
m_profCFuncs = false;
|
||||
m_profThreads = false;
|
||||
m_protectIds = false;
|
||||
m_preprocOnly = false;
|
||||
m_preprocNoLine = false;
|
||||
m_public = false;
|
||||
|
@ -118,6 +118,7 @@ class V3Options {
|
||||
bool m_debugLeak; // main switch: --debug-leak
|
||||
bool m_debugNondeterminism; // main switch: --debug-nondeterminism
|
||||
bool m_debugPartition; // main switch: --debug-partition
|
||||
bool m_debugProtect; // main switch: --debug-protect
|
||||
bool m_debugSelfTest; // main switch: --debug-self-test
|
||||
bool m_decoration; // main switch: --decoration
|
||||
bool m_dpiHdrOnly; // main switch: --dpi-hdr-only
|
||||
@ -134,6 +135,7 @@ class V3Options {
|
||||
bool m_ppComments; // main switch: --pp-comments
|
||||
bool m_profCFuncs; // main switch: --prof-cfuncs
|
||||
bool m_profThreads; // main switch: --prof-threads
|
||||
bool m_protectIds; // main switch: --protect-ids
|
||||
bool m_public; // main switch: --public
|
||||
bool m_publicFlatRW; // main switch: --public-flat-rw
|
||||
bool m_relativeCFuncs; // main switch: --relative-cfuncs
|
||||
@ -188,6 +190,7 @@ class V3Options {
|
||||
string m_modPrefix; // main switch: --mod-prefix
|
||||
string m_pipeFilter; // main switch: --pipe-filter
|
||||
string m_prefix; // main switch: --prefix
|
||||
string m_protectKey; // main switch: --protect-key
|
||||
string m_topModule; // main switch: --top-module
|
||||
string m_unusedRegexp; // main switch: --unused-regexp
|
||||
string m_xAssign; // main switch: --x-assign
|
||||
@ -288,6 +291,7 @@ class V3Options {
|
||||
bool debugLeak() const { return m_debugLeak; }
|
||||
bool debugNondeterminism() const { return m_debugNondeterminism; }
|
||||
bool debugPartition() const { return m_debugPartition; }
|
||||
bool debugProtect() const { return m_debugProtect; }
|
||||
bool debugSelfTest() const { return m_debugSelfTest; }
|
||||
bool decoration() const { return m_decoration; }
|
||||
bool dpiHdrOnly() const { return m_dpiHdrOnly; }
|
||||
@ -310,6 +314,7 @@ class V3Options {
|
||||
bool ppComments() const { return m_ppComments; }
|
||||
bool profCFuncs() const { return m_profCFuncs; }
|
||||
bool profThreads() const { return m_profThreads; }
|
||||
bool protectIds() const { return m_protectIds; }
|
||||
bool allPublic() const { return m_public; }
|
||||
bool publicFlatRW() const { return m_publicFlatRW; }
|
||||
bool lintOnly() const { return m_lintOnly; }
|
||||
@ -351,6 +356,8 @@ class V3Options {
|
||||
string modPrefix() const { return m_modPrefix; }
|
||||
string pipeFilter() const { return m_pipeFilter; }
|
||||
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 unusedRegexp() const { return m_unusedRegexp; }
|
||||
string xAssign() const { return m_xAssign; }
|
||||
|
13
src/V3Os.cpp
13
src/V3Os.cpp
@ -31,6 +31,7 @@
|
||||
#include <cstdarg>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <memory>
|
||||
#include <sys/stat.h>
|
||||
@ -218,6 +219,18 @@ vluint64_t V3Os::rand64(vluint64_t* statep) {
|
||||
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)
|
||||
|
||||
|
@ -56,6 +56,7 @@ public:
|
||||
|
||||
// METHODS (random)
|
||||
static vluint64_t rand64(vluint64_t* statep);
|
||||
static string trueRandom(size_t size);
|
||||
|
||||
// METHODS (performance)
|
||||
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->isStatic(true);
|
||||
dpip->dpiExportWrapper(true);
|
||||
dpip->protect(false);
|
||||
dpip->cname(nodep->cname());
|
||||
// Add DPI reference to top, since it's a global function
|
||||
m_topScopep->scopep()->addActivep(dpip);
|
||||
@ -733,7 +734,8 @@ private:
|
||||
// If the find fails, it will throw an error
|
||||
stmt += "const VerilatedScope* __Vscopep = Verilated::dpiScope();\n";
|
||||
// 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
|
||||
// If __Vcb is null the exportFind function throws and error
|
||||
dpip->addStmtsp(new AstCStmt(nodep->fileline(), stmt));
|
||||
@ -741,7 +743,8 @@ private:
|
||||
|
||||
// Convert input/inout DPI arguments to Internal types
|
||||
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;
|
||||
for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp=stmtp->nextp()) {
|
||||
if (AstVar* portp = VN_CAST(stmtp, Var)) {
|
||||
@ -755,6 +758,9 @@ private:
|
||||
args = "";
|
||||
}
|
||||
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,
|
||||
portp->isWritable());
|
||||
argnodesp = argnodesp->addNextNull(refp);
|
||||
@ -775,6 +781,8 @@ private:
|
||||
args="";
|
||||
}
|
||||
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());
|
||||
argnodesp = argnodesp->addNextNull(refp);
|
||||
}
|
||||
@ -826,6 +834,7 @@ private:
|
||||
dpip->entryPoint(false);
|
||||
dpip->funcPublic(true);
|
||||
dpip->isStatic(false);
|
||||
dpip->protect(false);
|
||||
dpip->pure(nodep->pure());
|
||||
dpip->dpiImport(true);
|
||||
// Add DPI reference to top, since it's a global function
|
||||
@ -952,6 +961,7 @@ private:
|
||||
// Convert output/inout arguments back to internal type
|
||||
for (AstNode* stmtp = cfuncp->argsp(); stmtp; stmtp=stmtp->nextp()) {
|
||||
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())
|
||||
&& !portp->isDpiOpenArray()) {
|
||||
AstVarScope* portvscp = VN_CAST(portp->user2p(), VarScope); // Remembered when we created it earlier
|
||||
@ -984,6 +994,7 @@ private:
|
||||
rtnvarp = portp;
|
||||
rtnvarp->funcLocal(true);
|
||||
rtnvarp->name(rtnvarp->name()+"__Vfuncrtn"); // Avoid conflict with DPI function name
|
||||
if (nodep->dpiImport() || nodep->dpiExport()) rtnvarp->protect(false);
|
||||
}
|
||||
|
||||
if (nodep->dpiImport()) {
|
||||
@ -1245,6 +1256,11 @@ private:
|
||||
if (nodep->dpiImport()) modes++;
|
||||
if (nodep->dpiExport()) 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: "
|
||||
<<nodep->prettyNameQ());
|
||||
|
||||
|
@ -643,6 +643,9 @@ int main(int argc, char** argv, char** env) {
|
||||
V3File::writeTimes(v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()
|
||||
+"__verFiles.dat", argString);
|
||||
}
|
||||
if (v3Global.opt.protectIds()) {
|
||||
VIdProtect::writeMapFile(v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"__idmap.xml");
|
||||
}
|
||||
|
||||
// Final writing shouldn't throw warnings, but...
|
||||
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.
|
||||
int main() {
|
||||
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
|
||||
// executed.
|
||||
|
52
test_regress/t/t_protect_ids.pl
Executable file
52
test_regress/t/t_protect_ids.pl
Executable file
@ -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;
|
61
test_regress/t/t_protect_ids.v
Normal file
61
test_regress/t/t_protect_ids.v
Normal file
@ -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
|
8
test_regress/t/t_protect_ids_bad.out
Normal file
8
test_regress/t/t_protect_ids_bad.out
Normal file
@ -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
|
23
test_regress/t/t_protect_ids_bad.pl
Executable file
23
test_regress/t/t_protect_ids_bad.pl
Executable file
@ -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;
|
7
test_regress/t/t_protect_ids_bad.v
Normal file
7
test_regress/t/t_protect_ids_bad.v
Normal file
@ -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
|
51
test_regress/t/t_protect_ids_c.cpp
Normal file
51
test_regress/t/t_protect_ids_c.cpp
Normal file
@ -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;
|
||||
}
|
42
test_regress/t/t_protect_ids_key.out
Normal file
42
test_regress/t/t_protect_ids_key.out
Normal file
@ -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>
|
27
test_regress/t/t_protect_ids_key.pl
Executable file
27
test_regress/t/t_protect_ids_key.pl
Executable file
@ -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
Block a user