Support DPI imports and exports with double underscores.

This commit is contained in:
Wilson Snyder 2024-09-22 22:06:39 -04:00
parent d288488b7f
commit 706679e6b1
8 changed files with 40 additions and 10 deletions

View File

@ -27,6 +27,7 @@ Verilator 5.029 devel
* Support named event locals (#5422). [Krzysztof Bieganski, Antmicro Ltd.]
* Support basic dist constraints (#5431). [Arkadiusz Kozdra, Antmicro Ltd.]
* Support inside array constraints (#5448). [Arkadiusz Kozdra, Antmicro Ltd.]
* Support DPI imports and exports with double underscores.
* Add error on instances without parenthesis.
* Add partial coverage symbol and branch data in lcov info files (#5388). [Andrew Nolte]
* Add method to check if there are VPI callbacks of the given type (#5399). [Kaleb Barrett]

View File

@ -723,6 +723,14 @@ class TaskVisitor final : public VNVisitor {
return dpiproto;
}
static void checkLegalCIdentifier(AstNode* nodep, const string& name) {
if (name.end() != std::find_if(name.begin(), name.end(), [](char c) {
return !std::isalnum(c) && c != '_';
})) {
nodep->v3error("DPI function has illegal characters in C identifier name: " << name);
}
}
static AstNode* createDpiTemp(AstVar* portp, const string& suffix) {
const string stmt = portp->dpiTmpVarType(portp->name() + suffix) + ";\n";
return new AstCStmt{portp->fileline(), stmt};
@ -822,8 +830,11 @@ class TaskVisitor final : public VNVisitor {
}
AstCFunc* makeDpiExportDispatcher(AstNodeFTask* nodep, AstVar* rtnvarp) {
// Verilog name has __ conversion and other tricks, to match DPI C code, back that out
const string name = AstNode::prettyName(nodep->cname());
checkLegalCIdentifier(nodep, name);
const char* const tmpSuffixp = V3Task::dpiTemporaryVarSuffix();
AstCFunc* const funcp = new AstCFunc{nodep->fileline(), nodep->cname(), m_scopep,
AstCFunc* const funcp = new AstCFunc{nodep->fileline(), name, m_scopep,
(rtnvarp ? rtnvarp->dpiArgType(true, true) : "")};
funcp->dpiExportDispatcher(true);
funcp->dpiContext(nodep->dpiContext());
@ -831,7 +842,7 @@ class TaskVisitor final : public VNVisitor {
funcp->entryPoint(true);
funcp->isStatic(true);
funcp->protect(false);
funcp->cname(nodep->cname());
funcp->cname(name);
// Add DPI Export to top, since it's a global function
m_topScopep->scopep()->addBlocksp(funcp);
@ -949,15 +960,14 @@ class TaskVisitor final : public VNVisitor {
}
AstCFunc* makeDpiImportPrototype(AstNodeFTask* nodep, AstVar* rtnvarp) {
if (nodep->cname() != AstNode::prettyName(nodep->cname())) {
nodep->v3error("DPI function has illegal characters in C identifier name: "
<< AstNode::prettyNameQ(nodep->cname()));
}
// Verilog name has __ conversion and other tricks, to match DPI C code, back that out
const string name = AstNode::prettyName(nodep->cname());
checkLegalCIdentifier(nodep, name);
// Tasks (but not void functions) return a boolean 'int' indicating disabled
const string rtnType = rtnvarp ? rtnvarp->dpiArgType(true, true)
: nodep->dpiTask() ? "int"
: "";
AstCFunc* const funcp = new AstCFunc{nodep->fileline(), nodep->cname(), m_scopep, rtnType};
AstCFunc* const funcp = new AstCFunc{nodep->fileline(), name, m_scopep, rtnType};
funcp->dpiContext(nodep->dpiContext());
funcp->dpiImportPrototype(true);
funcp->dontCombine(true);

View File

@ -66,6 +66,9 @@ module t;
`endif
task dpix_t_time(input time i, output time o); o = ~i; endtask
export "DPI-C" function dpix__under___score;
function int dpix__under___score(input int i); return i + 1; endfunction
int lineno;
initial begin

View File

@ -59,6 +59,8 @@ extern void dpix_t_reg15(const svLogicVecVal* i, svLogicVecVal* o);
extern void dpix_t_reg95(const svLogicVecVal* i, svLogicVecVal* o);
extern void dpix_t_integer(const svLogicVecVal* i, svLogicVecVal* o);
extern void dpix_t_time(const svLogicVecVal* i, svLogicVecVal* o);
extern int dpix__under___score(int i);
}
#endif
@ -225,6 +227,8 @@ int dpix_run_tests() {
}
#endif
CHECK_RESULT(int, dpix__under___score(77), 78);
if (int bad = check_sub("top.t.a", 1)) return bad;
if (int bad = check_sub("top.t.b", 2)) return bad;

View File

@ -99,6 +99,9 @@ module t (/*AUTOARG*/
import "DPI-C" dpii_fa_bit = function int oth_f_int1(input int i);
import "DPI-C" dpii_fa_bit = function int oth_f_int2(input int i);
// Check Verilator doesn't convert double underscores
import "DPI-C" pure function int dpii__under___score(input int i);
bit i_b, o_b;
bit [7:0] i_b8;
bit [8:0] i_b9;
@ -256,6 +259,8 @@ module t (/*AUTOARG*/
if (oth_f_int1(32'd123) !== ~32'd123) $stop;
if (oth_f_int2(32'd124) !== ~32'd124) $stop;
if (dpii__under___score(32'd60) != 32'd61) $stop;
$write("*-* All Finished *-*\n");
$finish;
end

View File

@ -183,6 +183,8 @@ void dpii_v_bit96(const svBitVecVal* i, svBitVecVal* o) {
int dpii_f_strlen(const char* i) { return strlen(i); }
int dpii__under___score(int i) { return i + 1; }
//======================================================================
void dpii_f_void() {}

View File

@ -1,4 +1,7 @@
%Error: t/t_dpi_name_bad.v:12:32: DPI function has illegal characters in C identifier name: 'badly.named'
12 | import "DPI-C" function int \badly.named (int i);
%Error: t/t_dpi_name_bad.v:11:32: DPI function has illegal characters in C identifier name: badly.named
11 | import "DPI-C" function int \badly.named (int i);
| ^~~~~~~~~~~~
%Error: t/t_dpi_name_bad.v:14:17: DPI function has illegal characters in C identifier name: badly.expt
14 | function int \badly.expt ; return 0; endfunction
| ^~~~~~~~~~~
%Error: Exiting due to

View File

@ -8,9 +8,11 @@
module t ();
// Can't handle logic (yet?)
import "DPI-C" function int \badly.named (int i);
export "DPI-C" function \badly.expt ;
function int \badly.expt ; return 0; endfunction
initial begin
$stop;
end