Compare commits

...
6 Commits
Author SHA1 Message Date
Wilson Snyder 663a084ca4 Version bump
git-svn-id: file://localhost/svn/verilator/trunk/verilator@989 77ca24e4-aefa-0310-84f0-b9a241c72d87
2008-02-20 16:55:43 +00:00
Wilson Snyder b4d9ccd9af Fix assignments of {a,b,c} = {c,b,a}
git-svn-id: file://localhost/svn/verilator/trunk/verilator@988 77ca24e4-aefa-0310-84f0-b9a241c72d87
2008-02-20 16:54:41 +00:00
Wilson Snyder 98fff6a4ce Fix parsing of always @(*)
git-svn-id: file://localhost/svn/verilator/trunk/verilator@987 77ca24e4-aefa-0310-84f0-b9a241c72d87
2008-02-14 02:08:10 +00:00
Wilson Snyder 4977a5e1d9 Fix parse error on output reg signed
git-svn-id: file://localhost/svn/verilator/trunk/verilator@986 77ca24e4-aefa-0310-84f0-b9a241c72d87
2008-02-08 18:38:47 +00:00
Wilson Snyder e4297486ef Avoid creating obj_dir with --lint-only
git-svn-id: file://localhost/svn/verilator/trunk/verilator@985 77ca24e4-aefa-0310-84f0-b9a241c72d87
2008-01-31 14:49:27 +00:00
Wilson Snyder ad591767c9 Make obj_dir only when needed, and use OS calls rather than system to clean up
git-svn-id: file://localhost/svn/verilator/trunk/verilator@984 77ca24e4-aefa-0310-84f0-b9a241c72d87
2008-01-31 13:50:06 +00:00
22 changed files with 486 additions and 90 deletions
+10
View File
@@ -3,6 +3,16 @@ Revision history for Verilator
The contributors that suggested a given feature are shown in []. [by ...] The contributors that suggested a given feature are shown in []. [by ...]
indicates the contributor was also the author of the fix; Thanks! indicates the contributor was also the author of the fix; Thanks!
* Verilator 3.657 2008/02/20
**** Fix assignments of {a,b,c} = {c,b,a}. [Jonathan Kimmitt]
**** Fix Perl warning with --lint-only. [by Ding Xiaoliang]
**** Avoid creating obj_dir with --lint-only. [Ding Xiaoliang]
**** Fix parsing of always @(*). [Patricio Kaplan]
* Verilator 3.656 2008/01/18 * Verilator 3.656 2008/01/18
**** Wide VL_CONST_W_#X functions are now made automatically. [Bernard Deadman] **** Wide VL_CONST_W_#X functions are now made automatically. [Bernard Deadman]
+4
View File
@@ -52,6 +52,10 @@ Usability:
Better reporting of unopt problems, including what lines of code Better reporting of unopt problems, including what lines of code
Report more errors (all of them?) before exiting [Eugene Weber] Report more errors (all of them?) before exiting [Eugene Weber]
Internal Code:
Eliminate the AstNUser* passed to all visitors; its only needed in V3Width,
and removing it will speed up and simplify all the other code.
Performance: Performance:
Constant propagation Constant propagation
Extra cleaning AND: 1 & ((VARREF >> 1) | ((&VARREF >> 1) & VARREF)) Extra cleaning AND: 1 & ((VARREF >> 1) | ((&VARREF >> 1) & VARREF))
+2 -1
View File
@@ -91,6 +91,7 @@ if (! GetOptions (
"sp!" => sub {$Opt_Sp = 'sp';}, "sp!" => sub {$Opt_Sp = 'sp';},
"sc!" => sub {$Opt_Sp = 'sc';}, "sc!" => sub {$Opt_Sp = 'sc';},
"cc!" => sub {$Opt_Sp = 0;}, "cc!" => sub {$Opt_Sp = 0;},
"lint-only!" => sub {$Opt_Sp = 0;},
#"ignc!" => ..., # Undocumented debugging, disable $c but don't complain #"ignc!" => ..., # Undocumented debugging, disable $c but don't complain
# Additional parameters # Additional parameters
"<>" => sub {}, # Ignored "<>" => sub {}, # Ignored
@@ -434,7 +435,7 @@ to gcc -MP option.
=item --Mdir I<directory> =item --Mdir I<directory>
Specifies the name of the Make object directory. All generated files will Specifies the name of the Make object directory. All generated files will
be placed in this directory. be placed in this directory. If not specified, "obj_dir" is used.
=item --mod-prefix I<topname> =item --mod-prefix I<topname>
+115 -11
View File
@@ -39,11 +39,63 @@
#include "V3Width.h" #include "V3Width.h"
#include "V3Signed.h" #include "V3Signed.h"
//######################################################################
// Utilities
class ConstVarMarkVisitor : public AstNVisitor {
// NODE STATE
// AstVar::userp -> bool, Var marked, 0=not set yet
private:
// VISITORS
virtual void visit(AstVarRef* nodep, AstNUser*) {
if (nodep->varp()) nodep->varp()->user(1);
}
virtual void visit(AstNode* nodep, AstNUser*) {
nodep->iterateChildren(*this);
}
public:
// CONSTUCTORS
ConstVarMarkVisitor(AstNode* nodep) {
AstNode::userClearTree();
nodep->iterateAndNext(*this, NULL);
}
virtual ~ConstVarMarkVisitor() {}
};
class ConstVarFindVisitor : public AstNVisitor {
// NODE STATE
// AstVar::userp -> bool, input from ConstVarMarkVisitor
// MEMBERS
bool m_found;
private:
// VISITORS
virtual void visit(AstVarRef* nodep, AstNUser*) {
if (nodep->varp() && nodep->varp()->user()) m_found = true;
}
virtual void visit(AstNode* nodep, AstNUser*) {
nodep->iterateChildren(*this);
}
public:
// CONSTUCTORS
ConstVarFindVisitor(AstNode* nodep) {
m_found = false;
nodep->iterateAndNext(*this, NULL);
}
virtual ~ConstVarFindVisitor() {}
// METHODS
bool found() const { return m_found; }
};
//###################################################################### //######################################################################
// Const state, as a visitor of each AstNode // Const state, as a visitor of each AstNode
class ConstVisitor : public AstNVisitor { class ConstVisitor : public AstNVisitor {
private: private:
// NODE STATE
// ** only when m_warn is set. If state is needed other times,
// ** must track down everywhere V3Const is called and make sure no overlaps.
// AstVar::userp -> Used by ConstVarMarkVisitor/ConstVarFindVisitor
// STATE // STATE
bool m_params; // If true, propogate parameterized and true numbers only bool m_params; // If true, propogate parameterized and true numbers only
bool m_required; // If true, must become a constant bool m_required; // If true, must become a constant
@@ -494,10 +546,26 @@ private:
} }
} }
else if (!m_cpp && nodep->lhsp()->castConcat()) { else if (!m_cpp && nodep->lhsp()->castConcat()) {
UINFO(4," ASSI "<<nodep<<endl); bool need_temp = false;
if (m_warn && !nodep->castAssignDly()) { // Is same var on LHS and RHS?
ConstVarMarkVisitor mark(nodep->lhsp());
ConstVarFindVisitor find(nodep->rhsp());
if (find.found()) need_temp = true;
}
if (need_temp) {
// The first time we constify, there may be the same variable on the LHS
// and RHS. In that case, we must use temporaries, or {a,b}={b,a} will break.
UINFO(4," ASSITEMP "<<nodep<<endl);
// ASSIGN(CONCAT(lc1,lc2),rhs) -> ASSIGN(temp1,SEL(rhs,{size})),
// ASSIGN(temp2,SEL(newrhs,{size}))
// ASSIGN(lc1,temp1),
// ASSIGN(lc2,temp2)
} else {
UINFO(4," ASSI "<<nodep<<endl);
// ASSIGN(CONCAT(lc1,lc2),rhs) -> ASSIGN(lc1,SEL(rhs,{size})),
// ASSIGN(lc2,SEL(newrhs,{size}))
}
if (debug()>=9) nodep->dumpTree(cout," Ass_old: "); if (debug()>=9) nodep->dumpTree(cout," Ass_old: ");
// ASSIGN(CONCAT(lc1,lc2),rhs) -> ASSIGN(lc1,SEL(rhs,{size})),
// ASSIGN(lc2,SEL(newrhs,{size}))
// Unlink the stuff // Unlink the stuff
AstNode* lc1p = nodep->lhsp()->castConcat()->lhsp()->unlinkFrBack(); AstNode* lc1p = nodep->lhsp()->castConcat()->lhsp()->unlinkFrBack();
AstNode* lc2p = nodep->lhsp()->castConcat()->rhsp()->unlinkFrBack(); AstNode* lc2p = nodep->lhsp()->castConcat()->rhsp()->unlinkFrBack();
@@ -517,14 +585,50 @@ private:
sel2p->width(msb2-lsb2+1,msb2-lsb2+1); sel2p->width(msb2-lsb2+1,msb2-lsb2+1);
// Make new assigns of same flavor as old one // Make new assigns of same flavor as old one
//*** Not cloneTree; just one node. //*** Not cloneTree; just one node.
AstNodeAssign* asn1p=nodep->cloneType(lc1p, sel1p)->castNodeAssign(); AstNode* newp = NULL;
AstNodeAssign* asn2p=nodep->cloneType(lc2p, sel2p)->castNodeAssign(); if (!need_temp) {
asn1p->width(msb1-lsb1+1,msb1-lsb1+1); AstNodeAssign* asn1ap=nodep->cloneType(lc1p, sel1p)->castNodeAssign();
asn2p->width(msb2-lsb2+1,msb2-lsb2+1); AstNodeAssign* asn2ap=nodep->cloneType(lc2p, sel2p)->castNodeAssign();
nodep->addNextHere(asn1p); asn1ap->width(msb1-lsb1+1,msb1-lsb1+1);
nodep->addNextHere(asn2p); asn2ap->width(msb2-lsb2+1,msb2-lsb2+1);
if (debug()>=9) asn1p->dumpTree(cout," _new: "); newp = newp->addNext(asn1ap);
if (debug()>=9) asn2p->dumpTree(cout," _new: "); newp = newp->addNext(asn2ap);
} else {
if (!m_modp) nodep->v3fatalSrc("Not under module");
// We could create just one temp variable, but we'll get better optimization
// if we make one per term.
string name1 = ((string)"__Vconcswap__"+cvtToStr(m_modp->varNumGetInc()));
string name2 = ((string)"__Vconcswap__"+cvtToStr(m_modp->varNumGetInc()));
AstVar* temp1p = new AstVar(sel1p->fileline(), AstVarType::BLOCKTEMP, name1,
new AstRange(sel1p->fileline(), msb1-lsb1, 0));
AstVar* temp2p = new AstVar(sel2p->fileline(), AstVarType::BLOCKTEMP, name2,
new AstRange(sel2p->fileline(), msb2-lsb2, 0));
m_modp->addStmtp(temp1p);
m_modp->addStmtp(temp2p);
AstNodeAssign* asn1ap=nodep->cloneType
(new AstVarRef(sel1p->fileline(), temp1p, true),
sel1p)->castNodeAssign();
AstNodeAssign* asn2ap=nodep->cloneType
(new AstVarRef(sel2p->fileline(), temp2p, true),
sel2p)->castNodeAssign();
AstNodeAssign* asn1bp=nodep->cloneType
(lc1p, new AstVarRef(sel1p->fileline(), temp1p, false))
->castNodeAssign();
AstNodeAssign* asn2bp=nodep->cloneType
(lc2p, new AstVarRef(sel2p->fileline(), temp2p, false))
->castNodeAssign();
asn1ap->width(msb1-lsb1+1,msb1-lsb1+1);
asn1bp->width(msb1-lsb1+1,msb1-lsb1+1);
asn2ap->width(msb2-lsb2+1,msb2-lsb2+1);
asn2bp->width(msb2-lsb2+1,msb2-lsb2+1);
// This order matters
newp = newp->addNext(asn1ap);
newp = newp->addNext(asn2ap);
newp = newp->addNext(asn1bp);
newp = newp->addNext(asn2bp);
}
if (debug()>=9) newp->dumpTreeAndNext(cout," _new: ");
nodep->addNextHere(newp);
// Cleanup // Cleanup
nodep->unlinkFrBack()->deleteTree(); nodep=NULL; nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
conp->deleteTree(); conp=NULL; conp->deleteTree(); conp=NULL;
+9
View File
@@ -23,6 +23,7 @@
#include "verilatedos.h" #include "verilatedos.h"
#include <stdarg.h> #include <stdarg.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include <iomanip> #include <iomanip>
#include <memory> #include <memory>
@@ -232,6 +233,14 @@ bool V3File::checkTimes(const string& filename, const string& cmdline) {
return dependImp.checkTimes(filename, cmdline); return dependImp.checkTimes(filename, cmdline);
} }
void V3File::createMakeDir() {
static bool created = false;
if (!created) {
created = true;
mkdir(v3Global.opt.makeDir().c_str(), 0777);
}
}
//###################################################################### //######################################################################
// V3OutFile: A class for printing to a file, with automatic indentation of C++ code. // V3OutFile: A class for printing to a file, with automatic indentation of C++ code.
+6
View File
@@ -46,6 +46,7 @@ public:
return new_ofstream_nodepend (filename, append); return new_ofstream_nodepend (filename, append);
} }
static ofstream* new_ofstream_nodepend(const string& filename, bool append=false) { static ofstream* new_ofstream_nodepend(const string& filename, bool append=false) {
if (filename != "/dev/null") createMakeDir();
if (append) { if (append) {
return new ofstream(filename.c_str(), ios::app); return new ofstream(filename.c_str(), ios::app);
} else { } else {
@@ -53,15 +54,20 @@ public:
} }
} }
static FILE* new_fopen_w(const string& filename) { static FILE* new_fopen_w(const string& filename) {
if (filename != "/dev/null") createMakeDir();
addTgtDepend(filename); addTgtDepend(filename);
return fopen(filename.c_str(),"w"); return fopen(filename.c_str(),"w");
} }
// Dependencies // Dependencies
static void addSrcDepend(const string& filename); static void addSrcDepend(const string& filename);
static void addTgtDepend(const string& filename); static void addTgtDepend(const string& filename);
static void writeDepend(const string& filename); static void writeDepend(const string& filename);
static void writeTimes(const string& filename, const string& cmdline); static void writeTimes(const string& filename, const string& cmdline);
static bool checkTimes(const string& filename, const string& cmdline); static bool checkTimes(const string& filename, const string& cmdline);
// Directory utilities
static void createMakeDir();
}; };
//============================================================================ //============================================================================
+49
View File
@@ -226,6 +226,55 @@ string V3Options::filePath (FileLine* fl, const string& modname, const string& e
return ""; return "";
} }
void V3Options::unlinkRegexp(const string& dir, const string& regexp) {
if (DIR* dirp = opendir(dir.c_str())) {
while (struct dirent* direntp = readdir(dirp)) {
if (wildmatch(direntp->d_name, regexp.c_str())) {
string fullname = dir + "/" + string(direntp->d_name);
unlink (fullname.c_str());
}
}
closedir(dirp);
}
}
// Double procedures, inlined, unrolls loop much better
inline bool V3Options::wildmatchi(const char* s, const char* p) {
for ( ; *p; s++, p++) {
if (*p!='*') {
if (((*s)!=(*p)) && *p != '?')
return false;
}
else {
// Trailing star matches everything.
if (!*++p) return true;
while (wildmatch(s, p) == false)
if (*++s == '\0')
return false;
return true;
}
}
return(*s == '\0' || *s == '[');
}
bool V3Options::wildmatch(const char* s, const char* p) {
for ( ; *p; s++, p++) {
if (*p!='*') {
if (((*s)!=(*p)) && *p != '?')
return false;
}
else {
// Trailing star matches everything.
if (!*++p) return true;
while (wildmatchi(s, p) == false)
if (*++s == '\0')
return false;
return true;
}
}
return(*s == '\0' || *s == '[');
}
//###################################################################### //######################################################################
// V3 Options accessors // V3 Options accessors
+5
View File
@@ -115,6 +115,7 @@ class V3Options {
void optimize(int level); void optimize(int level);
void coverage(bool flag) { m_coverageLine = m_coverageUser = flag; } void coverage(bool flag) { m_coverageLine = m_coverageUser = flag; }
bool onoff(const char* sw, const char* arg, bool& flag); bool onoff(const char* sw, const char* arg, bool& flag);
static bool wildmatchi(const char* s, const char* p);
public: public:
// CREATORS // CREATORS
@@ -203,12 +204,16 @@ class V3Options {
void parseOptsList (FileLine* fl, int argc, char** argv); void parseOptsList (FileLine* fl, int argc, char** argv);
void parseOptsFile (FileLine* fl, const string& filename); void parseOptsFile (FileLine* fl, const string& filename);
// METHODS (generic string utilities)
static bool wildmatch(const char* s, const char* p);
// METHODS (generic file utilities) // METHODS (generic file utilities)
static string filenameFromDirBase (const string& dir, const string& basename); static string filenameFromDirBase (const string& dir, const string& basename);
static string filenameNonDir (const string& filename); ///< Return non-directory part of filename static string filenameNonDir (const string& filename); ///< Return non-directory part of filename
static string filenameNonExt (const string& filename); ///< Return non-extensioned (no .) part of filename static string filenameNonExt (const string& filename); ///< Return non-extensioned (no .) part of filename
static string filenameNonDirExt (const string& filename) { return filenameNonExt(filenameNonDir(filename)); } ///< Return basename of filename static string filenameNonDirExt (const string& filename) { return filenameNonExt(filenameNonDir(filename)); } ///< Return basename of filename
static string filenameDir (const string& filename); ///< Return directory part of filename static string filenameDir (const string& filename); ///< Return directory part of filename
static void unlinkRegexp(const string& dir, const string& regexp);
static string getenvStr(const char* envvar, const char* defaultValue) { static string getenvStr(const char* envvar, const char* defaultValue) {
if (const char* envvalue = getenv(envvar)) { if (const char* envvalue = getenv(envvar)) {
return envvalue; return envvalue;
+5 -27
View File
@@ -33,6 +33,7 @@
#include "V3PreShell.h" #include "V3PreShell.h"
#include "V3PreProc.h" #include "V3PreProc.h"
#include "V3File.h" #include "V3File.h"
#include "V3Read.h"
//###################################################################### //######################################################################
@@ -64,38 +65,15 @@ protected:
} }
} }
void preproc (FileLine* fl, const string& modname, const string& vppFilename) { void preproc (FileLine* fl, const string& modname, V3Read* readerp) {
// Preprocess the given module, putting output in vppFilename // Preprocess the given module, putting output in vppFilename
unlink(vppFilename.c_str());
UINFONL(1," Preprocessing "<<modname<<endl); UINFONL(1," Preprocessing "<<modname<<endl);
// Open
ofstream* ofp = NULL;
ostream* osp;
if (v3Global.opt.preprocOnly()) {
osp = &cout;
} else if (!v3Global.opt.keepTempFiles()) { // Must match unlink rule in V3Read.cpp
osp = ofp = V3File::new_ofstream_nodepend(vppFilename);
} else {
osp = ofp = V3File::new_ofstream(vppFilename);
}
if (osp->fail()) {
fl->v3error("Cannot write preprocessor output: "+vppFilename);
return;
}
// Preprocess // Preprocess
preprocOpen(fl, modname, "Cannot find file containing module: "); preprocOpen(fl, modname, "Cannot find file containing module: ");
while (!s_preprocp->isEof()) { while (!s_preprocp->isEof()) {
string line = s_preprocp->getline(); string line = s_preprocp->getline();
*osp << line; readerp->ppPushText(line);
}
// Close
if (ofp) {
ofp->close();
delete ofp;
osp = ofp = NULL;
} }
} }
@@ -129,8 +107,8 @@ V3PreProc* V3PreShellImp::s_preprocp = NULL;
void V3PreShell::boot(char** env) { void V3PreShell::boot(char** env) {
V3PreShellImp::s_preImp.boot(env); V3PreShellImp::s_preImp.boot(env);
} }
void V3PreShell::preproc(FileLine* fl, const string& modname, const string& vppFilename) { void V3PreShell::preproc(FileLine* fl, const string& modname, V3Read* readerp) {
V3PreShellImp::s_preImp.preproc(fl, modname, vppFilename); V3PreShellImp::s_preImp.preproc(fl, modname, readerp);
} }
void V3PreShell::preprocInclude(FileLine* fl, const string& modname) { void V3PreShell::preprocInclude(FileLine* fl, const string& modname) {
V3PreShellImp::s_preImp.preprocInclude(fl, modname); V3PreShellImp::s_preImp.preprocInclude(fl, modname);
+3 -1
View File
@@ -26,13 +26,15 @@
#include "verilatedos.h" #include "verilatedos.h"
#include "V3Error.h" #include "V3Error.h"
class V3Read;
//============================================================================ //============================================================================
class V3PreShell { class V3PreShell {
// Static class for calling preprocessor // Static class for calling preprocessor
public: public:
static void boot(char** env); static void boot(char** env);
static void preproc(FileLine* fileline, const string& module, const string& vppFilename); static void preproc(FileLine* fileline, const string& module, V3Read* readerp);
static void preprocInclude(FileLine* fileline, const string& module); static void preprocInclude(FileLine* fileline, const string& module);
static string dependFiles() { return ""; } // Perl only static string dependFiles() { return ""; } // Perl only
static void define(const string& name, const string& value); static void define(const string& name, const string& value);
+55 -22
View File
@@ -57,7 +57,7 @@ extern int yydebug;
class V3Lexer : public V3LexerBase { class V3Lexer : public V3LexerBase {
public: public:
// CONSTRUCTORS // CONSTRUCTORS
V3Lexer(std::istream* arg_yyin) : V3LexerBase(arg_yyin) {} V3Lexer() : V3LexerBase(NULL) {}
~V3Lexer() {} ~V3Lexer() {}
// METHODS // METHODS
void stateExitPsl() { void stateExitPsl() {
@@ -91,6 +91,29 @@ V3Read::~V3Read() {
parserClear(); parserClear();
} }
int V3Read::ppInputToLex(char* buf, int max_size) {
int got = 0;
while (got < max_size // Haven't got enough
&& !m_ppBuffers.empty()) { // And something buffered
string front = m_ppBuffers.front(); m_ppBuffers.pop_front();
int len = front.length();
if (len > (max_size-got)) { // Front string too big
string remainder = front.substr(max_size-got);
front = front.substr(0, max_size-got);
m_ppBuffers.push_front(remainder); // Put back remainder for next time
len = (max_size-got);
}
strncpy(buf+got, front.c_str(), len);
got += len;
}
if (debug()>=9) {
string out = string(buf,got);
cout<<" inputToLex got="<<got<<" '"<<out<<"'"<<endl;
}
// Note returns 0 at EOF
return got;
}
void V3Read::readFile(FileLine* fileline, const string& modfilename, bool inLibrary) { void V3Read::readFile(FileLine* fileline, const string& modfilename, bool inLibrary) {
string modname = V3Options::filenameNonExt(modfilename); string modname = V3Options::filenameNonExt(modfilename);
@@ -98,42 +121,52 @@ void V3Read::readFile(FileLine* fileline, const string& modfilename, bool inLibr
m_fileline = new FileLine(fileline); m_fileline = new FileLine(fileline);
m_inLibrary = inLibrary; m_inLibrary = inLibrary;
// Read it // Preprocess into m_ppBuffer
string vppfilename = v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"_"+modname+".vpp"; V3PreShell::preproc(fileline, modfilename, this);
V3PreShell::preproc(fileline, modfilename, vppfilename);
if (!v3Global.opt.preprocOnly()) { if (v3Global.opt.preprocOnly() || v3Global.opt.keepTempFiles()) {
lexFile (vppfilename, modfilename); // Create output file with all the preprocessor output we buffered up
string vppfilename = v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"_"+modname+".vpp";
ofstream* ofp = NULL;
ostream* osp;
if (v3Global.opt.preprocOnly()) {
osp = &cout;
} else {
osp = ofp = V3File::new_ofstream(vppfilename);
}
if (osp->fail()) {
fileline->v3error("Cannot write preprocessor output: "+vppfilename);
return;
} else {
for (deque<string>::iterator it = m_ppBuffers.begin(); it!=m_ppBuffers.end(); ++it) {
*osp << *it;
}
if (ofp) {
ofp->close();
delete ofp; ofp = NULL;
}
}
} }
if (!v3Global.opt.keepTempFiles()) { // Must match new_ofstream_nodepend rule in V3PreShell.cpp // Parse it
unlink (vppfilename.c_str()); if (!v3Global.opt.preprocOnly()) {
lexFile (modfilename);
} }
} }
void V3Read::lexFile(const string& vppfilename, const string& modname) { void V3Read::lexFile(const string& modname) {
// Open the preprocess output
// Don't track a input dependency, as we created the file ourselves
ifstream* fsp = V3File::new_ifstream_nodepend(vppfilename);
if (fsp->fail()) {
m_fileline->v3fatal("Module "<<modname<<" isn't found, or preprocessor errors in "<<vppfilename);
}
// Prepare for lexing // Prepare for lexing
UINFO(3,"Lexing "<<vppfilename<<endl); UINFO(3,"Lexing "<<modname<<endl);
V3Read::s_readp = this; V3Read::s_readp = this;
V3Read::fileline()->warnResetDefault(); // Reenable warnings on each file V3Read::fileline()->warnResetDefault(); // Reenable warnings on each file
if (m_lexerp) delete m_lexerp; // Restart from clean slate. if (m_lexerp) delete m_lexerp; // Restart from clean slate.
m_lexerp = new V3Lexer(fsp); m_lexerp = new V3Lexer();
// if (debug()) { m_lexerp->set_debug(~0); } // if (debug()) { m_lexerp->set_debug(~0); }
// if (debug()) yydebug = 1; // if (debug()) yydebug = 1;
UINFO(4,"Lexing Done "<<vppfilename<<endl); UINFO(4,"Lexing Done "<<modname<<endl);
// Lex it // Lex it
if (yyparse()) v3fatal("Cannot continue\n"); if (yyparse()) v3fatal("Cannot continue\n");
// Cleanup
fsp->close(); delete fsp; fsp = NULL;
} }
//====================================================================== //======================================================================
+7 -1
View File
@@ -45,6 +45,7 @@ class V3Read {
deque<string*> m_stringps; // Created strings for later cleanup deque<string*> m_stringps; // Created strings for later cleanup
deque<V3Number*> m_numberps; // Created numbers for later cleanup deque<V3Number*> m_numberps; // Created numbers for later cleanup
deque<FileLine> m_lintState; // Current lint state for save/restore deque<FileLine> m_lintState; // Current lint state for save/restore
deque<string> m_ppBuffers; // Preprocessor->lex buffer of characters to process
//int debug() { return 9; } //int debug() { return 9; }
protected: protected:
@@ -52,6 +53,7 @@ protected:
friend class V3Lexer; friend class V3Lexer;
friend class V3LexerBase; friend class V3LexerBase;
friend class FileLine; friend class FileLine;
friend class V3PreShellImp;
int yylexThis(); int yylexThis();
static bool optPsl(); static bool optPsl();
static void ppline (const char* text); static void ppline (const char* text);
@@ -64,6 +66,9 @@ protected:
static bool popBeginKeywords() { if (s_readp->m_inBeginKwd) { s_readp->m_inBeginKwd--; return true; } else return false; } static bool popBeginKeywords() { if (s_readp->m_inBeginKwd) { s_readp->m_inBeginKwd--; return true; } else return false; }
static int lastVerilogState() { return s_readp->m_lastVerilogState; } static int lastVerilogState() { return s_readp->m_lastVerilogState; }
void ppPushText(const string& text) { m_ppBuffers.push_back(text); }
int ppInputToLex(char* buf, int max_size);
public: // But for internal use only public: // But for internal use only
static string* newString(const string& text) { static string* newString(const string& text) {
// Allocate a string, remembering it so we can reclaim storage at lex end // Allocate a string, remembering it so we can reclaim storage at lex end
@@ -100,6 +105,7 @@ public: // But for internal use only
static void statePushVlg(); // Parser -> lexer communication static void statePushVlg(); // Parser -> lexer communication
static void statePop(); // Parser -> lexer communication static void statePop(); // Parser -> lexer communication
static int stateVerilogRecent(); // Parser -> lexer communication static int stateVerilogRecent(); // Parser -> lexer communication
static int flexPpInputToLex(char* buf, int max_size) { return s_readp->ppInputToLex(buf,max_size); }
public: public:
// CREATORS // CREATORS
@@ -118,7 +124,7 @@ public:
void readFile(FileLine* fileline, const string& modname, bool inLibrary); void readFile(FileLine* fileline, const string& modname, bool inLibrary);
private: private:
void lexFile(const string& vppfilename, const string& modname); void lexFile(const string& modname);
}; };
#endif // Guard #endif // Guard
+4 -7
View File
@@ -464,6 +464,7 @@ void process () {
V3EmitC::emitcSyms(); V3EmitC::emitcSyms();
V3EmitC::emitcTrace(); V3EmitC::emitcTrace();
} }
// Unfortunately we have some lint checks in emitc.
V3EmitC::emitc(); V3EmitC::emitc();
// Statistics // Statistics
@@ -521,13 +522,9 @@ int main(int argc, char** argv, char** env) {
//--FRONTEND------------------ //--FRONTEND------------------
// Cleanup // Cleanup
mkdir(v3Global.opt.makeDir().c_str(), 0777); V3Options::unlinkRegexp(v3Global.opt.makeDir(), v3Global.opt.prefix()+"_*.tree");
string cleanFilename = "/bin/rm -rf "+v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"_*.tree"; V3Options::unlinkRegexp(v3Global.opt.makeDir(), v3Global.opt.prefix()+"_*.dot");
system(cleanFilename.c_str()); V3Options::unlinkRegexp(v3Global.opt.makeDir(), v3Global.opt.prefix()+"_*.txt");
cleanFilename = "/bin/rm -rf "+v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"_*.dot";
system(cleanFilename.c_str());
cleanFilename = "/bin/rm -rf "+v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"_*.txt";
system(cleanFilename.c_str());
// Read first filename // Read first filename
v3Global.readFiles(); v3Global.readFiles();
+1 -1
View File
@@ -24,7 +24,7 @@
//********************************************************************** //**********************************************************************
//**** Version and host name //**** Version and host name
#define DTVERSION "Verilator 3.656 2008/01/18" #define DTVERSION "Verilator 3.657 2008/01/18"
//********************************************************************** //**********************************************************************
//**** Functions //**** Functions
+4 -1
View File
@@ -33,6 +33,9 @@ extern void yyerrorf(const char* format, ...);
#define STATE_VERILOG_RECENT S05 // State name for most recent Verilog Version #define STATE_VERILOG_RECENT S05 // State name for most recent Verilog Version
#define YY_INPUT(buf,result,max_size) \
result = V3Read::flexPpInputToLex(buf,max_size);
//====================================================================== //======================================================================
#define NEXTLINE() {V3Read::incLineno();} #define NEXTLINE() {V3Read::incLineno();}
@@ -698,7 +701,7 @@ escid \\[^ \t\f\r\n]+
/************************************************************************/ /************************************************************************/
/* Attributes */ /* Attributes */
<V95,V01,V05,S05>{ <V95,V01,V05,S05>{
"(*" { yymore(); yy_push_state(ATTRMODE); } "(*"/{ws}*[^)] { yymore(); yy_push_state(ATTRMODE); } // Doesn't match (*)
} }
/************************************************************************/ /************************************************************************/
+7 -7
View File
@@ -526,15 +526,15 @@ regsigList: regsig { $$ = $1; }
| regsigList ',' regsig { $$ = $1;$1->addNext($3); } | regsigList ',' regsig { $$ = $1;$1->addNext($3); }
; ;
portV2kDecl: varRESET varInput signingE v2kNetDeclE regrangeE portV2kSig { $$ = $6; } portV2kDecl: varRESET varInput v2kNetDeclE signingE regrangeE portV2kSig { $$ = $6; }
| varRESET varInout signingE v2kNetDeclE regrangeE portV2kSig { $$ = $6; } | varRESET varInout v2kNetDeclE signingE regrangeE portV2kSig { $$ = $6; }
| varRESET varOutput signingE v2kVarDeclE regrangeE portV2kSig { $$ = $6; } | varRESET varOutput v2kVarDeclE signingE regrangeE portV2kSig { $$ = $6; }
; ;
// IEEE: port_declaration - plus ';' // IEEE: port_declaration - plus ';'
portDecl: varRESET varInput signingE v2kVarDeclE regrangeE sigList ';' { $$ = $6; } portDecl: varRESET varInput v2kVarDeclE signingE regrangeE sigList ';' { $$ = $6; }
| varRESET varInout signingE v2kVarDeclE regrangeE sigList ';' { $$ = $6; } | varRESET varInout v2kVarDeclE signingE regrangeE sigList ';' { $$ = $6; }
| varRESET varOutput signingE v2kVarDeclE regrangeE sigList ';' { $$ = $6; } | varRESET varOutput v2kVarDeclE signingE regrangeE sigList ';' { $$ = $6; }
; ;
varDecl: varRESET varReg signingE regrangeE regsigList ';' { $$ = $5; } varDecl: varRESET varReg signingE regrangeE regsigList ';' { $$ = $5; }
@@ -838,7 +838,7 @@ eventControlE: /* empty */ { $$ = NULL; }
// IEEE: event_control // IEEE: event_control
eventControl: '@' '(' senList ')' { $$ = new AstSenTree($1,$3); } eventControl: '@' '(' senList ')' { $$ = new AstSenTree($1,$3); }
| '@' senitemVar { $$ = new AstSenTree($1,$2); } /* For events only */ | '@' senitemVar { $$ = new AstSenTree($1,$2); } /* For events only */
| '@' '(' '*' ')' { $$ = NULL; $2->v3error("Use @*. always @ (*) to be depreciated in Verilog 2005.\n"); } | '@' '(' '*' ')' { $$ = NULL; } /* Verilog 2001 */
| '@' '*' { $$ = NULL; } /* Verilog 2001 */ | '@' '*' { $$ = NULL; } /* Verilog 2001 */
; ;
+1 -1
View File
@@ -14,7 +14,7 @@
// please note it here, otherwise:** // please note it here, otherwise:**
// //
// This file ONLY is placed into the Public Domain, for any use, // This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2007 by Wilson Snyder. // without warranty, 2008 by Wilson Snyder.
module t (/*AUTOARG*/ module t (/*AUTOARG*/
// Inputs // Inputs
+2 -2
View File
@@ -1,4 +1,4 @@
// $Id:$ // $Id$
// DESCRIPTION: Verilator: Verilog Test module // DESCRIPTION: Verilator: Verilog Test module
// //
// This file ONLY is placed into the Public Domain, for any use, // This file ONLY is placed into the Public Domain, for any use,
@@ -14,7 +14,7 @@ module t (/*AUTOARG*/
reg [31:0] a, b, c; reg [31:0] a, b, c;
always @ (/*AS*/a or b) begin always @ (*) begin // Test Verilog 2001 (*)
// verilator lint_off COMBDLY // verilator lint_off COMBDLY
c <= a | b; c <= a | b;
// verilator lint_on COMBDLY // verilator lint_on COMBDLY
+12 -7
View File
@@ -15,21 +15,24 @@ module t (/*AUTOARG*/
reg [63:0] crc; reg [63:0] crc;
reg [63:0] sum; reg [63:0] sum;
reg [31:0] out1; wire [31:0] out1;
sub sub (.in1(crc[15:0]), .in2(crc[31:16]), .out1(out1)); wire [31:0] out2;
sub sub (.in1(crc[15:0]), .in2(crc[31:16]), .out1(out1), .out2);
always @ (posedge clk) begin always @ (posedge clk) begin
//$write("[%0t] cyc==%0d crc=%x sum=%x out=%x\n",$time, cyc, crc, sum, out1); `ifdef TEST_VERBOSE
$write("[%0t] cyc==%0d crc=%x sum=%x out=%x %x\n",$time, cyc, crc, sum, out1, out2);
`endif
cyc <= cyc + 1; cyc <= cyc + 1;
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]}; crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
sum <= {sum[62:0], sum[63]^sum[2]^sum[0]} ^ {32'h0,out1}; sum <= {sum[62:0], sum[63]^sum[2]^sum[0]} ^ {out2,out1};
if (cyc==1) begin if (cyc==1) begin
// Setup // Setup
crc <= 64'h00000000_00000097; crc <= 64'h00000000_00000097;
sum <= 64'h0; sum <= 64'h0;
end end
else if (cyc==90) begin else if (cyc==90) begin
if (sum !== 64'hc1f743ad62c2c04d) $stop; if (sum !== 64'he396068aba3898a2) $stop;
end end
else if (cyc==91) begin else if (cyc==91) begin
end end
@@ -49,18 +52,20 @@ endmodule
module sub (/*AUTOARG*/ module sub (/*AUTOARG*/
// Outputs // Outputs
out1, out1, out2,
// Inputs // Inputs
in1, in2 in1, in2
); );
input [15:0] in1; input [15:0] in1;
input [15:0] in2; input [15:0] in2;
output reg [31:0] out1; output reg signed [31:0] out1;
output reg unsigned [31:0] out2;
always @* begin always @* begin
// verilator lint_off WIDTH // verilator lint_off WIDTH
out1 = $signed(in1) * $signed(in2); out1 = $signed(in1) * $signed(in2);
out2 = $unsigned(in1) * $unsigned(in2);
// verilator lint_on WIDTH // verilator lint_on WIDTH
end end
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
# $Id$
# 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
# General Public License or the Perl Artistic License.
compile (
);
execute (
check_finished=>1,
);
ok(1);
1;
+165
View File
@@ -0,0 +1,165 @@
// $Id$
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2008 by Wilson Snyder.
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
integer cyc=0;
reg [63:0] crc;
reg [63:0] sum;
// Take CRC data and apply to testblock inputs
wire [31:0] Operand1 = crc[31:0];
wire [15:0] Operand2 = crc[47:32];
wire Unsigned = crc[48];
reg rst;
parameter wl = 16;
/*AUTOWIRE*/
// Beginning of automatic wires (for undeclared instantiated-module outputs)
wire [wl-1:0] Quotient; // From test of Test.v
wire [wl-1:0] Remainder; // From test of Test.v
// End of automatics
Test test (/*AUTOINST*/
// Outputs
.Quotient (Quotient[wl-1:0]),
.Remainder (Remainder[wl-1:0]),
// Inputs
.Operand1 (Operand1[wl*2-1:0]),
.Operand2 (Operand2[wl-1:0]),
.clk (clk),
.rst (rst),
.Unsigned (Unsigned));
// Aggregate outputs into a single result vector
wire [63:0] result = {32'h0, Quotient, Remainder};
// What checksum will we end up with
`define EXPECTED_SUM 64'h98d41f89a8be5693
// Test loop
always @ (posedge clk) begin
`ifdef TEST_VERBOSE
$write("[%0t] cyc==%0d crc=%x result=%x it=%x\n",$time, cyc, crc, result, test.Iteration);
`endif
cyc <= cyc + 1;
if (cyc < 20 || test.Iteration==4'd15) begin
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
end
sum <= result ^ {sum[62:0],sum[63]^sum[2]^sum[0]};
if (cyc==0) begin
// Setup
crc <= 64'h5aef0c8d_d70a4497;
rst <= 1'b1;
end
else if (cyc<20) begin
sum <= 64'h0;
rst <= 1'b0;
end
else if (cyc<90) begin
end
else if (cyc==99) begin
$write("[%0t] cyc==%0d crc=%x sum=%x\n",$time, cyc, crc, sum);
if (crc !== 64'h8dd70a44972ad809) $stop;
if (sum !== `EXPECTED_SUM) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule
module Test(clk, rst, Operand1, Operand2, Unsigned, Quotient, Remainder);
parameter wl = 16;
input [wl*2-1:0] Operand1;
input [wl-1:0] Operand2;
input clk, rst, Unsigned;
output [wl-1:0] Quotient, Remainder;
reg Cy, Overflow, Sign1, Sign2, Zero, Negative;
reg [wl-1:0] ah,al,Quotient, Remainder;
reg [3:0] Iteration;
reg [wl-1:0] sub_quot,op;
reg ah_ext;
reg [1:0] a,b,c,d,e;
always @(posedge clk) begin
if (!rst) begin
{a,b,c,d,e} = Operand1[9:0];
{a,b,c,d,e} = {e,d,c,b,a};
if (a != Operand1[1:0]) $stop;
if (b != Operand1[3:2]) $stop;
if (c != Operand1[5:4]) $stop;
if (d != Operand1[7:6]) $stop;
if (e != Operand1[9:8]) $stop;
end
end
always @(posedge clk) begin
if (rst) begin
Iteration <= 0;
Quotient <= 0;
Remainder <= 0;
end
else begin
if (Iteration == 0) begin
{ah,al} = Operand1;
op = Operand2;
Cy = 0;
Overflow = 0;
Sign1 = (~Unsigned)&ah[wl-1];
Sign2 = (~Unsigned)&(ah[wl-1]^op[wl-1]);
if (Sign1) {ah,al} = -{ah,al};
end
`define BUG1
`ifdef BUG1
{ah_ext,ah,al} = {ah,al,Cy};
`else
ah_ext = ah[15];
ah[15:1] = ah[14:0];
ah[0] = al[15];
al[15:1] = al[14:0];
al[0] = Cy;
`endif
`ifdef TEST_VERBOSE
$display("%x %x %x %x %x %x %x %x %x",
Iteration, ah, al, Quotient, Remainder, Overflow, ah_ext, sub_quot, Cy);
`endif
{Cy,sub_quot} = (~Unsigned)&op[wl-1]? {ah_ext,ah}+op : {ah_ext,ah} - {1'b1,op};
if (Cy)
begin
{ah_ext,ah} = {1'b0,sub_quot};
end
if (Iteration != 15 )
begin
if (ah_ext) Overflow = 1;
end
else
begin
if (al[14] && ~Unsigned) Overflow = 1;
Quotient <= Sign2 ? -{al[14:0],Cy} : {al[14:0],Cy};
Remainder <= Sign1 ? -ah : ah;
if (Overflow)
begin
Quotient <= Sign2 ? 16'h8001 : {Unsigned,{15{1'b1}}};
Remainder <= Unsigned ? 16'hffff : 16'h8000;
Zero = 1;
Negative = 1;
end
end
Iteration <= Iteration + 1; // Count number of times this instruction is repeated
end
end
endmodule
+2 -1
View File
@@ -8,7 +8,7 @@ if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
# General Public License or the Perl Artistic License. # General Public License or the Perl Artistic License.
compile ( compile (
v_flags2 => ["--lint-only"], v_flags2 => ["--lint-only --Mdir obj_lint_only"],
fails=>1, fails=>1,
expect=> expect=>
'%Error: t/t_var_in_assign_bad.v:\d+: Assigning to input variable: value '%Error: t/t_var_in_assign_bad.v:\d+: Assigning to input variable: value
@@ -16,5 +16,6 @@ compile (
%Error: Exiting due to.*', %Error: Exiting due to.*',
) if $Last_Self->{v3}; ) if $Last_Self->{v3};
(!-d "obj_lint_only") or $Last_Self->error("%Error: lint-only shouldn't make output directory");
ok(1); ok(1);
1; 1;