Compare commits

...
18 Commits
Author SHA1 Message Date
Wilson Snyder c4b1bc2506 Version bump
git-svn-id: file://localhost/svn/verilator/trunk/verilator@950 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-08-01 13:44:45 +00:00
Wilson Snyder 551393d443 Fix SC_LIBS missing from generated makefiles. [Ding Xiaoliang]
git-svn-id: file://localhost/svn/verilator/trunk/verilator@949 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-07-31 14:47:21 +00:00
Wilson Snyder 79d305f3e8 Match Verilog-Perl: Remove preprocessor adding newlines before `line.
git-svn-id: file://localhost/svn/verilator/trunk/verilator@948 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-07-30 15:00:21 +00:00
Wilson Snyder 822956e769 Add SystemVerilog end labels
git-svn-id: file://localhost/svn/verilator/trunk/verilator@947 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-07-18 17:58:53 +00:00
Wilson Snyder a681a6a6d5 Make -> a token to match verilog-perl
git-svn-id: file://localhost/svn/verilator/trunk/verilator@946 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-07-18 17:26:12 +00:00
Wilson Snyder 5f6d69affd Support SystemVerilog ==? and !=? operators.
git-svn-id: file://localhost/svn/verilator/trunk/verilator@945 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-07-18 15:01:39 +00:00
Wilson Snyder 4a9bea6980 Version bump; commentary
git-svn-id: file://localhost/svn/verilator/trunk/verilator@942 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-06-21 21:00:38 +00:00
Wilson Snyder bfddd80f43 Support V2K function/task argument lists.
git-svn-id: file://localhost/svn/verilator/trunk/verilator@941 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-06-19 23:43:14 +00:00
Wilson Snyder 84a778719a Fix constification removing continuous always blocks
git-svn-id: file://localhost/svn/verilator/trunk/verilator@940 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-06-15 14:39:52 +00:00
Wilson Snyder 829d80d5b5 Fix display constanting of neg quads. Part of previous checkin
git-svn-id: file://localhost/svn/verilator/trunk/verilator@939 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-06-14 21:27:40 +00:00
Wilson Snyder d6a5c97f3a Fix last change: percents must be literalized
git-svn-id: file://localhost/svn/verilator/trunk/verilator@938 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-06-14 18:34:08 +00:00
Wilson Snyder 4ba00bd256 Propagate constants into displays
git-svn-id: file://localhost/svn/verilator/trunk/verilator@937 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-06-14 17:29:37 +00:00
Wilson Snyder c18f9da400 Put display scope tracking under special node type
git-svn-id: file://localhost/svn/verilator/trunk/verilator@936 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-06-14 16:41:32 +00:00
Wilson Snyder 5b620a8dc5 Add V3Number display function, unused as yet
git-svn-id: file://localhost/svn/verilator/trunk/verilator@935 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-06-14 14:24:21 +00:00
Wilson Snyder 9c968c590c Fix Preprocessor dropping some line directives
git-svn-id: file://localhost/svn/verilator/trunk/verilator@934 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-06-13 17:34:09 +00:00
Wilson Snyder dff5d5c4e4 Report as many warning types as possible before exiting.
git-svn-id: file://localhost/svn/verilator/trunk/verilator@933 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-06-12 19:39:10 +00:00
Wilson Snyder 1265e8cce8 Support V2K portlists with input a,b,...
git-svn-id: file://localhost/svn/verilator/trunk/verilator@932 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-06-12 13:58:56 +00:00
Wilson Snyder 2b5d7eeb50 Lesser license for verilated files
git-svn-id: file://localhost/svn/verilator/trunk/verilator@931 77ca24e4-aefa-0310-84f0-b9a241c72d87
2007-06-11 17:07:11 +00:00
51 changed files with 899 additions and 143 deletions
+18
View File
@@ -3,6 +3,24 @@ 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.653 8/1/2007
**** Support SystemVerilog ==? and !=? operators.
**** Fix SC_LIBS missing from generated makefiles. [Ding Xiaoliang]
* Verilator 3.652 6/21/2007
**** Report as many warning types as possible before exiting.
**** Support V2K portlists with "input a,b,...". [Mark Nodine]
**** Support V2K function/task argument lists.
**** Optimize constant $display arguments.
**** Fix Preprocessor dropping some `line directives. [Mark Nodine]
* Verilator 3.651 5/22/2007 * Verilator 3.651 5/22/2007
*** Added verilator_profcfunc utility. [Gene Weber] *** Added verilator_profcfunc utility. [Gene Weber]
+1 -1
View File
@@ -4,7 +4,7 @@
# #
# This file is part of Verilator. # This file is part of Verilator.
# #
# Author: Wilson Snyder <[email protected]> or <[email protected]> # Author: Wilson Snyder <[email protected]>
# #
# Code available from: http://www.veripool.com/verilator # Code available from: http://www.veripool.com/verilator
# #
+6
View File
@@ -103,6 +103,12 @@ Performance:
If floped(a) & flopped(b) and no other a&b, then instead flop(a&b). If floped(a) & flopped(b) and no other a&b, then instead flop(a&b).
Sort by output bitselects so can combine more assignments (see DDP example dx_dm signal) Sort by output bitselects so can combine more assignments (see DDP example dx_dm signal)
All of the temp vars that get set, exp pre_ vars and never feedback
(not flops) don't need to be stored in the structs, but instead can
be per-invocation, and even better register-colored-like to reuse
the space. This will greatly reduce the data footprint.
//********************************************************************** //**********************************************************************
//* Detailed notes on 'todo' features //* Detailed notes on 'todo' features
+91 -4
View File
@@ -214,6 +214,66 @@ C++, and linked with the Verilated files.
The resulting executable will perform the actual simulation. The resulting executable will perform the actual simulation.
=head1 ARGUMENT SUMMARY
This is a short summary of the arguments to Verilator. See the detailed
descriptions in the next sections for more information.
{file.v} Verilog top level filenames
{file.c/cc/cpp} Optional C++ files to link in
--assert Enable all assertions
--bin <filename> Override Verilator binary
--cc Create C++ output
--compiler <compiler-name> Tune for specified C++ compiler
--coverage Enable all coverage
--coverage-line Enable line coverage
--coverage-user Enable PSL/SVL user coverage
-D<var>[=<value>] Set preprocessor define
--debug Enable debugging
--debug-check Enable debugging assertions
--dump-tree Enable dumping .tree files
-E Preprocess, but do not compile
--exe Link to create executable
-f <file> Parse options from a file
--help Display this help.
-I<dir> Directory to search for includes
--inhibit-sim Create function to turn off sim
--inline-mult <value> Tune module inlining
--lint-only Lint, but do not make output
--MMD Create .d dependency files
--MP Create phony dependency targets
--Mdir <directory> Name of output object directory
--mod-prefix <topname> Name to prepend to lower classes
--no-skip-identical Disable skipping identical output
-O0 Disable optimizations
-O3 High performance optimizations
-O<optimization-letter> Selectable optimizations
--output-split <bytes> Split .cpp files into pieces
--output-split-cfuncs <statements> Split .ccp functions
--pins64 Use uint64_t's for 33-64 bit sigs
--prefix <topname> Name of top level class
--profile-cfuncs Name functions for profiling
--private Debugging; see docs
--psl Enable PSL parsing
--public Debugging; see docs
--sc Create SystemC output
--sp Create SystemPerl output
--stats Create statistics file
--trace Enable waveform creation
--trace-depth <levels> Depth of tracing
-U<var> Undefine preprocessor define
--underline-zero Zero signals with leading _'s
-v <filename> Verilog library
-Werror-<message> Convert warning to error
-Wno-<message> Disable warning
-x-assign <mode> Initially assign Xs to this value
-y <dir> Directory to search for modules
+define+<var>+<value> Set preprocessor define
+incdir+<dir> Directory to search for includes
+libext+<ext>+[ext]... Extensions for finding modules
=head1 ARGUMENTS =head1 ARGUMENTS
=over 4 =over 4
@@ -320,6 +380,12 @@ internal assertions, debugging messages, and intermediate form dump files.
Rarely needed. Enable internal debugging assertion checks, without Rarely needed. Enable internal debugging assertion checks, without
changing debug verbosity. Enabled automatically when --debug specified. changing debug verbosity. Enabled automatically when --debug specified.
=item --dump-tree
Rarely needed. Enable writing .tree debug files. This is enabled with
--debug, so "--debug --no-dump-tree" may be useful if the dump files are
large and not desired.
=item -E =item -E
Preprocess the source code, but do not compile, as with 'gcc -E'. Output Preprocess the source code, but do not compile, as with 'gcc -E'. Output
@@ -944,12 +1010,14 @@ Verilator currently has very minimal support for SystemVerilog. As
SystemVerilog features enter common usage they will be added. Contact the SystemVerilog features enter common usage they will be added. Contact the
author if a feature you need is missing. author if a feature you need is missing.
Verilator implements the full SystemVerilog 1800-2005 preprocessor subset, Verilator implements the full SystemVerilog 1800-2005 preprocessor,
including function call-like preprocessor defines. including function call-like preprocessor defines.
Verilator supports $bits, $countones, $error, $fatal, $info, $isunknown, Verilator supports ==? and !=? operators, $bits, $countones, $error,
$onehot, $onehot0, $warning, always_comb, always_ff, always_latch, $fatal, $info, $isunknown, $onehot, $onehot0, $warning, always_comb,
do-while, and final. It also supports .name and .* interconnection. always_ff, always_latch, do-while, and final.
It also supports .name and .* interconnection.
Verilator partially supports assert. Verilator partially supports assert.
@@ -1870,6 +1938,25 @@ so your simulator shouldn't have to be -- and Verilator is closer to the
synthesis interpretation, so this is a good thing for getting working synthesis interpretation, so this is a good thing for getting working
silicon. silicon.
=item May programs I create with Verilator remain under my own copyright?
Yes, it's just like using GCC on your programs. If you change Verilator
itself, you must make the source code available under the GNU Public
License. However, the include and generated files use the GNU Lesser
Public License, which means that files using them are NOT required to be released.
You also have the option of using the Perl Artistic License, which again
does not require you release your Verilog or generated code.
=item Why is running Verilator so slow?
Verilator needs more memory then the resulting simulator will require, as
Verilator creates internally all of the state of the resulting simulator in
order to optimize it. If it takes more then a minute or so (and you're not
using --debug), see if your machine is paging; most likely you need to run
it on a machine with more memory. Verilator is a full 64 bit application
and may use more then 4GB, but about 1GB is the maximum typically needed.
=item How do I generate waveforms (traces) in C++? =item How do I generate waveforms (traces) in C++?
See the next question for SystemC mode. See the next question for SystemC mode.
+2 -2
View File
@@ -3,7 +3,7 @@
// //
// Copyright 2003-2007 by Wilson Snyder. This program is free software; you can // Copyright 2003-2007 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// General Public License or the Perl Artistic License. // Lesser General Public License or the Perl Artistic License.
// //
// Verilator is distributed in the hope that it will be useful, // Verilator is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -31,7 +31,7 @@
//=========================================================================== //===========================================================================
// Global variables // Global variables
int Verilated::s_randReset = false; int Verilated::s_randReset = 0;
int Verilated::s_debug = 1; int Verilated::s_debug = 1;
bool Verilated::s_calcUnusedSigs = false; bool Verilated::s_calcUnusedSigs = false;
bool Verilated::s_gotFinish = false; bool Verilated::s_gotFinish = false;
+1 -1
View File
@@ -3,7 +3,7 @@
// //
// Copyright 2003-2007 by Wilson Snyder. This program is free software; you can // Copyright 2003-2007 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// General Public License or the Perl Artistic License. // Lesser General Public License or the Perl Artistic License.
// //
// Verilator is distributed in the hope that it will be useful, // Verilator is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
+1 -1
View File
@@ -4,7 +4,7 @@
# #
# Copyright 2003-2007 by Wilson Snyder. This program is free software; you can # Copyright 2003-2007 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU # redistribute it and/or modify it under the terms of either the GNU
# General Public License or the Perl Artistic License. # Lesser General Public License or the Perl Artistic License.
###################################################################### ######################################################################
PERL = @PERL@ PERL = @PERL@
+1 -1
View File
@@ -7,7 +7,7 @@
// //
// Copyright 2003-2007 by Wilson Snyder. This program is free software; you can // Copyright 2003-2007 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// General Public License or the Perl Artistic License. // Lesser General Public License or the Perl Artistic License.
// //
// This is distributed in the hope that it will be useful, // This is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
+1 -1
View File
@@ -3,7 +3,7 @@
// //
// Copyright 2003-2007 by Wilson Snyder. This program is free software; you can // Copyright 2003-2007 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU // redistribute it and/or modify it under the terms of either the GNU
// General Public License or the Perl Artistic License. // Lesser General Public License or the Perl Artistic License.
// //
// Verilator is distributed in the hope that it will be useful, // Verilator is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
+3
View File
@@ -63,6 +63,9 @@ private:
AstNode* timesp = nodep->exprsp(); if (timesp) timesp->unlinkFrBack(); AstNode* timesp = nodep->exprsp(); if (timesp) timesp->unlinkFrBack();
timesp = timesp->addNext(new AstTime(nodep->fileline())); timesp = timesp->addNext(new AstTime(nodep->fileline()));
nodep->exprsp(timesp); nodep->exprsp(timesp);
if (!nodep->scopeNamep() && nodep->name().find("%m") != string::npos) {
nodep->scopeNamep(new AstScopeName(nodep->fileline()));
}
} }
AstNode* newIfAssertOn(AstNode* nodep) { AstNode* newIfAssertOn(AstNode* nodep) {
+51 -5
View File
@@ -1271,11 +1271,8 @@ public:
bool addNewline() const { return displayType().addNewline(); } // * = Add a newline for $display bool addNewline() const { return displayType().addNewline(); } // * = Add a newline for $display
AstNode* filep() const { return op2p(); } AstNode* filep() const { return op2p(); }
void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); } void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); }
AstNode* scopeAttrp() const { return op3p(); } AstScopeName* scopeNamep() const { return op3p()->castScopeName(); }
AstText* scopeTextp() const { return op3p()->castText(); } void scopeNamep(AstNode* nodep) { setNOp3p(nodep); }
void scopeAttrp(AstNode* nodep) { addOp3p(nodep); }
bool needScopeTracking() { return (displayType().needScopeTracking()
|| name().find("%m") != string::npos); }
}; };
struct AstFClose : public AstNodeStmt { struct AstFClose : public AstNodeStmt {
@@ -1726,6 +1723,22 @@ public:
int dimension() const { return m_dimension; } int dimension() const { return m_dimension; }
}; };
struct AstScopeName : public AstNode {
// For display %m
// Parents: DISPLAY
// Children: TEXT
AstScopeName(FileLine* fl)
: AstNode(fl) {}
virtual ~AstScopeName() {}
virtual AstType type() const { return AstType::SCOPENAME;}
virtual AstNode* clone() { return new AstScopeName(*this); }
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(AstNode* samep) const { return true; }
AstText* scopeAttrp() const { return op1p()->castText(); }
void scopeAttrp(AstNode* nodep) { addOp1p(nodep); }
};
//====================================================================== //======================================================================
// non-ary ops // non-ary ops
@@ -2593,6 +2606,39 @@ struct AstNeqCase : public AstNodeBiCom {
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;} virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;} virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
}; };
struct AstEqWild : public AstNodeBiop {
// Note wildcard operator rhs differs from lhs
AstEqWild(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
width(1,1); }
virtual ~AstEqWild() {}
virtual AstType type() const { return AstType::EQWILD;}
virtual AstNode* clone() { return new AstEqWild(*this); }
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opWildEq(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %k==? %r)"; }
virtual string emitOperator() { return "VL_EQ"; } // Until have 4 state anyways
virtual string emitSimpleOperator() { return "=="; }
virtual bool emitWordForm() { return true; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
};
struct AstNeqWild : public AstNodeBiop {
AstNeqWild(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
width(1,1); }
virtual ~AstNeqWild() {}
virtual AstType type() const { return AstType::NEQWILD;}
virtual AstNode* clone() { return new AstNeqWild(*this); }
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opWildNeq(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %k!=? %r)"; }
virtual string emitOperator() { return "VL_NEQ"; } // Until have 4 state anyways
virtual string emitSimpleOperator() { return "!="; }
virtual bool emitWordForm() { return true; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
};
struct AstConcat : public AstNodeBiop { struct AstConcat : public AstNodeBiop {
// If you're looking for {#{}}, see AstReplicate // If you're looking for {#{}}, see AstReplicate
AstConcat(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) { AstConcat(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
+2 -2
View File
@@ -131,10 +131,10 @@ private:
nodep->replaceWith(newp); nodep->replaceWith(newp);
nodep->deleteTree(); nodep=NULL; nodep->deleteTree(); nodep=NULL;
} }
virtual void visit(AstDisplay* nodep, AstNUser*) { virtual void visit(AstScopeName* nodep, AstNUser*) {
// If there's a %m in the display text, we add a special node that will contain the name() // If there's a %m in the display text, we add a special node that will contain the name()
// Similar code in V3Inline // Similar code in V3Inline
if (m_beginScope != "" && nodep->needScopeTracking()) { if (m_beginScope != "") {
// To keep correct visual order, must add before other Text's // To keep correct visual order, must add before other Text's
AstNode* afterp = nodep->scopeAttrp(); AstNode* afterp = nodep->scopeAttrp();
if (afterp) afterp->unlinkFrBackWithNext(); if (afterp) afterp->unlinkFrBackWithNext();
+3
View File
@@ -196,6 +196,9 @@ private:
virtual void visit(AstText* nodep, AstNUser*) { virtual void visit(AstText* nodep, AstNUser*) {
setClean (nodep, true); setClean (nodep, true);
} }
virtual void visit(AstScopeName* nodep, AstNUser*) {
setClean (nodep, true);
}
virtual void visit(AstSel* nodep, AstNUser*) { virtual void visit(AstSel* nodep, AstNUser*) {
operandTriop(nodep); operandTriop(nodep);
setClean (nodep, nodep->cleanOut()); setClean (nodep, nodep->cleanOut());
+69 -1
View File
@@ -802,7 +802,12 @@ private:
if (nodep->sensp()->castConst() if (nodep->sensp()->castConst()
|| (nodep->varrefp() && nodep->varrefp()->varp()->isParam())) { || (nodep->varrefp() && nodep->varrefp()->varp()->isParam())) {
// Constants in sensitivity lists may be removed (we'll simplify later) // Constants in sensitivity lists may be removed (we'll simplify later)
AstSenItem* newp = new AstSenItem(nodep->fileline(), AstSenItem::Never()); AstSenItem* newp;
if (nodep->isClocked()) { // A constant can never get a pos/negexge
newp = new AstSenItem(nodep->fileline(), AstSenItem::Never());
} else { // Otherwise it may compute a result that needs to settle out
newp = new AstSenItem(nodep->fileline(), AstSenItem::Combo());
}
nodep->replaceWith(newp); nodep->replaceWith(newp);
nodep->deleteTree(); nodep=NULL; nodep->deleteTree(); nodep=NULL;
} else if (nodep->sensp()->castNot()) { } else if (nodep->sensp()->castNot()) {
@@ -938,6 +943,63 @@ private:
} }
} }
virtual void visit(AstDisplay* nodep, AstNUser*) {
// Substitute constants into displays. The main point of this is to
// simplify assertion methodologies which call functions with display's.
// This eliminates a pile of wide temps, and makes the C a whole lot more readable.
nodep->iterateChildren(*this);
bool anyconst = false;
for (AstNode* argp = nodep->exprsp(); argp; argp=argp->nextp()) {
if (argp->castConst()) { anyconst=true; break; }
}
if (anyconst) {
//UINFO(9," Display in "<<nodep->text()<<endl);
string dispout = "";
string fmt = "";
bool inPct = false;
AstNode* argp = nodep->exprsp();
for (const char* inp = nodep->text().c_str(); *inp; inp++) {
char ch = *inp; // Breaks with iterators...
if (!inPct && ch=='%') {
inPct = true;
fmt = ch;
} else if (inPct && isdigit(ch)) {
fmt += ch;
} else if (inPct) {
inPct = false;
fmt += ch;
switch (tolower(ch)) {
case '%': break; // %% - just output a %
case 'm': break; // %m - auto insert "name"
default: // Most operators, just move to next argument
if (argp) {
AstNode* nextp=argp->nextp();
if (argp && argp->castConst()) { // Convert it
string out = argp->castConst()->num().displayed(fmt);
UINFO(9," DispConst: "<<fmt<<" -> "<<out<<" for "<<argp<<endl);
{ // fmt = out w/ replace % with %% as it must be literal.
fmt = "";
for (string::iterator pos = out.begin(); pos != out.end(); pos++) {
if (*pos == '%') fmt += '%';
fmt += *pos;
}
}
argp->unlinkFrBack()->deleteTree();
}
argp=nextp;
}
break;
} // switch
dispout += fmt;
} else {
dispout += ch;
}
}
nodep->text(dispout);
//UINFO(9," Display out "<<nodep->text()<<endl);
}
}
virtual void visit(AstWhile* nodep, AstNUser*) { virtual void visit(AstWhile* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (nodep->condp()->isZero()) { if (nodep->condp()->isZero()) {
@@ -1048,6 +1110,10 @@ private:
TREEOP ("AstLogNot{$lhsp.castEqCase}", "AstNeqCase{$lhsp->op1p(),$lhsp->op2p()}"); TREEOP ("AstLogNot{$lhsp.castEqCase}", "AstNeqCase{$lhsp->op1p(),$lhsp->op2p()}");
TREEOPV("AstNot {$lhsp.castNeqCase, $lhsp.width1}","AstEqCase {$lhsp->op1p(),$lhsp->op2p()}"); TREEOPV("AstNot {$lhsp.castNeqCase, $lhsp.width1}","AstEqCase {$lhsp->op1p(),$lhsp->op2p()}");
TREEOP ("AstLogNot{$lhsp.castNeqCase}", "AstEqCase {$lhsp->op1p(),$lhsp->op2p()}"); TREEOP ("AstLogNot{$lhsp.castNeqCase}", "AstEqCase {$lhsp->op1p(),$lhsp->op2p()}");
TREEOPV("AstNot {$lhsp.castEqWild, $lhsp.width1}","AstNeqWild{$lhsp->op1p(),$lhsp->op2p()}");
TREEOP ("AstLogNot{$lhsp.castEqWild}", "AstNeqWild{$lhsp->op1p(),$lhsp->op2p()}");
TREEOPV("AstNot {$lhsp.castNeqWild, $lhsp.width1}","AstEqWild {$lhsp->op1p(),$lhsp->op2p()}");
TREEOP ("AstLogNot{$lhsp.castNeqWild}", "AstEqWild {$lhsp->op1p(),$lhsp->op2p()}");
TREEOPV("AstNot {$lhsp.castEq, $lhsp.width1}", "AstNeq {$lhsp->op1p(),$lhsp->op2p()}"); TREEOPV("AstNot {$lhsp.castEq, $lhsp.width1}", "AstNeq {$lhsp->op1p(),$lhsp->op2p()}");
TREEOP ("AstLogNot{$lhsp.castEq}", "AstNeq {$lhsp->op1p(),$lhsp->op2p()}"); TREEOP ("AstLogNot{$lhsp.castEq}", "AstNeq {$lhsp->op1p(),$lhsp->op2p()}");
TREEOPV("AstNot {$lhsp.castNeq, $lhsp.width1}", "AstEq {$lhsp->op1p(),$lhsp->op2p()}"); TREEOPV("AstNot {$lhsp.castNeq, $lhsp.width1}", "AstEq {$lhsp->op1p(),$lhsp->op2p()}");
@@ -1089,6 +1155,7 @@ private:
TREEOP("AstXor {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP("AstXor {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstEq {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); // We let X==X -> 1, although in a true 4-state sim it's X. TREEOP("AstEq {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); // We let X==X -> 1, although in a true 4-state sim it's X.
TREEOP("AstEqCase {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); TREEOP("AstEqCase {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP("AstEqWild {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP("AstGt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP("AstGt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstGtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP("AstGtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstGte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); TREEOP("AstGte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
@@ -1099,6 +1166,7 @@ private:
TREEOP("AstLteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); TREEOP("AstLteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP("AstNeq {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP("AstNeq {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstNeqCase{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP("AstNeqCase{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstNeqWild{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP("AstLogAnd {operandsSame($lhsp,,$rhsp), $lhsp.width1}", "replaceWLhs(nodep)"); TREEOP("AstLogAnd {operandsSame($lhsp,,$rhsp), $lhsp.width1}", "replaceWLhs(nodep)");
TREEOP("AstLogOr {operandsSame($lhsp,,$rhsp), $lhsp.width1}", "replaceWLhs(nodep)"); TREEOP("AstLogOr {operandsSame($lhsp,,$rhsp), $lhsp.width1}", "replaceWLhs(nodep)");
///=== Verilog operators ///=== Verilog operators
+4 -3
View File
@@ -388,7 +388,7 @@ public:
} }
virtual void visit(AstMulS* nodep, AstNUser* vup) { virtual void visit(AstMulS* nodep, AstNUser* vup) {
if (nodep->widthWords() > VL_MULS_MAX_WORDS) { if (nodep->widthWords() > VL_MULS_MAX_WORDS) {
nodep->v3error("Signed multiply of "<<nodep->width()<<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h\n"); nodep->v3error("Unsupported: Signed multiply of "<<nodep->width()<<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h\n");
} }
visit(nodep->castNodeBiop(), vup); visit(nodep->castNodeBiop(), vup);
} }
@@ -1052,16 +1052,17 @@ void EmitCStmts::visit(AstDisplay* nodep, AstNUser*) {
// Spec: h d o b c l // Spec: h d o b c l
case 'b': displayArg(nodep,&elistp,fmt,'b'); break; case 'b': displayArg(nodep,&elistp,fmt,'b'); break;
case 'c': displayArg(nodep,&elistp,fmt,'c'); break; case 'c': displayArg(nodep,&elistp,fmt,'c'); break;
case 't':
case 'd': displayArg(nodep,&elistp,fmt,'u'); break; // Unsigned decimal case 'd': displayArg(nodep,&elistp,fmt,'u'); break; // Unsigned decimal
case 'o': displayArg(nodep,&elistp,fmt,'o'); break; case 'o': displayArg(nodep,&elistp,fmt,'o'); break;
case 'h': case 'h':
case 'x': displayArg(nodep,&elistp,fmt,'x'); break; case 'x': displayArg(nodep,&elistp,fmt,'x'); break;
case 's': displayArg(nodep,&elistp,fmt,'s'); break; case 's': displayArg(nodep,&elistp,fmt,'s'); break;
case 't': displayArg(nodep,&elistp,fmt,'u'); break;
case 'm': { case 'm': {
emitDispState.pushFormat("%s"); emitDispState.pushFormat("%s");
emitDispState.pushArg(NULL, "vlSymsp->name("); emitDispState.pushArg(NULL, "vlSymsp->name(");
for (AstText* textp=nodep->scopeTextp(); textp; textp=textp->nextp()->castText()) { if (!nodep->scopeNamep()) nodep->v3fatalSrc("Display with %m but no AstScopeName");
for (AstText* textp=nodep->scopeNamep()->scopeAttrp(); textp; textp=textp->nextp()->castText()) {
emitDispState.pushFormat(textp->text()); emitDispState.pushFormat(textp->text());
} }
break; break;
+1 -1
View File
@@ -138,7 +138,7 @@ public:
of.puts("\n# Link rules...\n"); of.puts("\n# Link rules...\n");
of.puts(v3Global.opt.prefix()+": $(VK_USER_OBJS) $(SP_SRCS) $(VM_PREFIX)__ALL.a\n"); of.puts(v3Global.opt.prefix()+": $(VK_USER_OBJS) $(SP_SRCS) $(VM_PREFIX)__ALL.a\n");
of.puts("\t$(LINK) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@ $(LIBS) 2>&1 | c++filt\n"); of.puts("\t$(LINK) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@ $(LIBS) $(SC_LIBS) 2>&1 | c++filt\n");
of.puts("\n"); of.puts("\n");
} }
+2
View File
@@ -246,6 +246,8 @@ public:
virtual void visit(AstText* nodep, AstNUser*) { virtual void visit(AstText* nodep, AstNUser*) {
ofp()->putsNoTracking(nodep->text()); ofp()->putsNoTracking(nodep->text());
} }
virtual void visit(AstScopeName* nodep, AstNUser*) {
}
virtual void visit(AstCStmt* nodep, AstNUser*) { virtual void visit(AstCStmt* nodep, AstNUser*) {
putbs("$_CSTMT("); putbs("$_CSTMT(");
nodep->bodysp()->iterateAndNext(*this); nodep->bodysp()->iterateAndNext(*this);
+30 -7
View File
@@ -34,7 +34,8 @@
FileLine FileLine::s_defaultFileLine = FileLine(EmptySecret()); FileLine FileLine::s_defaultFileLine = FileLine(EmptySecret());
int V3Error::s_errcnt = 0; int V3Error::s_errCount = 0;
int V3Error::s_warnCount = 0;
int V3Error::s_debugDefault = 0; int V3Error::s_debugDefault = 0;
ostringstream V3Error::s_errorStr; // Error string being formed ostringstream V3Error::s_errorStr; // Error string being formed
V3ErrorCode V3Error::s_errorCode = V3ErrorCode::FATAL; V3ErrorCode V3Error::s_errorCode = V3ErrorCode::FATAL;
@@ -187,25 +188,46 @@ string V3Error::lineStr (const char* filename, int lineno) {
return out.str(); return out.str();
} }
void V3Error::incWarnings() {
s_warnCount++;
if (errorOrWarnCount() == MAX_ERRORS) { // Not >= as would otherwise recurse
v3fatal ("Exiting due to too many errors encountered\n");
}
}
void V3Error::incErrors() { void V3Error::incErrors() {
s_errcnt++; s_errCount++;
if (errorCount() == MAX_ERRORS) { // Not >= as would otherwise recurse if (errorOrWarnCount() == MAX_ERRORS) { // Not >= as would otherwise recurse
v3fatal ("Exiting due to too many errors encountered\n"); v3fatal ("Exiting due to too many errors encountered\n");
} }
} }
void V3Error::abortIfErrors() { void V3Error::abortIfErrors() {
if (errorCount()) { if (errorCount()) {
v3fatal ("Exiting due to "<<dec<<errorCount()<<" warning(s)\n"); v3fatal ("Exiting due to "<<dec<<errorOrWarnCount()<<" warning(s)\n");
} }
} }
void V3Error::abortIfWarnings() {
if (errorOrWarnCount()) {
v3fatal ("Exiting due to "<<dec<<errorOrWarnCount()<<" warning(s)\n");
}
}
bool V3Error::isError(V3ErrorCode code) {
if (code==V3ErrorCode::SUPPRESS) return false;
else if (code==V3ErrorCode::FATAL) return true;
else if (code==V3ErrorCode::ERROR) return true;
else if (code<V3ErrorCode::FIRST_WARN
|| s_pretendError[code]) return true;
else return false;
}
string V3Error::msgPrefix(V3ErrorCode code) { string V3Error::msgPrefix(V3ErrorCode code) {
if (code==V3ErrorCode::SUPPRESS) return "-arning-suppressed: "; if (code==V3ErrorCode::SUPPRESS) return "-arning-suppressed: ";
else if (code==V3ErrorCode::FATAL) return "%Error: "; else if (code==V3ErrorCode::FATAL) return "%Error: ";
else if (code==V3ErrorCode::ERROR) return "%Error: "; else if (code==V3ErrorCode::ERROR) return "%Error: ";
else if (code<V3ErrorCode::FIRST_WARN else if (isError(code)) return "%Error-"+(string)code.ascii()+": ";
|| s_pretendError[code]) return "%Error-"+(string)code.ascii()+": ";
else return "%Warning-"+(string)code.ascii()+": "; else return "%Warning-"+(string)code.ascii()+": ";
} }
@@ -258,7 +280,8 @@ void V3Error::v3errorEnd (ostringstream& sstr) {
cerr<<msgPrefix()<<"else you may end up with different sim results."<<endl; cerr<<msgPrefix()<<"else you may end up with different sim results."<<endl;
} }
} }
incErrors(); if (isError(s_errorCode)) incErrors();
else incWarnings();
if (s_errorCode==V3ErrorCode::FATAL) { if (s_errorCode==V3ErrorCode::FATAL) {
static bool inFatal = false; static bool inFatal = false;
if (!inFatal) { if (!inFatal) {
+8 -2
View File
@@ -104,11 +104,13 @@ class V3Error {
static bool s_describedEachWarn[V3ErrorCode::MAX]; // Told user specifics about this warning static bool s_describedEachWarn[V3ErrorCode::MAX]; // Told user specifics about this warning
static bool s_pretendError[V3ErrorCode::MAX]; // Pretend this warning is an error static bool s_pretendError[V3ErrorCode::MAX]; // Pretend this warning is an error
static int s_debugDefault; // Default debugging level static int s_debugDefault; // Default debugging level
static int s_errcnt; // Error count static int s_errCount; // Error count
static int s_warnCount; // Error count
static ostringstream s_errorStr; // Error string being formed static ostringstream s_errorStr; // Error string being formed
static V3ErrorCode s_errorCode; // Error string being formed will abort static V3ErrorCode s_errorCode; // Error string being formed will abort
enum MaxErrors { MAX_ERRORS = 50 }; // Fatal after this may errors enum MaxErrors { MAX_ERRORS = 50 }; // Fatal after this may errors
static void incErrors(); static void incErrors();
static void incWarnings();
V3Error() { cerr<<("Static class"); abort(); } V3Error() { cerr<<("Static class"); abort(); }
@@ -118,12 +120,16 @@ class V3Error {
static void debugDefault(int level) { s_debugDefault = level; } static void debugDefault(int level) { s_debugDefault = level; }
static int debugDefault() { return s_debugDefault; } static int debugDefault() { return s_debugDefault; }
static string msgPrefix(V3ErrorCode code=s_errorCode); // returns %Error/%Warn static string msgPrefix(V3ErrorCode code=s_errorCode); // returns %Error/%Warn
static int errorCount() { return s_errcnt; } static int errorCount() { return s_errCount; }
static int warnCount() { return s_warnCount; }
static int errorOrWarnCount() { return errorCount()+warnCount(); }
// METHODS // METHODS
static void init(); static void init();
static void abortIfErrors(); static void abortIfErrors();
static void abortIfWarnings();
static void suppressThisWarning(); // Suppress next %Warn if user has it off static void suppressThisWarning(); // Suppress next %Warn if user has it off
static void pretendError(V3ErrorCode code, bool flag) { s_pretendError[code]=flag; } static void pretendError(V3ErrorCode code, bool flag) { s_pretendError[code]=flag; }
static bool isError(V3ErrorCode code);
static string v3sform (const char* format, ...); static string v3sform (const char* format, ...);
static string lineStr (const char* filename, int lineno); static string lineStr (const char* filename, int lineno);
static V3ErrorCode errorCode() { return s_errorCode; } static V3ErrorCode errorCode() { return s_errorCode; }
+2 -2
View File
@@ -233,10 +233,10 @@ private:
} }
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
virtual void visit(AstDisplay* nodep, AstNUser*) { virtual void visit(AstScopeName* nodep, AstNUser*) {
// If there's a %m in the display text, we add a special node that will contain the name() // If there's a %m in the display text, we add a special node that will contain the name()
// Similar code in V3Begin // Similar code in V3Begin
if (m_cellp && nodep->needScopeTracking()) { if (m_cellp) {
// To keep correct visual order, must add before other Text's // To keep correct visual order, must add before other Text's
AstNode* afterp = nodep->scopeAttrp(); AstNode* afterp = nodep->scopeAttrp();
if (afterp) afterp->unlinkFrBackWithNext(); if (afterp) afterp->unlinkFrBackWithNext();
+4
View File
@@ -335,6 +335,10 @@ private:
|| nodep->displayType() == AstDisplayType::FATAL)) { || nodep->displayType() == AstDisplayType::FATAL)) {
nodep->v3error(nodep->verilogKwd()+" only allowed under a assertion."); nodep->v3error(nodep->verilogKwd()+" only allowed under a assertion.");
} }
if (nodep->displayType().needScopeTracking()
|| nodep->name().find("%m") != string::npos) {
nodep->scopeNamep(new AstScopeName(nodep->fileline()));
}
} }
virtual void visit(AstScCtor* nodep, AstNUser*) { virtual void visit(AstScCtor* nodep, AstNUser*) {
+136 -27
View File
@@ -303,7 +303,7 @@ V3Number& V3Number::setMask(int nbits) {
} }
//====================================================================== //======================================================================
// ACCESSORS // ACCESSORS - as strings
string V3Number::ascii(bool prefixed, bool cleanVerilog) const { string V3Number::ascii(bool prefixed, bool cleanVerilog) const {
ostringstream out; ostringstream out;
@@ -334,34 +334,115 @@ string V3Number::ascii(bool prefixed, bool cleanVerilog) const {
if (binary) { if (binary) {
out<<"b"; out<<"b";
int bit=width()-1; out<<displayed("%0b");
while (bit && bitIs0(bit)) bit--;
for(; bit>=0; --bit) {
if (bitIs0(bit)) out<<'0';
else if (bitIs1(bit)) out<<'1';
else if (bitIsZ(bit)) out<<'z';
else out<<'x';
}
} }
else { else {
if (prefixed) out<<"h"; if (prefixed) out<<"h";
// Always deal with 4 bits at once. Note no 4-state, it's above. // Always deal with 4 bits at once. Note no 4-state, it's above.
int hexStart = width()-1; out<<displayed("%0h");
while (hexStart && bitIs0(hexStart)) hexStart--;
while ((hexStart&3)!=3) hexStart++;
for(int bit=hexStart; bit>0; ) {
int v = 0;
if (bitIs1(bit)) v |= 8; bit--;
if (bitIs1(bit)) v |= 4; bit--;
if (bitIs1(bit)) v |= 2; bit--;
if (bitIs1(bit)) v |= 1; bit--;
if (v>=10) out<<(char)('a'+v-10);
else out<<(char)('0'+v);
}
} }
return out.str(); return out.str();
} }
string V3Number::displayed(const string& vformat) const {
string::const_iterator pos = vformat.begin();
UASSERT(pos != vformat.end() && pos[0]=='%', "display with non format argument "<<*this);
pos++;
string fmtsize;
for (; pos != vformat.end() && isdigit(pos[0]); pos++) {
fmtsize += pos[0];
}
string str;
char code = tolower(pos[0]);
switch (code) {
case 'b': {
int bit = width()-1;
if (fmtsize == "0") while (bit && bitIs0(bit)) bit--;
for (; bit>=0; bit--) {
if (bitIs0(bit)) str+='0';
else if (bitIs1(bit)) str+='1';
else if (bitIsZ(bit)) str+='z';
else str+='x';
}
return str;
}
case 'o': {
int bit = width()-1;
if (fmtsize == "0") while (bit && bitIs0(bit)) bit--;
while ((bit%3)!=2) bit++;
for (; bit>0; bit -= 3) {
int v = bitsValue(bit-2, 3);
str += (char)('0'+v);
}
return str;
}
case 'h':
case 'x': {
int bit = width()-1;
if (fmtsize == "0") while (bit && bitIs0(bit)) bit--;
while ((bit%4)!=3) bit++;
for (; bit>0; bit -= 4) {
int v = bitsValue(bit-3, 4);
if (v>=10) str += (char)('a'+v-10);
else str += (char)('0'+v);
}
return str;
}
case 'c': {
if (this->width()>8) m_fileline->v3error("$display of char format of > 8 bit value");
int v = bitsValue(0, 8);
str += (char)(v);
return str;
}
case 's': {
// Spec says always drop leading zeros, this isn't quite right, we space pad.
int bit=this->width()-1;
bool start=true;
while ((bit%8)!=7) bit++;
for (; bit>=0; bit -= 8) {
int v = bitsValue(bit-7, 8);
if (!start || v) {
str += (char)((v==0)?' ':v);
start = false; // Drop leading 0s
} else {
if (fmtsize != "0") str += ' ';
}
}
return str;
}
case '~': // Signed decimal
case 't':
case 'd': { // Unsigned decimal
bool issigned = (code == '~');
if (fmtsize == "") {
double mantissabits = this->width() - (issigned?1:0);
double maxval = pow(2.0, mantissabits);
double dchars = log10(maxval)+1.0;
if (issigned) dchars++; // space for sign
fmtsize = cvtToStr(int(dchars));
}
if (width() > 64) {
m_fileline->v3error("Unsupported: $display of dec format of > 64 bit results (use hex format instead)");
return "ERR";
}
if (issigned) {
str = cvtToStr(asSQuad());
} else {
str = cvtToStr(asQuad());
}
int intfmtsize = atoi(fmtsize.c_str());
while ((int)(str.length()) < intfmtsize) str = " "+str;
return str;
}
default:
m_fileline->v3fatalSrc("Unknown $display format code for number: %"<<pos[0]);
return "ERR";
}
}
//======================================================================
// ACCESSORS - as numbers
uint32_t V3Number::asInt() const { uint32_t V3Number::asInt() const {
UASSERT(!isFourState(),"asInt with 4-state "<<*this); UASSERT(!isFourState(),"asInt with 4-state "<<*this);
UASSERT((width()<33 || (width()<65 && m_value[1]==0)), "Value too wide "<<*this); UASSERT((width()<33 || (width()<65 && m_value[1]==0)), "Value too wide "<<*this);
@@ -369,18 +450,24 @@ uint32_t V3Number::asInt() const {
} }
vlsint32_t V3Number::asSInt() const { vlsint32_t V3Number::asSInt() const {
UASSERT(!isFourState(),"asSInt with 4-state "<<*this); uint32_t v = asInt();
UASSERT((width()<33 || (width()<65 && m_value[1]==0)), "Value too wide "<<*this); uint32_t signExtend = (-(v & (1UL<<(width()-1))));
uint32_t signExtend = (-((m_value[0]) & (1UL<<(width()-1)))); uint32_t extended = v | signExtend;
uint32_t extended = m_value[0] | signExtend;
return (vlsint32_t)(extended); return (vlsint32_t)(extended);
} }
vluint64_t V3Number::asQuad() const { vluint64_t V3Number::asQuad() const {
UASSERT(!isFourState(),"asQuad with 4-state "<<*this); UASSERT(!isFourState(),"asQuad with 4-state "<<*this);
UASSERT(width()<65, "Value too wide "<<*this); UASSERT(width()<65, "Value too wide "<<*this);
if (width()<=32) return ((vluint64_t)m_value[0]); if (width()<=32) return ((vluint64_t)(asInt()));
else return ((vluint64_t)m_value[1]<<VL_ULL(32)) | ((vluint64_t)m_value[0]); return ((vluint64_t)m_value[1]<<VL_ULL(32)) | ((vluint64_t)m_value[0]);
}
vlsint64_t V3Number::asSQuad() const {
vluint64_t v = asQuad();
vluint64_t signExtend = (-(v & (VL_ULL(1)<<(width()-1))));
vluint64_t extended = v | signExtend;
return (vlsint64_t)(extended);
} }
uint32_t V3Number::asHash() const { uint32_t V3Number::asHash() const {
@@ -727,6 +814,28 @@ last:
return setSingleBits(outc); return setSingleBits(outc);
} }
V3Number& V3Number::opWildEq (const V3Number& lhs, const V3Number& rhs) {
char outc = 1;
for (int bit=0; bit<max(lhs.width(),rhs.width()); bit++) {
if (!rhs.bitIsXZ(bit)
&& lhs.bitIs(bit) != rhs.bitIs(bit)) { outc=0; goto last; }
if (lhs.bitIsXZ(bit)) outc='x';
}
last:
return setSingleBits(outc);
}
V3Number& V3Number::opWildNeq (const V3Number& lhs, const V3Number& rhs) {
char outc = 0;
for (int bit=0; bit<max(lhs.width(),rhs.width()); bit++) {
if (!rhs.bitIsXZ(bit)
&& lhs.bitIs(bit) != rhs.bitIs(bit)) { outc=1; goto last; }
if (lhs.bitIsXZ(bit)) outc='x';
}
last:
return setSingleBits(outc);
}
V3Number& V3Number::opGt (const V3Number& lhs, const V3Number& rhs) { V3Number& V3Number::opGt (const V3Number& lhs, const V3Number& rhs) {
// i op j, 1 bit return, max(L(lhs),L(rhs)) calculation, careful need to X/Z extend. // i op j, 1 bit return, max(L(lhs),L(rhs)) calculation, careful need to X/Z extend.
char outc = 0; char outc = 0;
+10
View File
@@ -94,6 +94,12 @@ private:
bool bitIsZ (int bit) const { bool bitIsZ (int bit) const {
if (bit>=m_width) return bitIsZ(m_width-1); if (bit>=m_width) return bitIsZ(m_width-1);
return ( (~m_value[bit/32] & (1UL<<(bit&31))) && (m_valueX[bit/32] & (1UL<<(bit&31))) ); } return ( (~m_value[bit/32] & (1UL<<(bit&31))) && (m_valueX[bit/32] & (1UL<<(bit&31))) ); }
uint32_t bitsValue(int lsb, int nbits) const {
uint32_t v=0;
for (int bitn=0; bitn<nbits; bitn++) { v |= (bitIs1(lsb+bitn)<<bitn); }
return v;
}
int words() const { return ((width()+31)/32); } int words() const { return ((width()+31)/32); }
public: public:
@@ -112,6 +118,7 @@ public:
// ACCESSORS // ACCESSORS
string ascii(bool prefixed=true, bool cleanVerilog=false) const; string ascii(bool prefixed=true, bool cleanVerilog=false) const;
string displayed(const string& format) const;
int width() const { return m_width; } int width() const { return m_width; }
int minWidth() const; // Minimum width that can represent this number (~== log2(num)+1) int minWidth() const; // Minimum width that can represent this number (~== log2(num)+1)
bool sized() const { return m_sized; } bool sized() const { return m_sized; }
@@ -129,6 +136,7 @@ public:
uint32_t asInt() const; uint32_t asInt() const;
vlsint32_t asSInt() const; vlsint32_t asSInt() const;
vluint64_t asQuad() const; vluint64_t asQuad() const;
vlsint64_t asSQuad() const;
uint32_t asHash() const; uint32_t asHash() const;
uint32_t dataWord(int word) const; uint32_t dataWord(int word) const;
uint32_t countOnes() const; uint32_t countOnes() const;
@@ -166,6 +174,8 @@ public:
V3Number& opCond (const V3Number& lhs, const V3Number& rhs, const V3Number& ths); V3Number& opCond (const V3Number& lhs, const V3Number& rhs, const V3Number& ths);
V3Number& opCaseEq (const V3Number& lhs, const V3Number& rhs); V3Number& opCaseEq (const V3Number& lhs, const V3Number& rhs);
V3Number& opCaseNeq (const V3Number& lhs, const V3Number& rhs); V3Number& opCaseNeq (const V3Number& lhs, const V3Number& rhs);
V3Number& opWildEq (const V3Number& lhs, const V3Number& rhs);
V3Number& opWildNeq (const V3Number& lhs, const V3Number& rhs);
// "standard" math // "standard" math
V3Number& opNot (const V3Number& lhs); V3Number& opNot (const V3Number& lhs);
V3Number& opLogNot (const V3Number& lhs); V3Number& opLogNot (const V3Number& lhs);
+3
View File
@@ -65,7 +65,10 @@ void test(string lhss, string op, string rhss, string exps) {
else if (op=="<<") gotnum.opShiftL (lhnum,rhnum); else if (op=="<<") gotnum.opShiftL (lhnum,rhnum);
else if (op=="==") gotnum.opEq (lhnum,rhnum); else if (op=="==") gotnum.opEq (lhnum,rhnum);
else if (op=="===") gotnum.opCaseEq (lhnum,rhnum); else if (op=="===") gotnum.opCaseEq (lhnum,rhnum);
else if (op=="==?") gotnum.opWildEq (lhnum,rhnum);
else if (op=="!=") gotnum.opNeq (lhnum,rhnum); else if (op=="!=") gotnum.opNeq (lhnum,rhnum);
else if (op=="!==") gotnum.opCaseNeq (lhnum,rhnum);
else if (op=="!=?") gotnum.opWildNeq (lhnum,rhnum);
else if (op=="<=") gotnum.opLte (lhnum,rhnum); else if (op=="<=") gotnum.opLte (lhnum,rhnum);
else if (op==">=") gotnum.opGte (lhnum,rhnum); else if (op==">=") gotnum.opGte (lhnum,rhnum);
else if (op=="&&") gotnum.opLogAnd (lhnum,rhnum); else if (op=="&&") gotnum.opLogAnd (lhnum,rhnum);
+1
View File
@@ -40,6 +40,7 @@
#define VP_DEFINE 261 #define VP_DEFINE 261
#define VP_ELSE 262 #define VP_ELSE 262
#define VP_ELSIF 263 #define VP_ELSIF 263
#define VP_LINE 264
#define VP_SYMBOL 300 #define VP_SYMBOL 300
#define VP_STRING 301 #define VP_STRING 301
+2 -1
View File
@@ -73,7 +73,8 @@ psl [p]sl
/**************************************************************/ /**************************************************************/
%% %%
<INITIAL>^{ws}*"`line"{ws}+.*{crnl} { V3PreLex::s_currentLexp->lineDirective(yytext); } <INITIAL>^{ws}*"`line"{ws}+.*{crnl} { V3PreLex::s_currentLexp->lineDirective(yytext);
return(VP_LINE); }
/* Special directives we recognise */ /* Special directives we recognise */
<INITIAL>"`include" { return(VP_INCLUDE); } <INITIAL>"`include" { return(VP_INCLUDE); }
+38 -5
View File
@@ -83,7 +83,9 @@ struct V3PreProcImp : public V3PreProc {
// For getRawToken/ `line insertion // For getRawToken/ `line insertion
string m_lineCmt; // Line comment(s) to be returned string m_lineCmt; // Line comment(s) to be returned
int m_lineAdd; // Empty lines to return to maintain line count bool m_lineCmtNl; ///< Newline needed before inserting lineCmt
int m_lineAdd; ///< Empty lines to return to maintain line count
bool m_rawAtBol; ///< Last rawToken left us at beginning of line
// For defines // For defines
string m_defName; // Define last name being defined string m_defName; // Define last name being defined
@@ -134,6 +136,7 @@ public:
virtual bool isEof() const { return (m_lexp==NULL); } virtual bool isEof() const { return (m_lexp==NULL); }
virtual string getline(); virtual string getline();
virtual void insertUnreadback(const string& text) { m_lineCmt += text; } virtual void insertUnreadback(const string& text) { m_lineCmt += text; }
void insertUnreadbackAtBol(const string& text);
// METHODS, callbacks // METHODS, callbacks
virtual void comment(const string& cmt); // Comment detected (if keepComments==2) virtual void comment(const string& cmt); // Comment detected (if keepComments==2)
@@ -151,6 +154,8 @@ public:
m_lineChars = ""; m_lineChars = "";
m_lastSym = ""; m_lastSym = "";
m_lineAdd = 0; m_lineAdd = 0;
m_lineCmtNl = false;
m_rawAtBol = true;
m_defDepth = 0; m_defDepth = 0;
} }
}; };
@@ -328,6 +333,7 @@ const char* V3PreProcImp::tokenName(int tok) {
case VP_DEFINE : return("DEFINE"); case VP_DEFINE : return("DEFINE");
case VP_ELSE : return("ELSE"); case VP_ELSE : return("ELSE");
case VP_ELSIF : return("ELSIF"); case VP_ELSIF : return("ELSIF");
case VP_LINE : return("LINE");
case VP_SYMBOL : return("SYMBOL"); case VP_SYMBOL : return("SYMBOL");
case VP_STRING : return("STRING"); case VP_STRING : return("STRING");
case VP_DEFVALUE : return("DEFVALUE"); case VP_DEFVALUE : return("DEFVALUE");
@@ -485,14 +491,24 @@ void V3PreProcImp::openFile(FileLine* fl, const string& filename) {
yy_switch_to_buffer(m_lexp->m_yyState); yy_switch_to_buffer(m_lexp->m_yyState);
} }
void V3PreProcImp::insertUnreadbackAtBol(const string& text) {
// Insert insuring we're at the beginning of line, for `line
// We don't always add a leading newline, as it may result in extra unreadback(newlines).
if (m_lineCmt == "") { m_lineCmtNl = true; }
else if (m_lineCmt[m_lineCmt.length()-1]!='\n') {
insertUnreadback("\n");
}
insertUnreadback(text);
}
void V3PreProcImp::addLineComment(int enter_exit_level) { void V3PreProcImp::addLineComment(int enter_exit_level) {
if (lineDirectives()) { if (lineDirectives()) {
char numbuf[20]; sprintf(numbuf, "%d", m_lexp->m_curFilelinep->lineno()); char numbuf[20]; sprintf(numbuf, "%d", m_lexp->m_curFilelinep->lineno());
char levelbuf[20]; sprintf(levelbuf, "%d", enter_exit_level); char levelbuf[20]; sprintf(levelbuf, "%d", enter_exit_level);
string cmt = ((string)"\n`line "+numbuf string cmt = ((string)"`line "+numbuf
+" \""+m_lexp->m_curFilelinep->filename()+"\" " +" \""+m_lexp->m_curFilelinep->filename()+"\" "
+levelbuf+"\n"); +levelbuf+"\n");
insertUnreadback(cmt); insertUnreadbackAtBol(cmt);
} }
} }
@@ -516,6 +532,7 @@ int V3PreProcImp::getRawToken() {
next_tok: next_tok:
if (m_lineAdd) { if (m_lineAdd) {
m_lineAdd--; m_lineAdd--;
m_rawAtBol = true;
yytext="\n"; yyleng=1; yytext="\n"; yyleng=1;
return (VP_TEXT); return (VP_TEXT);
} }
@@ -523,8 +540,13 @@ int V3PreProcImp::getRawToken() {
// We have some `line directive to return to the user. Do it. // We have some `line directive to return to the user. Do it.
static string rtncmt; // Keep the c string till next call static string rtncmt; // Keep the c string till next call
rtncmt = m_lineCmt; rtncmt = m_lineCmt;
if (m_lineCmtNl) {
if (!m_rawAtBol) rtncmt = "\n"+rtncmt;
m_lineCmtNl = false;
}
yytext=(char*)rtncmt.c_str(); yyleng=rtncmt.length(); yytext=(char*)rtncmt.c_str(); yyleng=rtncmt.length();
m_lineCmt = ""; m_lineCmt = "";
if (yyleng) m_rawAtBol = (yytext[yyleng-1]=='\n');
if (m_state!=ps_DEFVALUE) return (VP_TEXT); if (m_state!=ps_DEFVALUE) return (VP_TEXT);
else { else {
V3PreLex::s_currentLexp->appendDefValue(yytext,yyleng); V3PreLex::s_currentLexp->appendDefValue(yytext,yyleng);
@@ -532,6 +554,7 @@ int V3PreProcImp::getRawToken() {
} }
} }
if (isEof()) return (VP_EOF); if (isEof()) return (VP_EOF);
// Snarf next token from the file // Snarf next token from the file
m_fileline = m_lexp->m_curFilelinep; // Remember token start location m_fileline = m_lexp->m_curFilelinep; // Remember token start location
V3PreLex::s_currentLexp = m_lexp; // Tell parser where to get/put data V3PreLex::s_currentLexp = m_lexp; // Tell parser where to get/put data
@@ -552,6 +575,7 @@ int V3PreProcImp::getRawToken() {
goto next_tok; // Parse parent, or find the EOF. goto next_tok; // Parse parent, or find the EOF.
} }
if (yyleng) m_rawAtBol = (yytext[yyleng-1]=='\n');
return tok; return tok;
} }
} }
@@ -583,6 +607,10 @@ int V3PreProcImp::getToken() {
for (int len=0; len<yyleng; len++) { if (yytext[len]=='\n') m_lineAdd++; } for (int len=0; len<yyleng; len++) { if (yytext[len]=='\n') m_lineAdd++; }
goto next_tok; goto next_tok;
} }
if (tok==VP_LINE) {
addLineComment(0);
goto next_tok;
}
// Deal with some special parser states // Deal with some special parser states
switch (m_state) { switch (m_state) {
case ps_TOP: { case ps_TOP: {
@@ -867,7 +895,8 @@ string V3PreProcImp::getline() {
// Get a single line from the parse stream. Buffer unreturned text until the newline. // Get a single line from the parse stream. Buffer unreturned text until the newline.
if (isEof()) return ""; if (isEof()) return "";
char* rtnp; char* rtnp;
while (NULL==(rtnp=strchr(m_lineChars.c_str(),'\n'))) { bool gotEof = false;
while (NULL==(rtnp=strchr(m_lineChars.c_str(),'\n')) && !gotEof) {
int tok = getToken(); int tok = getToken();
if (debug()>4) { if (debug()>4) {
string buf = string (yytext, yyleng); string buf = string (yytext, yyleng);
@@ -878,9 +907,13 @@ string V3PreProcImp::getline() {
fileline()->lineno(), tokenName(tok), buf.c_str()); fileline()->lineno(), tokenName(tok), buf.c_str());
} }
if (tok==VP_EOF) { if (tok==VP_EOF) {
// Add a final newline, in case the user forgot the final \n. // Add a final newline, if the user forgot the final \n.
// Note tok==VP_EOF isn't always seen by us, as isEof() may be set earlier
if (m_lineChars != "" && m_lineChars[m_lineChars.length()-1] != '\n') {
m_lineChars.append("\n"); m_lineChars.append("\n");
} }
gotEof = true;
}
else if (tok==VP_PSL) { else if (tok==VP_PSL) {
m_lineChars.append(" psl "); m_lineChars.append(" psl ");
} }
+1 -3
View File
@@ -198,9 +198,8 @@ private:
nodep->taskp(NULL); nodep->taskp(NULL);
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
virtual void visit(AstDisplay* nodep, AstNUser*) { virtual void visit(AstScopeName* nodep, AstNUser*) {
// If there's a %m in the display text, we add a special node that will contain the name() // If there's a %m in the display text, we add a special node that will contain the name()
if (nodep->name().find("%m") != string::npos) {
string prefix = (string)(".")+m_scopep->prettyName(); string prefix = (string)(".")+m_scopep->prettyName();
// TOP and above will be the user's name(). // TOP and above will be the user's name().
// Note 'TOP.'is stripped by prettyName, but not 'TOP'. // Note 'TOP.'is stripped by prettyName, but not 'TOP'.
@@ -211,7 +210,6 @@ private:
nodep->scopeAttrp(new AstText(nodep->fileline(), prefix)); nodep->scopeAttrp(new AstText(nodep->fileline(), prefix));
if (afterp) nodep->scopeAttrp(afterp); if (afterp) nodep->scopeAttrp(afterp);
} }
}
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
virtual void visit(AstScope* nodep, AstNUser*) { virtual void visit(AstScope* nodep, AstNUser*) {
+2
View File
@@ -98,8 +98,10 @@ private:
// ... (Though they should match. We don't check.) // ... (Though they should match. We don't check.)
virtual void visit(AstEq* nodep, AstNUser*) { signed_Ou_Ix(nodep); } virtual void visit(AstEq* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstEqCase* nodep, AstNUser*) { signed_Ou_Ix(nodep); } virtual void visit(AstEqCase* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstEqWild* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstNeq* nodep, AstNUser*) { signed_Ou_Ix(nodep); } virtual void visit(AstNeq* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstNeqCase* nodep, AstNUser*){ signed_Ou_Ix(nodep); } virtual void visit(AstNeqCase* nodep, AstNUser*){ signed_Ou_Ix(nodep); }
virtual void visit(AstNeqWild* nodep, AstNUser*){ signed_Ou_Ix(nodep); }
//======= //=======
// Signed: Output signed iff LHS signed; unary operator // Signed: Output signed iff LHS signed; unary operator
+42
View File
@@ -106,6 +106,42 @@ private:
newp->iterateChildren(*this); newp->iterateChildren(*this);
} }
} }
void visitEqNeqWild(AstNodeBiop* nodep) {
UINFO(4," N/EQWILD->EQ "<<nodep<<endl);
V3Const::constifyTree(nodep->lhsp());
V3Const::constifyTree(nodep->rhsp());
if (nodep->lhsp()->castConst() && nodep->rhsp()->castConst()) {
// Both sides are constant, node can be constant
V3Const::constifyTree(nodep); nodep=NULL;
return;
} else {
AstNode* lhsp = nodep->lhsp()->unlinkFrBack();
AstNode* rhsp = nodep->rhsp()->unlinkFrBack();
AstNode* newp;
if (!rhsp->castConst()) {
nodep->v3error("Unsupported: RHS of ==? or !=? must be constant to be synthesizable"); // Says spec.
// Replace with anything that won't cause more errors
newp = new AstEq (nodep->fileline(), lhsp, rhsp);
} else {
// X or Z's become mask, ala case statements.
V3Number nummask (rhsp->fileline(), rhsp->width());
nummask.opBitsNonX(rhsp->castConst()->num());
V3Number numval (rhsp->fileline(), rhsp->width());
numval.opBitsOne (rhsp->castConst()->num());
AstNode* and1p = new AstAnd(nodep->fileline(), lhsp,
new AstConst(nodep->fileline(), nummask));
AstNode* and2p = new AstConst(nodep->fileline(), numval);
if (nodep->castEqWild())
newp = new AstEq (nodep->fileline(), and1p, and2p);
else newp = new AstNeq (nodep->fileline(), and1p, and2p);
rhsp->deleteTree(); rhsp=NULL;
}
nodep->replaceWith(newp);
nodep->deleteTree(); nodep=NULL;
// Iterate tree now that we may have gotten rid of the compare
newp->iterateChildren(*this);
}
}
virtual void visit(AstEqCase* nodep, AstNUser*) { virtual void visit(AstEqCase* nodep, AstNUser*) {
visitEqNeqCase(nodep); visitEqNeqCase(nodep);
@@ -113,6 +149,12 @@ private:
virtual void visit(AstNeqCase* nodep, AstNUser*) { virtual void visit(AstNeqCase* nodep, AstNUser*) {
visitEqNeqCase(nodep); visitEqNeqCase(nodep);
} }
virtual void visit(AstEqWild* nodep, AstNUser*) {
visitEqNeqWild(nodep);
}
virtual void visit(AstNeqWild* nodep, AstNUser*) {
visitEqNeqWild(nodep);
}
virtual void visit(AstIsUnknown* nodep, AstNUser*) { virtual void visit(AstIsUnknown* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
// Ahh, we're two state, so this is easy // Ahh, we're two state, so this is easy
+5
View File
@@ -117,6 +117,7 @@ private:
void width_O1_L_Rlhs(AstNode* nodep, AstNUser* vup); void width_O1_L_Rlhs(AstNode* nodep, AstNUser* vup);
virtual void visit(AstEq* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); } virtual void visit(AstEq* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); }
virtual void visit(AstEqCase* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); } virtual void visit(AstEqCase* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); }
virtual void visit(AstEqWild* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); }
virtual void visit(AstGt* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); } virtual void visit(AstGt* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); }
virtual void visit(AstGtS* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); } virtual void visit(AstGtS* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); }
virtual void visit(AstGte* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); } virtual void visit(AstGte* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); }
@@ -127,6 +128,7 @@ private:
virtual void visit(AstLteS* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); } virtual void visit(AstLteS* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); }
virtual void visit(AstNeq* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); } virtual void visit(AstNeq* nodep, AstNUser* vup) { width_O1_L_Rlhs(nodep,vup); }
virtual void visit(AstNeqCase* nodep, AstNUser* vup){ width_O1_L_Rlhs(nodep,vup); } virtual void visit(AstNeqCase* nodep, AstNUser* vup){ width_O1_L_Rlhs(nodep,vup); }
virtual void visit(AstNeqWild* nodep, AstNUser* vup){ width_O1_L_Rlhs(nodep,vup); }
// Widths: out width = lhs width = rhs width // Widths: out width = lhs width = rhs width
void width_Omax_L_Rlhs(AstNode* nodep, AstNUser* vup); void width_Omax_L_Rlhs(AstNode* nodep, AstNUser* vup);
@@ -385,6 +387,9 @@ private:
virtual void visit(AstText* nodep, AstNUser* vup) { virtual void visit(AstText* nodep, AstNUser* vup) {
// Only used in CStmts which don't care.... // Only used in CStmts which don't care....
} }
virtual void visit(AstScopeName* nodep, AstNUser* vup) {
// Only used in Displays which don't care....
}
virtual void visit(AstVar* nodep, AstNUser* vup) { virtual void visit(AstVar* nodep, AstNUser* vup) {
//if (debug()) nodep->dumpTree(cout," InitPre: "); //if (debug()) nodep->dumpTree(cout," InitPre: ");
// Must have deterministic constant width // Must have deterministic constant width
+1 -1
View File
@@ -538,7 +538,7 @@ int main(int argc, char** argv, char** env) {
// Final steps // Final steps
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("final.tree",99)); v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("final.tree",99));
V3Error::abortIfErrors(); V3Error::abortIfWarnings();
if (!v3Global.opt.lintOnly() && v3Global.opt.makeDepend()) { if (!v3Global.opt.lintOnly() && v3Global.opt.makeDepend()) {
V3File::writeDepend(v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"__ver.d"); V3File::writeDepend(v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"__ver.d");
+2 -2
View File
@@ -4,7 +4,7 @@
// //
// This file is part of Verilator. // This file is part of Verilator.
// //
// Author: Wilson Snyder <[email protected]> or <[email protected]> // Author: Wilson Snyder <[email protected]>
// //
// Code available from: http://www.veripool.com/verilator // Code available from: http://www.veripool.com/verilator
// //
@@ -24,7 +24,7 @@
//********************************************************************** //**********************************************************************
//**** Version and host name //**** Version and host name
#define DTVERSION "Verilator 3.651 4/20/2007" #define DTVERSION "Verilator 3.653 8/1/2007"
//********************************************************************** //**********************************************************************
//**** Functions //**** Functions
+9 -3
View File
@@ -567,6 +567,7 @@ escid \\[^ \t\f\r\n]+
"~^" {yylval.fileline = CRELINE(); return yP_XNOR;} "~^" {yylval.fileline = CRELINE(); return yP_XNOR;}
"~&" {yylval.fileline = CRELINE(); return yP_NAND;} "~&" {yylval.fileline = CRELINE(); return yP_NAND;}
"~|" {yylval.fileline = CRELINE(); return yP_NOR;} "~|" {yylval.fileline = CRELINE(); return yP_NOR;}
"->" {yylval.fileline = CRELINE(); return yP_MINUSGT;}
} }
/* Verilog 2001 Operators */ /* Verilog 2001 Operators */
@@ -578,11 +579,16 @@ escid \\[^ \t\f\r\n]+
"-:" {yylval.fileline = CRELINE(); return yP_MINUSCOLON;} "-:" {yylval.fileline = CRELINE(); return yP_MINUSCOLON;}
} }
/* SystemVerilog Operators */
<S05>{
"==?" {yylval.fileline = CRELINE(); return yP_WILDEQUAL;}
"!=?" {yylval.fileline = CRELINE(); return yP_WILDNOTEQUAL;}
}
/* PSL Operators */ /* PSL Operators */
<PSL>{ <PSL>{
"{" {yylval.fileline = CRELINE(); return yPSL_BRA;} // Avoid parser hitting concatenate. "{" {yylval.fileline = CRELINE(); return yPSL_BRA;} // Avoid parser hitting concatenate.
"}" {yylval.fileline = CRELINE(); return yPSL_KET;} // Avoid parser hitting concatenate. "}" {yylval.fileline = CRELINE(); return yPSL_KET;} // Avoid parser hitting concatenate.
"->" {yylval.fileline = CRELINE(); return yP_LOGIF;}
"<->" {yyerrorf("Unsupported: PSL operator not implemented: %s",yytext);} //Unsup in other tools "<->" {yyerrorf("Unsupported: PSL operator not implemented: %s",yytext);} //Unsup in other tools
"[*" {yyerrorf("Unsupported: PSL operator not implemented: %s",yytext);} // yP_BRA_STAR "[*" {yyerrorf("Unsupported: PSL operator not implemented: %s",yytext);} // yP_BRA_STAR
"[*]" {yyerrorf("Unsupported: PSL operator not implemented: %s",yytext);} // yP_BRA_STAR_KET "[*]" {yyerrorf("Unsupported: PSL operator not implemented: %s",yytext);} // yP_BRA_STAR_KET
@@ -659,7 +665,7 @@ escid \\[^ \t\f\r\n]+
<ATTRMODE>"*)" { yy_pop_state(); } <ATTRMODE>"*)" { yy_pop_state(); }
<ATTRMODE>. { yymore(); } <ATTRMODE>. { yymore(); }
<ATTRMODE><<EOF>> { yyerror("EOF in (*"); <ATTRMODE><<EOF>> { yyerror("EOF in (*");
yyleng = 0; } yyleng = 0; yy_pop_state(); }
/************************************************************************/ /************************************************************************/
/* Attributes */ /* Attributes */
@@ -718,7 +724,7 @@ escid \\[^ \t\f\r\n]+
<V95,V01,V05,S05,PSL>{ <V95,V01,V05,S05,PSL>{
"`"[a-zA-Z_0-9]+ { yyerrorf("Define or directive not defined: %s",yytext); } "`"[a-zA-Z_0-9]+ { yyerrorf("Define or directive not defined: %s",yytext); }
"//"[^\n]+ { } /* throw away single line comments */ "//"[^\n]* { } /* throw away single line comments */
. {yylval.fileline = CRELINE(); return yytext[0];} /* return single char ops. */ . {yylval.fileline = CRELINE(); return yytext[0];} /* return single char ops. */
} }
+41 -20
View File
@@ -256,7 +256,7 @@ class AstSenTree;
//******************** //********************
// PSL op precedence // PSL op precedence
%right<fileline> yP_LOGIF yP_LOGIFF %right<fileline> yP_MINUSGT yP_LOGIFF /* MinusGT == -> == PSL LogIf operator */
%right<fileline> yP_OR_MINUS_GT yP_OR_EQ_GT %right<fileline> yP_OR_MINUS_GT yP_OR_EQ_GT
%left<fileline> prPSLCLK %left<fileline> prPSLCLK
@@ -269,7 +269,7 @@ class AstSenTree;
%left<fileline> '^' %left<fileline> '^'
%left<fileline> yP_XNOR %left<fileline> yP_XNOR
%left<fileline> '&' yP_NAND %left<fileline> '&' yP_NAND
%left<fileline> yP_EQUAL yP_NOTEQUAL yP_CASEEQUAL yP_CASENOTEQUAL %left<fileline> yP_EQUAL yP_NOTEQUAL yP_CASEEQUAL yP_CASENOTEQUAL yP_WILDEQUAL yP_WILDNOTEQUAL
%left<fileline> '>' '<' yP_GTE yP_LTE %left<fileline> '>' '<' yP_GTE yP_LTE
%left<fileline> yP_SLEFT yP_SRIGHT yP_SSRIGHT %left<fileline> yP_SLEFT yP_SRIGHT yP_SSRIGHT
%left<fileline> '+' '-' %left<fileline> '+' '-'
@@ -288,7 +288,7 @@ class AstSenTree;
// Trailing E indicates this type may have empty match // Trailing E indicates this type may have empty match
%type<modulep> modHdr %type<modulep> modHdr
%type<nodep> modPortsE portList port %type<nodep> modPortsE portList port
%type<nodep> portV2kList portV2kSig %type<nodep> portV2kArgs portV2kList portV2kSecond portV2kSig
%type<nodep> portV2kDecl ioDecl varDecl %type<nodep> portV2kDecl ioDecl varDecl
%type<nodep> modParDecl modParList modParE %type<nodep> modParDecl modParList modParE
%type<nodep> modItem modItemList modItemListE modOrGenItem %type<nodep> modItem modItemList modItemListE modOrGenItem
@@ -325,7 +325,7 @@ class AstSenTree;
%type<nodep> taskDecl %type<nodep> taskDecl
%type<nodep> varDeclList %type<nodep> varDeclList
%type<funcp> funcDecl %type<funcp> funcDecl
%type<nodep> funcBody funcVarList funcVar %type<nodep> funcBody funcGuts funcVarList funcVar
%type<rangep> funcTypeE %type<rangep> funcTypeE
%type<rangep> instRangeE %type<rangep> instRangeE
%type<nodep> gateDecl %type<nodep> gateDecl
@@ -362,7 +362,7 @@ file: mod { }
//********************************************************************** //**********************************************************************
// Module headers // Module headers
mod: modHdr modParE modPortsE ';' modItemListE yENDMODULE mod: modHdr modParE modPortsE ';' modItemListE yENDMODULE endLabelE
{ $1->modTrace(V3Parse::s_trace); // Stash for implicit wires, etc { $1->modTrace(V3Parse::s_trace); // Stash for implicit wires, etc
if ($2) $1->addStmtp($2); if ($3) $1->addStmtp($3); if ($5) $1->addStmtp($5); } if ($2) $1->addStmtp($2); if ($3) $1->addStmtp($3); if ($5) $1->addStmtp($5); }
; ;
@@ -386,7 +386,7 @@ modParList: modParDecl { $$ = $1; }
modPortsE: /* empty */ { $$ = NULL; } modPortsE: /* empty */ { $$ = NULL; }
| '(' ')' { $$ = NULL; } | '(' ')' { $$ = NULL; }
| '(' {V3Parse::s_pinNum=1;} portList ')' { $$ = $3; } | '(' {V3Parse::s_pinNum=1;} portList ')' { $$ = $3; }
| '(' {V3Parse::s_pinNum=1;} portV2kList ')' { $$ = $3; } | '(' {V3Parse::s_pinNum=1;} portV2kArgs ')' { $$ = $3; }
; ;
portList: port { $$ = $1; } portList: port { $$ = $1; }
@@ -396,8 +396,17 @@ portList: port { $$ = $1; }
port: yaID portRangeE { $$ = new AstPort(CRELINE(),V3Parse::s_pinNum++,*$1); } port: yaID portRangeE { $$ = new AstPort(CRELINE(),V3Parse::s_pinNum++,*$1); }
; ;
portV2kList: portV2kDecl { $$ = $1; } portV2kArgs: portV2kDecl { $$ = $1; }
| portV2kList ',' portV2kDecl { $$ = $1->addNext($3); } | portV2kDecl ',' portV2kList { $$ = $1->addNext($3); }
;
portV2kList: portV2kSecond { $$ = $1; }
| portV2kList ',' portV2kSecond { $$ = $1->addNext($3); }
;
// Called only after a comma in a v2k list, to allow parsing "input a,b"
portV2kSecond: portV2kDecl { $$ = $1; }
| portV2kSig { $$ = $1; }
; ;
portV2kSig: sigAndAttr { $$=$1; $$->addNext(new AstPort(CRELINE(),V3Parse::s_pinNum++, V3Parse::s_varAttrp->name())); } portV2kSig: sigAndAttr { $$=$1; $$->addNext(new AstPort(CRELINE(),V3Parse::s_pinNum++, V3Parse::s_varAttrp->name())); }
@@ -528,8 +537,8 @@ genTopBlock: genItemList { $$ = $1; }
genItemBegin: yBEGIN genItemList yEND { $$ = new AstBegin($1,"genblk",$2); } genItemBegin: yBEGIN genItemList yEND { $$ = new AstBegin($1,"genblk",$2); }
| yBEGIN yEND { $$ = NULL; } | yBEGIN yEND { $$ = NULL; }
| yBEGIN ':' yaID genItemList yEND { $$ = new AstBegin($2,*$3,$4); } | yBEGIN ':' yaID genItemList yEND endLabelE { $$ = new AstBegin($2,*$3,$4); }
| yBEGIN ':' yaID yEND { $$ = NULL; } | yBEGIN ':' yaID yEND endLabelE { $$ = NULL; }
; ;
genItemList: genItem { $$ = $1; } genItemList: genItem { $$ = $1; }
@@ -746,8 +755,8 @@ senitemEdge: yPOSEDGE varRefDotBit { $$ = new AstSenItem($1,AstEdgeType::POSED
stmtBlock: stmt { $$ = $1; } stmtBlock: stmt { $$ = $1; }
| yBEGIN stmtList yEND { $$ = $2; } | yBEGIN stmtList yEND { $$ = $2; }
| yBEGIN yEND { $$ = NULL; } | yBEGIN yEND { $$ = NULL; }
| beginNamed stmtList yEND { $$ = $1; $1->addStmtp($2); } | beginNamed stmtList yEND endLabelE { $$ = $1; $1->addStmtp($2); }
| beginNamed yEND { $$ = $1; } | beginNamed yEND endLabelE { $$ = $1; }
; ;
beginNamed: yBEGIN ':' yaID varDeclList { $$ = new AstBegin($2,*$3,$4); } beginNamed: yBEGIN ':' yaID varDeclList { $$ = new AstBegin($2,*$3,$4); }
@@ -849,21 +858,26 @@ taskRef: idDotted { $$ = new AstTaskRef(CRELINE(),new AstParseRef($1->fileli
funcRef: idDotted '(' exprList ')' { $$ = new AstFuncRef($2,new AstParseRef($1->fileline(), AstParseRefExp::FUNC, $1), $3); } funcRef: idDotted '(' exprList ')' { $$ = new AstFuncRef($2,new AstParseRef($1->fileline(), AstParseRefExp::FUNC, $1), $3); }
; ;
taskDecl: yTASK taskAutoE yaID ';' stmtBlock yENDTASK { $$ = new AstTask ($1,*$3,$5);} taskDecl: yTASK taskAutoE yaID funcGuts yENDTASK endLabelE
| yTASK taskAutoE yaID ';' funcVarList stmtBlock yENDTASK { $$ = new AstTask ($1,*$3,$5); $5->addNextNull($6); } { $$ = new AstTask ($1,*$3,$4);}
; ;
funcDecl: yFUNCTION taskAutoE funcTypeE yaID ';' funcBody yENDFUNCTION { $$ = new AstFunc ($1,*$4,$6,$3); } funcDecl: yFUNCTION taskAutoE funcTypeE yaID funcGuts yENDFUNCTION endLabelE { $$ = new AstFunc ($1,*$4,$5,$3); }
| yFUNCTION taskAutoE ySIGNED funcTypeE yaID ';' funcBody yENDFUNCTION { $$ = new AstFunc ($1,*$5,$7,$4); $$->isSigned(true); } | yFUNCTION taskAutoE ySIGNED funcTypeE yaID funcGuts yENDFUNCTION endLabelE { $$ = new AstFunc ($1,*$5,$6,$4); $$->isSigned(true); }
| yFUNCTION taskAutoE funcTypeE yaID yVL_ISOLATE_ASSIGNMENTS ';' funcBody yENDFUNCTION { $$ = new AstFunc ($1,*$4,$7,$3); $$->attrIsolateAssign(true);} | yFUNCTION taskAutoE funcTypeE yaID yVL_ISOLATE_ASSIGNMENTS funcGuts yENDFUNCTION endLabelE { $$ = new AstFunc ($1,*$4,$6,$3); $$->attrIsolateAssign(true);}
| yFUNCTION taskAutoE ySIGNED funcTypeE yaID yVL_ISOLATE_ASSIGNMENTS ';' funcBody yENDFUNCTION { $$ = new AstFunc ($1,*$5,$8,$4); $$->attrIsolateAssign(true); $$->isSigned(true); } | yFUNCTION taskAutoE ySIGNED funcTypeE yaID yVL_ISOLATE_ASSIGNMENTS funcGuts yENDFUNCTION endLabelE { $$ = new AstFunc ($1,*$5,$7,$4); $$->attrIsolateAssign(true); $$->isSigned(true); }
; ;
taskAutoE: /* empty */ { } taskAutoE: /* empty */ { }
| yAUTOMATIC { } | yAUTOMATIC { }
; ;
funcGuts: '(' {V3Parse::s_pinNum=1;} portV2kArgs ')' ';' funcBody { $$ = $3->addNextNull($6); }
| ';' funcBody { $$ = $2; }
;
funcBody: funcVarList stmtBlock { $$ = $1;$1->addNextNull($2); } funcBody: funcVarList stmtBlock { $$ = $1;$1->addNextNull($2); }
| stmtBlock { $$ = $1; }
; ;
funcTypeE: /* empty */ { $$ = NULL; } funcTypeE: /* empty */ { $$ = NULL; }
@@ -899,6 +913,8 @@ exprNoStr: expr yP_OROR expr { $$ = new AstLogOr ($2,$1,$3); }
| expr yP_NOTEQUAL expr { $$ = new AstNeq ($2,$1,$3); } | expr yP_NOTEQUAL expr { $$ = new AstNeq ($2,$1,$3); }
| expr yP_CASEEQUAL expr { $$ = new AstEqCase ($2,$1,$3); } | expr yP_CASEEQUAL expr { $$ = new AstEqCase ($2,$1,$3); }
| expr yP_CASENOTEQUAL expr { $$ = new AstNeqCase ($2,$1,$3); } | expr yP_CASENOTEQUAL expr { $$ = new AstNeqCase ($2,$1,$3); }
| expr yP_WILDEQUAL expr { $$ = new AstEqWild ($2,$1,$3); }
| expr yP_WILDNOTEQUAL expr { $$ = new AstNeqWild ($2,$1,$3); }
| expr '>' expr { $$ = new AstGt ($2,$1,$3); } | expr '>' expr { $$ = new AstGt ($2,$1,$3); }
| expr '<' expr { $$ = new AstLt ($2,$1,$3); } | expr '<' expr { $$ = new AstLt ($2,$1,$3); }
| expr yP_GTE expr { $$ = new AstGte ($2,$1,$3); } | expr yP_GTE expr { $$ = new AstGte ($2,$1,$3); }
@@ -912,7 +928,7 @@ exprNoStr: expr yP_OROR expr { $$ = new AstLogOr ($2,$1,$3); }
| expr '/' expr { $$ = new AstDiv ($2,$1,$3); } | expr '/' expr { $$ = new AstDiv ($2,$1,$3); }
| expr '%' expr { $$ = new AstModDiv ($2,$1,$3); } | expr '%' expr { $$ = new AstModDiv ($2,$1,$3); }
| expr yP_POW expr { $$ = new AstPow ($2,$1,$3); } | expr yP_POW expr { $$ = new AstPow ($2,$1,$3); }
| expr yP_LOGIF expr { $$ = new AstLogIf ($2,$1,$3); } | expr yP_MINUSGT expr { $$ = new AstLogIf ($2,$1,$3); }
| expr yP_LOGIFF expr { $$ = new AstLogIff ($2,$1,$3); } | expr yP_LOGIFF expr { $$ = new AstLogIff ($2,$1,$3); }
| '-' expr %prec prUNARYARITH { $$ = new AstUnaryMin ($1,$2); } | '-' expr %prec prUNARYARITH { $$ = new AstUnaryMin ($1,$2); }
@@ -1091,13 +1107,14 @@ specifyJunk: dlyTerm {} /* ignored */
| yP_ANDAND {} | yP_GTE {} | yP_LTE {} | yP_ANDAND {} | yP_GTE {} | yP_LTE {}
| yP_EQUAL {} | yP_NOTEQUAL {} | yP_EQUAL {} | yP_NOTEQUAL {}
| yP_CASEEQUAL {} | yP_CASENOTEQUAL {} | yP_CASEEQUAL {} | yP_CASENOTEQUAL {}
| yP_WILDEQUAL {} | yP_WILDNOTEQUAL {}
| yP_XNOR {} | yP_NOR {} | yP_NAND {} | yP_XNOR {} | yP_NOR {} | yP_NAND {}
| yP_OROR {} | yP_OROR {}
| yP_SLEFT {} | yP_SRIGHT {} | yP_SSRIGHT {} | yP_SLEFT {} | yP_SRIGHT {} | yP_SSRIGHT {}
| yP_PLUSCOLON {} | yP_MINUSCOLON {} | yP_PLUSCOLON {} | yP_MINUSCOLON {}
| yP_POW {} | yP_POW {}
| yP_LOGIF {} | yP_MINUSGT {}
| yP_LOGIFF {} | yP_LOGIFF {}
| yPSL_BRA {} | yPSL_BRA {}
| yPSL_KET {} | yPSL_KET {}
@@ -1146,6 +1163,10 @@ concIdList: varRefDotBit { $$ = $1; }
| concIdList ',' varRefDotBit { $$ = new AstConcat($2,$1,$3); } | concIdList ',' varRefDotBit { $$ = new AstConcat($2,$1,$3); }
; ;
endLabelE: /* empty */ { }
| ':' yaID { }
;
//************************************************ //************************************************
// Asserts // Asserts
+1
View File
@@ -549,6 +549,7 @@ sub _make_main {
print $fh " double sim_time = 1000;\n"; print $fh " double sim_time = 1000;\n";
} }
print $fh " Verilated::debug(".($self->{verilated_debug}?1:0).");\n"; print $fh " Verilated::debug(".($self->{verilated_debug}?1:0).");\n";
print $fh " Verilated::randReset(".$self->{verilated_randReset}.");\n" if defined $self->{verilated_randReset};
print $fh " topp = new $VM_PREFIX (\"TOP\");\n"; print $fh " topp = new $VM_PREFIX (\"TOP\");\n";
my $set; my $set;
if ($self->sp) { if ($self->sp) {
+2
View File
@@ -24,6 +24,8 @@ execute (
[0] %x=00abc1234567812345678 %0x=abc1234567812345678 %o=012570110642547402215053170 %b=000001010101111000001001000110100010101100111100000010010001101000101011001111000 [0] %x=00abc1234567812345678 %0x=abc1234567812345678 %o=012570110642547402215053170 %b=000001010101111000001001000110100010101100111100000010010001101000101011001111000
[0] %s=! %s= what! %s= hmmm!1234 [0] %s=! %s= what! %s= hmmm!1234
[0] hello, from a very long string. Percent %s are literally substituted in.
*-* All Finished *-*
'), '),
); );
+3
View File
@@ -33,6 +33,9 @@ module t;
$display("[%0t] %%s=%s %%s=%s %%s=%s", $time, $display("[%0t] %%s=%s %%s=%s %%s=%s", $time,
str2[7:0], str2, str3); str2[7:0], str2, str3);
$display("[%0t] %s%s%s", $time,
"hel", "lo, fr", "om a very long string. Percent %s are literally substituted in.");
// Str check // Str check
`ifndef nc // NC-Verilog 5.3 chokes on this test `ifndef nc // NC-Verilog 5.3 chokes on this test
if (str !== 32'h00_bf_11_0a) $stop; if (str !== 32'h00_bf_11_0a) $stop;
+36
View File
@@ -0,0 +1,36 @@
#!/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.
top_filename("t/t_display.v");
compile (
v_flags2 => [$Last_Self->{v3}?"-O0":""],
);
execute (
check_finished=>1,
expect=>quotemeta(
'[0] In TOP.v: Hi
[0] In TOP.v.sub
[0] In TOP.v.sub.subblock
[0] In TOP.v.sub2
[0] In TOP.v.sub2.subblock2
[0] %X=0c %D=12 %0X=c %0O=14 %B=001100
[0] %x=0c %d=12 %0x=c %0o=14 %b=001100
[0] %x=00abbbbcccc %0x=abbbbcccc %o=00527356746314 %b=00000101010111011101110111100110011001100
[0] %x=00abc1234567812345678 %0x=abc1234567812345678 %o=012570110642547402215053170 %b=000001010101111000001001000110100010101100111100000010010001101000101011001111000
[0] %s=! %s= what! %s= hmmm!1234
[0] hello, from a very long string. Percent %s are literally substituted in.
*-* All Finished *-*
'),
);
ok(1);
1;
+6 -6
View File
@@ -13,12 +13,12 @@ compile (
execute ( execute (
check_finished=>1, check_finished=>1,
expect=> quotemeta( expect=> quotemeta(
'[0] %x=0bbccc %x=0bbccc %o=2736314 %b=010111011110011001100 %0d=769228 %d= 769228 '[0] lp %x=0bbccc %x=0bbccc %o=2736314 %b=010111011110011001100 %0d=769228 %d= 769228
[0] %x=1bbccc %x=1bbccc %o=6736314 %b=110111011110011001100 %0d=-279348 %d= -279348 [0] ln %x=1bbccc %x=1bbccc %o=6736314 %b=110111011110011001100 %0d=-279348 %d= -279348
[0] %x=000bbbbcccc %x=000bbbbcccc %o=00027356746314 %b=00000000010111011101110111100110011001100 %0d=3149647052 %d= 3149647052 [0] qp %x=001bbbbcccc %x=001bbbbcccc %o=00067356746314 %b=00000000110111011101110111100110011001100 %0d=7444614348 %d= 7444614348
[0] %x=100bbbbcccc %x=100bbbbcccc %o=20027356746314 %b=10000000010111011101110111100110011001100 %0d=-1096361980724 %d=-1096361980724 [0] qn %x=101bbbbcccc %x=101bbbbcccc %o=20067356746314 %b=10000000110111011101110111100110011001100 %0d=-1092067013428 %d=-1092067013428
[0] %x=000bc1234567812345678 %x=000bc1234567812345678 %o=000570110642547402215053170 %b=000000000101111000001001000110100010101100111100000010010001101000101011001111000 [0] wp %x=000bc1234567812345678 %x=000bc1234567812345678 %o=000570110642547402215053170 %b=000000000101111000001001000110100010101100111100000010010001101000101011001111000
[0] %x=000bc1234577812345678 %x=000bc1234577812345678 %o=000570110642567402215053170 %b=000000000101111000001001000110100010101110111100000010010001101000101011001111000 [0] wn %x=000bc1234577812345678 %x=000bc1234577812345678 %o=000570110642567402215053170 %b=000000000101111000001001000110100010101110111100000010010001101000101011001111000
'), '),
); );
+8 -8
View File
@@ -7,24 +7,24 @@
module t; module t;
reg signed [20:0] longp; initial longp = 21'shbbccc; reg signed [20:0] longp; initial longp = 21'shbbccc;
reg signed [20:0] longn; initial longn = 21'shbbccc; initial longn[20]=1'b1; reg signed [20:0] longn; initial longn = 21'shbbccc; initial longn[20]=1'b1;
reg signed [40:0] quadp; initial quadp = 41'shbbbb_cccc; reg signed [40:0] quadp; initial quadp = 41'sh1_bbbb_cccc;
reg signed [40:0] quadn; initial quadn = 41'shbbbb_cccc; initial quadn[40]=1'b1; reg signed [40:0] quadn; initial quadn = 41'sh1_bbbb_cccc; initial quadn[40]=1'b1;
reg signed [80:0] widep; initial widep = 81'shbc_1234_5678_1234_5678; reg signed [80:0] widep; initial widep = 81'shbc_1234_5678_1234_5678;
reg signed [80:0] widen; initial widen = 81'shbc_1234_5678_1234_5678; initial widen[40]=1'b1; reg signed [80:0] widen; initial widen = 81'shbc_1234_5678_1234_5678; initial widen[40]=1'b1;
initial begin initial begin
// Display formatting // Display formatting
$display("[%0t] %%x=%x %%x=%x %%o=%o %%b=%b %%0d=%0d %%d=%d", $time, $display("[%0t] lp %%x=%x %%x=%x %%o=%o %%b=%b %%0d=%0d %%d=%d", $time,
longp, longp, longp, longp, longp, longp); longp, longp, longp, longp, longp, longp);
$display("[%0t] %%x=%x %%x=%x %%o=%o %%b=%b %%0d=%0d %%d=%d", $time, $display("[%0t] ln %%x=%x %%x=%x %%o=%o %%b=%b %%0d=%0d %%d=%d", $time,
longn, longn, longn, longn, longn, longn); longn, longn, longn, longn, longn, longn);
$display("[%0t] %%x=%x %%x=%x %%o=%o %%b=%b %%0d=%0d %%d=%d", $time, $display("[%0t] qp %%x=%x %%x=%x %%o=%o %%b=%b %%0d=%0d %%d=%d", $time,
quadp, quadp, quadp, quadp, quadp, quadp); quadp, quadp, quadp, quadp, quadp, quadp);
$display("[%0t] %%x=%x %%x=%x %%o=%o %%b=%b %%0d=%0d %%d=%d", $time, $display("[%0t] qn %%x=%x %%x=%x %%o=%o %%b=%b %%0d=%0d %%d=%d", $time,
quadn, quadn, quadn, quadn, quadn, quadn); quadn, quadn, quadn, quadn, quadn, quadn);
$display("[%0t] %%x=%x %%x=%x %%o=%o %%b=%b", $time, $display("[%0t] wp %%x=%x %%x=%x %%o=%o %%b=%b", $time,
widep, widep, widep, widep); widep, widep, widep, widep);
$display("[%0t] %%x=%x %%x=%x %%o=%o %%b=%b", $time, $display("[%0t] wn %%x=%x %%x=%x %%o=%o %%b=%b", $time,
widen, widen, widen, widen); widen, widen, widen, widen);
$display; $display;
$write("*-* All Finished *-*\n"); $write("*-* All Finished *-*\n");
+29
View File
@@ -0,0 +1,29 @@
#!/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.
top_filename("t/t_display_signed.v");
compile (
v_flags2 => [$Last_Self->{v3}?"-O0":""],
);
execute (
check_finished=>1,
expect=> quotemeta(
'[0] lp %x=0bbccc %x=0bbccc %o=2736314 %b=010111011110011001100 %0d=769228 %d= 769228
[0] ln %x=1bbccc %x=1bbccc %o=6736314 %b=110111011110011001100 %0d=-279348 %d= -279348
[0] qp %x=001bbbbcccc %x=001bbbbcccc %o=00067356746314 %b=00000000110111011101110111100110011001100 %0d=7444614348 %d= 7444614348
[0] qn %x=101bbbbcccc %x=101bbbbcccc %o=20067356746314 %b=10000000110111011101110111100110011001100 %0d=-1092067013428 %d=-1092067013428
[0] wp %x=000bc1234567812345678 %x=000bc1234567812345678 %o=000570110642547402215053170 %b=000000000101111000001001000110100010101100111100000010010001101000101011001111000
[0] wn %x=000bc1234577812345678 %x=000bc1234577812345678 %o=000570110642567402215053170 %b=000000000101111000001001000110100010101110111100000010010001101000101011001111000
'),
);
ok(1);
1;
+6 -5
View File
@@ -44,7 +44,7 @@ module t;
reg [31:0] flocal; reg [31:0] flocal;
flocal = 1; flocal = 1;
global = global + flocal; global = global + flocal;
end end : named // SystemVerilog end labels
end end
endfunction endfunction
@@ -67,10 +67,11 @@ module t;
end end
endtask endtask
task incr; task incr (
output [31:0] z; // Check a V2K style input/output list
input [31:0] a; output [31:0] z,
input [31:0] inc; input [31:0] a, inc
);
z = a + inc; z = a + inc;
endtask endtask
+20
View File
@@ -0,0 +1,20 @@
#!/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.
$Last_Self->{verilated_randReset} = 1;
compile (
);
execute (
check_finished=>1,
);
ok(1);
1;
+75
View File
@@ -0,0 +1,75 @@
// $Id$
// DESCRIPTION: Verilator: Verilog Test module
// verilator lint_off WIDTH
// verilator lint_off VARHIDDEN
module t (
clk
);
input clk;
integer cyc=0;
reg [63:0] crc; initial crc = 64'h1;
chk chk (.clk (clk),
.rst_l (1'b1),
.expr (|crc),
);
always @ (posedge clk) begin
cyc <= cyc + 1;
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
if (cyc==0) begin
crc <= 64'h5aef0c8d_d70a4497;
end
else if (cyc<90) begin
end
else if (cyc==99) begin
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule
module chk (input clk, input rst_l, input expr);
integer errors; initial errors = 0;
task printerr;
input [8*64:1] msg;
begin
errors = errors + 1;
$write("%%Error: %0s\n", msg);
$stop;
end
endtask
always @(posedge clk) begin
if (rst_l) begin
if (expr == 1'b0) begin
printerr("expr not asserted");
end
end
end
wire noxs = ((expr ^ expr) == 1'b0);
reg hasx;
always @ (noxs) begin
if (noxs) begin
hasx = 1'b0;
end
else begin
hasx = 1'b1;
end
end
always @(posedge clk) begin
if (rst_l) begin
if (hasx) begin
printerr("expr has unknowns");
end
end
end
endmodule
+2 -2
View File
@@ -56,7 +56,7 @@ endmodule
module ftest( module ftest(
input [ 7:0 ] a, input [ 7:0 ] a,
input [ 7:0 ] b, b, // Test legal syntax
input clk, input clk,
output [ 7:0 ] z output [ 7:0 ] z
); );
@@ -85,7 +85,7 @@ endmodule // ftest
module mytop ( module mytop (
input [ 7:0 ] a, input [ 7:0 ] a,
input [ 7:0 ] b, b,
input clk, input clk,
output [ 7:0 ] z output [ 7:0 ] z
); );
+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;
+81
View File
@@ -0,0 +1,81 @@
// $Id$
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2007 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] in = crc[31:0];
/*AUTOWIRE*/
// Beginning of automatic wires (for undeclared instantiated-module outputs)
wire [3:0] out; // From test of Test.v
// End of automatics
Test test (/*AUTOINST*/
// Outputs
.out (out[3:0]),
// Inputs
.clk (clk),
.in (in[31:0]));
// Aggregate outputs into a single result vector
wire [63:0] result = {60'h0, out};
// What checksum will we end up with
`define EXPECTED_SUM 64'h1a0d07009b6a30d2
// Test loop
always @ (posedge clk) begin
`ifdef TEST_VERBOSE
$write("[%0t] cyc==%0d crc=%x result=%x\n",$time, cyc, crc, result);
`endif
cyc <= cyc + 1;
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
sum <= result ^ {sum[62:0],sum[63]^sum[2]^sum[0]};
if (cyc==0) begin
// Setup
crc <= 64'h5aef0c8d_d70a4497;
end
else if (cyc<10) begin
sum <= 64'h0;
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'hc77bb9b3784ea091) $stop;
if (sum !== `EXPECTED_SUM) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule
module Test (/*AUTOARG*/
// Outputs
out,
// Inputs
clk, in
);
input clk;
input [31:0] in;
output [3:0] out;
assign out[0] = in[3:0] ==? 4'b1001;
assign out[1] = in[3:0] !=? 4'b1001;
assign out[2] = in[3:0] ==? 4'bx01x;
assign out[3] = in[3:0] !=? 4'bx01x;
endmodule
+2 -8
View File
@@ -1,4 +1,3 @@
`line 1 "t/t_preproc.v" 1 `line 1 "t/t_preproc.v" 1
@@ -10,7 +9,6 @@
`line 9 "t/t_preproc.v" 0 `line 9 "t/t_preproc.v" 0
`line 1 "t/t_preproc_inc2.v" 1 `line 1 "t/t_preproc_inc2.v" 1
@@ -19,8 +17,8 @@ At file t/t_preproc_inc2.v line 4
`line 6 "t/t_preproc_inc2.v" 0 `line 6 "t/t_preproc_inc2.v" 0
`line 1 "t/t_preproc_inc3.v" 1 `line 1 "t/t_preproc_inc3.v" 1
`line 2 "inc3_a_filename_from_line_directive" 0
@@ -41,14 +39,10 @@ At file t/t_preproc_inc2.v line 4
`line 17 "inc3_a_filename_from_line_directive" 0 `line 17 "inc3_a_filename_from_line_directive" 0
`line 18 "inc3_a_filename_from_line_directive" 2 `line 18 "inc3_a_filename_from_line_directive" 2
`line 6 "t/t_preproc_inc2.v" 0 `line 6 "t/t_preproc_inc2.v" 0
`line 7 "t/t_preproc_inc2.v" 2 `line 7 "t/t_preproc_inc2.v" 2
`line 9 "t/t_preproc.v" 0 `line 9 "t/t_preproc.v" 0
@@ -148,4 +142,4 @@ $display( "left side: \" right side\"" )
`line 95 "t/t_preproc.v" 0 `line 95 "t/t_preproc.v" 0
Line_Preproc_Check 96 Line_Preproc_Check 96
`line 97 "t/t_preproc.v" 2
+1 -2
View File
@@ -1,4 +1,3 @@
`line 1 "t/t_preproc_psl.v" 1 `line 1 "t/t_preproc_psl.v" 1
@@ -74,4 +73,4 @@ psl assert always sig!=90;
72 72
`line 73 "t/t_preproc_psl.v" 2
+1 -2
View File
@@ -1,4 +1,3 @@
`line 1 "t/t_preproc_psl.v" 1 `line 1 "t/t_preproc_psl.v" 1
@@ -74,4 +73,4 @@ psl assert always sig!=90;
72 72
`line 73 "t/t_preproc_psl.v" 2