DPI: Support strings in DPI Imports
This commit is contained in:
parent
08b63b4f01
commit
788f69a8c9
|
|
@ -1843,6 +1843,11 @@ full nor unique.
|
|||
|
||||
All specify blocks and timing checks are ignored.
|
||||
|
||||
=item string
|
||||
|
||||
String is supported only to the point that they can be passed to DPI
|
||||
imports.
|
||||
|
||||
=item timeunit, timeprecision
|
||||
|
||||
All timing control statements are ignored.
|
||||
|
|
|
|||
|
|
@ -616,6 +616,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
|||
// File I/O
|
||||
|
||||
void _VL_VINT_TO_STRING(int obits, char* destoutp, WDataInP sourcep) {
|
||||
// See also VL_DATA_TO_STRING_NW
|
||||
int lsb=obits-1;
|
||||
bool start=true;
|
||||
char* destp = destoutp;
|
||||
|
|
@ -901,6 +902,29 @@ IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rw
|
|||
return 1;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// Heavy functions
|
||||
|
||||
string VL_CVT_PACK_STR_NW(int lwords, WDataInP lwp) {
|
||||
// See also _VL_VINT_TO_STRING
|
||||
char destout[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1];
|
||||
int obits = lwords * VL_WORDSIZE;
|
||||
int lsb=obits-1;
|
||||
bool start=true;
|
||||
char* destp = destout;
|
||||
int len = 0;
|
||||
for (; lsb>=0; lsb--) {
|
||||
lsb = (lsb / 8) * 8; // Next digit
|
||||
IData charval = (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 0xff;
|
||||
if (!start || charval) {
|
||||
*destp++ = (charval==0)?' ':charval;
|
||||
len++;
|
||||
start = false; // Drop leading 0s
|
||||
}
|
||||
}
|
||||
return string(destout, len);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// Verilated:: Methods
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
// <iostream> avoided to reduce compile time
|
||||
// <string> avoided to reduce compile time
|
||||
// <string> avoided and instead in verilatedheavy.h to reduce compile time
|
||||
using namespace std;
|
||||
|
||||
//=========================================================================
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
// -*- C++ -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2010-2010 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.
|
||||
//
|
||||
//*************************************************************************
|
||||
///
|
||||
/// \file
|
||||
/// \brief Verilator: String include for all Verilated C files
|
||||
///
|
||||
/// This file is included automatically by Verilator at the top of
|
||||
/// all C++ files it generates. It is used when strings or other
|
||||
/// heavyweight types are required; these contents are not part of
|
||||
/// verilated.h to save compile time when such types aren't used.
|
||||
///
|
||||
/// Code available from: http://www.veripool.org/verilator
|
||||
///
|
||||
//*************************************************************************
|
||||
|
||||
|
||||
#ifndef _VERILATEDHEAVY_H_
|
||||
#define _VERILATEDHEAVY_H_ 1 ///< Header Guard
|
||||
|
||||
#include "verilated.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
//======================================================================
|
||||
|
||||
extern string VL_CVT_PACK_STR_NW(int lwords, WDataInP lwp);
|
||||
inline string VL_CVT_PACK_STR_NQ(QData lhs) {
|
||||
IData lw[2]; VL_SET_WQ(lw, lhs);
|
||||
return VL_CVT_PACK_STR_NW(2, lw);
|
||||
}
|
||||
inline string VL_CVT_PACK_STR_NI(IData lhs) {
|
||||
IData lw[1]; lw[0] = lhs;
|
||||
return VL_CVT_PACK_STR_NW(1, lw);
|
||||
}
|
||||
|
||||
#endif // Guard
|
||||
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "verilatedos.h"
|
||||
#include "verilated.h"
|
||||
#include "verilatedheavy.h"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
|
|
|||
|
|
@ -272,6 +272,9 @@ public:
|
|||
bool isDpiUnsupported() const {
|
||||
return (m_e==LOGIC || m_e==TIME || m_e==REALTIME);
|
||||
}
|
||||
bool isOpaque() const { // IE not a simple number we can bit optimize
|
||||
return (m_e==STRING || m_e==SCOPEPTR || m_e==CHARPTR);
|
||||
}
|
||||
};
|
||||
inline bool operator== (AstBasicDTypeKwd lhs, AstBasicDTypeKwd rhs) { return (lhs.m_e == rhs.m_e); }
|
||||
inline bool operator== (AstBasicDTypeKwd lhs, AstBasicDTypeKwd::en rhs) { return (lhs.m_e == rhs); }
|
||||
|
|
@ -918,6 +921,9 @@ struct AstNodeMath : public AstNode {
|
|||
virtual string emitC() = 0;
|
||||
virtual string emitSimpleOperator() { return ""; }
|
||||
virtual bool cleanOut() = 0; // True if output has extra upper bits zero
|
||||
// Someday we will generically support data types on every math node
|
||||
// Until then isOpaque indicates we shouldn't constant optimize this node type
|
||||
bool isOpaque() { return castCvtPackString(); }
|
||||
};
|
||||
|
||||
struct AstNodeTermop : public AstNodeMath {
|
||||
|
|
|
|||
|
|
@ -108,10 +108,14 @@ string AstVar::vlArgType(bool named, bool forReturn) const {
|
|||
string arg;
|
||||
if (isWide() && isInOnly()) arg += "const ";
|
||||
AstBasicDType* bdtypep = basicp();
|
||||
bool strtype = bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::STRING;
|
||||
if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::CHARPTR) {
|
||||
arg += "const char*";
|
||||
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::SCOPEPTR) {
|
||||
arg += "const VerilatedScope*";
|
||||
} else if (strtype) {
|
||||
if (isInOnly()) arg += "const ";
|
||||
arg += "string";
|
||||
} else if (widthMin() <= 8) {
|
||||
arg += "CData";
|
||||
} else if (widthMin() <= 16) {
|
||||
|
|
@ -123,11 +127,11 @@ string AstVar::vlArgType(bool named, bool forReturn) const {
|
|||
} else if (isWide()) {
|
||||
arg += "WData"; // []'s added later
|
||||
}
|
||||
if (isWide()) {
|
||||
if (isWide() && !strtype) {
|
||||
arg += " (& "+name();
|
||||
arg += ")["+cvtToStr(widthWords())+"]";
|
||||
} else {
|
||||
if (isOutput()) arg += "&";
|
||||
if (isOutput() || (strtype && isInput())) arg += "&";
|
||||
if (named) arg += " "+name();
|
||||
}
|
||||
return arg;
|
||||
|
|
|
|||
|
|
@ -228,7 +228,7 @@ private:
|
|||
setSignedState(signst);
|
||||
if (!rangep) { // Set based on keyword properties
|
||||
// V3Width will pull from this width
|
||||
if (keyword().width() > 1) rangep = new AstRange(fileline(), keyword().width()-1, 0);
|
||||
if (keyword().width() > 1 && !isOpaque()) rangep = new AstRange(fileline(), keyword().width()-1, 0);
|
||||
width(keyword().width(), keyword().width());
|
||||
} else {
|
||||
widthFrom(rangep); // Maybe unknown if parameters underneath it
|
||||
|
|
@ -254,6 +254,7 @@ public:
|
|||
virtual int widthTotalBytes() const; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
|
||||
AstBasicDTypeKwd keyword() const { return m_keyword; } // Avoid using - use isSomething accessors instead
|
||||
bool isBitLogic() const { return keyword().isBitLogic(); }
|
||||
bool isOpaque() const { return keyword().isOpaque(); }
|
||||
bool isSloppy() const { return keyword().isSloppy(); }
|
||||
bool isZeroInit() const { return keyword().isZeroInit(); }
|
||||
int msb() const { if (!rangep()) return 0; return rangep()->msbConst(); }
|
||||
|
|
@ -2420,6 +2421,20 @@ public:
|
|||
int size() const { return m_size; }
|
||||
};
|
||||
|
||||
struct AstCvtPackString : public AstNodeUniop {
|
||||
// Convert to Verilator Packed Pack (aka Pack)
|
||||
AstCvtPackString(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
width(64,64); } // Really, width should be dtypep -> STRING
|
||||
ASTNODE_NODE_FUNCS(CvtPackString, CVTPACKSTRING)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { V3ERROR_NA; }
|
||||
virtual string emitVerilog() { return "%f$_CAST(%l)"; }
|
||||
virtual string emitC() { return "VL_CVT_PACK_STR_N%lq(%lW, %li)"; }
|
||||
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;}
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(AstNode* samep) const { return true; }
|
||||
};
|
||||
|
||||
struct AstFEof : public AstNodeUniop {
|
||||
AstFEof(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {}
|
||||
ASTNODE_NODE_FUNCS(FEof, FEOF)
|
||||
|
|
|
|||
|
|
@ -1090,6 +1090,11 @@ private:
|
|||
nodep->v3error("Expecting expression to be constant, but variable isn't const: "<<nodep->itemp()->prettyName());
|
||||
}
|
||||
}
|
||||
|
||||
// virtual void visit(AstCvtPackString* nodep, AstNUser*) {
|
||||
// Not constant propagated (for today) because AstMath::isOpaque is set
|
||||
// Someday if lower is constant, convert to quoted "string".
|
||||
|
||||
virtual void visit(AstAttrOf* nodep, AstNUser*) {
|
||||
// Don't iterate children, don't want to loose VarRef.
|
||||
if (nodep->attrType()==AstAttrType::BITS) {
|
||||
|
|
@ -1504,7 +1509,7 @@ private:
|
|||
TREEOP1("AstSel{warnSelect(nodep)}", "NEVER");
|
||||
// Generic constants on both side. Do this first to avoid other replacements
|
||||
TREEOP("AstNodeBiop {$lhsp.castConst, $rhsp.castConst}", "replaceConst(nodep)");
|
||||
TREEOP("AstNodeUniop{$lhsp.castConst}", "replaceConst(nodep)");
|
||||
TREEOP("AstNodeUniop{$lhsp.castConst, !nodep->isOpaque()}", "replaceConst(nodep)");
|
||||
// Zero on one side or the other
|
||||
TREEOP("AstAdd {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP("AstAnd {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
|
|
|
|||
|
|
@ -861,6 +861,14 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) {
|
|||
+","+cvtToStr(basicp->widthWords()));
|
||||
puts(");\n");
|
||||
}
|
||||
} else if (basicp && basicp->isOpaque()) {
|
||||
// strings and other fundamental c types
|
||||
puts(nodep->vlArgType(true,false));
|
||||
// This isn't very robust and may need cleanup for other data types
|
||||
for (AstArrayDType* arrayp=nodep->dtypeSkipRefp()->castArrayDType(); arrayp; arrayp = arrayp->dtypeSkipRefp()->castArrayDType()) {
|
||||
puts("["+cvtToStr(arrayp->elementsConst())+"]");
|
||||
}
|
||||
puts(";\n");
|
||||
} else {
|
||||
// Arrays need a small alignment, but may need different padding after.
|
||||
// For example three VL_SIG8's needs alignment 1 but size 3.
|
||||
|
|
@ -1226,6 +1234,9 @@ void EmitCImp::emitVarResets(AstNodeModule* modp) {
|
|||
if (varp->isIO() && modp->isTop() && optSystemC()) {
|
||||
// System C top I/O doesn't need loading, as the lower level subinst code does it.
|
||||
}
|
||||
else if (varp->basicp() && varp->basicp()->keyword() == AstBasicDTypeKwd::STRING) {
|
||||
// Constructor deals with it
|
||||
}
|
||||
else if (varp->isParam()) {
|
||||
if (!varp->hasSimpleInit()) nodep->v3fatalSrc("No init for a param?");
|
||||
//puts("// parameter "+varp->name()+" = "+varp->initp()->name()+"\n");
|
||||
|
|
@ -1483,8 +1494,9 @@ void EmitCStmts::emitVarList(AstNode* firstp, EisWhich which, const string& pref
|
|||
// But for now, Smallest->largest makes it more likely a small offset will allow access to the signal.
|
||||
for (int isstatic=1; isstatic>=0; isstatic--) {
|
||||
if (prefixIfImp!="" && !isstatic) continue;
|
||||
for (int size=0; size<8; size++) {
|
||||
if (size==3) continue;
|
||||
const int sortmax = 9;
|
||||
for (int sort=0; sort<sortmax; sort++) {
|
||||
if (sort==3) continue;
|
||||
for (AstNode* nodep=firstp; nodep; nodep = nodep->nextp()) {
|
||||
if (AstVar* varp = nodep->castVar()) {
|
||||
bool doit = true;
|
||||
|
|
@ -1498,15 +1510,16 @@ void EmitCStmts::emitVarList(AstNode* firstp, EisWhich which, const string& pref
|
|||
if (varp->isStatic() ? !isstatic : isstatic) doit=false;
|
||||
if (doit) {
|
||||
int sigbytes = varp->dtypeSkipRefp()->widthAlignBytes();
|
||||
int sortbytes = 7;
|
||||
int sortbytes = sortmax-1;
|
||||
if (varp->isUsedClock() && varp->widthMin()==1) sortbytes = 0;
|
||||
else if (varp->dtypeSkipRefp()->castArrayDType()) sortbytes=7;
|
||||
else if (varp->dtypeSkipRefp()->castArrayDType()) sortbytes=8;
|
||||
else if (varp->basicp() && varp->basicp()->isOpaque()) sortbytes=7;
|
||||
else if (varp->isScBv()) sortbytes=6;
|
||||
else if (sigbytes==8) sortbytes=5;
|
||||
else if (sigbytes==4) sortbytes=4;
|
||||
else if (sigbytes==2) sortbytes=2;
|
||||
else if (sigbytes==1) sortbytes=1;
|
||||
if (size==sortbytes) {
|
||||
if (sort==sortbytes) {
|
||||
emitVarDecl(varp, prefixIfImp);
|
||||
}
|
||||
}
|
||||
|
|
@ -1556,7 +1569,11 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
|
|||
}
|
||||
|
||||
ofp()->putsIntTopInclude();
|
||||
puts("#include \"verilated.h\"\n");
|
||||
if (v3Global.needHeavy()) {
|
||||
puts("#include \"verilatedheavy.h\"\n");
|
||||
} else {
|
||||
puts("#include \"verilated.h\"\n");
|
||||
}
|
||||
if (v3Global.opt.coverage()) {
|
||||
puts("#include \"SpCoverage.h\"\n");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ class EmitCInlines : EmitCBaseVisitor {
|
|||
// VISITORS
|
||||
virtual void visit(AstVar* nodep, AstNUser*) {
|
||||
// All wide constants load into variables, so we can just hunt for them
|
||||
nodep->iterateChildren(*this);
|
||||
if (nodep->widthWords() >= EMITCINLINES_NUM_CONSTW ) {
|
||||
if (int(m_wordWidths.size()) <= nodep->widthWords()) {
|
||||
m_wordWidths.resize(nodep->widthWords()+5);
|
||||
|
|
@ -55,6 +56,11 @@ class EmitCInlines : EmitCBaseVisitor {
|
|||
v3Global.needHInlines(true);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstBasicDType* nodep, AstNUser*) {
|
||||
if (nodep->keyword() == AstBasicDTypeKwd::STRING) {
|
||||
v3Global.needHeavy(true); // #include <string> via verilatedheavy.h when we create symbol file
|
||||
}
|
||||
}
|
||||
|
||||
// NOPs
|
||||
virtual void visit(AstNodeStmt*, AstNUser*) {}
|
||||
|
|
|
|||
|
|
@ -181,6 +181,12 @@ void EmitCSyms::emitSymHdr() {
|
|||
puts("#define _"+symClassName()+"_H_\n");
|
||||
puts("\n");
|
||||
|
||||
if (v3Global.needHeavy()) {
|
||||
puts("#include \"verilatedheavy.h\"\n");
|
||||
} else {
|
||||
puts("#include \"verilated.h\"\n");
|
||||
}
|
||||
|
||||
// for
|
||||
puts("\n// INCLUDE MODULE CLASSES\n");
|
||||
for (AstNodeModule* nodep = v3Global.rootp()->modulesp(); nodep; nodep=nodep->nextp()->castNodeModule()) {
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ class V3Global {
|
|||
int m_debugFileNumber; // Number to append to debug files created
|
||||
bool m_assertWidthsSame; // Tree should have width()==widthMin()
|
||||
bool m_needHInlines; // Need __Inlines file
|
||||
bool m_needHeavy; // Need verilatedheavy.h include
|
||||
bool m_dpi; // Need __Dpi include files
|
||||
|
||||
public:
|
||||
|
|
@ -57,6 +58,7 @@ public:
|
|||
m_debugFileNumber = 0;
|
||||
m_assertWidthsSame = false;
|
||||
m_needHInlines = false;
|
||||
m_needHeavy = false;
|
||||
m_dpi = false;
|
||||
}
|
||||
void clear() {
|
||||
|
|
@ -78,6 +80,8 @@ public:
|
|||
}
|
||||
bool needHInlines() const { return m_needHInlines; }
|
||||
void needHInlines(bool flag) { m_needHInlines=flag; }
|
||||
bool needHeavy() const { return m_needHeavy; }
|
||||
void needHeavy(bool flag) { m_needHeavy=flag; }
|
||||
bool dpi() const { return m_dpi; }
|
||||
void dpi(bool flag) { m_dpi = flag; }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -503,15 +503,6 @@ private:
|
|||
}
|
||||
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*) {
|
||||
// Cell: Resolve its filename. If necessary, parse it.
|
||||
m_cellp = nodep;
|
||||
|
|
|
|||
|
|
@ -110,6 +110,8 @@ private:
|
|||
virtual void visit(AstNeq* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
|
||||
virtual void visit(AstNeqCase* nodep, AstNUser*){ signed_Ou_Ix(nodep); }
|
||||
virtual void visit(AstNeqWild* nodep, AstNUser*){ signed_Ou_Ix(nodep); }
|
||||
// ... Opaque returns, so arbitrary
|
||||
virtual void visit(AstCvtPackString* nodep, AstNUser*){ signed_Ou_Ix(nodep); }
|
||||
|
||||
//========
|
||||
// Signed: Output signed
|
||||
|
|
|
|||
|
|
@ -592,6 +592,9 @@ private:
|
|||
stmt += "(void*)";
|
||||
}
|
||||
stmt += portp->name()+frSuffix;
|
||||
if (portp->basicp() && portp->basicp()->keyword()==AstBasicDTypeKwd::STRING) {
|
||||
stmt += ".c_str()";
|
||||
}
|
||||
}
|
||||
stmt += ";\n";
|
||||
return new AstCStmt(portp->fileline(), stmt);
|
||||
|
|
|
|||
|
|
@ -481,6 +481,9 @@ private:
|
|||
nodep->width(selwidth,selwidth);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstCvtPackString* nodep, AstNUser* vup) {
|
||||
nodep->lhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||
}
|
||||
virtual void visit(AstAttrOf* nodep, AstNUser*) {
|
||||
nodep->fromp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||
nodep->width(32,1); // Approximation, unsized 32
|
||||
|
|
@ -947,11 +950,22 @@ private:
|
|||
if (accept_mode) {
|
||||
// Prelim may cause the node to get replaced; we've lost our
|
||||
// pointer, so need to iterate separately later
|
||||
if (portp->basicp() && portp->basicp()->keyword()==AstBasicDTypeKwd::STRING
|
||||
&& !pinp->castCvtPackString()
|
||||
&& !(pinp->castVarRef() && pinp->castVarRef()->varp()->basicp()->keyword()==AstBasicDTypeKwd::STRING)) {
|
||||
AstNRelinker handle;
|
||||
pinp->unlinkFrBack(&handle); // No next, that's the next pin
|
||||
AstNode* newp = new AstCvtPackString(pinp->fileline(), pinp);
|
||||
handle.relink(newp);
|
||||
pinp = newp;
|
||||
}
|
||||
pinp->accept(*this,WidthVP(portp->width(),portp->widthMin(),PRELIM).p()); pinp=NULL;
|
||||
} else {
|
||||
// Do PRELIM again, because above accept may have exited early due to node replacement
|
||||
pinp->accept(*this,WidthVP(portp->width(),portp->widthMin(),BOTH).p());
|
||||
widthCheck(nodep,"Function Argument",pinp,portp->width(),portp->widthMin());
|
||||
if (portp->basicp() && !portp->basicp()->isOpaque()) {
|
||||
widthCheck(nodep,"Function Argument",pinp,portp->width(),portp->widthMin());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,8 +38,8 @@ module t ();
|
|||
import "DPI-C" pure function shortint dpii_f_shortint (input shortint i);
|
||||
import "DPI-C" pure function longint dpii_f_longint (input longint i);
|
||||
import "DPI-C" pure function chandle dpii_f_chandle (input chandle i);
|
||||
`ifndef VERILATOR
|
||||
import "DPI-C" pure function string dpii_f_string (input string i);
|
||||
`ifndef VERILATOR
|
||||
import "DPI-C" pure function real dpii_f_real (input real i);
|
||||
`endif
|
||||
`ifndef NO_SHORTREAL
|
||||
|
|
@ -52,14 +52,16 @@ module t ();
|
|||
import "DPI-C" pure function void dpii_v_shortint (input shortint i, output shortint o);
|
||||
import "DPI-C" pure function void dpii_v_longint (input longint i, output longint o);
|
||||
import "DPI-C" pure function void dpii_v_chandle (input chandle i, output chandle o);
|
||||
`ifndef VERILATOR
|
||||
import "DPI-C" pure function void dpii_v_string (input string i, output string o);
|
||||
`ifndef VERILATOR
|
||||
import "DPI-C" pure function void dpii_v_real (input real i, output real o);
|
||||
`endif
|
||||
`ifndef NO_SHORTREAL
|
||||
import "DPI-C" pure function void dpii_v_shortreal(input shortreal i, output shortreal o);
|
||||
`endif
|
||||
|
||||
import "DPI-C" pure function int dpii_f_strlen (input string i);
|
||||
|
||||
import "DPI-C" function void dpii_f_void ();
|
||||
|
||||
// Try a task
|
||||
|
|
@ -86,8 +88,8 @@ module t ();
|
|||
shortint i_s, o_s;
|
||||
longint i_l, o_l;
|
||||
chandle i_c, o_c;
|
||||
`ifndef VERILATOR
|
||||
string i_n, o_n;
|
||||
`ifndef VERILATOR
|
||||
real i_d, o_d;
|
||||
`endif
|
||||
`ifndef NO_SHORTREAL
|
||||
|
|
@ -134,8 +136,8 @@ module t ();
|
|||
if (dpii_f_shortint (i_s) !== ~i_s) $stop;
|
||||
if (dpii_f_longint (i_l) !== ~i_l) $stop;
|
||||
if (dpii_f_chandle (i_c) !== i_c) $stop;
|
||||
`ifndef VERILATOR
|
||||
if (dpii_f_string (i_n) != i_n) $stop;
|
||||
`ifndef VERILATOR
|
||||
if (dpii_f_real (i_d) != i_d+1.5) $stop;
|
||||
`endif
|
||||
`ifndef NO_SHORTREAL
|
||||
|
|
@ -148,16 +150,22 @@ module t ();
|
|||
dpii_v_shortint (i_s,o_s); if (o_s !== ~i_s) $stop;
|
||||
dpii_v_longint (i_l,o_l); if (o_l !== ~i_l) $stop;
|
||||
dpii_v_chandle (i_c,o_c); if (o_c !== i_c) $stop;
|
||||
`ifndef VERILATOR
|
||||
`ifndef VCS // Strange link error
|
||||
dpii_v_string (i_n,o_n); if (o_n != i_n) $stop;
|
||||
`endif
|
||||
`ifndef VERILATOR
|
||||
dpii_v_real (i_d,o_d); if (o_d != i_d+1.5) $stop;
|
||||
`endif
|
||||
`ifndef NO_SHORTREAL
|
||||
dpii_v_shortreal(i_f,o_f); if (o_f != i_f+1.5) $stop;
|
||||
`endif
|
||||
|
||||
if (dpii_f_strlen ("")!=0) $stop;
|
||||
if (dpii_f_strlen ("s")!=1) $stop;
|
||||
if (dpii_f_strlen ("st")!=2) $stop;
|
||||
if (dpii_f_strlen ("str")!=3) $stop;
|
||||
if (dpii_f_strlen ("stri")!=4) $stop;
|
||||
if (dpii_f_strlen ("string_l")!=8) $stop;
|
||||
if (dpii_f_strlen ("string_len")!=10) $stop;
|
||||
|
||||
dpii_f_void();
|
||||
dpii_t_void();
|
||||
dpii_t_void_context();
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <svdpi.h>
|
||||
#include <cstring>
|
||||
|
||||
//======================================================================
|
||||
|
||||
|
|
@ -63,6 +64,8 @@ extern "C" {
|
|||
extern int dpii_t_void_context ();
|
||||
extern int dpii_t_int (int i, int *o);
|
||||
|
||||
extern int dpii_f_strlen (const char* i);
|
||||
|
||||
extern int dpii_fa_bit(int i);
|
||||
}
|
||||
#endif
|
||||
|
|
@ -97,6 +100,8 @@ void dpii_v_string (const char* i, const char** o) { *o = i; }
|
|||
void dpii_v_real (double i, double* o) { *o = i + 1.5; }
|
||||
void dpii_v_shortreal(float i, float* o) { *o = i + 1.5; }
|
||||
|
||||
int dpii_f_strlen (const char* i) { return strlen(i); }
|
||||
|
||||
//======================================================================
|
||||
|
||||
void dpii_f_void () {}
|
||||
|
|
|
|||
Loading…
Reference in New Issue