DPI import: Allow system calls to call imports
This commit is contained in:
parent
a40fae04ce
commit
5a9309de78
|
|
@ -1148,6 +1148,14 @@ command line, or the link), you'd then:
|
||||||
#include "Vour__Dpi.h"
|
#include "Vour__Dpi.h"
|
||||||
int add (int a, int b) { return a+b; }
|
int add (int a, int b) { return a+b; }
|
||||||
|
|
||||||
|
Verilator also extends the DPI format to allow using the same scheme to
|
||||||
|
efficiently add system functions. Simply use a dollar-sign prefixed system
|
||||||
|
function name for the import, but note it must be escaped.
|
||||||
|
|
||||||
|
export "DPI-C" function integer \$myRand;
|
||||||
|
|
||||||
|
initial $display("myRand=%d", $myRand());
|
||||||
|
|
||||||
=head1 CROSS COMPILATION
|
=head1 CROSS COMPILATION
|
||||||
|
|
||||||
Verilator supports cross-compiling Verilated code. This is generally used
|
Verilator supports cross-compiling Verilated code. This is generally used
|
||||||
|
|
|
||||||
14
src/V3Ast.h
14
src/V3Ast.h
|
|
@ -206,6 +206,8 @@ public:
|
||||||
enum en {
|
enum en {
|
||||||
BIT, BYTE, CHANDLE, INT, INTEGER, LOGIC, LONGINT,
|
BIT, BYTE, CHANDLE, INT, INTEGER, LOGIC, LONGINT,
|
||||||
REAL, REALTIME, SHORTINT, SHORTREAL, TIME,
|
REAL, REALTIME, SHORTINT, SHORTREAL, TIME,
|
||||||
|
// Closer to a class type, but limited usage
|
||||||
|
STRING,
|
||||||
// Internal types
|
// Internal types
|
||||||
LOGIC_IMPLICIT
|
LOGIC_IMPLICIT
|
||||||
};
|
};
|
||||||
|
|
@ -214,6 +216,7 @@ public:
|
||||||
static const char* names[] = {
|
static const char* names[] = {
|
||||||
"bit", "byte", "chandle", "int", "integer", "logic", "longint",
|
"bit", "byte", "chandle", "int", "integer", "logic", "longint",
|
||||||
"real", "realtime", "shortint", "shortreal", "time",
|
"real", "realtime", "shortint", "shortreal", "time",
|
||||||
|
"string",
|
||||||
"LOGIC_IMPLICIT"
|
"LOGIC_IMPLICIT"
|
||||||
};
|
};
|
||||||
return names[m_e];
|
return names[m_e];
|
||||||
|
|
@ -222,6 +225,7 @@ public:
|
||||||
static const char* names[] = {
|
static const char* names[] = {
|
||||||
"unsigned char", "char", "void*", "int", "int", "svLogic", "long long",
|
"unsigned char", "char", "void*", "int", "int", "svLogic", "long long",
|
||||||
"double", "double", "short int", "float", "long long",
|
"double", "double", "short int", "float", "long long",
|
||||||
|
"char*",
|
||||||
""
|
""
|
||||||
};
|
};
|
||||||
return names[m_e];
|
return names[m_e];
|
||||||
|
|
@ -241,6 +245,7 @@ public:
|
||||||
case LONGINT: return 64;
|
case LONGINT: return 64;
|
||||||
case SHORTINT: return 16;
|
case SHORTINT: return 16;
|
||||||
case TIME: return 64;
|
case TIME: return 64;
|
||||||
|
case STRING: return 64; // Just the pointer, for today
|
||||||
default: return 0;
|
default: return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -251,7 +256,8 @@ public:
|
||||||
return m_e==INTEGER || m_e==LOGIC || m_e==LOGIC_IMPLICIT;
|
return m_e==INTEGER || m_e==LOGIC || m_e==LOGIC_IMPLICIT;
|
||||||
}
|
}
|
||||||
int isZeroInit() const { // Otherwise initializes to X
|
int isZeroInit() const { // Otherwise initializes to X
|
||||||
return m_e==BIT || m_e==BYTE || m_e==CHANDLE || m_e==INT || m_e==LONGINT || m_e==SHORTINT;
|
return (m_e==BIT || m_e==BYTE || m_e==CHANDLE || m_e==INT || m_e==LONGINT || m_e==SHORTINT
|
||||||
|
|| m_e==STRING);
|
||||||
}
|
}
|
||||||
int isSloppy() const { // Don't be as anal about width warnings
|
int isSloppy() const { // Don't be as anal about width warnings
|
||||||
return !(m_e==LOGIC || m_e==BIT);
|
return !(m_e==LOGIC || m_e==BIT);
|
||||||
|
|
@ -1250,7 +1256,6 @@ private:
|
||||||
bool m_dpiTask:1; // DPI import task (vs. void function)
|
bool m_dpiTask:1; // DPI import task (vs. void function)
|
||||||
bool m_pure:1; // DPI import pure
|
bool m_pure:1; // DPI import pure
|
||||||
public:
|
public:
|
||||||
// Node that simply puts name into the output stream
|
|
||||||
AstNodeFTask(FileLine* fileline, const string& name, AstNode* stmtsp)
|
AstNodeFTask(FileLine* fileline, const string& name, AstNode* stmtsp)
|
||||||
: AstNode(fileline)
|
: AstNode(fileline)
|
||||||
, m_name(name), m_taskPublic(false), m_didSigning(false)
|
, m_name(name), m_taskPublic(false), m_didSigning(false)
|
||||||
|
|
@ -1306,6 +1311,11 @@ public:
|
||||||
, m_taskp(NULL), m_packagep(NULL) {
|
, m_taskp(NULL), m_packagep(NULL) {
|
||||||
setOp1p(namep); addNOp2p(pinsp);
|
setOp1p(namep); addNOp2p(pinsp);
|
||||||
}
|
}
|
||||||
|
AstNodeFTaskRef(FileLine* fl, const string& name, AstNode* pinsp)
|
||||||
|
:AstNode(fl)
|
||||||
|
, m_taskp(NULL), m_name(name), m_packagep(NULL) {
|
||||||
|
addNOp2p(pinsp);
|
||||||
|
}
|
||||||
ASTNODE_BASE_FUNCS(NodeFTaskRef)
|
ASTNODE_BASE_FUNCS(NodeFTaskRef)
|
||||||
virtual bool broken() const { return m_taskp && !m_taskp->brokeExists(); }
|
virtual bool broken() const { return m_taskp && !m_taskp->brokeExists(); }
|
||||||
virtual void cloneRelink() { if (m_taskp && m_taskp->clonep()) {
|
virtual void cloneRelink() { if (m_taskp && m_taskp->clonep()) {
|
||||||
|
|
|
||||||
|
|
@ -973,6 +973,8 @@ struct AstTaskRef : public AstNodeFTaskRef {
|
||||||
// A reference to a task
|
// A reference to a task
|
||||||
AstTaskRef(FileLine* fl, AstParseRef* namep, AstNode* pinsp)
|
AstTaskRef(FileLine* fl, AstParseRef* namep, AstNode* pinsp)
|
||||||
:AstNodeFTaskRef(fl, namep, pinsp) {}
|
:AstNodeFTaskRef(fl, namep, pinsp) {}
|
||||||
|
AstTaskRef(FileLine* fl, const string& name, AstNode* pinsp)
|
||||||
|
:AstNodeFTaskRef(fl, name, pinsp) {}
|
||||||
ASTNODE_NODE_FUNCS(TaskRef, TASKREF)
|
ASTNODE_NODE_FUNCS(TaskRef, TASKREF)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -980,6 +982,8 @@ struct AstFuncRef : public AstNodeFTaskRef {
|
||||||
// A reference to a function
|
// A reference to a function
|
||||||
AstFuncRef(FileLine* fl, AstParseRef* namep, AstNode* pinsp)
|
AstFuncRef(FileLine* fl, AstParseRef* namep, AstNode* pinsp)
|
||||||
:AstNodeFTaskRef(fl, namep, pinsp) {}
|
:AstNodeFTaskRef(fl, namep, pinsp) {}
|
||||||
|
AstFuncRef(FileLine* fl, const string& name, AstNode* pinsp)
|
||||||
|
:AstNodeFTaskRef(fl, name, pinsp) {}
|
||||||
ASTNODE_NODE_FUNCS(FuncRef, FUNCREF)
|
ASTNODE_NODE_FUNCS(FuncRef, FUNCREF)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -439,6 +439,14 @@ private:
|
||||||
}
|
}
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstBasicDType* nodep, AstNUser*) {
|
||||||
|
if (m_idState==ID_RESOLVE && nodep->keyword()==AstBasicDTypeKwd::STRING) {
|
||||||
|
if (!(m_ftaskp && m_ftaskp->dpiImport() && 0/*UNIMP*/)) {
|
||||||
|
nodep->v3error("Unsupported: SystemVerilog 'string' anywhere but DPI import __format");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
}
|
||||||
|
|
||||||
virtual void visit(AstCell* nodep, AstNUser*) {
|
virtual void visit(AstCell* nodep, AstNUser*) {
|
||||||
// Cell: Resolve its filename. If necessary, parse it.
|
// Cell: Resolve its filename. If necessary, parse it.
|
||||||
|
|
|
||||||
|
|
@ -128,8 +128,10 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void reinsert(AstNode* nodep, V3SymTable* parentp=NULL) {
|
void reinsert(AstNode* nodep, V3SymTable* parentp=NULL) {
|
||||||
|
reinsert(nodep, parentp, nodep->name());
|
||||||
|
}
|
||||||
|
void reinsert(AstNode* nodep, V3SymTable* parentp, string name) {
|
||||||
if (!parentp) parentp = symCurrentp();
|
if (!parentp) parentp = symCurrentp();
|
||||||
string name = nodep->name();
|
|
||||||
if (name == "") { // New name with space in name so can't collide with users
|
if (name == "") { // New name with space in name so can't collide with users
|
||||||
name = string(" anon") + nodep->type().ascii() + cvtToStr(++s_anonNum);
|
name = string(" anon") + nodep->type().ascii() + cvtToStr(++s_anonNum);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,8 +48,8 @@ extern void yyerrorf(const char* format, ...);
|
||||||
#define FL { yylval.fl = CRELINE(); }
|
#define FL { yylval.fl = CRELINE(); }
|
||||||
|
|
||||||
#define RETURN_BBOX_SYS_OR_MSG(msg,yytext) { \
|
#define RETURN_BBOX_SYS_OR_MSG(msg,yytext) { \
|
||||||
if (v3Global.opt.bboxSys()) return yD_aIGNORE; \
|
if (!v3Global.opt.bboxSys()) yyerrorf(msg,yytext); \
|
||||||
else yyerrorf(msg,yytext); }
|
return yaD_IGNORE; }
|
||||||
|
|
||||||
void V3ParseImp::ppline (const char* textp) {
|
void V3ParseImp::ppline (const char* textp) {
|
||||||
// Handle `line directive
|
// Handle `line directive
|
||||||
|
|
@ -388,6 +388,7 @@ escid \\[^ \t\f\r\n]+
|
||||||
"pure" { FL; return yPURE; }
|
"pure" { FL; return yPURE; }
|
||||||
"shortint" { FL; return ySHORTINT; }
|
"shortint" { FL; return ySHORTINT; }
|
||||||
"static" { FL; return ySTATIC; }
|
"static" { FL; return ySTATIC; }
|
||||||
|
"string" { FL; return ySTRING; }
|
||||||
"timeprecision" { FL; return yTIMEPRECISION; }
|
"timeprecision" { FL; return yTIMEPRECISION; }
|
||||||
"timeunit" { FL; return yTIMEUNIT; }
|
"timeunit" { FL; return yTIMEUNIT; }
|
||||||
"typedef" { FL; return yTYPEDEF; }
|
"typedef" { FL; return yTYPEDEF; }
|
||||||
|
|
@ -443,7 +444,6 @@ escid \\[^ \t\f\r\n]+
|
||||||
"return" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
"return" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||||
"shortreal" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
"shortreal" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||||
"solve" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
"solve" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||||
"string" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
|
||||||
"struct" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
"struct" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||||
"super" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
"super" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||||
"tagged" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
"tagged" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented: %s",yytext); }
|
||||||
|
|
@ -473,7 +473,13 @@ escid \\[^ \t\f\r\n]+
|
||||||
|
|
||||||
/* Default PLI rule */
|
/* Default PLI rule */
|
||||||
<V95,V01,V05,S05,PSL>{
|
<V95,V01,V05,S05,PSL>{
|
||||||
"$"[a-zA-Z_$][a-zA-Z0-9_$]* { FL; RETURN_BBOX_SYS_OR_MSG("Unsupported or unknown PLI call: %s",yytext); }
|
"$"[a-zA-Z_$][a-zA-Z0-9_$]* { string str (yytext,yyleng);
|
||||||
|
yylval.strp = PARSEP->newString(AstNode::encodeName(str));
|
||||||
|
// Lookup unencoded name including the $, to avoid hitting normal signals
|
||||||
|
if (SYMP->symCurrentp()->findIdUpward(str)) {
|
||||||
|
FL; return yaD_DPI;
|
||||||
|
} else { FL; RETURN_BBOX_SYS_OR_MSG("Unsupported or unknown PLI call: %s",yytext); }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
|
||||||
|
|
@ -132,7 +132,9 @@ public:
|
||||||
}
|
}
|
||||||
string deQuote(FileLine* fileline, string text);
|
string deQuote(FileLine* fileline, string text);
|
||||||
void checkDpiVer(FileLine* fileline, const string& str) {
|
void checkDpiVer(FileLine* fileline, const string& str) {
|
||||||
if (str != "DPI-C") { fileline->v3error("Unsupported DPI type '"<<str<<"': Use 'DPI-C'"); }
|
if (str != "DPI-C" && !v3Global.opt.bboxSys()) {
|
||||||
|
fileline->v3error("Unsupported DPI type '"<<str<<"': Use 'DPI-C'");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -203,6 +205,9 @@ class AstSenTree;
|
||||||
%token<strp> yaSCCTOR "`systemc_implementation BLOCK"
|
%token<strp> yaSCCTOR "`systemc_implementation BLOCK"
|
||||||
%token<strp> yaSCDTOR "`systemc_imp_header BLOCK"
|
%token<strp> yaSCDTOR "`systemc_imp_header BLOCK"
|
||||||
|
|
||||||
|
%token<strp> yaD_IGNORE "${ignored-bbox-sys}"
|
||||||
|
%token<strp> yaD_DPI "${dpi-sys}"
|
||||||
|
|
||||||
// <fl> is the fileline, abbreviated to shorten "$<fl>1" references
|
// <fl> is the fileline, abbreviated to shorten "$<fl>1" references
|
||||||
%token<fl> '!'
|
%token<fl> '!'
|
||||||
%token<fl> '#'
|
%token<fl> '#'
|
||||||
|
|
@ -318,6 +323,7 @@ class AstSenTree;
|
||||||
%token<fl> ySPECIFY "specify"
|
%token<fl> ySPECIFY "specify"
|
||||||
%token<fl> ySPECPARAM "specparam"
|
%token<fl> ySPECPARAM "specparam"
|
||||||
%token<fl> ySTATIC "static"
|
%token<fl> ySTATIC "static"
|
||||||
|
%token<fl> ySTRING "string"
|
||||||
%token<fl> ySUPPLY0 "supply0"
|
%token<fl> ySUPPLY0 "supply0"
|
||||||
%token<fl> ySUPPLY1 "supply1"
|
%token<fl> ySUPPLY1 "supply1"
|
||||||
%token<fl> yTABLE "table"
|
%token<fl> yTABLE "table"
|
||||||
|
|
@ -375,7 +381,6 @@ class AstSenTree;
|
||||||
%token<fl> yD_VALUEPLUSARGS "$value$plusargs"
|
%token<fl> yD_VALUEPLUSARGS "$value$plusargs"
|
||||||
%token<fl> yD_WARNING "$warning"
|
%token<fl> yD_WARNING "$warning"
|
||||||
%token<fl> yD_WRITE "$write"
|
%token<fl> yD_WRITE "$write"
|
||||||
%token<fl> yD_aIGNORE "${ignored-bbox-sys}"
|
|
||||||
|
|
||||||
%token<fl> yPSL "psl"
|
%token<fl> yPSL "psl"
|
||||||
%token<fl> yPSL_ASSERT "PSL assert"
|
%token<fl> yPSL_ASSERT "PSL assert"
|
||||||
|
|
@ -1053,7 +1058,7 @@ data_typeNoRef<dtypep>: // ==IEEE: data_type, excluding class_type etc referenc
|
||||||
//UNSUP yUNION taggedE packedSigningE '{' struct_union_memberList '}' packed_dimensionListE
|
//UNSUP yUNION taggedE packedSigningE '{' struct_union_memberList '}' packed_dimensionListE
|
||||||
//UNSUP { UNSUP }
|
//UNSUP { UNSUP }
|
||||||
//UNSUP enumDecl { UNSUP }
|
//UNSUP enumDecl { UNSUP }
|
||||||
//UNSUP ySTRING { UNSUP }
|
| ySTRING { $$ = new AstBasicDType($1,AstBasicDTypeKwd::STRING); }
|
||||||
| yCHANDLE { $$ = new AstBasicDType($1,AstBasicDTypeKwd::CHANDLE); }
|
| yCHANDLE { $$ = new AstBasicDType($1,AstBasicDTypeKwd::CHANDLE); }
|
||||||
//UNSUP yEVENT { UNSUP }
|
//UNSUP yEVENT { UNSUP }
|
||||||
//UNSUP yVIRTUAL__INTERFACE yINTERFACE id/*interface*/ { UNSUP }
|
//UNSUP yVIRTUAL__INTERFACE yINTERFACE id/*interface*/ { UNSUP }
|
||||||
|
|
@ -1922,8 +1927,11 @@ function_subroutine_callNoMethod<nodep>: // IEEE: function_subroutine_call (as f
|
||||||
|
|
||||||
system_t_call<nodep>: // IEEE: system_tf_call (as task)
|
system_t_call<nodep>: // IEEE: system_tf_call (as task)
|
||||||
//
|
//
|
||||||
yD_aIGNORE '(' ')' { $$ = NULL; }
|
yaD_IGNORE '(' ')' { $$ = NULL; }
|
||||||
| yD_aIGNORE '(' exprList ')' { $$ = NULL; }
|
| yaD_IGNORE '(' exprList ')' { $$ = NULL; }
|
||||||
|
//
|
||||||
|
| yaD_DPI '(' ')' { $$ = new AstTaskRef($2,*$1,NULL); }
|
||||||
|
| yaD_DPI '(' exprList ')' { $$ = new AstTaskRef($2,*$1,$3); }
|
||||||
//
|
//
|
||||||
| yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCStmt($1,$3)); }
|
| yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCStmt($1,$3)); }
|
||||||
| yD_FCLOSE '(' idClassSel ')' { $$ = new AstFClose($1, $3); }
|
| yD_FCLOSE '(' idClassSel ')' { $$ = new AstFClose($1, $3); }
|
||||||
|
|
@ -1962,8 +1970,11 @@ system_t_call<nodep>: // IEEE: system_tf_call (as task)
|
||||||
;
|
;
|
||||||
|
|
||||||
system_f_call<nodep>: // IEEE: system_tf_call (as func)
|
system_f_call<nodep>: // IEEE: system_tf_call (as func)
|
||||||
yD_aIGNORE '(' ')' { $$ = new AstConst($1,V3Number($1,"'b0")); } // Unsized 0
|
yaD_IGNORE '(' ')' { $$ = new AstConst($2,V3Number($2,"'b0")); } // Unsized 0
|
||||||
| yD_aIGNORE '(' exprList ')' { $$ = new AstConst($1,V3Number($1,"'b0")); } // Unsized 0
|
| yaD_IGNORE '(' exprList ')' { $$ = new AstConst($2,V3Number($2,"'b0")); } // Unsized 0
|
||||||
|
//
|
||||||
|
| yaD_DPI '(' ')' { $$ = new AstFuncRef($2,*$1,NULL); }
|
||||||
|
| yaD_DPI '(' exprList ')' { $$ = new AstFuncRef($2,*$1,$3); }
|
||||||
//
|
//
|
||||||
| yD_BITS '(' expr ')' { $$ = new AstAttrOf($1,AstAttrType::BITS,$3); }
|
| yD_BITS '(' expr ')' { $$ = new AstAttrOf($1,AstAttrType::BITS,$3); }
|
||||||
| yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCFunc($1,$3)); }
|
| yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCFunc($1,$3)); }
|
||||||
|
|
@ -2154,10 +2165,14 @@ parenE:
|
||||||
dpi_import_export<nodep>: // ==IEEE: dpi_import_export
|
dpi_import_export<nodep>: // ==IEEE: dpi_import_export
|
||||||
yIMPORT yaSTRING dpi_tf_import_propertyE dpi_importLabelE function_prototype ';'
|
yIMPORT yaSTRING dpi_tf_import_propertyE dpi_importLabelE function_prototype ';'
|
||||||
{ $$ = $5; if (*$4!="") $5->cname(*$4); $5->dpiContext($3==iprop_CONTEXT); $5->pure($3==iprop_PURE);
|
{ $$ = $5; if (*$4!="") $5->cname(*$4); $5->dpiContext($3==iprop_CONTEXT); $5->pure($3==iprop_PURE);
|
||||||
$5->dpiImport(true); GRAMMARP->checkDpiVer($1,*$2); v3Global.dpi(true); }
|
$5->dpiImport(true); GRAMMARP->checkDpiVer($1,*$2); v3Global.dpi(true);
|
||||||
|
if ($$->prettyName()[0]=='$') SYMP->reinsert($$,NULL,$$->prettyName()); // For $SysTF overriding
|
||||||
|
SYMP->reinsert($$); }
|
||||||
| yIMPORT yaSTRING dpi_tf_import_propertyE dpi_importLabelE task_prototype ';'
|
| yIMPORT yaSTRING dpi_tf_import_propertyE dpi_importLabelE task_prototype ';'
|
||||||
{ $$ = $5; if (*$4!="") $5->cname(*$4); $5->dpiContext($3==iprop_CONTEXT); $5->pure($3==iprop_PURE);
|
{ $$ = $5; if (*$4!="") $5->cname(*$4); $5->dpiContext($3==iprop_CONTEXT); $5->pure($3==iprop_PURE);
|
||||||
$5->dpiImport(true); $5->dpiTask(true); GRAMMARP->checkDpiVer($1,*$2); v3Global.dpi(true); }
|
$5->dpiImport(true); $5->dpiTask(true); GRAMMARP->checkDpiVer($1,*$2); v3Global.dpi(true);
|
||||||
|
if ($$->prettyName()[0]=='$') SYMP->reinsert($$,NULL,$$->prettyName()); // For $SysTF overriding
|
||||||
|
SYMP->reinsert($$); }
|
||||||
| yEXPORT yaSTRING dpi_importLabelE yFUNCTION idAny ';' { $$ = new AstDpiExport($1,*$5,*$3);
|
| yEXPORT yaSTRING dpi_importLabelE yFUNCTION idAny ';' { $$ = new AstDpiExport($1,*$5,*$3);
|
||||||
GRAMMARP->checkDpiVer($1,*$2); v3Global.dpi(true); }
|
GRAMMARP->checkDpiVer($1,*$2); v3Global.dpi(true); }
|
||||||
| yEXPORT yaSTRING dpi_importLabelE yTASK idAny ';' { $$ = new AstDpiExport($1,*$5,*$3);
|
| yEXPORT yaSTRING dpi_importLabelE yTASK idAny ';' { $$ = new AstDpiExport($1,*$5,*$3);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
#!/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.
|
||||||
|
|
||||||
|
compile (
|
||||||
|
v_flags2 => ["t/t_dpi_sys_c.cpp"],
|
||||||
|
);
|
||||||
|
|
||||||
|
execute (
|
||||||
|
check_finished=>1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// Copyright 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.
|
||||||
|
|
||||||
|
module t ();
|
||||||
|
|
||||||
|
import "DPI-C" dpii_sys_task = function void \$dpii_sys (integer i);
|
||||||
|
import "DPI-C" dpii_sys_func = function int \$dpii_func (integer i);
|
||||||
|
|
||||||
|
`ifndef verilator
|
||||||
|
`error "Only Verilator supports PLI-ish DPI calls."
|
||||||
|
`endif
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$dpii_sys(1);
|
||||||
|
if ($dpii_func(2) != 3) $stop;
|
||||||
|
$dpii_sys(10);
|
||||||
|
if ($dpii_func(2) != 12) $stop;
|
||||||
|
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
// -*- C++ -*-
|
||||||
|
//*************************************************************************
|
||||||
|
//
|
||||||
|
// 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 <stdio.h>
|
||||||
|
#include <svdpi.h>
|
||||||
|
|
||||||
|
//======================================================================
|
||||||
|
|
||||||
|
#if defined(VERILATOR)
|
||||||
|
# include "Vt_dpi_sys__Dpi.h"
|
||||||
|
#elif defined(VCS)
|
||||||
|
# include "../vc_hdrs.h"
|
||||||
|
#elif defined(CADENCE)
|
||||||
|
# define NEED_EXTERNS
|
||||||
|
#else
|
||||||
|
# error "Unknown simulator for DPI test"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef NEED_EXTERNS
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
extern void dpii_sys_task (int i);
|
||||||
|
extern int dpii_sys_func (int i);
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//======================================================================
|
||||||
|
|
||||||
|
static int hidden = 0;
|
||||||
|
|
||||||
|
void dpii_sys_task(int i) {
|
||||||
|
hidden = i;
|
||||||
|
}
|
||||||
|
int dpii_sys_func(int i) {
|
||||||
|
return i + hidden;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue