2012-04-13 01:08:20 +00:00
|
|
|
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
2012-03-20 20:13:10 +00:00
|
|
|
|
//*************************************************************************
|
|
|
|
|
// DESCRIPTION: Verilator: Emit Verilog from tree
|
|
|
|
|
//
|
|
|
|
|
// Code available from: http://www.veripool.org/verilator
|
|
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
//
|
2018-01-02 23:05:06 +00:00
|
|
|
|
// Copyright 2004-2018 by Wilson Snyder. This program is free software; you can
|
2012-03-20 20:13:10 +00:00
|
|
|
|
// 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 "config_build.h"
|
|
|
|
|
#include "verilatedos.h"
|
|
|
|
|
#include <cstdio>
|
|
|
|
|
#include <cstdarg>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <cmath>
|
|
|
|
|
#include <map>
|
|
|
|
|
#include <vector>
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
|
|
|
|
|
#include "V3Global.h"
|
2012-08-27 01:13:47 +00:00
|
|
|
|
#include "V3String.h"
|
2012-03-20 20:13:10 +00:00
|
|
|
|
#include "V3EmitXml.h"
|
|
|
|
|
#include "V3EmitCBase.h"
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
// Emit statements and math operators
|
|
|
|
|
|
2016-02-04 23:30:21 +00:00
|
|
|
|
class EmitXmlFileVisitor : public AstNVisitor {
|
2017-11-09 02:27:15 +00:00
|
|
|
|
// NODE STATE
|
|
|
|
|
//Entire netlist:
|
|
|
|
|
// AstNode::user1 -> uint64_t, number to connect crossrefs
|
|
|
|
|
|
2012-03-20 20:13:10 +00:00
|
|
|
|
// MEMBERS
|
|
|
|
|
V3OutFile* m_ofp;
|
2017-11-09 02:27:15 +00:00
|
|
|
|
uint64_t m_id;
|
2012-03-20 20:13:10 +00:00
|
|
|
|
|
|
|
|
|
// METHODS
|
2018-05-14 10:50:47 +00:00
|
|
|
|
VL_DEBUG_FUNC; // Declare debug()
|
2012-03-20 20:13:10 +00:00
|
|
|
|
|
|
|
|
|
// Outfile methods
|
|
|
|
|
V3OutFile* ofp() const { return m_ofp; }
|
|
|
|
|
virtual void puts(const string& str) { ofp()->puts(str); }
|
|
|
|
|
virtual void putbs(const string& str) { ofp()->putbs(str); }
|
|
|
|
|
virtual void putfs(AstNode*, const string& str) { putbs(str); }
|
|
|
|
|
virtual void putqs(AstNode*, const string& str) { putbs(str); }
|
|
|
|
|
virtual void putsNoTracking(const string& str) { ofp()->putsNoTracking(str); }
|
|
|
|
|
virtual void putsQuoted(const string& str) {
|
|
|
|
|
// Quote \ and " for use inside C programs
|
|
|
|
|
// Don't use to quote a filename for #include - #include doesn't \ escape.
|
|
|
|
|
// Duplicate in V3File - here so we can print to string
|
|
|
|
|
putsNoTracking("\"");
|
2014-11-28 17:40:46 +00:00
|
|
|
|
putsNoTracking(V3Number::quoteNameControls(str));
|
2012-03-20 20:13:10 +00:00
|
|
|
|
putsNoTracking("\"");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// XML methods
|
2017-11-09 02:27:15 +00:00
|
|
|
|
void outputId(AstNode* nodep) {
|
|
|
|
|
if (!nodep->user1()) { nodep->user1(++m_id); }
|
|
|
|
|
puts("\""+cvtToStr(nodep->user1())+"\"");
|
|
|
|
|
}
|
2012-03-20 20:13:10 +00:00
|
|
|
|
void outputTag(AstNode* nodep, string tag) {
|
2012-08-27 01:13:47 +00:00
|
|
|
|
if (tag=="") tag = VString::downcase(nodep->typeName());
|
2012-03-20 20:13:10 +00:00
|
|
|
|
puts("<"+tag+" "+nodep->fileline()->xml());
|
2018-02-02 02:32:58 +00:00
|
|
|
|
if (VN_IS(nodep, NodeDType)) { puts(" id="); outputId(nodep); }
|
2012-03-20 20:13:10 +00:00
|
|
|
|
if (nodep->name()!="") { puts(" name="); putsQuoted(nodep->prettyName()); }
|
2017-10-06 11:33:52 +00:00
|
|
|
|
if (nodep->tag()!="") { puts(" tag="); putsQuoted(nodep->tag()); }
|
2018-02-02 02:32:58 +00:00
|
|
|
|
if (AstNodeDType* dtp = VN_CAST(nodep, NodeDType)) {
|
2017-11-09 23:04:16 +00:00
|
|
|
|
if (dtp->subDTypep()) { puts(" sub_dtype_id="); outputId(dtp->subDTypep()->skipRefp()); }
|
2017-11-09 02:27:15 +00:00
|
|
|
|
} else {
|
2017-11-09 23:04:16 +00:00
|
|
|
|
if (nodep->dtypep()) { puts(" dtype_id="); outputId(nodep->dtypep()->skipRefp()); }
|
2017-11-09 02:27:15 +00:00
|
|
|
|
}
|
2012-03-20 20:13:10 +00:00
|
|
|
|
}
|
|
|
|
|
void outputChildrenEnd(AstNode* nodep, string tag) {
|
2012-08-27 01:13:47 +00:00
|
|
|
|
if (tag=="") tag = VString::downcase(nodep->typeName());
|
2012-03-20 20:13:10 +00:00
|
|
|
|
if (nodep->op1p() || nodep->op2p() || nodep->op3p() || nodep->op4p()) {
|
|
|
|
|
puts(">\n");
|
2018-05-11 00:55:37 +00:00
|
|
|
|
iterateChildren(nodep);
|
2012-03-20 20:13:10 +00:00
|
|
|
|
puts("</"+tag+">\n");
|
|
|
|
|
} else {
|
|
|
|
|
puts("/>\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// VISITORS
|
2018-01-31 12:25:10 +00:00
|
|
|
|
virtual void visit(AstAssignW* nodep) {
|
|
|
|
|
outputTag(nodep, "contassign"); // IEEE: vpiContAssign
|
|
|
|
|
outputChildrenEnd(nodep, "contassign");
|
|
|
|
|
}
|
|
|
|
|
virtual void visit(AstCell* nodep) {
|
|
|
|
|
outputTag(nodep, "instance"); // IEEE: vpiInstance
|
|
|
|
|
puts(" defName="); putsQuoted(nodep->modName()); // IEEE vpiDefName
|
|
|
|
|
outputChildrenEnd(nodep, "instance");
|
|
|
|
|
}
|
2016-11-27 13:11:38 +00:00
|
|
|
|
virtual void visit(AstNetlist* nodep) {
|
2012-03-20 20:13:10 +00:00
|
|
|
|
puts("<netlist>\n");
|
2018-05-11 00:55:37 +00:00
|
|
|
|
iterateChildren(nodep);
|
2012-03-20 20:13:10 +00:00
|
|
|
|
puts("</netlist>\n");
|
|
|
|
|
}
|
2016-11-27 13:11:38 +00:00
|
|
|
|
virtual void visit(AstNodeModule* nodep) {
|
2012-03-20 20:13:10 +00:00
|
|
|
|
outputTag(nodep, "");
|
|
|
|
|
if (nodep->level()==1 || nodep->level()==2) // ==2 because we don't add wrapper when in XML mode
|
|
|
|
|
puts(" topModule=\"1\""); // IEEE vpiTopModule
|
|
|
|
|
outputChildrenEnd(nodep, "");
|
|
|
|
|
}
|
2016-11-27 13:11:38 +00:00
|
|
|
|
virtual void visit(AstPin* nodep) {
|
2012-03-20 20:13:10 +00:00
|
|
|
|
// What we call a pin in verilator is a port in the IEEE spec.
|
|
|
|
|
outputTag(nodep, "port"); // IEEE: vpiPort
|
|
|
|
|
if (nodep->modVarp()->isInOnly())
|
|
|
|
|
puts(" direction=\"in\"");
|
|
|
|
|
else if (nodep->modVarp()->isOutOnly())
|
|
|
|
|
puts(" direction=\"out\"");
|
|
|
|
|
else puts(" direction=\"inout\"");
|
|
|
|
|
puts(" portIndex=\""+cvtToStr(nodep->pinNum())+"\""); // IEEE: vpiPortIndex
|
|
|
|
|
// Children includes vpiHighConn and vpiLowConn; we don't support port bits (yet?)
|
|
|
|
|
outputChildrenEnd(nodep, "port");
|
|
|
|
|
}
|
2018-01-31 12:29:14 +00:00
|
|
|
|
virtual void visit(AstSenItem* nodep) {
|
|
|
|
|
outputTag(nodep, "");
|
|
|
|
|
puts(" edgeType=\""+cvtToStr(nodep->edgeType().ascii())+"\""); // IEEE vpiTopModule
|
|
|
|
|
outputChildrenEnd(nodep, "");
|
|
|
|
|
}
|
2012-03-20 20:13:10 +00:00
|
|
|
|
|
|
|
|
|
// Data types
|
2016-11-27 13:11:38 +00:00
|
|
|
|
virtual void visit(AstBasicDType* nodep) {
|
2017-11-09 02:27:15 +00:00
|
|
|
|
outputTag(nodep, "basicdtype ");
|
2012-03-20 20:13:10 +00:00
|
|
|
|
if (nodep->isRanged()) {
|
|
|
|
|
puts(" left=\""+cvtToStr(nodep->left())+"\"");
|
|
|
|
|
puts(" right=\""+cvtToStr(nodep->right())+"\"");
|
|
|
|
|
}
|
|
|
|
|
puts("/>\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Default
|
2016-11-27 13:11:38 +00:00
|
|
|
|
virtual void visit(AstNode* nodep) {
|
2012-03-20 20:13:10 +00:00
|
|
|
|
outputTag(nodep, "");
|
|
|
|
|
outputChildrenEnd(nodep, "");
|
|
|
|
|
}
|
|
|
|
|
public:
|
|
|
|
|
EmitXmlFileVisitor(AstNode* nodep, V3OutFile* ofp) {
|
|
|
|
|
m_ofp = ofp;
|
2017-11-09 02:27:15 +00:00
|
|
|
|
m_id = 0;
|
2018-05-11 00:55:37 +00:00
|
|
|
|
iterate(nodep);
|
2012-03-20 20:13:10 +00:00
|
|
|
|
}
|
|
|
|
|
virtual ~EmitXmlFileVisitor() {}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
// EmitXml class functions
|
|
|
|
|
|
|
|
|
|
void V3EmitXml::emitxml() {
|
|
|
|
|
UINFO(2,__FUNCTION__<<": "<<endl);
|
|
|
|
|
// All-in-one file
|
|
|
|
|
V3OutXmlFile of (v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+".xml");
|
|
|
|
|
of.putsHeader();
|
|
|
|
|
of.puts("<!-- DESCR" "IPTION: Verilator output: XML representation of netlist -->\n");
|
|
|
|
|
of.puts("<verilator_xml>\n");
|
|
|
|
|
{
|
2018-01-31 12:25:10 +00:00
|
|
|
|
std::stringstream sstr;
|
2012-03-20 20:13:10 +00:00
|
|
|
|
FileLine::fileNameNumMapDumpXml(sstr);
|
|
|
|
|
of.puts(sstr.str());
|
|
|
|
|
}
|
|
|
|
|
EmitXmlFileVisitor visitor (v3Global.rootp(), &of);
|
|
|
|
|
of.puts("</verilator_xml>\n");
|
|
|
|
|
}
|