2012-04-13 01:08:20 +00:00
|
|
|
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
2006-08-26 11:35:28 +00:00
|
|
|
|
//*************************************************************************
|
|
|
|
|
// DESCRIPTION: Verilator: Emit Verilog from tree
|
|
|
|
|
//
|
2008-04-25 12:14:27 +00:00
|
|
|
|
// Code available from: http://www.veripool.org/verilator
|
2006-08-26 11:35:28 +00:00
|
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
//
|
2014-01-07 00:28:57 +00:00
|
|
|
|
// Copyright 2004-2014 by Wilson Snyder. This program is free software; you can
|
2006-08-26 11:35:28 +00:00
|
|
|
|
// redistribute it and/or modify it under the terms of either the GNU
|
2009-05-04 21:07:57 +00:00
|
|
|
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
|
|
|
|
// Version 2.0.
|
2006-08-26 11:35:28 +00:00
|
|
|
|
//
|
|
|
|
|
// 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.
|
|
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
|
2006-12-18 19:20:45 +00:00
|
|
|
|
#include "config_build.h"
|
|
|
|
|
#include "verilatedos.h"
|
2008-06-30 17:11:25 +00:00
|
|
|
|
#include <cstdio>
|
|
|
|
|
#include <cstdarg>
|
2006-08-26 11:35:28 +00:00
|
|
|
|
#include <unistd.h>
|
2008-06-30 17:11:25 +00:00
|
|
|
|
#include <cmath>
|
2006-08-26 11:35:28 +00:00
|
|
|
|
#include <map>
|
|
|
|
|
#include <vector>
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
|
|
|
|
|
#include "V3Global.h"
|
|
|
|
|
#include "V3EmitV.h"
|
|
|
|
|
#include "V3EmitCBase.h"
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
// Emit statements and math operators
|
|
|
|
|
|
2008-11-20 12:55:54 +00:00
|
|
|
|
class EmitVBaseVisitor : public EmitCBaseVisitor {
|
|
|
|
|
// MEMBERS
|
2006-08-26 11:35:28 +00:00
|
|
|
|
bool m_suppressSemi;
|
2009-12-29 03:19:03 +00:00
|
|
|
|
AstSenTree* m_sensesp;
|
2006-08-26 11:35:28 +00:00
|
|
|
|
|
|
|
|
|
// METHODS
|
2009-01-21 21:56:50 +00:00
|
|
|
|
static int debug() {
|
|
|
|
|
static int level = -1;
|
|
|
|
|
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
|
|
|
|
|
return level;
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-20 12:55:54 +00:00
|
|
|
|
virtual void puts(const string& str) = 0;
|
|
|
|
|
virtual void putbs(const string& str) = 0;
|
2010-01-07 21:41:19 +00:00
|
|
|
|
virtual void putfs(AstNode* nodep, const string& str) = 0; // Fileline and node %% mark
|
|
|
|
|
virtual void putqs(AstNode* nodep, const string& str) = 0; // Fileline quiet w/o %% mark
|
2008-11-20 12:55:54 +00:00
|
|
|
|
virtual void putsNoTracking(const string& str) = 0;
|
2009-12-29 03:19:03 +00:00
|
|
|
|
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("\"");
|
|
|
|
|
putsNoTracking(AstNode::quoteName(str));
|
|
|
|
|
putsNoTracking("\"");
|
|
|
|
|
}
|
2012-03-20 20:01:53 +00:00
|
|
|
|
|
2006-08-26 11:35:28 +00:00
|
|
|
|
// VISITORS
|
|
|
|
|
virtual void visit(AstNetlist* nodep, AstNUser*) {
|
|
|
|
|
nodep->iterateChildren(*this);
|
|
|
|
|
}
|
2010-01-08 03:44:30 +00:00
|
|
|
|
virtual void visit(AstNodeModule* nodep, AstNUser*) {
|
|
|
|
|
putfs(nodep, nodep->verilogKwd()+" "+modClassName(nodep)+";\n");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
nodep->iterateChildren(*this);
|
2010-01-08 03:44:30 +00:00
|
|
|
|
putqs(nodep, "end"+nodep->verilogKwd()+"\n");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
|
|
|
|
virtual void visit(AstNodeFTask* nodep, AstNUser*) {
|
2009-12-29 03:19:03 +00:00
|
|
|
|
putfs(nodep, nodep->isFunction() ? "function":"task");
|
2009-12-03 11:55:29 +00:00
|
|
|
|
puts(" ");
|
2011-01-19 16:44:23 +00:00
|
|
|
|
puts(nodep->prettyName());
|
2006-08-26 11:35:28 +00:00
|
|
|
|
puts(";\n");
|
2010-01-07 21:41:19 +00:00
|
|
|
|
putqs(nodep, "begin\n"); // Only putfs the first time for each visitor; later for same node is putqs
|
2006-08-26 11:35:28 +00:00
|
|
|
|
nodep->stmtsp()->iterateAndNext(*this);
|
2010-01-07 21:41:19 +00:00
|
|
|
|
putqs(nodep, "end\n");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void visit(AstBegin* nodep, AstNUser*) {
|
2011-11-29 23:23:18 +00:00
|
|
|
|
if (nodep->unnamed()) {
|
|
|
|
|
putbs("begin\n");
|
|
|
|
|
} else {
|
|
|
|
|
putbs("begin : "+nodep->name()+"\n");
|
|
|
|
|
}
|
2006-08-26 11:35:28 +00:00
|
|
|
|
nodep->iterateChildren(*this);
|
|
|
|
|
puts("end\n");
|
|
|
|
|
}
|
|
|
|
|
virtual void visit(AstGenerate* nodep, AstNUser*) {
|
2009-12-29 03:19:03 +00:00
|
|
|
|
putfs(nodep, "generate\n");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
nodep->iterateChildren(*this);
|
2010-01-07 21:41:19 +00:00
|
|
|
|
putqs(nodep, "end\n");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
|
|
|
|
virtual void visit(AstFinal* nodep, AstNUser*) {
|
2009-12-29 03:19:03 +00:00
|
|
|
|
putfs(nodep, "final begin\n");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
nodep->iterateChildren(*this);
|
2010-01-07 21:41:19 +00:00
|
|
|
|
putqs(nodep, "end\n");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
|
|
|
|
virtual void visit(AstInitial* nodep, AstNUser*) {
|
2009-12-29 03:19:03 +00:00
|
|
|
|
putfs(nodep,"initial begin\n");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
nodep->iterateChildren(*this);
|
2010-01-07 21:41:19 +00:00
|
|
|
|
putqs(nodep, "end\n");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
|
|
|
|
virtual void visit(AstAlways* nodep, AstNUser*) {
|
2009-12-29 03:19:03 +00:00
|
|
|
|
putfs(nodep,"always ");
|
|
|
|
|
if (m_sensesp) m_sensesp->iterateAndNext(*this); // In active
|
|
|
|
|
else nodep->sensesp()->iterateAndNext(*this);
|
2008-11-20 12:55:54 +00:00
|
|
|
|
putbs(" begin\n");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
nodep->bodysp()->iterateAndNext(*this);
|
2010-01-07 21:41:19 +00:00
|
|
|
|
putqs(nodep,"end\n");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
2010-04-06 00:01:17 +00:00
|
|
|
|
virtual void visit(AstAlwaysPublic* nodep, AstNUser*) {
|
|
|
|
|
putfs(nodep,"/*verilator public_flat_rw ");
|
|
|
|
|
if (m_sensesp) m_sensesp->iterateAndNext(*this); // In active
|
|
|
|
|
else nodep->sensesp()->iterateAndNext(*this);
|
|
|
|
|
putqs(nodep," ");
|
|
|
|
|
nodep->bodysp()->iterateAndNext(*this);
|
|
|
|
|
putqs(nodep,"*/\n");
|
|
|
|
|
}
|
2006-08-26 11:35:28 +00:00
|
|
|
|
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
|
|
|
|
|
nodep->lhsp()->iterateAndNext(*this);
|
2009-12-29 03:19:03 +00:00
|
|
|
|
putfs(nodep," "+nodep->verilogKwd()+" ");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
nodep->rhsp()->iterateAndNext(*this);
|
|
|
|
|
if (!m_suppressSemi) puts(";\n");
|
|
|
|
|
}
|
|
|
|
|
virtual void visit(AstAssignDly* nodep, AstNUser*) {
|
|
|
|
|
nodep->lhsp()->iterateAndNext(*this);
|
2009-12-29 03:19:03 +00:00
|
|
|
|
putfs(nodep," <= ");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
nodep->rhsp()->iterateAndNext(*this);
|
|
|
|
|
puts(";\n");
|
|
|
|
|
}
|
|
|
|
|
virtual void visit(AstAssignAlias* nodep, AstNUser*) {
|
2009-10-07 01:46:24 +00:00
|
|
|
|
putbs("alias ");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
nodep->lhsp()->iterateAndNext(*this);
|
2009-12-29 03:19:03 +00:00
|
|
|
|
putfs(nodep," = ");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
nodep->rhsp()->iterateAndNext(*this);
|
|
|
|
|
if (!m_suppressSemi) puts(";\n");
|
|
|
|
|
}
|
|
|
|
|
virtual void visit(AstAssignW* nodep, AstNUser*) {
|
2009-12-29 03:19:03 +00:00
|
|
|
|
putfs(nodep,"assign ");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
nodep->lhsp()->iterateAndNext(*this);
|
|
|
|
|
putbs(" = ");
|
|
|
|
|
nodep->rhsp()->iterateAndNext(*this);
|
|
|
|
|
if (!m_suppressSemi) puts(";\n");
|
|
|
|
|
}
|
2010-02-14 15:01:21 +00:00
|
|
|
|
virtual void visit(AstBreak* nodep, AstNUser*) {
|
|
|
|
|
putbs("break");
|
|
|
|
|
if (!m_suppressSemi) puts(";\n");
|
|
|
|
|
}
|
2006-08-26 11:35:28 +00:00
|
|
|
|
virtual void visit(AstSenTree* nodep, AstNUser*) {
|
2008-11-20 12:55:54 +00:00
|
|
|
|
// AstSenItem is called for dumping in isolation by V3Order
|
2009-12-29 03:19:03 +00:00
|
|
|
|
putfs(nodep,"@(");
|
2009-01-07 14:37:59 +00:00
|
|
|
|
for (AstNode* expp=nodep->sensesp(); expp; expp = expp->nextp()) {
|
2009-12-29 00:49:40 +00:00
|
|
|
|
expp->accept(*this);
|
2010-01-07 21:41:19 +00:00
|
|
|
|
if (expp->nextp()) putqs(expp->nextp()," or ");
|
2009-01-07 14:37:59 +00:00
|
|
|
|
}
|
2008-11-20 12:55:54 +00:00
|
|
|
|
puts(")");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
2009-01-07 14:37:59 +00:00
|
|
|
|
virtual void visit(AstSenGate* nodep, AstNUser*) {
|
|
|
|
|
emitVerilogFormat(nodep, nodep->emitVerilog(), nodep->sensesp(), nodep->rhsp());
|
|
|
|
|
}
|
2006-08-26 11:35:28 +00:00
|
|
|
|
virtual void visit(AstSenItem* nodep, AstNUser*) {
|
2009-12-29 03:19:03 +00:00
|
|
|
|
putfs(nodep,"");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
puts(nodep->edgeType().verilogKwd());
|
2008-11-20 12:55:54 +00:00
|
|
|
|
if (nodep->sensp()) puts(" ");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
nodep->iterateChildren(*this);
|
|
|
|
|
}
|
|
|
|
|
virtual void visit(AstNodeCase* nodep, AstNUser*) {
|
2010-12-26 02:58:28 +00:00
|
|
|
|
putfs(nodep,"");
|
|
|
|
|
if (AstCase* casep = nodep->castCase()) {
|
|
|
|
|
if (casep->priorityPragma()) puts("priority ");
|
|
|
|
|
if (casep->uniquePragma()) puts("unique ");
|
|
|
|
|
if (casep->unique0Pragma()) puts("unique0 ");
|
|
|
|
|
}
|
|
|
|
|
puts(nodep->verilogKwd());
|
2006-08-26 11:35:28 +00:00
|
|
|
|
puts(" (");
|
|
|
|
|
nodep->exprp()->iterateAndNext(*this);
|
|
|
|
|
puts(")\n");
|
|
|
|
|
if (AstCase* casep = nodep->castCase()) {
|
|
|
|
|
if (casep->fullPragma() || casep->parallelPragma()) {
|
|
|
|
|
puts(" // synopsys");
|
|
|
|
|
if (casep->fullPragma()) puts(" full_case");
|
|
|
|
|
if (casep->parallelPragma()) puts(" parallel_case");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
nodep->itemsp()->iterateAndNext(*this);
|
2010-01-07 21:41:19 +00:00
|
|
|
|
putqs(nodep,"endcase\n");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
|
|
|
|
virtual void visit(AstCaseItem* nodep, AstNUser*) {
|
|
|
|
|
if (nodep->condsp()) {
|
|
|
|
|
nodep->condsp()->iterateAndNext(*this);
|
|
|
|
|
} else putbs("default");
|
2009-12-29 03:19:03 +00:00
|
|
|
|
putfs(nodep,": begin ");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
nodep->bodysp()->iterateAndNext(*this);
|
2010-01-07 21:41:19 +00:00
|
|
|
|
putqs(nodep,"end\n");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
|
|
|
|
virtual void visit(AstComment* nodep, AstNUser*) {
|
|
|
|
|
puts((string)"// "+nodep->name()+"\n");
|
|
|
|
|
nodep->iterateChildren(*this);
|
|
|
|
|
}
|
2010-02-14 15:01:21 +00:00
|
|
|
|
virtual void visit(AstContinue* nodep, AstNUser*) {
|
|
|
|
|
putbs("continue");
|
|
|
|
|
if (!m_suppressSemi) puts(";\n");
|
|
|
|
|
}
|
2008-12-10 22:10:03 +00:00
|
|
|
|
virtual void visit(AstCoverDecl*, AstNUser*) {} // N/A
|
|
|
|
|
virtual void visit(AstCoverInc*, AstNUser*) {} // N/A
|
2008-12-12 20:34:02 +00:00
|
|
|
|
virtual void visit(AstCoverToggle*, AstNUser*) {} // N/A
|
2008-07-01 18:15:10 +00:00
|
|
|
|
|
2009-11-24 02:24:55 +00:00
|
|
|
|
void visitNodeDisplay(AstNode* nodep, AstNode* fileOrStrgp, const string& text, AstNode* exprsp) {
|
2009-12-29 03:19:03 +00:00
|
|
|
|
putfs(nodep,nodep->verilogKwd());
|
2006-08-26 11:35:28 +00:00
|
|
|
|
putbs(" (");
|
2009-11-24 02:24:55 +00:00
|
|
|
|
if (fileOrStrgp) { fileOrStrgp->iterateAndNext(*this); putbs(","); }
|
2009-12-29 03:19:03 +00:00
|
|
|
|
putsQuoted(text);
|
2008-07-01 18:15:10 +00:00
|
|
|
|
for (AstNode* expp=exprsp; expp; expp = expp->nextp()) {
|
2006-08-26 11:35:28 +00:00
|
|
|
|
puts(",");
|
|
|
|
|
expp->iterateAndNext(*this);
|
|
|
|
|
}
|
|
|
|
|
puts(");\n");
|
|
|
|
|
}
|
2011-06-29 01:26:49 +00:00
|
|
|
|
virtual void visit(AstDisable* nodep, AstNUser*) {
|
|
|
|
|
putbs("disable "+nodep->name()+";\n");
|
|
|
|
|
}
|
2008-07-01 18:15:10 +00:00
|
|
|
|
virtual void visit(AstDisplay* nodep, AstNUser*) {
|
2010-01-17 20:53:12 +00:00
|
|
|
|
visitNodeDisplay(nodep, nodep->filep(), nodep->fmtp()->text(), nodep->fmtp()->exprsp());
|
2008-07-01 18:15:10 +00:00
|
|
|
|
}
|
|
|
|
|
virtual void visit(AstFScanF* nodep, AstNUser*) {
|
|
|
|
|
visitNodeDisplay(nodep, nodep->filep(), nodep->text(), nodep->exprsp());
|
|
|
|
|
}
|
|
|
|
|
virtual void visit(AstSScanF* nodep, AstNUser*) {
|
|
|
|
|
visitNodeDisplay(nodep, nodep->fromp(), nodep->text(), nodep->exprsp());
|
|
|
|
|
}
|
2009-11-24 02:24:55 +00:00
|
|
|
|
virtual void visit(AstSFormat* nodep, AstNUser*) {
|
2010-01-17 20:53:12 +00:00
|
|
|
|
visitNodeDisplay(nodep, nodep->lhsp(), nodep->fmtp()->text(), nodep->fmtp()->exprsp());
|
2009-11-24 02:24:55 +00:00
|
|
|
|
}
|
2010-01-18 00:13:44 +00:00
|
|
|
|
virtual void visit(AstSFormatF* nodep, AstNUser*) {
|
|
|
|
|
visitNodeDisplay(nodep, NULL, nodep->text(), nodep->exprsp());
|
|
|
|
|
}
|
2009-11-19 22:04:21 +00:00
|
|
|
|
virtual void visit(AstValuePlusArgs* nodep, AstNUser*) {
|
|
|
|
|
visitNodeDisplay(nodep, NULL, nodep->text(), nodep->exprsp());
|
|
|
|
|
}
|
2008-07-01 18:15:10 +00:00
|
|
|
|
|
2006-08-26 11:35:28 +00:00
|
|
|
|
virtual void visit(AstFOpen* nodep, AstNUser*) {
|
2009-12-29 03:19:03 +00:00
|
|
|
|
putfs(nodep,nodep->verilogKwd());
|
2006-08-26 11:35:28 +00:00
|
|
|
|
putbs(" (");
|
2014-04-17 02:33:25 +00:00
|
|
|
|
if (nodep->filep()) nodep->filep()->iterateAndNext(*this);
|
2006-08-26 11:35:28 +00:00
|
|
|
|
putbs(",");
|
2014-04-17 02:33:25 +00:00
|
|
|
|
if (nodep->filenamep()) nodep->filenamep()->iterateAndNext(*this);
|
2006-08-26 11:35:28 +00:00
|
|
|
|
putbs(",");
|
2014-04-17 02:33:25 +00:00
|
|
|
|
if (nodep->modep()) nodep->modep()->iterateAndNext(*this);
|
2006-08-26 11:35:28 +00:00
|
|
|
|
puts(");\n");
|
|
|
|
|
}
|
|
|
|
|
virtual void visit(AstFClose* nodep, AstNUser*) {
|
2009-12-29 03:19:03 +00:00
|
|
|
|
putfs(nodep,nodep->verilogKwd());
|
2006-08-26 11:35:28 +00:00
|
|
|
|
putbs(" (");
|
2014-04-17 02:33:25 +00:00
|
|
|
|
if (nodep->filep()) nodep->filep()->iterateAndNext(*this);
|
2006-08-26 11:35:28 +00:00
|
|
|
|
puts(");\n");
|
|
|
|
|
}
|
2008-06-27 12:45:05 +00:00
|
|
|
|
virtual void visit(AstFFlush* nodep, AstNUser*) {
|
2009-12-29 03:19:03 +00:00
|
|
|
|
putfs(nodep,nodep->verilogKwd());
|
2008-06-27 12:45:05 +00:00
|
|
|
|
putbs(" (");
|
2014-04-17 02:33:25 +00:00
|
|
|
|
if (nodep->filep()) nodep->filep()->iterateAndNext(*this);
|
2008-06-27 12:45:05 +00:00
|
|
|
|
puts(");\n");
|
|
|
|
|
}
|
2010-02-14 15:01:21 +00:00
|
|
|
|
virtual void visit(AstJumpGo* nodep, AstNUser*) {
|
|
|
|
|
putbs("disable "+cvtToStr((void*)(nodep->labelp()))+";\n");
|
|
|
|
|
}
|
|
|
|
|
virtual void visit(AstJumpLabel* nodep, AstNUser*) {
|
|
|
|
|
putbs("begin : "+cvtToStr((void*)(nodep))+"\n");
|
2014-04-17 02:33:25 +00:00
|
|
|
|
if (nodep->stmtsp()) nodep->stmtsp()->iterateAndNext(*this);
|
2010-02-14 15:01:21 +00:00
|
|
|
|
puts("end\n");
|
|
|
|
|
}
|
2006-12-19 14:09:57 +00:00
|
|
|
|
virtual void visit(AstReadMem* nodep, AstNUser*) {
|
2009-12-29 03:19:03 +00:00
|
|
|
|
putfs(nodep,nodep->verilogKwd());
|
2006-12-19 14:09:57 +00:00
|
|
|
|
putbs(" (");
|
2014-04-17 02:33:25 +00:00
|
|
|
|
if (nodep->filenamep()) nodep->filenamep()->iterateAndNext(*this);
|
2006-12-19 14:09:57 +00:00
|
|
|
|
putbs(",");
|
2014-04-17 02:33:25 +00:00
|
|
|
|
if (nodep->memp()) nodep->memp()->iterateAndNext(*this);
|
|
|
|
|
if (nodep->lsbp()) { putbs(","); nodep->lsbp()->iterateAndNext(*this); }
|
|
|
|
|
if (nodep->msbp()) { putbs(","); nodep->msbp()->iterateAndNext(*this); }
|
2006-12-19 14:09:57 +00:00
|
|
|
|
puts(");\n");
|
|
|
|
|
}
|
2010-12-30 12:55:31 +00:00
|
|
|
|
virtual void visit(AstSysIgnore* nodep, AstNUser*) {
|
|
|
|
|
putfs(nodep,nodep->verilogKwd());
|
|
|
|
|
putbs(" (");
|
2014-04-17 02:33:25 +00:00
|
|
|
|
nodep->exprsp()->iterateAndNext(*this);
|
2010-12-30 12:55:31 +00:00
|
|
|
|
puts(");\n");
|
|
|
|
|
}
|
2006-08-26 11:35:28 +00:00
|
|
|
|
virtual void visit(AstNodeFor* nodep, AstNUser*) {
|
2009-12-29 03:19:03 +00:00
|
|
|
|
putfs(nodep,"for (");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
m_suppressSemi = true;
|
|
|
|
|
nodep->initsp()->iterateAndNext(*this);
|
|
|
|
|
puts(";");
|
|
|
|
|
nodep->condp()->iterateAndNext(*this);
|
|
|
|
|
puts(";");
|
2006-09-05 20:06:23 +00:00
|
|
|
|
nodep->incsp()->iterateAndNext(*this);
|
2006-08-26 11:35:28 +00:00
|
|
|
|
m_suppressSemi = false;
|
2009-12-29 03:19:03 +00:00
|
|
|
|
puts(") begin\n");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
nodep->bodysp()->iterateAndNext(*this);
|
2010-01-07 21:41:19 +00:00
|
|
|
|
putqs(nodep,"end\n");
|
2009-02-26 03:06:59 +00:00
|
|
|
|
}
|
|
|
|
|
virtual void visit(AstRepeat* nodep, AstNUser*) {
|
2009-12-29 03:19:03 +00:00
|
|
|
|
putfs(nodep,"repeat (");
|
2009-02-26 03:06:59 +00:00
|
|
|
|
nodep->countp()->iterateAndNext(*this);
|
2009-12-29 03:19:03 +00:00
|
|
|
|
puts(") begin\n");
|
2009-02-26 03:06:59 +00:00
|
|
|
|
nodep->bodysp()->iterateAndNext(*this);
|
2009-12-29 03:19:03 +00:00
|
|
|
|
putfs(nodep,"end\n");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
|
|
|
|
virtual void visit(AstWhile* nodep, AstNUser*) {
|
|
|
|
|
nodep->precondsp()->iterateAndNext(*this);
|
2009-12-29 03:19:03 +00:00
|
|
|
|
putfs(nodep,"while (");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
nodep->condp()->iterateAndNext(*this);
|
2009-12-29 03:19:03 +00:00
|
|
|
|
puts(") begin\n");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
nodep->bodysp()->iterateAndNext(*this);
|
2010-02-14 15:01:21 +00:00
|
|
|
|
nodep->incsp()->iterateAndNext(*this);
|
2006-08-26 11:35:28 +00:00
|
|
|
|
nodep->precondsp()->iterateAndNext(*this); // Need to recompute before next loop
|
2009-12-29 03:19:03 +00:00
|
|
|
|
putfs(nodep,"end\n");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
|
|
|
|
virtual void visit(AstNodeIf* nodep, AstNUser*) {
|
2010-12-26 02:58:28 +00:00
|
|
|
|
putfs(nodep,"");
|
|
|
|
|
if (AstIf* ifp = nodep->castIf()) {
|
|
|
|
|
if (ifp->priorityPragma()) puts("priority ");
|
|
|
|
|
if (ifp->uniquePragma()) puts("unique ");
|
|
|
|
|
if (ifp->unique0Pragma()) puts("unique0 ");
|
|
|
|
|
}
|
|
|
|
|
puts("if (");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
nodep->condp()->iterateAndNext(*this);
|
|
|
|
|
puts(") begin\n");
|
|
|
|
|
nodep->ifsp()->iterateAndNext(*this);
|
|
|
|
|
if (nodep->elsesp()) {
|
2010-01-07 21:41:19 +00:00
|
|
|
|
putqs(nodep,"end\n");
|
|
|
|
|
putqs(nodep,"else begin\n");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
nodep->elsesp()->iterateAndNext(*this);
|
|
|
|
|
}
|
2010-01-07 21:41:19 +00:00
|
|
|
|
putqs(nodep,"end\n");
|
2010-02-14 15:01:21 +00:00
|
|
|
|
}
|
|
|
|
|
virtual void visit(AstReturn* nodep, AstNUser*) {
|
|
|
|
|
putfs(nodep,"return ");
|
|
|
|
|
nodep->lhsp()->iterateAndNext(*this);
|
|
|
|
|
puts(";\n");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
2009-12-29 03:19:03 +00:00
|
|
|
|
virtual void visit(AstStop* nodep, AstNUser*) {
|
|
|
|
|
putfs(nodep,"$stop;\n");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
2009-12-29 03:19:03 +00:00
|
|
|
|
virtual void visit(AstFinish* nodep, AstNUser*) {
|
|
|
|
|
putfs(nodep,"$finish;\n");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
|
|
|
|
virtual void visit(AstText* nodep, AstNUser*) {
|
2008-11-20 12:55:54 +00:00
|
|
|
|
putsNoTracking(nodep->text());
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
2007-06-14 16:41:32 +00:00
|
|
|
|
virtual void visit(AstScopeName* nodep, AstNUser*) {
|
|
|
|
|
}
|
2006-08-26 11:35:28 +00:00
|
|
|
|
virtual void visit(AstCStmt* nodep, AstNUser*) {
|
2009-12-29 03:19:03 +00:00
|
|
|
|
putfs(nodep,"$_CSTMT(");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
nodep->bodysp()->iterateAndNext(*this);
|
|
|
|
|
puts(");\n");
|
|
|
|
|
}
|
|
|
|
|
virtual void visit(AstCMath* nodep, AstNUser*) {
|
2009-12-29 03:19:03 +00:00
|
|
|
|
putfs(nodep,"$_CMATH(");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
nodep->bodysp()->iterateAndNext(*this);
|
|
|
|
|
puts(");\n");
|
|
|
|
|
}
|
|
|
|
|
virtual void visit(AstUCStmt* nodep, AstNUser*) {
|
2009-12-29 03:19:03 +00:00
|
|
|
|
putfs(nodep,"$c(");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
nodep->bodysp()->iterateAndNext(*this);
|
|
|
|
|
puts(");\n");
|
|
|
|
|
}
|
|
|
|
|
virtual void visit(AstUCFunc* nodep, AstNUser*) {
|
2009-12-29 03:19:03 +00:00
|
|
|
|
putfs(nodep,"$c(");
|
2010-01-09 14:05:00 +00:00
|
|
|
|
nodep->bodysp()->iterateAndNext(*this);
|
|
|
|
|
puts(")");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Operators
|
|
|
|
|
virtual void emitVerilogFormat(AstNode* nodep, const string& format,
|
|
|
|
|
AstNode* lhsp=NULL, AstNode* rhsp=NULL, AstNode* thsp=NULL) {
|
|
|
|
|
// Look at emitVerilog() format for term/uni/dual/triops,
|
|
|
|
|
// and write out appropriate text.
|
2009-12-29 03:19:03 +00:00
|
|
|
|
// %f Potential fileline-if-change and line break
|
2006-08-26 11:35:28 +00:00
|
|
|
|
// %l lhsp - if appropriate
|
|
|
|
|
// %r rhsp - if appropriate
|
|
|
|
|
// %t thsp - if appropriate
|
2012-04-29 14:14:13 +00:00
|
|
|
|
// %d dtypep - if appropriate
|
2006-08-26 11:35:28 +00:00
|
|
|
|
// %k Potential line break
|
|
|
|
|
bool inPct = false;
|
|
|
|
|
putbs("");
|
|
|
|
|
for (string::const_iterator pos = format.begin(); pos != format.end(); ++pos) {
|
|
|
|
|
if (pos[0]=='%') {
|
|
|
|
|
inPct = true;
|
|
|
|
|
} else if (!inPct) { // Normal text
|
|
|
|
|
string s; s+=pos[0]; puts(s);
|
|
|
|
|
} else { // Format character
|
|
|
|
|
inPct = false;
|
|
|
|
|
switch (*pos) {
|
|
|
|
|
case '%': puts("%"); break;
|
2009-12-29 03:19:03 +00:00
|
|
|
|
case 'f': putfs(nodep,""); break;
|
2006-08-26 11:35:28 +00:00
|
|
|
|
case 'k': putbs(""); break;
|
|
|
|
|
case 'l': {
|
|
|
|
|
if (!lhsp) { nodep->v3fatalSrc("emitVerilog() references undef node"); }
|
|
|
|
|
else lhsp->iterateAndNext(*this);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case 'r': {
|
|
|
|
|
if (!rhsp) { nodep->v3fatalSrc("emitVerilog() references undef node"); }
|
|
|
|
|
else rhsp->iterateAndNext(*this);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case 't': {
|
|
|
|
|
if (!thsp) { nodep->v3fatalSrc("emitVerilog() references undef node"); }
|
|
|
|
|
else thsp->iterateAndNext(*this);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2012-04-29 14:14:13 +00:00
|
|
|
|
case 'd': {
|
|
|
|
|
if (!nodep->dtypep()) { nodep->v3fatalSrc("emitVerilog() references undef node"); }
|
|
|
|
|
else nodep->dtypep()->iterateAndNext(*this);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2006-08-26 11:35:28 +00:00
|
|
|
|
default:
|
|
|
|
|
nodep->v3fatalSrc("Unknown emitVerilog format code: %"<<pos[0]);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void visit(AstNodeTermop* nodep, AstNUser*) {
|
|
|
|
|
emitVerilogFormat(nodep, nodep->emitVerilog());
|
|
|
|
|
}
|
|
|
|
|
virtual void visit(AstNodeUniop* nodep, AstNUser*) {
|
|
|
|
|
emitVerilogFormat(nodep, nodep->emitVerilog(), nodep->lhsp());
|
|
|
|
|
}
|
|
|
|
|
virtual void visit(AstNodeBiop* nodep, AstNUser*) {
|
|
|
|
|
emitVerilogFormat(nodep, nodep->emitVerilog(), nodep->lhsp(), nodep->rhsp());
|
|
|
|
|
}
|
|
|
|
|
virtual void visit(AstNodeTriop* nodep, AstNUser*) {
|
|
|
|
|
emitVerilogFormat(nodep, nodep->emitVerilog(), nodep->lhsp(), nodep->rhsp(), nodep->thsp());
|
|
|
|
|
}
|
|
|
|
|
virtual void visit(AstAttrOf* nodep, AstNUser*) {
|
2009-12-29 03:19:03 +00:00
|
|
|
|
putfs(nodep,"$_ATTROF(");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
nodep->fromp()->iterateAndNext(*this);
|
2013-01-20 17:19:22 +00:00
|
|
|
|
if (nodep->dimp()) {
|
|
|
|
|
putbs(",");
|
|
|
|
|
nodep->dimp()->iterateAndNext(*this);
|
|
|
|
|
}
|
2006-08-26 11:35:28 +00:00
|
|
|
|
puts(")");
|
|
|
|
|
}
|
2014-03-31 00:28:51 +00:00
|
|
|
|
virtual void visit(AstInitArray* nodep, AstNUser*) {
|
|
|
|
|
putfs(nodep,"`{");
|
|
|
|
|
for (AstNode* subp = nodep->initsp(); subp; subp=subp->nextp()) {
|
|
|
|
|
subp->accept(*this);
|
|
|
|
|
if (subp->nextp()) putbs(",");
|
|
|
|
|
}
|
|
|
|
|
puts("}");
|
|
|
|
|
}
|
2006-08-26 11:35:28 +00:00
|
|
|
|
virtual void visit(AstNodeCond* nodep, AstNUser*) {
|
|
|
|
|
putbs("(");
|
2009-12-29 03:19:03 +00:00
|
|
|
|
nodep->condp()->iterateAndNext(*this); putfs(nodep," ? ");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
nodep->expr1p()->iterateAndNext(*this); putbs(" : ");
|
|
|
|
|
nodep->expr2p()->iterateAndNext(*this); puts(")");
|
|
|
|
|
}
|
|
|
|
|
virtual void visit(AstRange* nodep, AstNUser*) {
|
|
|
|
|
puts("[");
|
2009-12-29 03:19:03 +00:00
|
|
|
|
if (nodep->msbp()->castConst() && nodep->lsbp()->castConst()) {
|
|
|
|
|
// Looks nicer if we print [1:0] rather than [32'sh1:32sh0]
|
2012-03-20 00:25:35 +00:00
|
|
|
|
puts(cvtToStr(nodep->leftp()->castConst()->toSInt())); puts(":");
|
|
|
|
|
puts(cvtToStr(nodep->rightp()->castConst()->toSInt())); puts("]");
|
2009-12-29 03:19:03 +00:00
|
|
|
|
} else {
|
2012-03-20 00:25:35 +00:00
|
|
|
|
nodep->leftp()->iterateAndNext(*this); puts(":");
|
|
|
|
|
nodep->rightp()->iterateAndNext(*this); puts("]");
|
2009-12-29 03:19:03 +00:00
|
|
|
|
}
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
|
|
|
|
virtual void visit(AstSel* nodep, AstNUser*) {
|
|
|
|
|
nodep->fromp()->iterateAndNext(*this); puts("[");
|
|
|
|
|
if (nodep->lsbp()->castConst()) {
|
|
|
|
|
if (nodep->widthp()->isOne()) {
|
2009-12-29 03:19:03 +00:00
|
|
|
|
if (nodep->lsbp()->castConst()) {
|
|
|
|
|
puts(cvtToStr(nodep->lsbp()->castConst()->toSInt()));
|
|
|
|
|
} else {
|
|
|
|
|
nodep->lsbp()->iterateAndNext(*this);
|
|
|
|
|
}
|
2006-08-26 11:35:28 +00:00
|
|
|
|
} else {
|
2008-10-06 13:59:22 +00:00
|
|
|
|
puts(cvtToStr(nodep->lsbp()->castConst()->toSInt()
|
|
|
|
|
+nodep->widthp()->castConst()->toSInt()
|
2006-08-26 11:35:28 +00:00
|
|
|
|
-1));
|
|
|
|
|
puts(":");
|
2008-10-06 13:59:22 +00:00
|
|
|
|
puts(cvtToStr(nodep->lsbp()->castConst()->toSInt()));
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
|
|
|
|
} else {
|
2009-12-29 03:19:03 +00:00
|
|
|
|
nodep->lsbp()->iterateAndNext(*this); putfs(nodep,"+:");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
nodep->widthp()->iterateAndNext(*this); puts("]");
|
|
|
|
|
}
|
|
|
|
|
puts("]");
|
|
|
|
|
}
|
2009-11-07 04:16:06 +00:00
|
|
|
|
virtual void visit(AstTypedef* nodep, AstNUser*) {
|
2009-12-29 03:19:03 +00:00
|
|
|
|
putfs(nodep,"typedef ");
|
2009-11-07 04:16:06 +00:00
|
|
|
|
nodep->dtypep()->iterateAndNext(*this); puts(" ");
|
2011-01-19 16:44:23 +00:00
|
|
|
|
puts(nodep->prettyName());
|
2009-11-07 04:16:06 +00:00
|
|
|
|
puts(";\n");
|
|
|
|
|
}
|
2009-12-29 03:19:03 +00:00
|
|
|
|
virtual void visit(AstBasicDType* nodep, AstNUser*) {
|
|
|
|
|
if (nodep->isSigned()) putfs(nodep,"signed ");
|
|
|
|
|
putfs(nodep,nodep->prettyName());
|
2011-01-19 16:44:23 +00:00
|
|
|
|
if (nodep->rangep()) { puts(" "); nodep->rangep()->iterateAndNext(*this); puts(" "); }
|
2012-03-04 21:18:41 +00:00
|
|
|
|
else if (nodep->isRanged()) { puts(" ["); puts(cvtToStr(nodep->msb())); puts(":0] "); }
|
2009-12-29 03:19:03 +00:00
|
|
|
|
}
|
2011-07-02 16:45:26 +00:00
|
|
|
|
virtual void visit(AstConstDType* nodep, AstNUser*) {
|
|
|
|
|
putfs(nodep,"const ");
|
2013-02-02 20:40:59 +00:00
|
|
|
|
nodep->subDTypep()->accept(*this);
|
2012-04-14 16:43:03 +00:00
|
|
|
|
}
|
2013-01-12 21:19:25 +00:00
|
|
|
|
virtual void visit(AstNodeArrayDType* nodep, AstNUser*) {
|
2013-02-02 20:40:59 +00:00
|
|
|
|
nodep->subDTypep()->accept(*this);
|
2012-04-22 23:18:51 +00:00
|
|
|
|
nodep->rangep()->iterateAndNext(*this);
|
2011-07-02 16:45:26 +00:00
|
|
|
|
}
|
2012-07-29 14:16:20 +00:00
|
|
|
|
virtual void visit(AstNodeClassDType* nodep, AstNUser*) {
|
|
|
|
|
puts(nodep->verilogKwd()+" ");
|
|
|
|
|
if (nodep->packed()) puts("packed ");
|
|
|
|
|
puts("\n");
|
|
|
|
|
nodep->membersp()->iterateAndNext(*this);
|
|
|
|
|
puts("}");
|
|
|
|
|
}
|
|
|
|
|
virtual void visit(AstMemberDType* nodep, AstNUser*) {
|
2013-02-02 20:40:59 +00:00
|
|
|
|
nodep->subDTypep()->accept(*this);
|
2012-07-29 14:16:20 +00:00
|
|
|
|
puts(" ");
|
|
|
|
|
puts(nodep->name());
|
|
|
|
|
puts("}");
|
|
|
|
|
}
|
2006-08-26 11:35:28 +00:00
|
|
|
|
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
|
2011-01-19 16:44:23 +00:00
|
|
|
|
if (nodep->dotted()!="") { putfs(nodep,nodep->dotted()); puts("."); puts(nodep->prettyName()); }
|
|
|
|
|
else { putfs(nodep,nodep->prettyName()); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
puts("(");
|
|
|
|
|
nodep->pinsp()->iterateAndNext(*this);
|
|
|
|
|
puts(")");
|
|
|
|
|
}
|
2013-08-18 00:34:49 +00:00
|
|
|
|
virtual void visit(AstArg* nodep, AstNUser*) {
|
|
|
|
|
nodep->exprp()->iterateAndNext(*this);
|
|
|
|
|
}
|
2006-08-26 11:35:28 +00:00
|
|
|
|
// Terminals
|
|
|
|
|
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
2010-01-08 18:29:00 +00:00
|
|
|
|
if (nodep->varScopep())
|
|
|
|
|
putfs(nodep,nodep->varScopep()->prettyName());
|
|
|
|
|
else {
|
|
|
|
|
putfs(nodep,nodep->hiername());
|
|
|
|
|
puts(nodep->varp()->prettyName());
|
|
|
|
|
}
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
|
|
|
|
virtual void visit(AstVarXRef* nodep, AstNUser*) {
|
2009-12-29 03:19:03 +00:00
|
|
|
|
putfs(nodep,nodep->dotted());
|
2006-08-26 11:35:28 +00:00
|
|
|
|
puts(".");
|
2010-01-07 21:41:19 +00:00
|
|
|
|
puts(nodep->varp()->prettyName());
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
|
|
|
|
virtual void visit(AstConst* nodep, AstNUser*) {
|
2009-12-29 03:19:03 +00:00
|
|
|
|
putfs(nodep,nodep->num().ascii(true,true));
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
2010-01-18 01:06:08 +00:00
|
|
|
|
virtual void visit(AstConstString* nodep, AstNUser*) {
|
|
|
|
|
putfs(nodep,"");
|
|
|
|
|
putsQuoted(nodep->name());
|
|
|
|
|
}
|
2006-08-26 11:35:28 +00:00
|
|
|
|
|
|
|
|
|
// Just iterate
|
|
|
|
|
virtual void visit(AstTopScope* nodep, AstNUser*) {
|
|
|
|
|
nodep->iterateChildren(*this);
|
|
|
|
|
}
|
|
|
|
|
virtual void visit(AstScope* nodep, AstNUser*) {
|
|
|
|
|
nodep->iterateChildren(*this);
|
|
|
|
|
}
|
|
|
|
|
virtual void visit(AstVar* nodep, AstNUser*) {
|
2009-12-29 03:19:03 +00:00
|
|
|
|
putfs(nodep,nodep->verilogKwd());
|
2006-08-26 11:35:28 +00:00
|
|
|
|
puts(" ");
|
2014-05-10 11:50:04 +00:00
|
|
|
|
nodep->dtypep()->iterate(*this); puts(" ");
|
2011-01-19 16:44:23 +00:00
|
|
|
|
puts(nodep->prettyName());
|
2006-08-26 11:35:28 +00:00
|
|
|
|
puts(";\n");
|
|
|
|
|
}
|
2009-12-29 03:19:03 +00:00
|
|
|
|
virtual void visit(AstActive* nodep, AstNUser*) {
|
|
|
|
|
m_sensesp = nodep->sensesp();
|
2010-01-07 21:41:19 +00:00
|
|
|
|
nodep->stmtsp()->iterateAndNext(*this);
|
2009-12-29 03:19:03 +00:00
|
|
|
|
m_sensesp = NULL;
|
|
|
|
|
}
|
|
|
|
|
virtual void visit(AstVarScope*, AstNUser*) {}
|
2006-08-26 11:35:28 +00:00
|
|
|
|
virtual void visit(AstNodeText*, AstNUser*) {}
|
|
|
|
|
virtual void visit(AstTraceDecl*, AstNUser*) {}
|
|
|
|
|
virtual void visit(AstTraceInc*, AstNUser*) {}
|
|
|
|
|
// NOPs
|
|
|
|
|
virtual void visit(AstPragma*, AstNUser*) {}
|
|
|
|
|
virtual void visit(AstCell*, AstNUser*) {} // Handled outside the Visit class
|
|
|
|
|
// Default
|
|
|
|
|
virtual void visit(AstNode* nodep, AstNUser*) {
|
2009-07-09 21:39:24 +00:00
|
|
|
|
puts((string)"\n???? // "+nodep->prettyTypeName()+"\n");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
nodep->iterateChildren(*this);
|
2009-12-29 03:19:03 +00:00
|
|
|
|
// Not v3fatalSrc so we keep processing
|
|
|
|
|
nodep->v3error("Internal: Unknown node type reached emitter: "<<nodep->prettyTypeName());
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
2010-01-09 14:05:00 +00:00
|
|
|
|
EmitVBaseVisitor(AstSenTree* domainp=NULL) { // Domain for printing one a ALWAYS under a ACTIVE
|
2006-08-26 11:35:28 +00:00
|
|
|
|
m_suppressSemi = false;
|
2010-01-09 14:05:00 +00:00
|
|
|
|
m_sensesp = domainp;
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
2008-11-20 12:55:54 +00:00
|
|
|
|
virtual ~EmitVBaseVisitor() {}
|
2006-08-26 11:35:28 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
2008-11-20 12:55:54 +00:00
|
|
|
|
// Emit to an output file
|
2006-08-26 11:35:28 +00:00
|
|
|
|
|
2008-11-20 12:55:54 +00:00
|
|
|
|
class EmitVFileVisitor : public EmitVBaseVisitor {
|
|
|
|
|
// MEMBERS
|
|
|
|
|
V3OutFile* m_ofp;
|
|
|
|
|
// METHODS
|
2009-07-22 18:38:20 +00:00
|
|
|
|
V3OutFile* ofp() const { return m_ofp; }
|
2009-12-29 03:19:03 +00:00
|
|
|
|
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); }
|
2010-01-07 21:41:19 +00:00
|
|
|
|
virtual void putqs(AstNode*, const string& str) { putbs(str); }
|
2009-12-29 03:19:03 +00:00
|
|
|
|
virtual void putsNoTracking(const string& str) { ofp()->putsNoTracking(str); }
|
2008-11-20 12:55:54 +00:00
|
|
|
|
public:
|
|
|
|
|
EmitVFileVisitor(AstNode* nodep, V3OutFile* ofp) {
|
|
|
|
|
m_ofp = ofp;
|
|
|
|
|
nodep->accept(*this);
|
|
|
|
|
}
|
|
|
|
|
virtual ~EmitVFileVisitor() {}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
// Emit to a stream (perhaps stringstream)
|
|
|
|
|
|
|
|
|
|
class EmitVStreamVisitor : public EmitVBaseVisitor {
|
|
|
|
|
// MEMBERS
|
|
|
|
|
ostream& m_os;
|
|
|
|
|
// METHODS
|
2009-12-29 03:19:03 +00:00
|
|
|
|
virtual void putsNoTracking(const string& str) { m_os<<str; }
|
2010-01-07 21:41:19 +00:00
|
|
|
|
virtual void puts(const string& str) { putsNoTracking(str); }
|
|
|
|
|
virtual void putbs(const string& str) { puts(str); }
|
|
|
|
|
virtual void putfs(AstNode*, const string& str) { putbs(str); }
|
|
|
|
|
virtual void putqs(AstNode*, const string& str) { putbs(str); }
|
2012-03-20 19:57:29 +00:00
|
|
|
|
public:
|
2008-11-20 12:55:54 +00:00
|
|
|
|
EmitVStreamVisitor(AstNode* nodep, ostream& os)
|
|
|
|
|
: m_os(os) {
|
|
|
|
|
nodep->accept(*this);
|
|
|
|
|
}
|
|
|
|
|
virtual ~EmitVStreamVisitor() {}
|
|
|
|
|
};
|
2006-08-26 11:35:28 +00:00
|
|
|
|
|
2010-01-07 21:41:19 +00:00
|
|
|
|
//######################################################################
|
|
|
|
|
// Emit to a stream (perhaps stringstream)
|
|
|
|
|
|
|
|
|
|
class EmitVPrefixedFormatter : public V3OutFormatter {
|
|
|
|
|
ostream& m_os;
|
|
|
|
|
string m_prefix; // What to print at beginning of each line
|
2010-01-15 14:30:20 +00:00
|
|
|
|
int m_flWidth; // Padding of fileline
|
2010-01-07 21:41:19 +00:00
|
|
|
|
int m_column; // Rough location; need just zero or non-zero
|
|
|
|
|
FileLine* m_prefixFl;
|
|
|
|
|
// METHODS
|
|
|
|
|
virtual void putcOutput(char chr) {
|
|
|
|
|
if (chr == '\n') {
|
|
|
|
|
m_column = 0;
|
|
|
|
|
m_os<<chr;
|
|
|
|
|
} else {
|
|
|
|
|
if (m_column == 0) {
|
|
|
|
|
m_column = 10;
|
|
|
|
|
m_os<<m_prefixFl->ascii()+":";
|
2010-01-15 14:30:20 +00:00
|
|
|
|
m_os<<V3OutFile::indentSpaces(m_flWidth-(m_prefixFl->ascii().length()+1));
|
2010-01-07 21:41:19 +00:00
|
|
|
|
m_os<<" ";
|
|
|
|
|
m_os<<m_prefix;
|
|
|
|
|
}
|
|
|
|
|
m_column++;
|
|
|
|
|
m_os<<chr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
public:
|
|
|
|
|
void prefixFl(FileLine* fl) { m_prefixFl = fl; }
|
|
|
|
|
FileLine* prefixFl() const { return m_prefixFl; }
|
|
|
|
|
int column() const { return m_column; }
|
2010-01-15 14:30:20 +00:00
|
|
|
|
EmitVPrefixedFormatter(ostream& os, const string& prefix, int flWidth)
|
2012-03-20 19:57:29 +00:00
|
|
|
|
: V3OutFormatter("__STREAM", V3OutFormatter::LA_VERILOG)
|
|
|
|
|
, m_os(os), m_prefix(prefix), m_flWidth(flWidth) {
|
2010-01-07 21:41:19 +00:00
|
|
|
|
m_column = 0;
|
|
|
|
|
m_prefixFl = v3Global.rootp()->fileline(); // NETLIST's fileline instead of NULL to avoid NULL checks
|
|
|
|
|
}
|
|
|
|
|
virtual ~EmitVPrefixedFormatter() {
|
|
|
|
|
if (m_column) puts("\n");
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class EmitVPrefixedVisitor : public EmitVBaseVisitor {
|
|
|
|
|
// MEMBERS
|
|
|
|
|
EmitVPrefixedFormatter m_formatter; // Special verilog formatter (Way down the inheritance is another unused V3OutFormatter)
|
|
|
|
|
bool m_user3mark; // nodep->user3() if set means mark with %%
|
|
|
|
|
// METHODS
|
|
|
|
|
virtual void putsNoTracking(const string& str) { m_formatter.putsNoTracking(str); }
|
|
|
|
|
virtual void puts(const string& str) { m_formatter.puts(str); }
|
|
|
|
|
// We don't use m_formatter's putbs because the tokens will change filelines
|
|
|
|
|
// and insert returns at the proper locations
|
|
|
|
|
virtual void putbs(const string& str) { m_formatter.puts(str); }
|
|
|
|
|
virtual void putfs(AstNode* nodep, const string& str) { putfsqs(nodep,str,false); }
|
|
|
|
|
virtual void putqs(AstNode* nodep, const string& str) { putfsqs(nodep,str,true); }
|
|
|
|
|
void putfsqs(AstNode* nodep, const string& str, bool quiet) {
|
|
|
|
|
if (m_formatter.prefixFl() != nodep->fileline()) {
|
|
|
|
|
m_formatter.prefixFl(nodep->fileline());
|
|
|
|
|
if (m_formatter.column()) puts("\n"); // This in turn will print the m_prefixFl
|
|
|
|
|
}
|
|
|
|
|
if (!quiet && nodep->user3()) puts("%%");
|
|
|
|
|
putbs(str);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
2010-01-15 14:30:20 +00:00
|
|
|
|
EmitVPrefixedVisitor(AstNode* nodep, ostream& os, const string& prefix, int flWidth,
|
2010-01-09 14:05:00 +00:00
|
|
|
|
AstSenTree* domainp, bool user3mark)
|
2010-01-15 14:30:20 +00:00
|
|
|
|
: EmitVBaseVisitor(domainp), m_formatter(os, prefix, flWidth), m_user3mark(user3mark) {
|
2010-01-07 21:41:19 +00:00
|
|
|
|
if (user3mark) { AstUser3InUse::check(); }
|
|
|
|
|
nodep->accept(*this);
|
|
|
|
|
}
|
|
|
|
|
virtual ~EmitVPrefixedVisitor() {}
|
|
|
|
|
};
|
|
|
|
|
|
2006-08-26 11:35:28 +00:00
|
|
|
|
//######################################################################
|
|
|
|
|
// EmitV class functions
|
|
|
|
|
|
|
|
|
|
void V3EmitV::emitv() {
|
|
|
|
|
UINFO(2,__FUNCTION__<<": "<<endl);
|
|
|
|
|
if (1) {
|
|
|
|
|
// All-in-one file
|
|
|
|
|
V3OutVFile of (v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"__Vout.v");
|
|
|
|
|
of.putsHeader();
|
2009-12-03 01:09:13 +00:00
|
|
|
|
of.puts("# DESCR" "IPTION: Verilator output: Verilog representation of internal tree for debug\n");
|
2008-11-20 12:55:54 +00:00
|
|
|
|
EmitVFileVisitor visitor (v3Global.rootp(), &of);
|
2006-08-26 11:35:28 +00:00
|
|
|
|
} else {
|
|
|
|
|
// Process each module in turn
|
2009-11-07 11:20:20 +00:00
|
|
|
|
for (AstNodeModule* modp = v3Global.rootp()->modulesp(); modp; modp=modp->nextp()->castNodeModule()) {
|
2008-11-20 12:55:54 +00:00
|
|
|
|
V3OutVFile of (v3Global.opt.makeDir()
|
|
|
|
|
+"/"+EmitCBaseVisitor::modClassName(modp)+"__Vout.v");
|
2006-08-26 11:35:28 +00:00
|
|
|
|
of.putsHeader();
|
2008-11-20 12:55:54 +00:00
|
|
|
|
EmitVFileVisitor visitor (modp, &of);
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2008-11-20 12:55:54 +00:00
|
|
|
|
|
|
|
|
|
void V3EmitV::verilogForTree(AstNode* nodep, ostream& os) {
|
|
|
|
|
EmitVStreamVisitor(nodep, os);
|
|
|
|
|
}
|
2010-01-07 21:41:19 +00:00
|
|
|
|
|
2010-01-15 14:30:20 +00:00
|
|
|
|
void V3EmitV::verilogPrefixedTree(AstNode* nodep, ostream& os, const string& prefix, int flWidth,
|
2010-01-09 14:05:00 +00:00
|
|
|
|
AstSenTree* domainp, bool user3mark) {
|
2010-01-15 14:30:20 +00:00
|
|
|
|
EmitVPrefixedVisitor(nodep, os, prefix, flWidth, domainp, user3mark);
|
2010-01-07 21:41:19 +00:00
|
|
|
|
}
|