mirror of
https://github.com/verilator/verilator.git
synced 2025-04-25 10:06:54 +00:00
Internals: Move __Dpi.h writing to EmitCSyms to save a visitor pass
This commit is contained in:
parent
3386466e7a
commit
eb4a686b14
@ -82,23 +82,6 @@ public:
|
|||||||
void emitOpName(AstNode* nodep, const string& format,
|
void emitOpName(AstNode* nodep, const string& format,
|
||||||
AstNode* lhsp, AstNode* rhsp, AstNode* thsp);
|
AstNode* lhsp, AstNode* rhsp, AstNode* thsp);
|
||||||
|
|
||||||
string cFuncArgs(AstCFunc* nodep) {
|
|
||||||
// Return argument list for given C function
|
|
||||||
string args = nodep->argTypes();
|
|
||||||
// Might be a user function with argument list.
|
|
||||||
for (AstNode* stmtp = nodep->argsp(); stmtp; stmtp=stmtp->nextp()) {
|
|
||||||
if (AstVar* portp = stmtp->castVar()) {
|
|
||||||
if (portp->isIO() && !portp->isFuncReturn()) {
|
|
||||||
if (args != "") args+= ", ";
|
|
||||||
if (nodep->dpiImport()) args += portp->dpiArgType(true,false);
|
|
||||||
else if (nodep->funcPublic()) args += portp->cPubArgType(true,false);
|
|
||||||
else args += portp->vlArgType(true,false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return args;
|
|
||||||
}
|
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
|
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
|
||||||
bool paren = true; bool decind = false;
|
bool paren = true; bool decind = false;
|
||||||
@ -2131,66 +2114,6 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//######################################################################
|
|
||||||
// DPI definitions
|
|
||||||
|
|
||||||
class EmitCDpi : EmitCStmts {
|
|
||||||
// METHODS
|
|
||||||
void newOutCFile() {
|
|
||||||
string filename = (v3Global.opt.makeDir()+"/"+ topClassName()
|
|
||||||
+ "__Dpi.h");
|
|
||||||
|
|
||||||
AstCFile* cfilep = newCFile(filename, false/*slow*/, false/*source*/);
|
|
||||||
cfilep->support(true);
|
|
||||||
|
|
||||||
if (m_ofp) v3fatalSrc("Previous file not closed");
|
|
||||||
m_ofp = new V3OutCFile (filename);
|
|
||||||
m_ofp->putsHeader();
|
|
||||||
}
|
|
||||||
|
|
||||||
void emitTop() {
|
|
||||||
puts("// DESCR" "IPTION: Verilator output: Prototypes for DPI import and export functions.\n");
|
|
||||||
puts("//\n");
|
|
||||||
puts("// Verilator includes this file in all generated .cpp files that use DPI functions.\n");
|
|
||||||
puts("// Manually include this file where DPI .c import functions are declared to insure\n");
|
|
||||||
puts("// the C functions match the expectations of the DPI imports.\n");
|
|
||||||
puts("\n");
|
|
||||||
puts("#ifdef __cplusplus\n");
|
|
||||||
puts("extern \"C\" {\n");
|
|
||||||
puts("#endif\n");
|
|
||||||
puts("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void emitBottom() {
|
|
||||||
puts("\n");
|
|
||||||
puts("#ifdef __cplusplus\n");
|
|
||||||
puts("}\n");
|
|
||||||
puts("#endif\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// VISITORS
|
|
||||||
virtual void visit(AstNodeModule* nodep, AstNUser*) {
|
|
||||||
nodep->iterateChildren(*this);
|
|
||||||
}
|
|
||||||
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
|
||||||
if (nodep->dpiImport()) {
|
|
||||||
puts("// dpi import at "+nodep->fileline()->ascii()+"\n");
|
|
||||||
puts("extern "+nodep->rtnTypeVoid()+" "+nodep->name()+" ("+cFuncArgs(nodep)+");\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
EmitCDpi() {}
|
|
||||||
virtual ~EmitCDpi() {}
|
|
||||||
void main() {
|
|
||||||
// Put out the file
|
|
||||||
newOutCFile();
|
|
||||||
emitTop();
|
|
||||||
v3Global.rootp()->accept(*this);
|
|
||||||
emitBottom();
|
|
||||||
delete m_ofp; m_ofp=NULL;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// EmitC class functions
|
// EmitC class functions
|
||||||
|
|
||||||
@ -2214,10 +2137,3 @@ void V3EmitC::emitcTrace() {
|
|||||||
{ EmitCTrace imp (false); imp.main(); }
|
{ EmitCTrace imp (false); imp.main(); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void V3EmitC::emitcDpi() {
|
|
||||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
|
||||||
if (v3Global.dpi()) {
|
|
||||||
{ EmitCDpi imp; imp.main(); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -35,7 +35,6 @@ public:
|
|||||||
static void emitcInlines();
|
static void emitcInlines();
|
||||||
static void emitcSyms();
|
static void emitcSyms();
|
||||||
static void emitcTrace();
|
static void emitcTrace();
|
||||||
static void emitcDpi();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // Guard
|
#endif // Guard
|
||||||
|
@ -136,6 +136,22 @@ public:
|
|||||||
v3Global.rootp()->addFilesp(cfilep);
|
v3Global.rootp()->addFilesp(cfilep);
|
||||||
return cfilep;
|
return cfilep;
|
||||||
}
|
}
|
||||||
|
string cFuncArgs(AstCFunc* nodep) {
|
||||||
|
// Return argument list for given C function
|
||||||
|
string args = nodep->argTypes();
|
||||||
|
// Might be a user function with argument list.
|
||||||
|
for (AstNode* stmtp = nodep->argsp(); stmtp; stmtp=stmtp->nextp()) {
|
||||||
|
if (AstVar* portp = stmtp->castVar()) {
|
||||||
|
if (portp->isIO() && !portp->isFuncReturn()) {
|
||||||
|
if (args != "") args+= ", ";
|
||||||
|
if (nodep->dpiImport()) args += portp->dpiArgType(true,false);
|
||||||
|
else if (nodep->funcPublic()) args += portp->cPubArgType(true,false);
|
||||||
|
else args += portp->vlArgType(true,false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
EmitCBaseVisitor() {
|
EmitCBaseVisitor() {
|
||||||
|
@ -44,25 +44,29 @@ class EmitCSyms : EmitCBaseVisitor {
|
|||||||
// AstNodeModule::user1() -> bool. Set true __Vconfigure called
|
// AstNodeModule::user1() -> bool. Set true __Vconfigure called
|
||||||
AstUser1InUse m_inuser1;
|
AstUser1InUse m_inuser1;
|
||||||
|
|
||||||
|
// TYPES
|
||||||
typedef map<string,AstScopeName*> ScopeNames;
|
typedef map<string,AstScopeName*> ScopeNames;
|
||||||
|
|
||||||
// STATE
|
|
||||||
AstNodeModule* m_modp; // Current module
|
|
||||||
typedef pair<AstScope*,AstNodeModule*> ScopeModPair;
|
typedef pair<AstScope*,AstNodeModule*> ScopeModPair;
|
||||||
vector<ScopeModPair> m_scopes; // Every scope by module
|
|
||||||
ScopeNames m_scopeNames; // Each unique AstScopeName
|
|
||||||
V3LanguageWords m_words; // Reserved word detector
|
|
||||||
int m_coverBins; // Coverage bin number
|
|
||||||
|
|
||||||
// METHODS
|
|
||||||
void emitInt();
|
|
||||||
void emitImp();
|
|
||||||
struct CmpName {
|
struct CmpName {
|
||||||
inline bool operator () (const ScopeModPair& lhsp, const ScopeModPair& rhsp) const {
|
inline bool operator () (const ScopeModPair& lhsp, const ScopeModPair& rhsp) const {
|
||||||
return lhsp.first->name() < rhsp.first->name();
|
return lhsp.first->name() < rhsp.first->name();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// STATE
|
||||||
|
AstNodeModule* m_modp; // Current module
|
||||||
|
vector<ScopeModPair> m_scopes; // Every scope by module
|
||||||
|
vector<AstCFunc*> m_dpis; // DPI functions
|
||||||
|
ScopeNames m_scopeNames; // Each unique AstScopeName
|
||||||
|
V3LanguageWords m_words; // Reserved word detector
|
||||||
|
int m_coverBins; // Coverage bin number
|
||||||
|
|
||||||
|
// METHODS
|
||||||
|
void emitSymHdr();
|
||||||
|
void emitSymImp();
|
||||||
|
void emitDpiHdr();
|
||||||
|
void emitDpiImp();
|
||||||
|
|
||||||
void nameCheck(AstNode* nodep) {
|
void nameCheck(AstNode* nodep) {
|
||||||
// Prevent GCC compile time error; name check all things that reach C++ code
|
// Prevent GCC compile time error; name check all things that reach C++ code
|
||||||
if (nodep->name() != "") {
|
if (nodep->name() != "") {
|
||||||
@ -84,8 +88,11 @@ class EmitCSyms : EmitCBaseVisitor {
|
|||||||
sort(m_scopes.begin(), m_scopes.end(), CmpName());
|
sort(m_scopes.begin(), m_scopes.end(), CmpName());
|
||||||
|
|
||||||
// Output
|
// Output
|
||||||
emitInt();
|
emitSymHdr();
|
||||||
emitImp();
|
emitSymImp();
|
||||||
|
if (v3Global.dpi()) {
|
||||||
|
emitDpiHdr();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeModule* nodep, AstNUser*) {
|
virtual void visit(AstNodeModule* nodep, AstNUser*) {
|
||||||
nameCheck(nodep);
|
nameCheck(nodep);
|
||||||
@ -109,6 +116,12 @@ class EmitCSyms : EmitCBaseVisitor {
|
|||||||
nodep->binNum(m_coverBins++);
|
nodep->binNum(m_coverBins++);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
if (nodep->dpiImport()) {
|
||||||
|
m_dpis.push_back(nodep);
|
||||||
|
}
|
||||||
|
}
|
||||||
// NOPs
|
// NOPs
|
||||||
virtual void visit(AstConst*, AstNUser*) {}
|
virtual void visit(AstConst*, AstNUser*) {}
|
||||||
// Default
|
// Default
|
||||||
@ -126,7 +139,8 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void EmitCSyms::emitInt() {
|
void EmitCSyms::emitSymHdr() {
|
||||||
|
UINFO(6,__FUNCTION__<<": "<<endl);
|
||||||
string filename = v3Global.opt.makeDir()+"/"+symClassName()+".h";
|
string filename = v3Global.opt.makeDir()+"/"+symClassName()+".h";
|
||||||
newCFile(filename, true/*slow*/, false/*source*/);
|
newCFile(filename, true/*slow*/, false/*source*/);
|
||||||
V3OutCFile hf (filename);
|
V3OutCFile hf (filename);
|
||||||
@ -199,7 +213,8 @@ void EmitCSyms::emitInt() {
|
|||||||
puts("#endif /*guard*/\n");
|
puts("#endif /*guard*/\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitCSyms::emitImp() {
|
void EmitCSyms::emitSymImp() {
|
||||||
|
UINFO(6,__FUNCTION__<<": "<<endl);
|
||||||
string filename = v3Global.opt.makeDir()+"/"+symClassName()+".cpp";
|
string filename = v3Global.opt.makeDir()+"/"+symClassName()+".cpp";
|
||||||
AstCFile* cfilep = newCFile(filename, true/*slow*/, true/*source*/);
|
AstCFile* cfilep = newCFile(filename, true/*slow*/, true/*source*/);
|
||||||
cfilep->support(true);
|
cfilep->support(true);
|
||||||
@ -281,6 +296,42 @@ void EmitCSyms::emitImp() {
|
|||||||
puts("\n");
|
puts("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
|
||||||
|
void EmitCSyms::emitDpiHdr() {
|
||||||
|
UINFO(6,__FUNCTION__<<": "<<endl);
|
||||||
|
string filename = v3Global.opt.makeDir()+"/"+topClassName()+"__Dpi.h";
|
||||||
|
AstCFile* cfilep = newCFile(filename, false/*slow*/, false/*source*/);
|
||||||
|
cfilep->support(true);
|
||||||
|
V3OutCFile hf (filename);
|
||||||
|
m_ofp = &hf;
|
||||||
|
|
||||||
|
m_ofp->putsHeader();
|
||||||
|
puts("// DESCR" "IPTION: Verilator output: Prototypes for DPI import and export functions.\n");
|
||||||
|
puts("//\n");
|
||||||
|
puts("// Verilator includes this file in all generated .cpp files that use DPI functions.\n");
|
||||||
|
puts("// Manually include this file where DPI .c import functions are declared to insure\n");
|
||||||
|
puts("// the C functions match the expectations of the DPI imports.\n");
|
||||||
|
puts("\n");
|
||||||
|
puts("#ifdef __cplusplus\n");
|
||||||
|
puts("extern \"C\" {\n");
|
||||||
|
puts("#endif\n");
|
||||||
|
puts("\n");
|
||||||
|
|
||||||
|
for (vector<AstCFunc*>::iterator it = m_dpis.begin(); it != m_dpis.end(); ++it) {
|
||||||
|
AstCFunc* nodep = *it;
|
||||||
|
if (nodep->dpiImport()) {
|
||||||
|
puts("// dpi import at "+nodep->fileline()->ascii()+"\n");
|
||||||
|
puts("extern "+nodep->rtnTypeVoid()+" "+nodep->name()+" ("+cFuncArgs(nodep)+");\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
puts("\n");
|
||||||
|
puts("#ifdef __cplusplus\n");
|
||||||
|
puts("}\n");
|
||||||
|
puts("#endif\n");
|
||||||
|
}
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// EmitC class functions
|
// EmitC class functions
|
||||||
|
|
||||||
|
@ -507,7 +507,6 @@ void process () {
|
|||||||
V3EmitC::emitcInlines();
|
V3EmitC::emitcInlines();
|
||||||
V3EmitC::emitcSyms();
|
V3EmitC::emitcSyms();
|
||||||
V3EmitC::emitcTrace();
|
V3EmitC::emitcTrace();
|
||||||
V3EmitC::emitcDpi();
|
|
||||||
}
|
}
|
||||||
// Unfortunately we have some lint checks in emitc.
|
// Unfortunately we have some lint checks in emitc.
|
||||||
V3EmitC::emitc();
|
V3EmitC::emitc();
|
||||||
|
Loading…
Reference in New Issue
Block a user