Compare commits

..
33 Commits
Author SHA1 Message Date
Wilson Snyder ad53833040 Version bump 2011-07-28 19:53:54 -04:00
Wilson Snyder bc8c85668a Support coverage in -cc and -sc output modes. 2011-07-28 19:41:05 -04:00
Wilson Snyder d12a3dde45 Fix cast compile warning 2011-07-28 07:59:30 -04:00
Wilson Snyder 301c878c0f Merge branch 'master' of ssh://git-verilator-wsnyder/git/verilator 2011-07-28 07:56:44 -04:00
Wilson Snyder bd55bfa071 Support more vpi file functions 2011-07-28 07:05:40 -04:00
Wilson Snyder 6d2f09b579 Fix vpi_register_cb using bad s_cb_data, bug370. 2011-07-27 13:03:49 -04:00
Wilson Snyder 4bfea7f54d Merge branch 'master' of ssh://git-verilator-wsnyder/git/verilator 2011-07-26 18:30:25 -04:00
Wilson Snyder 55906486d8 Support 'real' numbers and related functions. 2011-07-24 15:01:51 -04:00
Wilson Snyder d5478e6e08 tests: Print status to stderr 2011-07-24 15:01:36 -04:00
Wilson Snyder d88d85c172 Internals: Real2: Create numeric class; no functional change intended 2011-07-23 19:58:34 -04:00
Wilson Snyder 59c3c536c7 Internals: Real1: properly lex doubles 2011-07-23 08:25:41 -04:00
Wilson Snyder a007458cb8 Internals: Rename float/double to match real branch. No functional change. 2011-07-21 22:10:25 -04:00
Wilson Snyder d051912f21 Internals: Rename functions to match real branch. No functional change. 2011-07-21 21:32:31 -04:00
Wilson Snyder a547158a50 bisonpre: Merge from Verilog-Perl 2011-07-21 20:34:33 -04:00
Wilson Snyder 95f2351aa0 Tests: %t formatting 2011-07-21 19:37:53 -04:00
Wilson Snyder 698aaffb0b Fix missing leading zeros in %0d, bug367 2011-07-14 07:39:11 -04:00
Wilson Snyder 73eccecbf8 Merge branch 'master' of ssh://git-verilator-wsnyder/git/verilator 2011-07-11 08:10:28 -04:00
Wilson Snyder ae4a261463 Internals: Rename UnaryMin to Negate. No functional change. 2011-07-08 06:03:07 -04:00
Wilson Snyder c9f0d0cec2 Recognize pragma synthesys to match vhier 2011-07-07 13:30:27 -04:00
Wilson Snyder 4fa1e45d45 Internals: Move width internals to inside class; move WidthCommit. No functional change 2011-07-06 19:03:40 -04:00
Wilson Snyder 1b3d252bfe Internals: Cleanup Dead code 2011-07-06 18:46:41 -04:00
Wilson Snyder a9ba4a9fcd Internals: Cleanups in V3Signed towards reals; no functional change 2011-07-05 21:05:35 -04:00
Wilson Snyder 7f49619875 Fix VL_FCLOSE declaration, broke two commits ago, bug363 2011-07-05 20:42:33 -04:00
Wilson Snyder 696660639a Support 'const' variables in limited cases; similar to enums. 2011-07-02 12:45:26 -04:00
Wilson Snyder da4323062d Commentary 2011-07-01 15:23:09 -04:00
Wilson Snyder a901e171b2 Support $fopen and I/O with integer instead of `verilator_file_descriptor. 2011-07-01 13:41:21 -04:00
Wilson Snyder 6e41d532fe Use 'vluint64_t' for SystemC instead of (same sized) 'uint64' for MSVC++. 2011-06-29 19:19:01 -04:00
Wilson Snyder 4fc78ffb58 Merge branch 'master' of ssh://git-verilator-wsnyder/git/verilator 2011-06-29 14:22:59 -04:00
Wilson Snyder 8137f41fc3 Support disable for loop escapes. 2011-06-28 21:26:49 -04:00
Wilson Snyder 2e9471797d Version to devel 2011-06-28 21:11:29 -04:00
Wilson Snyder 3fd2108b10 Merge branch 'master' of ssh://git-verilator-wsnyder/git/verilator 2011-05-20 15:34:30 -04:00
Wilson Snyder 96e2a407f4 Merge branch 'master' of ssh://git-verilator-wsnyder/git/verilator 2011-05-20 13:40:18 -04:00
Wilson Snyder ca83fd6dc1 CDC: edge report under debug 2011-04-20 10:11:35 -04:00
85 changed files with 2820 additions and 1330 deletions
+19
View File
@@ -3,6 +3,25 @@ Revision history for Verilator
The contributors that suggested a given feature are shown in []. [by ...]
indicates the contributor was also the author of the fix; Thanks!
* Verilator 3.820 2011/07/28
** Support 'real' numbers and related functions.
*** Support 'const' variables in limited cases; similar to enums. [Alex Solomatnikov]
*** Support disable for loop escapes.
*** Support $fopen and I/O with integer instead of `verilator_file_descriptor.
*** Support coverage in -cc and -sc output modes. [John Li]
Note this requires SystemPerl 1.338 or newer.
**** Fix vpi_register_cb using bad s_cb_data, bug370. [by Thomas Watts]
**** Fix $display missing leading zeros in %0d, bug367. [Alex Solomatnikov]
**** Use 'vluint64_t' for SystemC instead of (same sized) 'uint64' for MSVC++.
* Verilator 3.813 2011/06/28
*** Support bit vectors > 64 bits wide in DPI import and exports.
+24 -21
View File
@@ -268,7 +268,7 @@ descriptions in the next sections for more information.
--MP Create phony dependency targets
--Mdir <directory> Name of output object directory
--mod-prefix <topname> Name to prepend to lower classes
--no-pins64 Don't use uint64_t's for 33-64 bit sigs
--no-pins64 Don't use vluint64_t's for 33-64 bit sigs
--no-skip-identical Disable skipping identical output
+notimingchecks Ignored
-O0 Disable optimizations
@@ -713,7 +713,7 @@ Backward compatible alias for "--pins-bv 65". Note that's a 65, not a 64.
=item --pins-bv I<width>
Specifies SystemC inputs/outputs of greater than or equal to I<width> bits
wide should use sc_bv's instead of uint32/uint64_t's. The default is
wide should use sc_bv's instead of uint32/vluint64_t's. The default is
"--pins-bv 65". Versions before Verilator 3.671 defaulted to "--pins-bv
33". The more sc_bv is used, the worse for performance.
@@ -930,8 +930,8 @@ Enables the specified warning message.
Enable all lint related warning messages (note by default they are already
enabled), but do not affect style messages. This is equivalent to
"-Wwarn-CASEINCOMPLETE -Wwarn-CASEOVERLAP -Wwarn-CASEX -Wwarn-CASEWITHX
-Wwarn-CMPCONST -Wwarn-IMPLICIT -Wwarn-LITENDIAN -Wwarn-UNSIGNED
-Wwarn-WIDTH".
-Wwarn-CMPCONST -Wwarn-IMPLICIT -Wwarn-LITENDIAN -Wwarn-REALCVT
-Wwarn-UNSIGNED -Wwarn-WIDTH".
=item -Wwarn-style
@@ -1352,7 +1352,7 @@ will plug directly into a SystemC netlist.
The SC_MODULE gets the same pinout as the Verilog module, with the
following type conversions: Pins of a single bit become bool. Pins 2-32
bits wide become uint32_t's. Pins 33-64 bits wide become sc_bv's or
uint64_t's depending on the --no-pins64 switch. Wider pins become sc_bv's.
vluint64_t's depending on the --no-pins64 switch. Wider pins become sc_bv's.
(Uints simulate the fastest so are used where possible.)
Lower modules are not pure SystemC code. This is a feature, as using the
@@ -1661,7 +1661,7 @@ please file a bug if a feature you need is missing.
Verilator supports ==? and !=? operators, ++ and -- in some contexts,
$bits, $countones, $error, $fatal, $info, $isunknown, $onehot, $onehot0,
$unit, $warning, always_comb, always_ff, always_latch, bit, byte, chandle,
do-while, enum, export, final, import, int, logic, longint, package,
const, do-while, enum, export, final, import, int, logic, longint, package,
program, shortint, time, typedef, var, void, priority case/if, and unique
case/if.
@@ -1711,8 +1711,8 @@ assertion clocks.
=head2 Synthesis Directive Assertion Support
With the --assert switch, Verilator reads any "//synopsys full_case" or "//
synopsys parallel_case" directives. The same applies to any "//cadence" or
"// ambit synthesis" directives of the same form.
synopsys parallel_case" directives. The same applies to any "// ambit
synthesis", "//cadence" or "//pragma" directives of the same form.
When these synthesis directives are discovered, Verilator will either
formally prove the directive to be true, or failing that, will insert the
@@ -2096,7 +2096,7 @@ that Verilator will print a list of known scopes to help your debugging.
=head2 Floating Point
Floating Point numbers are not synthesizable, and so not supported.
Floating Point (real) numbers are supported.
=head2 Latches
@@ -2258,6 +2258,13 @@ not arrays nor structs.
Treated as a "longint"; does not yet warn about operations that are
specified as illegal on chandles.
=item disable
Disable statements may be used only if the block being disabled is a block
the disable statement itself is inside. This was commonly used to provide
loop break and continue functionality before SystemVerilog added the break
and continue keywords.
=item priority if, unique if
Priority and unique if's are treated as normal ifs and not asserted to be
@@ -2306,11 +2313,6 @@ The rarely used optional parameter to $finish and $stop is ignored.
File descriptors passed to the file PLI calls must be file descriptors, not
MCDs, which includes the mode parameter to $fopen being mandatory.
Verilator will convert the integer used to hold the file descriptor into a
internal FILE*. To prevent core dumps due to mis-use, and because integers
are 32 bits while FILE*s may be 64 bits, the descriptor must be stored in a
reg [63:0] rather than an integer. The define `verilator_file_descriptor in
verilated.v can be used to hide this difference.
=item $fscanf, $sscanf
@@ -2334,10 +2336,6 @@ Read memory commands should work properly. Note Verilator and the Verilog
specification does not include support for readmem to multi-dimensional
arrays.
=item $realtime
Treated as $time.
=item $test$plusargs, $value$plusargs
Supported, but the instantiating C++/SystemC testbench must call
@@ -2617,6 +2615,11 @@ not really needed. The best solution is to insure that each module is in a
unique file by the same name. Otherwise, make sure all library files are
read in as libraries with -v, instead of automatically with -y.
=item REALCVT
Warns that a real number is being implicitly rounded to an integer, with
possible loss of precision.
=item REDEFMACRO
Warns that you have redefined the same macro with a different value, for
@@ -3051,8 +3054,8 @@ network disk. Network disks are generally far slower.
=item How do I do coverage analysis?
Verilator supports both block (line) coverage and user inserted functional
coverage. Both currently require SystemPerl output mode and the SystemPerl
package.
coverage. Both require the SystemPerl package to be installed but do not
require use of the SystemPerl output mode.
First, run verilator with the --coverage option. If you're using your own
makefile, compile the model with the GCC flag -DSP_COVERAGE_ENABLE (if
@@ -3175,7 +3178,7 @@ as you would any other member variable.
Signals are the smallest of 8 bit chars, 16 bit shorts, 32 bit longs, or 64
bit long longs that fits the width of the signal. Generally, you can use
just uint32_t's for 1 to 32 bits, or uint64_t for 1 to 64 bits, and the
just uint32_t's for 1 to 32 bits, or vluint64_t for 1 to 64 bits, and the
compiler will properly up-convert smaller entities.
Signals wider than 64 bits are stored as an array of 32-bit uint32_t's.
+53 -12
View File
@@ -26,7 +26,6 @@
#define _VERILATED_CPP_
#include "verilated_imp.h"
#include <cctype>
#include <vector>
#define VL_VALUE_STRING_MAX_WIDTH 1024 ///< Max static char array for VL_VALUE_STRING
@@ -285,12 +284,15 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
// Note also assumes variables < 64 are not wide, this assumption is
// sometimes not true in low-level routines written here in verilated.cpp
static VL_THREAD char tmp[VL_VALUE_STRING_MAX_WIDTH];
static VL_THREAD char tmpf[VL_VALUE_STRING_MAX_WIDTH];
const char* pctp = NULL; // Most recent %##.##g format
bool inPct = false;
bool widthSet = false;
int width = 0;
const char* pos = formatp;
for (; *pos; ++pos) {
if (!inPct && pos[0]=='%') {
pctp = pos;
inPct = true;
widthSet = false;
width = 0;
@@ -312,6 +314,9 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
widthSet = true;
width = width*10 + (fmt - '0');
break;
case '.':
inPct = true; // Get more digits
break;
case '%':
output += '%';
break;
@@ -325,6 +330,16 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
output += cstrp;
break;
}
case 'e':
case 'f':
case 'g': {
double d = va_arg(ap, double);
strncpy(tmpf, pctp, pos-pctp+1);
tmpf[pos-pctp+1] = '\0';
sprintf(tmp, tmpf, d);
output += tmp;
break;
}
default: {
// Deal with all read-and-print somethings
const int lbits = va_arg(ap, int);
@@ -358,14 +373,26 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
case 'd': { // Signed decimal
int digits=sprintf(tmp,"%" VL_PRI64 "d",(vlsint64_t)(VL_EXTENDS_QQ(lbits,lbits,ld)));
int needmore = width-digits;
if (needmore>0) output.append(needmore,' '); // Pre-pad spaces
if (needmore>0) {
if (pctp && pctp[0] && pctp[1]=='0') { //%0
output.append(needmore,'0'); // Pre-pad zero
} else {
output.append(needmore,' '); // Pre-pad spaces
}
}
output += tmp;
break;
}
case 'u': { // Unsigned decimal
int digits=sprintf(tmp,"%" VL_PRI64 "u",ld);
int needmore = width-digits;
if (needmore>0) output.append(needmore,' '); // Pre-pad spaces
if (needmore>0) {
if (pctp && pctp[0] && pctp[1]=='0') { //%0
output.append(needmore,'0'); // Pre-pad zero
} else {
output.append(needmore,' '); // Pre-pad spaces
}
}
output += tmp;
break;
}
@@ -628,6 +655,10 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
//===========================================================================
// File I/O
FILE* VL_CVT_I_FP(IData lhs) {
return VerilatedImp::fdToFp(lhs);
}
void _VL_VINT_TO_STRING(int obits, char* destoutp, WDataInP sourcep) {
// See also VL_DATA_TO_STRING_NW
int lsb=obits-1;
@@ -655,8 +686,8 @@ void _VL_STRING_TO_VINT(int obits, void* destp, int srclen, const char* srcp) {
for (; i<bytes; i++) { *op++ = 0; }
}
IData VL_FGETS_IXQ(int obits, void* destp, QData fpq) {
FILE* fp = VL_CVT_Q_FP(fpq);
IData VL_FGETS_IXI(int obits, void* destp, IData fpi) {
FILE* fp = VL_CVT_I_FP(fpi);
if (VL_UNLIKELY(!fp)) return 0;
// The string needs to be padded with 0's in unused spaces in front of
@@ -683,16 +714,26 @@ IData VL_FGETS_IXQ(int obits, void* destp, QData fpq) {
return got;
}
QData VL_FOPEN_QI(QData filename, IData mode) {
IData VL_FOPEN_QI(QData filename, IData mode) {
IData fnw[2]; VL_SET_WQ(fnw, filename);
return VL_FOPEN_WI(2, fnw, mode);
}
QData VL_FOPEN_WI(int fnwords, WDataInP filenamep, IData mode) {
IData VL_FOPEN_WI(int fnwords, WDataInP filenamep, IData mode) {
char filenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1];
_VL_VINT_TO_STRING(fnwords*VL_WORDSIZE, filenamez, filenamep);
char modez[5];
_VL_VINT_TO_STRING(VL_WORDSIZE, modez, &mode);
return VL_CVT_FP_Q(fopen(filenamez,modez));
return VL_FOPEN_S(filenamez,modez);
}
IData VL_FOPEN_S(const char* filenamep, const char* modep) {
return VerilatedImp::fdNew(fopen(filenamep,modep));
}
void VL_FCLOSE_I(IData fdi) {
FILE* fp = VL_CVT_I_FP(fdi);
if (VL_UNLIKELY(!fp)) return;
fclose(fp);
VerilatedImp::fdDelete(fdi);
}
void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...) {
@@ -726,8 +767,8 @@ void VL_WRITEF(const char* formatp, ...) {
VL_PRINTF("%s", output.c_str());
}
void VL_FWRITEF(QData fpq, const char* formatp, ...) {
FILE* fp = VL_CVT_Q_FP(fpq);
void VL_FWRITEF(IData fpi, const char* formatp, ...) {
FILE* fp = VL_CVT_I_FP(fpi);
if (VL_UNLIKELY(!fp)) return;
va_list ap;
@@ -739,8 +780,8 @@ void VL_FWRITEF(QData fpq, const char* formatp, ...) {
fputs(output.c_str(), fp);
}
IData VL_FSCANF_IX(QData fpq, const char* formatp, ...) {
FILE* fp = VL_CVT_Q_FP(fpq);
IData VL_FSCANF_IX(IData fpi, const char* formatp, ...) {
FILE* fp = VL_CVT_I_FP(fpi);
if (VL_UNLIKELY(!fp)) return 0;
va_list ap;
+38 -23
View File
@@ -35,6 +35,7 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
// <iostream> avoided to reduce compile time
// <string> avoided and instead in verilated_heavy.h to reduce compile time
using namespace std;
@@ -321,11 +322,14 @@ extern WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp); ///< Zero reset a
extern WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, bool is_modulus);
/// File I/O
extern IData VL_FGETS_IXQ(int obits, void* destp, QData fpq);
extern IData VL_FGETS_IXI(int obits, void* destp, IData fpi);
extern QData VL_FOPEN_WI(int fnwords, WDataInP ofilename, IData mode);
extern QData VL_FOPEN_QI(QData ofilename, IData mode);
inline QData VL_FOPEN_II(IData ofilename, IData mode) { return VL_FOPEN_QI(ofilename,mode); }
extern IData VL_FOPEN_S(const char* filenamep, const char* mode);
extern IData VL_FOPEN_WI(int fnwords, WDataInP ofilename, IData mode);
extern IData VL_FOPEN_QI(QData ofilename, IData mode);
inline IData VL_FOPEN_II(IData ofilename, IData mode) { return VL_FOPEN_QI(ofilename,mode); }
extern void VL_FCLOSE_I(IData fdi);
extern void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
WDataInP ofilename, void* memp, IData start, IData end);
@@ -336,9 +340,9 @@ inline void VL_READMEM_I(bool hex, int width, int depth, int array_lsb, int fnwo
VL_READMEM_Q(hex, width,depth,array_lsb,fnwords, ofilename,memp,start,end); }
extern void VL_WRITEF(const char* formatp, ...);
extern void VL_FWRITEF(QData fpq, const char* formatp, ...);
extern void VL_FWRITEF(IData fpi, const char* formatp, ...);
extern IData VL_FSCANF_IX(QData fpq, const char* formatp, ...);
extern IData VL_FSCANF_IX(IData fpi, const char* formatp, ...);
extern IData VL_SSCANF_IIX(int lbits, IData ld, const char* formatp, ...);
extern IData VL_SSCANF_IQX(int lbits, QData ld, const char* formatp, ...);
extern IData VL_SSCANF_IWX(int lbits, WDataInP lwp, const char* formatp, ...);
@@ -364,15 +368,24 @@ extern const char* vl_mc_scan_plusargs(const char* prefixp); // PLIish
#define VL_SET_QW(lwp) ( ((QData)(lwp[0])) | ((QData)(lwp[1])<<((QData)(VL_WORDSIZE)) ))
#define _VL_SET_QII(ld,rd) ( ((QData)(ld)<<VL_ULL(32)) | (QData)(rd) )
/// Return FILE* from IData
extern FILE* VL_CVT_I_FP(IData lhs);
// Use a union to avoid cast-to-different-size warnings
/// Return FILE* from QData
static inline FILE* VL_CVT_Q_FP(QData lhs) { union { FILE* fp; QData q; } u; u.q=lhs; return u.fp; }
/// Return void* from QData
static inline void* VL_CVT_Q_VP(QData lhs) { union { void* fp; QData q; } u; u.q=lhs; return u.fp; }
/// Return QData from FILE*
static inline QData VL_CVT_FP_Q(FILE* fp) { union { FILE* fp; QData q; } u; u.q=0; u.fp=fp; return u.q; }
/// Return QData from void*
static inline QData VL_CVT_VP_Q(void* fp) { union { void* fp; QData q; } u; u.q=0; u.fp=fp; return u.q; }
/// Return double from QData (bits, not numerically)
static inline double VL_CVT_D_Q(QData lhs) { union { double d; QData q; } u; u.q=lhs; return u.d; }
/// Return QData from double (bits, not numerically)
static inline QData VL_CVT_Q_D(double lhs) { union { double d; QData q; } u; u.d=lhs; return u.q; }
/// Return double from QData (numeric)
static inline double VL_ITOR_D_I(IData lhs) { return ((double)((vlsint32_t)(lhs))); }
/// Return QData from double (numeric)
static inline IData VL_RTOI_I_D(double lhs) { return ((vlsint32_t)(trunc(lhs))); }
/// Return QData from double (numeric)
static inline IData VL_RTOIROUND_I_D(double lhs) { return ((vlsint32_t)(round(lhs))); }
// Sign extend such that if MSB set, we get ffff_ffff, else 0s
// (Requires clean input)
@@ -402,9 +415,11 @@ void _VL_DEBUG_PRINT_W(int lbits, WDataInP iwp);
#if defined(SYSTEMC_VERSION) && (SYSTEMC_VERSION>20011000)
# define VL_TIME_I() ((IData)(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
# define VL_TIME_Q() ((QData)(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
# define VL_TIME_D() ((double)(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
#else
# define VL_TIME_I() ((IData)(sc_time_stamp()*VL_TIME_MULTIPLIER))
# define VL_TIME_Q() ((QData)(sc_time_stamp()*VL_TIME_MULTIPLIER))
# define VL_TIME_D() ((double)(sc_time_stamp()*VL_TIME_MULTIPLIER))
extern double sc_time_stamp();
#endif
@@ -947,11 +962,11 @@ static inline WDataOutP VL_SUB_W(int words, WDataOutP owp,WDataInP lwp,WDataInP
// Optimization bug in GCC 2.96 and presumably all-pre GCC 3 versions need this workaround,
// we can't just
//# define VL_UNARYMIN_I(data) (-(data))
static inline IData VL_UNARYMIN_I(IData data) { return -data; }
static inline QData VL_UNARYMIN_Q(QData data) { return -data; }
//# define VL_NEGATE_I(data) (-(data))
static inline IData VL_NEGATE_I(IData data) { return -data; }
static inline QData VL_NEGATE_Q(QData data) { return -data; }
static inline WDataOutP VL_UNARYMIN_W(int words, WDataOutP owp,WDataInP lwp){
static inline WDataOutP VL_NEGATE_W(int words, WDataOutP owp,WDataInP lwp){
QData carry = 0;
for (int i=0; i<words; i++) {
carry = carry + (QData)(IData)(~lwp[i]);
@@ -998,18 +1013,18 @@ static inline WDataOutP VL_MULS_WWW(int,int lbits,int, WDataOutP owp,WDataInP lw
IData lneg = VL_SIGN_I(lbits,lwp[words-1]);
if (lneg) { // Negate lhs
lwusp = lwstore;
VL_UNARYMIN_W(words, lwstore, lwp);
VL_NEGATE_W(words, lwstore, lwp);
lwstore[words-1] &= VL_MASK_I(lbits); // Clean it
}
IData rneg = VL_SIGN_I(lbits,rwp[words-1]);
if (rneg) { // Negate rhs
rwusp = rwstore;
VL_UNARYMIN_W(words, rwstore, rwp);
VL_NEGATE_W(words, rwstore, rwp);
rwstore[words-1] &= VL_MASK_I(lbits); // Clean it
}
VL_MUL_W(words,owp,lwusp,rwusp);
owp[words-1] &= VL_MASK_I(lbits); // Clean. Note it's ok for the multiply to overflow into the sign bit
if ((lneg ^ rneg) & 1) { // Negate output (not using UNARYMIN, as owp==lwp)
if ((lneg ^ rneg) & 1) { // Negate output (not using NEGATE, as owp==lwp)
QData carry = 0;
for (int i=0; i<words; i++) {
carry = carry + (QData)(IData)(~owp[i]);
@@ -1056,12 +1071,12 @@ static inline WDataOutP VL_DIVS_WWW(int lbits, WDataOutP owp,WDataInP lwp,WDataI
IData rwstore[VL_MULS_MAX_WORDS];
WDataInP ltup = lwp;
WDataInP rtup = rwp;
if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), lwstore, lwp)); }
if (rsign) { rtup = _VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), rwstore, rwp)); }
if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), lwstore, lwp)); }
if (rsign) { rtup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), rwstore, rwp)); }
if ((lsign && !rsign) || (!lsign && rsign)) {
IData qNoSign[VL_MULS_MAX_WORDS];
VL_DIV_WWW(lbits,qNoSign,ltup,rtup);
_VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), owp, qNoSign));
_VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), owp, qNoSign));
return owp;
} else {
return VL_DIV_WWW(lbits,owp,ltup,rtup);
@@ -1075,12 +1090,12 @@ static inline WDataOutP VL_MODDIVS_WWW(int lbits, WDataOutP owp,WDataInP lwp,WDa
IData rwstore[VL_MULS_MAX_WORDS];
WDataInP ltup = lwp;
WDataInP rtup = rwp;
if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), lwstore, lwp)); }
if (rsign) { rtup = _VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), rwstore, rwp)); }
if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), lwstore, lwp)); }
if (rsign) { rtup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), rwstore, rwp)); }
if (lsign) { // Only dividend sign matters for modulus
IData qNoSign[VL_MULS_MAX_WORDS];
VL_MODDIV_WWW(lbits,qNoSign,ltup,rtup);
_VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), owp, qNoSign));
_VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), owp, qNoSign));
return owp;
} else {
return VL_MODDIV_WWW(lbits,owp,ltup,rtup);
+4
View File
@@ -116,6 +116,10 @@ ifeq ($(VM_SP),1)
$(SP_PREPROC) -M sp_preproc.d --tree $(VM_PREFIX).sp_tree \
--preproc $(VK_CLASSES_SP)
else
ifeq ($(VM_COVERAGE),1)
CPPFLAGS += -I$(SYSTEMPERL_INCLUDE)
VPATH += $(SYSTEMPERL_INCLUDE)
endif
preproc:
endif
+2 -6
View File
@@ -27,11 +27,7 @@
`define coverage_block_off
`endif
// Hide file descriptor difference
`ifdef verilator
`define verilator_file_descriptor reg [63:0]
`else
`define verilator_file_descriptor integer
`endif
// Hide file descriptor difference - deprecated - for older versions
`define verilator_file_descriptor integer
`endif // guard
+39 -1
View File
@@ -35,6 +35,7 @@
#include <map>
#include <vector>
#include <deque>
#include <string>
class VerilatedScope;
@@ -62,9 +63,18 @@ class VerilatedImp {
ExportNameMap m_exportMap; ///< Map of <export_func_proto, func number>
int m_exportNext; ///< Next export funcnum
// File I/O
vector<FILE*> m_fdps; ///< File descriptors
deque<IData> m_fdFree; ///< List of free descriptors (SLOW - FOPEN/CLOSE only)
public: // But only for verilated*.cpp
// CONSTRUCTORS
VerilatedImp() : m_argVecLoaded(false), m_exportNext(0) {}
VerilatedImp() : m_argVecLoaded(false), m_exportNext(0) {
m_fdps.resize(3);
m_fdps[0] = stdin;
m_fdps[1] = stdout;
m_fdps[2] = stderr;
}
~VerilatedImp() {}
// METHODS - arguments
@@ -184,6 +194,34 @@ public: // But only for verilated*.cpp
}
// We don't free up m_exportMap until the end, because we can't be sure
// what other models are using the assigned funcnum's.
public: // But only for verilated*.cpp
// METHODS - file IO
static IData fdNew(FILE* fp) {
if (VL_UNLIKELY(!fp)) return 0;
// Bit 31 indicates it's a descriptor not a MCD
if (s_s.m_fdFree.empty()) {
// Need to create more space in m_fdps and m_fdFree
size_t start = s_s.m_fdps.size();
s_s.m_fdps.resize(start*2);
for (size_t i=start; i<start*2; i++) s_s.m_fdFree.push_back((IData)i);
}
IData idx = s_s.m_fdFree.back(); s_s.m_fdFree.pop_back();
s_s.m_fdps[idx] = fp;
return (idx | (1UL<<31)); // bit 31 indicates not MCD
}
static void fdDelete(IData fdi) {
IData idx = VL_MASK_I(31) & fdi;
if (VL_UNLIKELY(!(fdi & (1ULL<<31)) || idx >= s_s.m_fdps.size())) return;
if (VL_UNLIKELY(!s_s.m_fdps[idx])) return; // Already free
s_s.m_fdps[idx] = NULL;
s_s.m_fdFree.push_back(idx);
}
static inline FILE* fdToFp(IData fdi) {
IData idx = VL_MASK_I(31) & fdi;
if (VL_UNLIKELY(!(fdi & (1ULL<<31)) || idx >= s_s.m_fdps.size())) return NULL;
return s_s.m_fdps[idx];
}
};
#endif // Guard
+40 -20
View File
@@ -95,9 +95,12 @@ typedef PLI_INT32 (*VerilatedPliCb)(struct t_cb_data *);
class VerilatedVpioCb : public VerilatedVpio {
t_cb_data m_cbData;
s_vpi_value m_value;
QData m_time;
public:
VerilatedVpioCb(const t_cb_data* cbDatap, QData time) : m_cbData(*cbDatap), m_time(time) {}
VerilatedVpioCb(const t_cb_data* cbDatap, QData time) : m_cbData(*cbDatap), m_time(time) {
m_cbData.value = &m_value;
}
virtual ~VerilatedVpioCb() {}
static inline VerilatedVpioCb* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioCb*>((VerilatedVpio*)h); }
vluint32_t reason() const { return m_cbData.reason; }
@@ -326,6 +329,7 @@ public:
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: value_callback %p %s v[0]=%d\n",
vop,varop->fullname(), *((CData*)newDatap)););
memcpy(prevDatap, newDatap, varop->entSize());
vpi_get_value(vop->cb_datap()->obj, vop->cb_datap()->value);
(vop->cb_rtnp()) (vop->cb_datap());
}
}
@@ -735,19 +739,26 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
// I/O routines
//-PLI_UINT32 vpi_mcd_open(PLI_BYTE8 *fileName) {
//- _VL_VPI_UNIMP(); return 0;
//-}
//-PLI_UINT32 vpi_mcd_close(PLI_UINT32 mcd) {
//- _VL_VPI_UNIMP(); return 0;
//-}
//-PLI_BYTE8 *vpi_mcd_name(PLI_UINT32 cd) {
//- _VL_VPI_UNIMP(); return 0;
//-}
//-PLI_INT32 vpi_mcd_printf(PLI_UINT32 mcd, PLI_BYTE8 *format, ...) {
PLI_UINT32 vpi_mcd_open(PLI_BYTE8 *filenamep) {
return VL_FOPEN_S(filenamep,"wb");
}
PLI_UINT32 vpi_mcd_close(PLI_UINT32 mcd) {
VL_FCLOSE_I(mcd); return 0;
}
//-PLI_BYTE8 *vpi_mcd_name(PLI_UINT32 mcd) {
//- _VL_VPI_UNIMP(); return 0;
//-}
PLI_INT32 vpi_mcd_printf(PLI_UINT32 mcd, PLI_BYTE8 *formatp, ...) {
va_list ap;
va_start(ap,formatp);
int chars = vpi_mcd_vprintf(mcd, formatp, ap);
va_end(ap);
return chars;
}
PLI_INT32 vpi_printf(PLI_BYTE8 *formatp, ...) {
va_list ap;
va_start(ap,formatp);
@@ -760,15 +771,24 @@ PLI_INT32 vpi_vprintf(PLI_BYTE8* formatp, va_list ap) {
return VL_VPRINTF(formatp, ap);
}
//-PLI_INT32 vpi_mcd_vprintf(PLI_UINT32 mcd, PLI_BYTE8 *format, va_list ap) {
//- _VL_VPI_UNIMP(); return 0;
//-}
//-PLI_INT32 vpi_flush(void) {
//- _VL_VPI_UNIMP(); return 0;
//-}
//-PLI_INT32 vpi_mcd_flush(PLI_UINT32 mcd) {
//- _VL_VPI_UNIMP(); return 0;
//-}
PLI_INT32 vpi_mcd_vprintf(PLI_UINT32 mcd, PLI_BYTE8 *format, va_list ap) {
FILE* fp = VL_CVT_I_FP(mcd);
if (VL_UNLIKELY(!fp)) return 0;
int chars = vfprintf(fp, format, ap);
return chars;
}
PLI_INT32 vpi_flush(void) {
Verilated::flushCall();
return 0;
}
PLI_INT32 vpi_mcd_flush(PLI_UINT32 mcd) {
FILE* fp = VL_CVT_I_FP(mcd);
if (VL_UNLIKELY(!fp)) return 1;
fflush(fp);
return 0;
}
// utility routines
+1 -1
View File
@@ -256,7 +256,7 @@ sub gentree {
'TRACE' => sub { p "TRACE what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
'UCFUNC' => sub { p '$c(';p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p ")"; },
'UCSTMT' => sub { p '$c(';p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p ");";nl; },
'UNARYMIN' => sub { p " -";p1; },
'NEGATE' => sub { p " -";p1; },
'VAR' => sub { p_var(); },
'VARPIN' => sub { p "VARPIN what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
'VARREF' => sub { a1; },
-1
View File
@@ -209,7 +209,6 @@ RAW_OBJS = \
V3PreShell.o \
V3Premit.o \
V3Scope.o \
V3Signed.o \
V3Slice.o \
V3Split.o \
V3SplitAs.o \
+4 -2
View File
@@ -74,7 +74,9 @@ void AstNode::init() {
m_clonep = NULL;
m_cloneCnt = 0;
// Attributes
m_signed = false;
m_numeric = (int)AstNumeric::UNSIGNED;
m_didWidth = false;
m_doingWidth = false;
m_width = 0;
m_widthMin = 0;
m_user1p = NULL;
@@ -873,7 +875,7 @@ bool AstNode::sameTreeIter(AstNode* node2p, bool ignNext) {
if (this==NULL || node2p==NULL) return false;
if (this->type() != node2p->type()
|| this->width() != node2p->width()
|| this->isSigned() != node2p->isSigned()
|| this->numeric() != node2p->numeric()
|| !this->same(node2p)) {
return false;
}
+62 -15
View File
@@ -56,6 +56,36 @@ public:
//######################################################################
class AstNumeric {
public:
enum en {
UNSIGNED,
SIGNED,
DOUBLE
// Limited to 2 bits, unless change V3Ast's packing function
};
enum en m_e;
const char* ascii() const {
static const char* names[] = {
"UNSIGNED","SIGNED","DOUBLE"
};
return names[m_e];
};
inline AstNumeric () {}
inline AstNumeric (en _e) : m_e(_e) {}
explicit inline AstNumeric (int _e) : m_e(static_cast<en>(_e)) {}
operator en () const { return m_e; }
inline bool isDouble() const { return m_e==DOUBLE; }
inline bool isSigned() const { return m_e==SIGNED; }
inline bool isUnsigned() const { return m_e==UNSIGNED; }
};
inline bool operator== (AstNumeric lhs, AstNumeric rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator== (AstNumeric lhs, AstNumeric::en rhs) { return (lhs.m_e == rhs); }
inline bool operator== (AstNumeric::en lhs, AstNumeric rhs) { return (lhs == rhs.m_e); }
inline ostream& operator<<(ostream& os, AstNumeric rhs) { return os<<rhs.ascii(); }
//######################################################################
class AstPragmaType {
public:
enum en {
@@ -209,7 +239,7 @@ class AstBasicDTypeKwd {
public:
enum en {
BIT, BYTE, CHANDLE, INT, INTEGER, LOGIC, LONGINT,
REAL, REALTIME, SHORTINT, SHORTREAL, TIME,
DOUBLE, SHORTINT, FLOAT, TIME,
// Closer to a class type, but limited usage
STRING,
// Internal types for mid-steps
@@ -221,7 +251,7 @@ public:
const char* ascii() const {
static const char* names[] = {
"bit", "byte", "chandle", "int", "integer", "logic", "longint",
"real", "realtime", "shortint", "shortreal", "time",
"real", "shortint", "shortreal", "time",
"string",
"VerilatedScope*", "char*",
"LOGIC_IMPLICIT"
@@ -231,7 +261,7 @@ public:
const char* dpiType() const {
static const char* names[] = {
"unsigned char", "char", "void*", "int", "int", "svLogic", "long long",
"double", "double", "short int", "float", "long long",
"double", "short int", "float", "long long",
"const char*",
"dpiScope", "const char*",
""
@@ -251,6 +281,8 @@ public:
case INTEGER: return 32;
case LOGIC: return 1;
case LONGINT: return 64;
case DOUBLE: return 64;
case FLOAT: return 32;
case SHORTINT: return 16;
case TIME: return 64;
case STRING: return 64; // Just the pointer, for today
@@ -265,7 +297,7 @@ public:
}
bool isZeroInit() const { // Otherwise initializes to X
return (m_e==BIT || m_e==BYTE || m_e==CHANDLE || m_e==INT || m_e==LONGINT || m_e==SHORTINT
|| m_e==STRING);
|| m_e==STRING || m_e==DOUBLE || m_e==FLOAT);
}
bool isSloppy() const { // Don't be as anal about width warnings
return !(m_e==LOGIC || m_e==BIT);
@@ -274,10 +306,13 @@ public:
return (m_e==LOGIC || m_e==BIT);
}
bool isDpiUnsupported() const {
return (m_e==LOGIC || m_e==TIME || m_e==REALTIME);
return (m_e==LOGIC || m_e==TIME);
}
bool isOpaque() const { // IE not a simple number we can bit optimize
return (m_e==STRING || m_e==SCOPEPTR || m_e==CHARPTR);
return (m_e==STRING || m_e==SCOPEPTR || m_e==CHARPTR || m_e==DOUBLE || m_e==FLOAT);
}
bool isDouble() const {
return (m_e==DOUBLE);
}
};
inline bool operator== (AstBasicDTypeKwd lhs, AstBasicDTypeKwd rhs) { return (lhs.m_e == rhs.m_e); }
@@ -684,7 +719,9 @@ class AstNode {
static int s_cloneCntGbl; // Count of which userp is set
// Attributes
bool m_signed:1; // Node is signed
uint32_t m_numeric:2; // Node is real/signed - important that bitfields remain unsigned
bool m_didWidth:1; // Did V3Width computation
bool m_doingWidth:1; // Inside V3Width
// // Space for more bools here
int m_width; // Bit width of operation
@@ -780,6 +817,8 @@ public:
static int instrCountLd() { return 2; } ///< Instruction cycles to load memory
static int instrCountMul() { return 3; } ///< Instruction cycles to multiply integers
static int instrCountPli() { return 20; } ///< Instruction cycles to call pli routines
static int instrCountDouble() { return 8; } ///< Instruction cycles to convert or do floats
static int instrCountDoubleDiv() { return 40; } ///< Instruction cycles to divide floats
static int instrCountCall() { return instrCountBranch()+10; } ///< Instruction cycles to call subroutine
static int instrCountTime() { return instrCountCall()+5; } ///< Instruction cycles to determine simulation time
@@ -807,10 +846,18 @@ public:
bool widthSized() const { return !m_widthMin || m_widthMin==m_width; }
void width(int width, int sized) { m_width=width; m_widthMin=sized; }
void widthFrom(AstNode* fromp) { if (fromp) { m_width=fromp->m_width; m_widthMin=fromp->m_widthMin; }}
void widthSignedFrom(AstNode* fromp) { widthFrom(fromp); signedFrom(fromp); }
void signedFrom(AstNode* fromp) { if (fromp) { m_signed=fromp->m_signed; }}
void isSigned(bool flag) { m_signed=flag; }
bool isSigned() const { return m_signed; }
void widthSignedFrom(AstNode* fromp) { widthFrom(fromp); numericFrom(fromp); }
void numericFrom(AstNode* fromp) { numeric(fromp->numeric()); }
void numeric(AstNumeric flag) { m_numeric = (int)flag; if (flag.isDouble()) width(64,64); }
AstNumeric numeric() const { return AstNumeric(m_numeric); }
bool isDouble() const { return numeric().isDouble(); }
bool isSigned() const { return numeric().isSigned(); }
void isSigned(bool flag) { numeric(flag ? AstNumeric::SIGNED : AstNumeric::UNSIGNED); }
bool isUnsigned() const { return numeric().isUnsigned(); }
void didWidth(bool flag) { m_didWidth=flag; }
bool didWidth() const { return m_didWidth; }
void doingWidth(bool flag) { m_doingWidth=flag; }
bool doingWidth() const { return m_doingWidth; }
bool isQuad() const { return (width()>VL_WORDSIZE && width()<=VL_QUADSIZE); }
bool isWide() const { return (width()>VL_QUADSIZE); }
@@ -981,6 +1028,8 @@ struct AstNodeUniop : public AstNodeMath {
virtual void numberOperate(V3Number& out, const V3Number& lhs) = 0; // Set out to evaluation of a AstConst'ed lhs
virtual bool cleanLhs() = 0;
virtual bool sizeMattersLhs() = 0; // True if output result depends on lhs size
virtual bool signedFlavor() const { return false; } // Signed flavor of nodes with both flavors?
virtual bool doubleFlavor() const { return false; } // D flavor of nodes with both flavors?
virtual int instrCount() const { return widthInstrs(); }
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(AstNode*) const { return true; }
@@ -1003,6 +1052,7 @@ struct AstNodeBiop : public AstNodeMath {
virtual bool sizeMattersLhs() = 0; // True if output result depends on lhs size
virtual bool sizeMattersRhs() = 0; // True if output result depends on rhs size
virtual bool signedFlavor() const { return false; } // Signed flavor of nodes with both flavors?
virtual bool doubleFlavor() const { return false; } // D flavor of nodes with both flavors?
virtual int instrCount() const { return widthInstrs(); }
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(AstNode*) const { return true; }
@@ -1275,7 +1325,6 @@ private:
string m_name; // Name of task
string m_cname; // Name of task if DPI import
bool m_taskPublic:1; // Public task
bool m_didSigning:1; // V3Signed completed; can skip iteration
bool m_attrIsolateAssign:1;// User isolate_assignments attribute
bool m_prototype:1; // Just a prototype
bool m_dpiExport:1; // DPI exported
@@ -1286,7 +1335,7 @@ private:
public:
AstNodeFTask(FileLine* fileline, const string& name, AstNode* stmtsp)
: AstNode(fileline)
, m_name(name), m_taskPublic(false), m_didSigning(false)
, m_name(name), m_taskPublic(false)
, m_attrIsolateAssign(false), m_prototype(false)
, m_dpiExport(false), m_dpiImport(false), m_dpiContext(false)
, m_dpiTask(false), m_pure(false) {
@@ -1313,8 +1362,6 @@ public:
void scopeNamep(AstNode* nodep) { setNOp4p(nodep); }
void taskPublic(bool flag) { m_taskPublic=flag; }
bool taskPublic() const { return m_taskPublic; }
void didSigning(bool flag) { m_didSigning=flag; }
bool didSigning() const { return m_didSigning; }
void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; }
bool attrIsolateAssign() const { return m_attrIsolateAssign; }
void prototype(bool flag) { m_prototype = flag; }
+9 -3
View File
@@ -113,6 +113,10 @@ string AstVar::vlArgType(bool named, bool forReturn) const {
arg += "const char*";
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::SCOPEPTR) {
arg += "const VerilatedScope*";
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::DOUBLE) {
arg += "double";
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::FLOAT) {
arg += "float";
} else if (strtype) {
if (isInOnly()) arg += "const ";
arg += "string";
@@ -185,7 +189,7 @@ string AstVar::cPubArgType(bool named, bool forReturn) const {
} else if (isWide()) {
arg += "uint32_t"; // []'s added later
} else {
arg += "uint64_t";
arg += "vluint64_t";
}
if (isWide()) {
if (forReturn) v3error("Unsupported: Public functions with >64 bit outputs; make an output of a public task instead");
@@ -237,7 +241,7 @@ string AstVar::scType() const {
return "uint32_t";
}
} else {
return "uint64_t";
return "vluint64_t";
}
}
@@ -499,6 +503,7 @@ void AstNode::dump(ostream& os) {
<<((editCount()>=editCountLast())?"#>":">")
<<" {"<<dec<<fileline()->lineno()<<"}"
<<" "<<(isSigned()?"s":"")
<<(isDouble()?"d":"")
<<"w"<<(widthSized()?"":"u")<<width();
if (!widthSized()) os<<"/"<<widthMin();
if (name()!="") os<<" "<<AstNode::quoteName(name());
@@ -608,7 +613,8 @@ void AstVar::dump(ostream& str) {
else if (isInput()) str<<" [I]";
else if (isOutput()) str<<" [O]";
}
if (isUsedClock()) str<<" [C]";
if (isConst()) str<<" [CONST]";
if (isUsedClock()) str<<" [CLK]";
if (isSigPublic()) str<<" [P]";
if (isUsedLoopIdx()) str<<" [LOOP]";
if (attrClockEn()) str<<" [aCLKEN]";
+306 -26
View File
@@ -46,19 +46,25 @@ struct AstConst : public AstNodeMath {
private:
V3Number m_num; // Constant value
public:
class Unsized32 {}; // for creator type-overload selection
AstConst(FileLine* fl, const V3Number& num)
:AstNodeMath(fl)
,m_num(num) {
width(m_num.width(), m_num.sized()?0:m_num.minWidth());
isSigned(m_num.isSigned());
numeric(m_num.isDouble() ? AstNumeric::DOUBLE
: m_num.isSigned() ? AstNumeric::SIGNED
: AstNumeric::UNSIGNED);
}
AstConst(FileLine* fl, uint32_t num)
:AstNodeMath(fl)
,m_num(V3Number(fl,32,num)) { width(m_num.width(), m_num.sized()?0:m_num.minWidth()); }
class Unsized32 {}; // for creator type-overload selection
AstConst(FileLine* fl, Unsized32, uint32_t num) // Unsized 32-bit integer of specified value
:AstNodeMath(fl)
,m_num(V3Number(fl,32,num)) { m_num.width(32,false); width(32,m_num.minWidth()); }
class RealDouble {}; // for creator type-overload selection
AstConst(FileLine* fl, RealDouble, double num)
:AstNodeMath(fl)
,m_num(V3Number(fl,64)) { m_num.setDouble(num); numeric(AstNumeric::DOUBLE); }
class LogicFalse {};
AstConst(FileLine* fl, LogicFalse) // Shorthand const 0, know the dtype should be a logic of size 1
:AstNodeMath(fl)
@@ -258,7 +264,8 @@ private:
m_keyword = AstBasicDTypeKwd::LOGIC;
}
if (signst == signedst_NOP && keyword().isSigned()) signst = signedst_SIGNED;
setSignedState(signst);
if (keyword().isDouble()) numeric(AstNumeric::DOUBLE);
else setSignedState(signst);
if (!rangep) { // Set based on keyword properties
// V3Width will pull from this width
if (keyword().width() > 1 && !isOpaque()) rangep = new AstRange(fileline(), keyword().width()-1, 0);
@@ -278,7 +285,8 @@ public:
AstRange* rangep() const { return op1p()->castRange(); } // op1 = Range of variable
void rangep(AstRange* nodep) { setNOp1p(nodep); }
void setSignedState(AstSignedState signst) {
if (signst!=signedst_NOP) isSigned(signst==signedst_SIGNED);
if (signst==signedst_UNSIGNED) numeric(AstNumeric::UNSIGNED);
else if (signst==signedst_SIGNED) numeric(AstNumeric::SIGNED);
}
// METHODS
virtual AstBasicDType* basicp() const { return (AstBasicDType*)this; } // (Slow) recurse down to find basic data type
@@ -300,6 +308,25 @@ public:
void implicit(bool flag) { m_implicit = flag; }
};
struct AstConstDType : public AstNodeDType {
// const data type, ie "const some_dtype var_name [2:0]"
// ConstDType are removed in V3LinkLValue and become AstVar::isConst.
// When more generic types are supported AstConstDType will be propagated further.
AstConstDType(FileLine* fl, AstNodeDType* dtypep)
: AstNodeDType(fl) {
setOp1p(dtypep);
widthSignedFrom(dtypep);
}
ASTNODE_NODE_FUNCS(ConstDType, CONSTDTYPE)
AstNodeDType* dtypep() const { return op1p()->castNodeDType(); } // op1 = Range of variable
void dtypep(AstNodeDType* nodep) { setOp1p(nodep); }
// METHODS
virtual AstBasicDType* basicp() const { return dtypep()->basicp(); } // (Slow) recurse down to find basic data type
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const { return dtypep()->widthAlignBytes(); }
virtual int widthTotalBytes() const { return dtypep()->widthTotalBytes(); }
};
struct AstRefDType : public AstNodeDType {
private:
AstTypedef* m_defp;
@@ -562,8 +589,6 @@ private:
bool m_attrClockEn:1;// User clock enable attribute
bool m_attrIsolateAssign:1;// User isolate_assignments attribute
bool m_attrSFormat:1;// User sformat attribute
bool m_didSigning:1; // V3Signed completed; can skip iteration
bool m_didWidth:1; // V3Width completed; can skip iteration
bool m_fileDescr:1; // File descriptor
bool m_isConst:1; // Table contains constant data
bool m_isStatic:1; // Static variable
@@ -577,7 +602,6 @@ private:
m_sigPublic=false; m_sigModPublic=false; m_sigUserRdPublic=false; m_sigUserRWPublic=false;
m_funcLocal=false; m_funcReturn=false;
m_attrClockEn=false; m_attrIsolateAssign=false; m_attrSFormat=false;
m_didSigning=false; m_didWidth=false;
m_fileDescr=false; m_isConst=false; m_isStatic=false;
m_trace=false;
}
@@ -588,6 +612,7 @@ public:
init();
combineType(type); setOp1p(dtypep);
if (dtypep && dtypep->basicp()) {
numericFrom(dtypep);
width(dtypep->basicp()->width(), 0);
} else width(1, 0);
}
@@ -607,6 +632,7 @@ public:
if (examplep->dtypep()) {
setOp1p(examplep->dtypep()->cloneTree(true));
}
numericFrom(examplep);
width(examplep->width(), examplep->widthMin());
}
ASTNODE_NODE_FUNCS(Var, VAR)
@@ -640,10 +666,6 @@ public:
void attrScClocked(bool flag) { m_scClocked = flag; }
void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; }
void attrSFormat(bool flag) { m_attrSFormat = flag; }
void didSigning(bool flag) { m_didSigning=flag; }
bool didSigning() const { return m_didSigning; }
void didWidth(bool flag) { m_didWidth=flag; }
bool didWidth() const { return m_didWidth; }
void usedClock(bool flag) { m_usedClock = flag; }
void usedParam(bool flag) { m_usedParam = flag; }
void usedLoopIdx(bool flag) { m_usedLoopIdx = flag; }
@@ -677,7 +699,7 @@ public:
bool isToggleCoverable() const { return ((isIO() || isSignal())
&& (isIO() || isBitLogic())
// Wrapper would otherwise duplicate wrapped module's coverage
&& !isSc() && !isPrimaryIO()); }
&& !isSc() && !isPrimaryIO() && !isConst()); }
bool isStatementTemp() const { return (varType()==AstVarType::STMTTEMP); }
bool isMovableToBlock() const { return (varType()==AstVarType::BLOCKTEMP || isFuncLocal()); }
bool isPure() const { return (varType()==AstVarType::XTEMP); }
@@ -1435,6 +1457,15 @@ struct AstCondBound : public AstNodeCond {
ASTNODE_NODE_FUNCS(CondBound, CONDBOUND)
};
struct AstCondD : public AstNodeCond {
// Conditional ?: statement, double rhs/lhs/out
// Parents: MATH
// Children: MATH
AstCondD(FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p)
: AstNodeCond(fl, condp, expr1p, expr2p) { numeric(AstNumeric::DOUBLE); }
ASTNODE_NODE_FUNCS(CondD, CONDD)
};
struct AstCoverDecl : public AstNodeStmt {
// Coverage analysis point declaration
// Parents: {statement list}
@@ -1605,7 +1636,7 @@ public:
void ignoreOverlap(bool flag) { m_ignoreOverlap = flag; }
};
class AstSFormatF : public AstNode {
struct AstSFormatF : public AstNode {
// Convert format to string, generally under a AstDisplay or AstSFormat
// Also used as "real" function for /*verilator sformat*/ functions
string m_text;
@@ -1973,6 +2004,18 @@ struct AstContinue : public AstNodeStmt {
virtual bool isSplittable() const { return false; } // SPECIAL: We don't process code after breaks
};
struct AstDisable : public AstNodeStmt {
private:
string m_name; // Name of block
public:
AstDisable(FileLine* fileline, const string& name)
: AstNodeStmt(fileline), m_name(name) {}
ASTNODE_NODE_FUNCS(Disable, DISABLE)
virtual string name() const { return m_name; } // * = Block name
void name(const string& flag) { m_name=flag; }
virtual bool isSplittable() const { return false; } // SPECIAL: We don't process code after breaks
};
struct AstReturn : public AstNodeStmt {
AstReturn(FileLine* fileline, AstNode* lhsp=NULL)
: AstNodeStmt (fileline) {
@@ -2416,6 +2459,20 @@ struct AstTime : public AstNodeTermop {
virtual bool same(AstNode* samep) const { return true; }
};
struct AstTimeD : public AstNodeTermop {
AstTimeD(FileLine* fl) : AstNodeTermop(fl) {
numeric(AstNumeric::DOUBLE); }
ASTNODE_NODE_FUNCS(TimeD, TIMED)
virtual string emitVerilog() { return "%f$realtime"; }
virtual string emitC() { return "VL_TIME_D()"; }
virtual bool cleanOut() { return true; }
virtual bool isGateOptimizable() const { return false; }
virtual bool isPredictOptimizable() const { return false; }
virtual int instrCount() const { return instrCountTime(); }
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(AstNode* samep) const { return true; }
};
struct AstUCFunc : public AstNodeMath {
// User's $c function
// Perhaps this should be a AstNodeListop; but there's only one list math right now
@@ -2441,19 +2498,32 @@ struct AstUCFunc : public AstNodeMath {
//======================================================================
// Unary ops
struct AstUnaryMin : public AstNodeUniop {
AstUnaryMin(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
struct AstNegate : public AstNodeUniop {
AstNegate(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
if (lhsp) widthSignedFrom(lhsp); }
ASTNODE_NODE_FUNCS(UnaryMin, UNARYMIN)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opUnaryMin(lhs); }
ASTNODE_NODE_FUNCS(Negate, NEGATE)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opNegate(lhs); }
virtual string emitVerilog() { return "%f(- %l)"; }
virtual string emitC() { return "VL_UNARYMIN_%lq(%lW, %P, %li)"; }
virtual string emitC() { return "VL_NEGATE_%lq(%lW, %P, %li)"; }
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;}
virtual bool sizeMattersLhs() {return true;}
};
struct AstNegateD : public AstNodeUniop {
AstNegateD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
numeric(AstNumeric::DOUBLE); }
ASTNODE_NODE_FUNCS(NegateD, NEGATED)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opNegateD(lhs); }
virtual string emitVerilog() { return "%f(- %l)"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual string emitSimpleOperator() { return "-"; }
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;}
virtual bool sizeMattersLhs() {return false;}
virtual int instrCount() const { return instrCountDouble(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstRedAnd : public AstNodeUniop {
AstRedAnd(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
width(1,1); }
width(1,1); numeric(AstNumeric::UNSIGNED); }
ASTNODE_NODE_FUNCS(RedAnd, REDAND)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedAnd(lhs); }
virtual string emitVerilog() { return "%f(& %l)"; }
@@ -2463,7 +2533,7 @@ struct AstRedAnd : public AstNodeUniop {
};
struct AstRedOr : public AstNodeUniop {
AstRedOr(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
width(1,1); }
width(1,1); numeric(AstNumeric::UNSIGNED); }
ASTNODE_NODE_FUNCS(RedOr, REDOR)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedOr(lhs); }
virtual string emitVerilog() { return "%f(| %l)"; }
@@ -2473,7 +2543,7 @@ struct AstRedOr : public AstNodeUniop {
};
struct AstRedXor : public AstNodeUniop {
AstRedXor(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
width(1,1); }
width(1,1); numeric(AstNumeric::UNSIGNED); }
ASTNODE_NODE_FUNCS(RedXor, REDXOR)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedXor(lhs); }
virtual string emitVerilog() { return "%f(^ %l)"; }
@@ -2487,7 +2557,7 @@ struct AstRedXor : public AstNodeUniop {
struct AstRedXnor : public AstNodeUniop {
// AstRedXnors are replaced with AstRedXors in V3Const.
AstRedXnor(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
width(1,1); }
width(1,1); numeric(AstNumeric::UNSIGNED); }
ASTNODE_NODE_FUNCS(RedXnor, REDXNOR)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedXnor(lhs); }
virtual string emitVerilog() { return "%f(~^ %l)"; }
@@ -2545,7 +2615,7 @@ struct AstExtendS : public AstNodeUniop {
struct AstSigned : public AstNodeUniop {
// $signed(lhs)
AstSigned(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
isSigned(true);
numeric(AstNumeric::SIGNED);
}
ASTNODE_NODE_FUNCS(Signed, SIGNED)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); out.isSigned(false); }
@@ -2558,7 +2628,7 @@ struct AstSigned : public AstNodeUniop {
struct AstUnsigned : public AstNodeUniop {
// $unsigned(lhs)
AstUnsigned(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
isSigned(false);
numeric(AstNumeric::UNSIGNED);
}
ASTNODE_NODE_FUNCS(Unsigned, UNSIGNED)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); out.isSigned(false); }
@@ -2568,6 +2638,63 @@ struct AstUnsigned : public AstNodeUniop {
virtual bool sizeMattersLhs() {return true;} // Eliminated before matters
virtual int instrCount() const { return 0; }
};
struct AstRToIS : public AstNodeUniop {
// $rtoi(lhs)
AstRToIS(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
width(32,32); }
ASTNODE_NODE_FUNCS(RToIS, RTOIS)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRToIS(lhs); }
virtual string emitVerilog() { return "%f$rtoi(%l)"; }
virtual string emitC() { return "VL_RTOI_I_D(%li)"; }
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;} // Eliminated before matters
virtual bool sizeMattersLhs() {return false;} // Eliminated before matters
virtual int instrCount() const { return instrCountDouble(); }
};
struct AstRToIRoundS : public AstNodeUniop {
AstRToIRoundS(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
width(32,32); }
ASTNODE_NODE_FUNCS(RToIRoundS, RTOIROUNDS)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRToIRoundS(lhs); }
virtual string emitVerilog() { return "%f$rtoi_rounded(%l)"; }
virtual string emitC() { return "VL_RTOIROUND_I_D(%li)"; }
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;} // Eliminated before matters
virtual bool sizeMattersLhs() {return false;} // Eliminated before matters
virtual int instrCount() const { return instrCountDouble(); }
};
struct AstIToRD : public AstNodeUniop {
AstIToRD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
numeric(AstNumeric::DOUBLE); }
ASTNODE_NODE_FUNCS(IToRD, ITORD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opIToRD(lhs); }
virtual string emitVerilog() { return "%f$itor(%l)"; }
virtual string emitC() { return "VL_ITOR_D_I(%li)"; }
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;} // Eliminated before matters
virtual bool sizeMattersLhs() {return false;} // Eliminated before matters
virtual int instrCount() const { return instrCountDouble(); }
};
struct AstRealToBits : public AstNodeUniop {
AstRealToBits(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
width(64,64); }
ASTNODE_NODE_FUNCS(RealToBits, REALTOBITS)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRealToBits(lhs); }
virtual string emitVerilog() { return "%f$realtobits(%l)"; }
virtual string emitC() { return "VL_CVT_Q_D(%li)"; }
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;} // Eliminated before matters
virtual bool sizeMattersLhs() {return false;} // Eliminated before matters
virtual int instrCount() const { return instrCountDouble(); }
};
struct AstBitsToRealD : public AstNodeUniop {
AstBitsToRealD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
numeric(AstNumeric::DOUBLE); }
ASTNODE_NODE_FUNCS(BitsToRealD, BITSTOREALD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opBitsToRealD(lhs); }
virtual string emitVerilog() { return "%f$bitstoreal(%l)"; }
virtual string emitC() { return "VL_CVT_D_Q(%li)"; }
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;} // Eliminated before matters
virtual bool sizeMattersLhs() {return false;} // Eliminated before matters
virtual int instrCount() const { return instrCountDouble(); }
};
struct AstCLog2 : public AstNodeUniop {
AstCLog2(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(CLog2, CLOG2)
@@ -2685,7 +2812,7 @@ struct AstFEof : public AstNodeUniop {
ASTNODE_NODE_FUNCS(FEof, FEOF)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { V3ERROR_NA; }
virtual string emitVerilog() { return "%f$feof(%l)"; }
virtual string emitC() { return "(%li ? feof(VL_CVT_Q_FP(%li)) : true)"; }
virtual string emitC() { return "(%li ? feof(VL_CVT_I_FP(%li)) : true)"; }
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return true;}
virtual bool sizeMattersLhs() {return false;}
virtual int instrCount() const { return widthInstrs()*16; }
@@ -2698,7 +2825,7 @@ struct AstFGetC : public AstNodeUniop {
virtual void numberOperate(V3Number& out, const V3Number& lhs) { V3ERROR_NA; }
virtual string emitVerilog() { return "%f$fgetc(%l)"; }
// Non-existent filehandle returns EOF
virtual string emitC() { return "(%li ? fgetc(VL_CVT_Q_FP(%li)) : -1)"; }
virtual string emitC() { return "(%li ? fgetc(VL_CVT_I_FP(%li)) : -1)"; }
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return true;}
virtual bool sizeMattersLhs() {return false;}
virtual int instrCount() const { return widthInstrs()*64; }
@@ -2820,6 +2947,20 @@ struct AstEq : public AstNodeBiCom {
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
};
struct AstEqD : public AstNodeBiCom {
AstEqD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
width(1,1); }
ASTNODE_NODE_FUNCS(EqD, EQD)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opEqD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f== %r)"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual string emitSimpleOperator() { return "=="; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return instrCountDouble(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstNeq : public AstNodeBiCom {
AstNeq(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
width(1,1); }
@@ -2832,6 +2973,20 @@ struct AstNeq : public AstNodeBiCom {
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
};
struct AstNeqD : public AstNodeBiCom {
AstNeqD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
width(1,1); }
ASTNODE_NODE_FUNCS(NeqD, NEQD)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opNeqD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f!= %r)"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual string emitSimpleOperator() { return "!="; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return instrCountDouble(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstLt : public AstNodeBiop {
AstLt(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
width(1,1); }
@@ -2844,6 +2999,20 @@ struct AstLt : public AstNodeBiop {
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
};
struct AstLtD : public AstNodeBiop {
AstLtD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
width(1,1); }
ASTNODE_NODE_FUNCS(LtD, LTD)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLtD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f< %r)"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual string emitSimpleOperator() { return "<"; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return instrCountDouble(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstLtS : public AstNodeBiop {
AstLtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
width(1,1); }
@@ -2869,6 +3038,20 @@ struct AstGt : public AstNodeBiop {
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
};
struct AstGtD : public AstNodeBiop {
AstGtD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
width(1,1); }
ASTNODE_NODE_FUNCS(GtD, GTD)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGtD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f> %r)"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual string emitSimpleOperator() { return ">"; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return instrCountDouble(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstGtS : public AstNodeBiop {
AstGtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
width(1,1); }
@@ -2894,6 +3077,20 @@ struct AstGte : public AstNodeBiop {
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
};
struct AstGteD : public AstNodeBiop {
AstGteD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
width(1,1); }
ASTNODE_NODE_FUNCS(GteD, GTED)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGteD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f>= %r)"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual string emitSimpleOperator() { return ">="; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return instrCountDouble(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstGteS : public AstNodeBiop {
AstGteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
width(1,1); }
@@ -2919,6 +3116,20 @@ struct AstLte : public AstNodeBiop {
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
};
struct AstLteD : public AstNodeBiop {
AstLteD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
width(1,1); }
ASTNODE_NODE_FUNCS(LteD, LTED)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLteD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f<= %r)"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual string emitSimpleOperator() { return "<="; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return instrCountDouble(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstLteS : public AstNodeBiop {
AstLteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
width(1,1); }
@@ -2987,6 +3198,20 @@ struct AstAdd : public AstNodeBiComAsv {
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
};
struct AstAddD : public AstNodeBiComAsv {
AstAddD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
numeric(AstNumeric::DOUBLE); }
ASTNODE_NODE_FUNCS(AddD, ADDD)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opAddD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f+ %r)"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual string emitSimpleOperator() { return "+"; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return instrCountDouble(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstSub : public AstNodeBiop {
AstSub(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
if (lhsp) widthSignedFrom(lhsp); }
@@ -2999,6 +3224,20 @@ struct AstSub : public AstNodeBiop {
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
};
struct AstSubD : public AstNodeBiop {
AstSubD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
numeric(AstNumeric::DOUBLE); }
ASTNODE_NODE_FUNCS(SubD, SUBD)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opSubD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f- %r)"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual string emitSimpleOperator() { return "-"; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return instrCountDouble(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstMul : public AstNodeBiComAsv {
AstMul(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
if (lhsp) widthSignedFrom(lhsp); }
@@ -3012,6 +3251,20 @@ struct AstMul : public AstNodeBiComAsv {
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
virtual int instrCount() const { return widthInstrs()*instrCountMul(); }
};
struct AstMulD : public AstNodeBiComAsv {
AstMulD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
numeric(AstNumeric::DOUBLE); }
ASTNODE_NODE_FUNCS(MulD, MULD)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opMulD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f* %r)"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual string emitSimpleOperator() { return "*"; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
virtual int instrCount() const { return instrCountDouble(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstMulS : public AstNodeBiComAsv {
AstMulS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
if (lhsp) widthSignedFrom(lhsp); }
@@ -3038,6 +3291,20 @@ struct AstDiv : public AstNodeBiop {
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
virtual int instrCount() const { return widthInstrs()*instrCountDiv(); }
};
struct AstDivD : public AstNodeBiop {
AstDivD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
numeric(AstNumeric::DOUBLE); }
ASTNODE_NODE_FUNCS(DivD, DIVD)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opDivD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f/ %r)"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual string emitSimpleOperator() { return "/"; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return instrCountDoubleDiv(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstDivS : public AstNodeBiop {
AstDivS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
if (lhsp) widthSignedFrom(lhsp); }
@@ -3088,6 +3355,19 @@ struct AstPow : public AstNodeBiop {
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return widthInstrs()*instrCountMul(); }
};
struct AstPowD : public AstNodeBiop {
AstPowD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
numeric(AstNumeric::DOUBLE); }
ASTNODE_NODE_FUNCS(PowD, POWD)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opPowD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f** %r)"; }
virtual string emitC() { return "pow(%li,%ri)"; }
virtual bool cleanOut() {return false;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return instrCountDoubleDiv(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstPowS : public AstNodeBiop {
AstPowS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
if (lhsp) widthSignedFrom(lhsp); }
+6 -2
View File
@@ -148,17 +148,19 @@ private:
bool isCaseTreeFast(AstCase* nodep) {
int width = 0;
bool opaque = false;
m_caseItems = 0;
m_caseNoOverlapsAllCovered = true;
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) {
if (icondp->width() > width) width = icondp->width();
if (icondp->isDouble()) opaque = true;
if (!icondp->castConst()) width = CASE_BARF; // Can't parse; not a constant
m_caseItems++;
}
}
m_caseWidth = width;
if (width==0 || width > CASE_OVERLAP_WIDTH) {
if (width==0 || width > CASE_OVERLAP_WIDTH || opaque) {
m_caseNoOverlapsAllCovered = false;
return false; // Too wide for analysis
}
@@ -348,7 +350,9 @@ private:
and1p = cexprp->cloneTree(false);
and2p = icondp;
}
AstEq* condp = new AstEq(itemp->fileline(), and1p, and2p);
AstNodeBiop* condp = (and1p->isDouble()
? (new AstEqD(itemp->fileline(), and1p, and2p))->castNodeBiop()
: (new AstEq(itemp->fileline(), and1p, and2p))->castNodeBiop());
if (!ifexprp) {
ifexprp = condp;
} else {
+1 -1
View File
@@ -135,7 +135,7 @@ private:
insureLower32Cast(nodep);
nodep->user1(1);
}
virtual void visit(AstUnaryMin* nodep, AstNUser*) {
virtual void visit(AstNegate* nodep, AstNUser*) {
nodep->iterateChildren(*this);
nodep->user1(nodep->lhsp()->user1());
if (nodep->lhsp()->widthMin()==1) {
+11 -1
View File
@@ -476,6 +476,12 @@ private:
void edgeReport() {
// Make report of all signal names and what clock edges they have
//
// Due to flattening, many interesting direct-connect signals are
// lost, so we can't make a report showing I/Os for a low level
// module. Disabling flattening though makes us consider each
// signal in it's own unique clock domain.
UINFO(3,__FUNCTION__<<": "<<endl);
// Trace all sources and sinks
@@ -505,6 +511,10 @@ private:
ostringstream os;
os.setf(ios::left);
// Module name - doesn't work due to flattening having lost the original
// so we assume the modulename matches the filebasename
string fname = vvertexp->varScp()->fileline()->filebasename() + ":";
os<<" "<<setw(20)<<fname;
os<<" "<<setw(8)<<whatp;
os<<" "<<setw(40)<<vvertexp->varScp()->prettyName();
os<<" SRC=";
@@ -739,7 +749,7 @@ public:
nodep->accept(*this);
analyze();
//edgeReport(); // Not useful at the moment
if (debug()>=1) edgeReport(); // Not useful to users at the moment
if (0) { *m_ofp<<"\nDBG-test-dumper\n"; V3EmitV::verilogPrefixedTree(nodep, *m_ofp, "DBG ",40,NULL,true); *m_ofp<<endl; }
}
+8 -3
View File
@@ -37,7 +37,6 @@
#include "V3Const.h"
#include "V3Ast.h"
#include "V3Width.h"
#include "V3Signed.h"
#include "V3Simulate.h"
//######################################################################
@@ -1519,7 +1518,7 @@ private:
if (!inPct && ch=='%') {
inPct = true;
fmt = ch;
} else if (inPct && isdigit(ch)) {
} else if (inPct && (isdigit(ch) || ch=='.')) {
fmt += ch;
} else if (inPct) {
inPct = false;
@@ -1664,7 +1663,7 @@ private:
TREEOP ("AstShiftRS{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
TREEOP ("AstXor {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
TREEOP ("AstXnor {$lhsp.isZero, $rhsp}", "AstNot{$rhsp}");
TREEOP ("AstSub {$lhsp.isZero, $rhsp}", "AstUnaryMin{$rhsp}");
TREEOP ("AstSub {$lhsp.isZero, $rhsp}", "AstNegate{$rhsp}");
TREEOP ("AstAdd {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
TREEOP ("AstAnd {$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
TREEOP ("AstLogAnd{$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
@@ -1783,17 +1782,23 @@ private:
TREEOP ("AstXnor {operandsSame($lhsp,,$rhsp)}", "replaceAllOnes(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 ("AstEqD {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 ("AstEqWild {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstGt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstGtD {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstGtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstGte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstGteD {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstGteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstLt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstLtD {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstLtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstLte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstLteD {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstLteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstNeq {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstNeqD {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)");
+16 -8
View File
@@ -344,13 +344,11 @@ public:
puts(");\n");
}
virtual void visit(AstFClose* nodep, AstNUser*) {
puts("if (");
puts("VL_FCLOSE_I(");
nodep->filep()->iterateAndNext(*this);
puts(") { fclose (VL_CVT_Q_FP(");
nodep->filep()->iterateAndNext(*this);
puts(")); ");
puts("); ");
nodep->filep()->iterateAndNext(*this); // For saftey, so user doesn't later WRITE with it.
puts("=0; }\n");
puts("=0;\n");
}
virtual void visit(AstFFlush* nodep, AstNUser*) {
if (!nodep->filep()) {
@@ -358,7 +356,7 @@ public:
} else {
puts("if (");
nodep->filep()->iterateAndNext(*this);
puts(") { fflush (VL_CVT_Q_FP(");
puts(") { fflush (VL_CVT_I_FP(");
nodep->filep()->iterateAndNext(*this);
puts(")); }\n");
}
@@ -547,6 +545,8 @@ public:
ofp()->printf(",0x%08" VL_PRI64 "x", (vluint64_t)(nodep->num().dataWord(word)));
}
ofp()->printf(",0x%08" VL_PRI64 "x)", (vluint64_t)(nodep->num().dataWord(0)));
} else if (nodep->isDouble()) {
ofp()->printf("%g", nodep->num().toDouble());
} else if (nodep->isQuad()) {
vluint64_t num = nodep->toUQuad();
if (num<10) ofp()->printf("VL_ULL(%" VL_PRI64 "d)", num);
@@ -1212,6 +1212,7 @@ void EmitCStmts::displayNode(AstNode* nodep, AstScopeName* scopenamep,
switch (tolower(pos[0])) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case '.':
// Digits, like %5d, etc.
vfmt += pos[0];
inPct = true; // Get more digits
@@ -1230,6 +1231,9 @@ void EmitCStmts::displayNode(AstNode* nodep, AstScopeName* scopenamep,
case 'h':
case 'x': displayArg(nodep,&elistp,isScan, vfmt,'x'); break;
case 's': displayArg(nodep,&elistp,isScan, vfmt,'s'); break;
case 'e': displayArg(nodep,&elistp,isScan, vfmt,'e'); break;
case 'f': displayArg(nodep,&elistp,isScan, vfmt,'f'); break;
case 'g': displayArg(nodep,&elistp,isScan, vfmt,'g'); break;
case 'm': {
if (!scopenamep) nodep->v3fatalSrc("Display with %m but no AstScopeName");
string suffix = scopenamep->scopePrettyName();
@@ -2011,7 +2015,9 @@ class EmitCTrace : EmitCStmts {
return varp->isSc() && varp->isScBv();
}
void emitTraceInitOne(AstTraceDecl* nodep) {
if (nodep->isWide()) {
if (nodep->isDouble()) {
puts("vcdp->declDouble");
} else if (nodep->isWide()) {
puts("vcdp->declArray");
} else if (nodep->isQuad()) {
puts("vcdp->declQuad ");
@@ -2040,7 +2046,9 @@ class EmitCTrace : EmitCStmts {
string full = ((m_funcp->funcType() == AstCFuncType::TRACE_FULL
|| m_funcp->funcType() == AstCFuncType::TRACE_FULL_SUB)
? "full":"chg");
if (nodep->isWide() || emitTraceIsScBv(nodep)) {
if (nodep->isDouble()) {
puts("vcdp->"+full+"Double");
} else if (nodep->isWide() || emitTraceIsScBv(nodep)) {
puts("vcdp->"+full+"Array");
} else if (nodep->isQuad()) {
puts("vcdp->"+full+"Quad ");
+9 -4
View File
@@ -84,10 +84,15 @@ public:
if (v3Global.opt.systemPerl()) {
putMakeClassEntry(of, "Sp.cpp"); // Note Sp.cpp includes SpTraceVcdC
}
else if (v3Global.opt.trace()) {
putMakeClassEntry(of, "verilated_vcd_c.cpp");
if (v3Global.opt.systemC()) {
putMakeClassEntry(of, "verilated_vcd_sc.cpp");
else {
if (v3Global.opt.coverage()) {
putMakeClassEntry(of, "SpCoverage.cpp");
}
if (v3Global.opt.trace()) {
putMakeClassEntry(of, "verilated_vcd_c.cpp");
if (v3Global.opt.systemC()) {
putMakeClassEntry(of, "verilated_vcd_sc.cpp");
}
}
}
}
+7
View File
@@ -217,6 +217,9 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
}
puts(");\n");
}
virtual void visit(AstDisable* nodep, AstNUser*) {
putbs("disable "+nodep->name()+";\n");
}
virtual void visit(AstDisplay* nodep, AstNUser*) {
visitNodeDisplay(nodep, nodep->filep(), nodep->fmtp()->text(), nodep->fmtp()->exprsp());
}
@@ -480,6 +483,10 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
putfs(nodep,nodep->prettyName());
if (nodep->rangep()) { puts(" "); nodep->rangep()->iterateAndNext(*this); puts(" "); }
}
virtual void visit(AstConstDType* nodep, AstNUser*) {
putfs(nodep,"const ");
nodep->dtypep()->iterateAndNext(*this);
}
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
if (nodep->dotted()!="") { putfs(nodep,nodep->dotted()); puts("."); puts(nodep->prettyName()); }
else { putfs(nodep,nodep->prettyName()); }
+3 -1
View File
@@ -73,6 +73,7 @@ public:
LITENDIAN, // Little bit endian vector
MODDUP, // Duplicate module
MULTIDRIVEN, // Driven from multiple blocks
REALCVT, // Real conversion
REDEFMACRO, // Redefining existing define macro
STMTDLY, // Delayed statement
SYMRSVDWORD, // Symbol is Reserved Word
@@ -111,7 +112,7 @@ public:
"IFDEPTH", "IMPERFECTSCH", "IMPLICIT", "IMPURE", "INCABSPATH",
"LITENDIAN", "MODDUP",
"MULTIDRIVEN",
"REDEFMACRO",
"REALCVT", "REDEFMACRO",
"STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET",
"UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNSIGNED", "UNUSED",
"VARHIDDEN", "WIDTH", "WIDTHCONCAT",
@@ -135,6 +136,7 @@ public:
|| m_e==CMPCONST
|| m_e==IMPLICIT
|| m_e==LITENDIAN
|| m_e==REALCVT
|| m_e==UNSIGNED
|| m_e==WIDTH); }
// Warnings that are style only
+2 -3
View File
@@ -696,8 +696,7 @@ private:
int lhswidth = lhsp->widthMin();
if (lhswidth==1) {
UINFO(8," REPLICATE(w1) "<<nodep<<endl);
newp = new AstUnaryMin (nodep->fileline(),
lhsp);
newp = new AstNegate (nodep->fileline(), lhsp);
} else {
UINFO(8," REPLICATE "<<nodep<<endl);
AstConst* constp = nodep->rhsp()->castConst();
@@ -731,7 +730,7 @@ private:
for (int w=0; w<rhsp->widthWords(); w++) {
AstNode* newp;
if (lhswidth==1) {
newp = new AstUnaryMin (nodep->fileline(), lhsp->cloneTree(true));
newp = new AstNegate (nodep->fileline(), lhsp->cloneTree(true));
newp->width(VL_WORDSIZE,VL_WORDSIZE);
} else {
newp = newAstWordSelClone (lhsp, w);
+1 -1
View File
@@ -428,7 +428,7 @@ private:
if (dtypep) dtypep->unlinkFrBack();
else dtypep = new AstBasicDType(nodep->fileline(), AstBasicDTypeKwd::LOGIC);
AstVar* newvarp = new AstVar(nodep->fileline(), AstVarType::OUTPUT, nodep->name(), dtypep);
newvarp->isSigned(nodep->isSigned());
if (nodep->isSigned()) newvarp->numeric(AstNumeric::SIGNED);
newvarp->funcReturn(true);
newvarp->trace(false); // Not user visible
newvarp->attrIsolateAssign(nodep->attrIsolateAssign());
+24 -3
View File
@@ -135,8 +135,8 @@ private:
// Spec says value is integral, if negative is ignored
AstVar* varp = new AstVar(nodep->fileline(), AstVarType::BLOCKTEMP, name,
AstLogicPacked(), 32);
varp->isSigned(true);
varp->dtypep()->isSigned(true);
varp->numeric(AstNumeric::SIGNED);
varp->dtypep()->numeric(AstNumeric::SIGNED);
varp->usedLoopIdx(true);
m_modp->addStmtp(varp);
AstNode* initsp = new AstAssign(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, true),
@@ -144,7 +144,7 @@ private:
AstNode* decp = new AstAssign(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, true),
new AstSub(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false),
new AstConst(nodep->fileline(), 1)));
AstNode* zerosp = new AstConst(nodep->fileline(), 0); zerosp->isSigned(true);
AstNode* zerosp = new AstConst(nodep->fileline(), 0); zerosp->numeric(AstNumeric::SIGNED);
AstNode* condp = new AstGtS(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false),
zerosp);
AstNode* bodysp = nodep->bodysp(); if (bodysp) bodysp->unlinkFrBackWithNext();
@@ -211,6 +211,27 @@ private:
}
nodep->unlinkFrBack(); pushDeletep(nodep); nodep=NULL;
}
virtual void visit(AstDisable* nodep, AstNUser*) {
UINFO(8," DISABLE "<<nodep<<endl);
nodep->iterateChildren(*this);
AstBegin* beginp = NULL;
for (BeginStack::reverse_iterator it = m_beginStack.rbegin(); it != m_beginStack.rend(); ++it) {
UINFO(9," UNDERBLK "<<*it<<endl);
if ((*it)->name() == nodep->name()) {
beginp = *it;
break;
}
}
//if (debug()>=9) { UINFO(0,"\n"); beginp->dumpTree(cout," labeli: "); }
if (!beginp) { nodep->v3error("disable isn't underneath a begin with name: "<<nodep->name()); }
else {
// Jump to the end of the named begin
AstJumpLabel* labelp = findAddLabel(beginp, false);
nodep->addNextHere(new AstJumpGo(nodep->fileline(), labelp));
}
nodep->unlinkFrBack(); pushDeletep(nodep); nodep=NULL;
//if (debug()>=9) { UINFO(0,"\n"); beginp->dumpTree(cout," labelo: "); }
}
virtual void visit(AstVarRef* nodep, AstNUser*) {
if (m_loopInc && nodep->varp()) nodep->varp()->usedLoopIdx(true);
}
+11
View File
@@ -45,6 +45,7 @@ private:
// STATE
bool m_setRefLvalue; // Set VarRefs to lvalues for pin assignments
AstInitial* m_initialp; // In an initial block
AstNodeFTask* m_ftaskp; // Function or task we're inside
// METHODS
@@ -67,6 +68,10 @@ private:
nodep->v3error("Assigning to input variable: "<<nodep->prettyName());
}
}
if (nodep->lvalue() && nodep->varp()->isConst()
&& !m_initialp) { // Too loose, but need to allow our generated first assignment
nodep->v3error("Assigning to const variable: "<<nodep->prettyName());
}
}
nodep->iterateChildren(*this);
}
@@ -222,6 +227,11 @@ private:
}
m_setRefLvalue = last_setRefLvalue;
}
virtual void visit(AstInitial* nodep, AstNUser*) {
m_initialp = nodep;
nodep->iterateChildren(*this);
m_initialp = NULL;
}
virtual void visit(AstNodeFTask* nodep, AstNUser*) {
m_ftaskp = nodep;
nodep->iterateChildren(*this);
@@ -259,6 +269,7 @@ public:
LinkLValueVisitor(AstNode* nodep, bool start) {
m_setRefLvalue = start;
m_ftaskp = NULL;
m_initialp = NULL;
nodep->accept(*this);
}
virtual ~LinkLValueVisitor() {}
+4
View File
@@ -95,6 +95,9 @@ private:
nodep->dtypeSkipRefp()->castArrayDType())) {
nodep->v3error("Unsupported: Inputs and outputs must be simple data types");
}
if (nodep->dtypeSkipRefp()->castConstDType()) {
nodep->isConst(true);
}
if (m_ftaskp) nodep->funcLocal(true);
if (nodep->isSigModPublic()) {
nodep->sigModPublic(false); // We're done with this attribute
@@ -254,6 +257,7 @@ private:
switch (tolower(ch)) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case '.':
inPct = true;
break;
case '%': break; // %% - just output a %
+141 -19
View File
@@ -27,6 +27,8 @@
#include <algorithm>
#include "V3Number.h"
#define MAX_SPRINTF_DOUBLE_SIZE 100 // Maximum characters with a sprintf %e/%f/%g (probably < 30)
//######################################################################
// Read class functions
// CREATION
@@ -44,6 +46,7 @@ void V3Number::width(int width, bool sized) {
void V3Number::init (FileLine* fileline, int swidth) {
m_fileline = fileline;
m_signed = false;
m_double = false;
m_autoExtend = false;
m_fromString = false;
width(swidth);
@@ -298,6 +301,24 @@ V3Number& V3Number::setLong(uint32_t value) {
m_value[0] = value;
return *this;
}
V3Number& V3Number::setLongS(vlsint32_t value) {
for (int i=0; i<words(); i++) m_value[i]=m_valueX[i] = 0;
union { uint32_t u; vlsint32_t s; } u;
u.s = value;
m_value[0] = u.u;
return *this;
}
V3Number& V3Number::setDouble(double value) {
if (VL_UNLIKELY(width()!=64)) {
m_fileline->v3fatalSrc("Real operation on wrong sized number");
}
m_double = true;
union { double d; uint32_t u[2]; } u;
u.d = value;
for (int i=2; i<words(); i++) m_value[i]=m_valueX[i] = 0;
m_value[0] = u.u[0]; m_value[1] = u.u[1];
return *this;
}
V3Number& V3Number::setSingleBits(char value) {
for (int i=1/*upper*/; i<words(); i++) m_value[i]=m_valueX[i] = 0;
m_value[0] = (value=='1'||value=='x'||value==1||value==3);
@@ -306,12 +327,12 @@ V3Number& V3Number::setSingleBits(char value) {
}
V3Number& V3Number::setAllBits0() {
for (int i=0; i<words(); i++) { m_value[i] = m_valueX[i]=0; }
return *this;
for (int i=0; i<words(); i++) { m_value[i] = m_valueX[i]=0; }
return *this;
}
V3Number& V3Number::setAllBits1() {
for (int i=0; i<words(); i++) { m_value[i]= ~0; m_valueX[i] = 0; }
return *this;
for (int i=0; i<words(); i++) { m_value[i]= ~0; m_valueX[i] = 0; }
return *this;
}
V3Number& V3Number::setAllBitsX() {
for (int i=0; i<words(); i++) { m_value[i]=m_valueX[i] = ~0; }
@@ -333,6 +354,10 @@ V3Number& V3Number::setMask(int nbits) {
string V3Number::ascii(bool prefixed, bool cleanVerilog) const {
ostringstream out;
if (isDouble()) {
out<<toDouble();
return out.str();
}
if (prefixed) {
if (sized()) {
out<<width()<<"'";
@@ -375,6 +400,9 @@ bool V3Number::displayedFmtLegal(char format) {
case 'b': return true;
case 'c': return true;
case 'd': return true; // Unsigned decimal
case 'e': return true;
case 'f': return true;
case 'g': return true;
case 'h': return true;
case 'o': return true;
case 's': return true;
@@ -390,7 +418,7 @@ string V3Number::displayed(const string& vformat) const {
UASSERT(pos != vformat.end() && pos[0]=='%', "display with non format argument "<<*this);
pos++;
string fmtsize;
for (; pos != vformat.end() && isdigit(pos[0]); pos++) {
for (; pos != vformat.end() && (isdigit(pos[0]) || pos[0]=='.'); pos++) {
fmtsize += pos[0];
}
string str;
@@ -472,9 +500,20 @@ string V3Number::displayed(const string& vformat) const {
str = cvtToStr(toUQuad());
}
int intfmtsize = atoi(fmtsize.c_str());
while ((int)(str.length()) < intfmtsize) str = " "+str;
bool zeropad = fmtsize.length()>0 && fmtsize[0]=='0';
while ((int)(str.length()) < intfmtsize) {
if (zeropad) str = "0"+str;
else str = " "+str;
}
return str;
}
case 'e':
case 'f':
case 'g': {
char tmp[MAX_SPRINTF_DOUBLE_SIZE];
sprintf(tmp, vformat.c_str(), toDouble());
return tmp;
}
default:
m_fileline->v3fatalSrc("Unknown $display format code for number: %"<<pos[0]);
return "ERR";
@@ -490,6 +529,18 @@ uint32_t V3Number::toUInt() const {
return m_value[0];
}
double V3Number::toDouble() const {
if (VL_UNLIKELY(!isDouble())) {
m_fileline->v3fatalSrc("Real conversion on non real number");
}
if (VL_UNLIKELY(width()!=64)) {
m_fileline->v3fatalSrc("Real operation on wrong sized number");
}
union { double d; uint32_t u[2]; } u;
u.u[0] = m_value[0]; u.u[1] = m_value[1];
return u.d;
}
vlsint32_t V3Number::toSInt() const {
if (isSigned()) {
uint32_t v = toUInt();
@@ -1049,7 +1100,7 @@ V3Number& V3Number::opShiftR (const V3Number& lhs, const V3Number& rhs) {
V3Number& V3Number::opShiftRS (const V3Number& lhs, const V3Number& rhs) {
// L(lhs) bit return
// The spec says a unsigned >>> still acts as a normal >>.
// We presume it is signed; as that's V3Signed's job to convert to opShiftR
// We presume it is signed; as that's V3Width's job to convert to opShiftR
if (rhs.isFourState()) return setAllBitsX();
setZero();
uint32_t rhsval = rhs.toUInt();
@@ -1079,12 +1130,12 @@ V3Number& V3Number::opAbsS (const V3Number& lhs) {
// op i, L(lhs) bit return
if (lhs.isFourState()) return setAllBitsX();
if (lhs.isNegative()) {
return opUnaryMin(lhs);
return opNegate(lhs);
} else {
return opAssign(lhs);
}
}
V3Number& V3Number::opUnaryMin (const V3Number& lhs) {
V3Number& V3Number::opNegate (const V3Number& lhs) {
// op i, L(lhs) bit return
if (lhs.isFourState()) return setAllBitsX();
V3Number notlhs (lhs.m_fileline, width());
@@ -1112,7 +1163,7 @@ V3Number& V3Number::opSub (const V3Number& lhs, const V3Number& rhs) {
// i op j, max(L(lhs),L(rhs)) bit return, if any 4-state, 4-state return
if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX();
V3Number negrhs (rhs.m_fileline, rhs.width());
negrhs.opUnaryMin(rhs);
negrhs.opNegate(rhs);
return opAdd(lhs, negrhs);
}
V3Number& V3Number::opMul (const V3Number& lhs, const V3Number& rhs) {
@@ -1140,12 +1191,12 @@ V3Number& V3Number::opMul (const V3Number& lhs, const V3Number& rhs) {
V3Number& V3Number::opMulS (const V3Number& lhs, const V3Number& rhs) {
// Signed multiply
if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX();
V3Number lhsNoSign = lhs; if (lhs.isNegative()) lhsNoSign.opUnaryMin(lhs);
V3Number rhsNoSign = rhs; if (rhs.isNegative()) rhsNoSign.opUnaryMin(rhs);
V3Number lhsNoSign = lhs; if (lhs.isNegative()) lhsNoSign.opNegate(lhs);
V3Number rhsNoSign = rhs; if (rhs.isNegative()) rhsNoSign.opNegate(rhs);
V3Number qNoSign = opMul(lhsNoSign,rhsNoSign);
if ((lhs.isNegative() && !rhs.isNegative())
|| (!lhs.isNegative() && rhs.isNegative())) {
opUnaryMin(qNoSign);
opNegate(qNoSign);
} else {
opAssign(qNoSign);
}
@@ -1169,13 +1220,13 @@ V3Number& V3Number::opDivS (const V3Number& lhs, const V3Number& rhs) {
//UINFO(9, ">>divs-start "<<lhs<<" "<<rhs<<endl);
if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX();
if (rhs.isEqZero()) return setAllBitsX();
V3Number lhsNoSign = lhs; if (lhs.isNegative()) lhsNoSign.opUnaryMin(lhs);
V3Number rhsNoSign = rhs; if (rhs.isNegative()) rhsNoSign.opUnaryMin(rhs);
V3Number lhsNoSign = lhs; if (lhs.isNegative()) lhsNoSign.opNegate(lhs);
V3Number rhsNoSign = rhs; if (rhs.isNegative()) rhsNoSign.opNegate(rhs);
V3Number qNoSign = opDiv(lhsNoSign,rhsNoSign);
//UINFO(9, " >divs-mid "<<lhs<<" "<<rhs<<" "<<qNoSign<<endl);
if ((lhs.isNegative() && !rhs.isNegative())
|| (!lhs.isNegative() && rhs.isNegative())) {
opUnaryMin(qNoSign);
opNegate(qNoSign);
} else {
opAssign(qNoSign);
}
@@ -1198,11 +1249,11 @@ V3Number& V3Number::opModDivS (const V3Number& lhs, const V3Number& rhs) {
// Signed moddiv
if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX();
if (rhs.isEqZero()) return setAllBitsX();
V3Number lhsNoSign = lhs; if (lhs.isNegative()) lhsNoSign.opUnaryMin(lhs);
V3Number rhsNoSign = rhs; if (rhs.isNegative()) rhsNoSign.opUnaryMin(rhs);
V3Number lhsNoSign = lhs; if (lhs.isNegative()) lhsNoSign.opNegate(lhs);
V3Number rhsNoSign = rhs; if (rhs.isNegative()) rhsNoSign.opNegate(rhs);
V3Number qNoSign = opModDiv(lhsNoSign,rhsNoSign);
if (lhs.isNegative()) { // Just lhs' sign (*DIFFERENT FROM PERL, which uses rhs sign*)
opUnaryMin(qNoSign);
opNegate(qNoSign);
} else {
opAssign(qNoSign);
}
@@ -1434,3 +1485,74 @@ V3Number& V3Number::opCond (const V3Number& lhs, const V3Number& if1s, const V3
}
return *this;
}
//======================================================================
// Ops - Floating point
V3Number& V3Number::opIToRD (const V3Number& lhs) {
return setDouble(lhs.toSInt());
}
V3Number& V3Number::opRToIS (const V3Number& lhs) {
double v = trunc(lhs.toDouble());
vlsint32_t i = (vlsint32_t)v; // C converts from double to vlsint32
return setLongS(i);
}
V3Number& V3Number::opRToIRoundS (const V3Number& lhs) {
double v = round(lhs.toDouble());
vlsint32_t i = (vlsint32_t)v; // C converts from double to vlsint32
return setLongS(i);
}
V3Number& V3Number::opRealToBits (const V3Number& lhs) {
// Conveniently our internal format is identical so we can copy bits...
if (lhs.width()!=64 || this->width()!=64) {
m_fileline->v3fatalSrc("Real operation on wrong sized number");
}
return opAssign(lhs);
}
V3Number& V3Number::opBitsToRealD (const V3Number& lhs) {
// Conveniently our internal format is identical so we can copy bits...
if (lhs.width()!=64 || this->width()!=64) {
m_fileline->v3fatalSrc("Real operation on wrong sized number");
}
return opAssign(lhs);
}
V3Number& V3Number::opNegateD (const V3Number& lhs) {
return setDouble(- lhs.toDouble());
}
V3Number& V3Number::opAddD (const V3Number& lhs, const V3Number& rhs) {
return setDouble(lhs.toDouble() + rhs.toDouble());
}
V3Number& V3Number::opSubD (const V3Number& lhs, const V3Number& rhs) {
return setDouble(lhs.toDouble() - rhs.toDouble());
}
V3Number& V3Number::opMulD (const V3Number& lhs, const V3Number& rhs) {
return setDouble(lhs.toDouble() * rhs.toDouble());
}
V3Number& V3Number::opDivD (const V3Number& lhs, const V3Number& rhs) {
// On exceptions, we just generate 'inf' through floating point
// IEEE says it's implementation defined what happens
return setDouble(lhs.toDouble() / rhs.toDouble());
}
V3Number& V3Number::opPowD (const V3Number& lhs, const V3Number& rhs) {
// On exceptions, we just generate 'inf' through floating point
// IEEE says it's implementation defined what happens
return setDouble(pow(lhs.toDouble(), rhs.toDouble()));
}
V3Number& V3Number::opEqD (const V3Number& lhs, const V3Number& rhs) {
return setSingleBits(lhs.toDouble() == rhs.toDouble());
}
V3Number& V3Number::opNeqD (const V3Number& lhs, const V3Number& rhs) {
return setSingleBits(lhs.toDouble() != rhs.toDouble());
}
V3Number& V3Number::opGtD (const V3Number& lhs, const V3Number& rhs) {
return setSingleBits(lhs.toDouble() > rhs.toDouble());
}
V3Number& V3Number::opGteD (const V3Number& lhs, const V3Number& rhs) {
return setSingleBits(lhs.toDouble() >= rhs.toDouble());
}
V3Number& V3Number::opLtD (const V3Number& lhs, const V3Number& rhs) {
return setSingleBits(lhs.toDouble() < rhs.toDouble());
}
V3Number& V3Number::opLteD (const V3Number& lhs, const V3Number& rhs) {
return setSingleBits(lhs.toDouble() <= rhs.toDouble());
}
+25 -1
View File
@@ -35,6 +35,7 @@ class V3Number {
int m_width; // Width as specified/calculated.
bool m_sized:1; // True if the user specified the width, else we track it.
bool m_signed:1; // True if signed value
bool m_double:1; // True if double real value
bool m_fromString:1; // True if from string
bool m_autoExtend:1; // True if SystemVerilog extend-to-any-width
FileLine* m_fileline;
@@ -50,6 +51,8 @@ public:
V3Number& setZero();
V3Number& setQuad(vluint64_t value);
V3Number& setLong(uint32_t value);
V3Number& setLongS(vlsint32_t value);
V3Number& setDouble(double value);
void setBit (int bit, char value) { // Note must be pre-zeroed!
if (bit>=m_width) return;
if (value=='0'||value==0) m_value [bit/32] &= ~(1UL<<(bit&31));
@@ -132,6 +135,7 @@ public:
bool autoExtend() const { return m_autoExtend; }
bool isFromString() const { return m_fromString; }
bool isSigned() const { return m_signed; } // Only correct for parsing of numbers from strings, otherwise not used (use AstConst::isSigned())
bool isDouble() const { return m_double; } // Only correct for parsing of numbers from strings, otherwise not used (use AstConst::isSigned())
bool isNegative() const { return bitIs1(width()-1); }
bool isFourState() const { for (int i=0;i<words();i++) {if (m_valueX[i]) return true;} return false; }
bool hasZ() const { for(int i=0;i<words();i++) {if((~m_value[i]) & m_valueX[i]) return true;} return false;}
@@ -151,6 +155,7 @@ public:
vluint64_t toUQuad() const;
vlsint64_t toSQuad() const;
string toString() const;
double toDouble() const;
uint32_t toHash() const;
uint32_t dataWord(int word) const;
uint32_t countOnes() const;
@@ -203,7 +208,7 @@ public:
V3Number& opLogAnd (const V3Number& lhs, const V3Number& rhs);
V3Number& opLogOr (const V3Number& lhs, const V3Number& rhs);
V3Number& opAbsS (const V3Number& lhs);
V3Number& opUnaryMin(const V3Number& lhs);
V3Number& opNegate (const V3Number& lhs);
V3Number& opAdd (const V3Number& lhs, const V3Number& rhs);
V3Number& opSub (const V3Number& lhs, const V3Number& rhs);
V3Number& opMul (const V3Number& lhs, const V3Number& rhs);
@@ -236,6 +241,25 @@ public:
V3Number& opLte (const V3Number& lhs, const V3Number& rhs);
V3Number& opLteS (const V3Number& lhs, const V3Number& rhs); // Signed
// "D" - double (aka real) math
V3Number& opIToRD (const V3Number& lhs);
V3Number& opRToIS (const V3Number& lhs);
V3Number& opRToIRoundS (const V3Number& lhs);
V3Number& opRealToBits (const V3Number& lhs);
V3Number& opBitsToRealD(const V3Number& lhs);
V3Number& opNegateD (const V3Number& lhs);
V3Number& opAddD (const V3Number& lhs, const V3Number& rhs);
V3Number& opSubD (const V3Number& lhs, const V3Number& rhs);
V3Number& opMulD (const V3Number& lhs, const V3Number& rhs);
V3Number& opDivD (const V3Number& lhs, const V3Number& rhs);
V3Number& opPowD (const V3Number& lhs, const V3Number& rhs);
// Comparisons
V3Number& opEqD (const V3Number& lhs, const V3Number& rhs);
V3Number& opNeqD (const V3Number& lhs, const V3Number& rhs);
V3Number& opGtD (const V3Number& lhs, const V3Number& rhs);
V3Number& opGteD (const V3Number& lhs, const V3Number& rhs);
V3Number& opLtD (const V3Number& lhs, const V3Number& rhs);
V3Number& opLteD (const V3Number& lhs, const V3Number& rhs);
};
inline ostream& operator<<(ostream& os, V3Number rhs) { return os<<rhs.ascii(); }
+3 -3
View File
@@ -51,7 +51,7 @@ void test(string lhss, string op, string rhss, string exps) {
else if (op=="repl") gotnum.opRepl (lhnum,rhnum);
else if (op=="~") gotnum.opNot (lhnum);
else if (op=="!") gotnum.opLogNot (lhnum);
else if (op=="unaryMin") gotnum.opUnaryMin (lhnum);
else if (op=="negate") gotnum.opNegate (lhnum);
else if (op=="+") gotnum.opAdd (lhnum,rhnum);
else if (op=="-") gotnum.opSub (lhnum,rhnum);
else if (op=="*") gotnum.opMul (lhnum,rhnum);
@@ -96,8 +96,8 @@ int main() {
test("32'b0x","|","32'b10","32'b1x");
test("32'b10","&","32'b11","32'b10");
test("32'b10","+","32'b10","32'b100");
test("3'b000","unaryMin","","3'b000");
test("3'b001","unaryMin","","3'b111");
test("3'b000","negate","","3'b000");
test("3'b001","negate","","3'b111");
test("32'b11","-","32'b001","32'b10");
test("3'b000","-","3'b111","3'b001");
test("3'b000","-","3'b000","3'b000");
-1
View File
@@ -43,7 +43,6 @@
#include "V3Case.h"
#include "V3Const.h"
#include "V3Width.h"
#include "V3Signed.h"
#include "V3Unroll.h"
//######################################################################
+1
View File
@@ -254,6 +254,7 @@ public:
void verilatorCmtLintSave();
void verilatorCmtLintRestore();
void verilatorCmtBad(const char* text);
double parseDouble(const char* text, size_t length);
void pushBeginKeywords(int state) { m_inBeginKwd++; m_lastVerilogState=state; }
bool popBeginKeywords() { if (m_inBeginKwd) { m_inBeginKwd--; return true; } else return false; }
int lastVerilogState() { return m_lastVerilogState; }
+3
View File
@@ -393,6 +393,9 @@ void V3PreProcImp::comment(const string& text) {
} else if (0==(strncmp(cp,"cadence",strlen("cadence")))) {
cp+=strlen("cadence");
synth = true;
} else if (0==(strncmp(cp,"pragma",strlen("pragma")))) {
cp+=strlen("pragma");
synth = true;
} else if (0==(strncmp(cp,"ambit synthesis",strlen("ambit synthesis")))) {
cp+=strlen("ambit synthesis");
synth = true;
+6 -6
View File
@@ -208,12 +208,12 @@ private:
// Then over shifting gives the sign bit, not all zeros
// Note *NOT* clean output -- just like normal shift!
// Create equivalent of VL_SIGNONES_(node_width)
constzerop = new AstUnaryMin (nodep->fileline(),
new AstShiftR(nodep->fileline(),
nodep->lhsp()->cloneTree(false),
new AstConst(nodep->fileline(),
nodep->widthMin()-1),
nodep->width()));
constzerop = new AstNegate (nodep->fileline(),
new AstShiftR(nodep->fileline(),
nodep->lhsp()->cloneTree(false),
new AstConst(nodep->fileline(),
nodep->widthMin()-1),
nodep->width()));
} else {
V3Number zeronum (nodep->fileline(), nodep->width(), 0);
constzerop = new AstConst(nodep->fileline(), zeronum);
-450
View File
@@ -1,450 +0,0 @@
//*************************************************************************
// DESCRIPTION: Verilator: Signed/unsigned resolution
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2005-2011 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
//
// Verilator is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//*************************************************************************
// Signedness depends on:
// Decimal numbers are signed
// Based numbers are unsigned unless 's' prefix
// Comparison results are unsigned
// Bit&Part selects are unsigned, even if whole
// Concatenates are unsigned
// Ignore signedness of self-determined:
// shift rhs, ** rhs, x?: lhs, concat and replicate members
// Else, if any operand unsigned, output unsigned
//*************************************************************************
#include "config_build.h"
#include "verilatedos.h"
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <map>
#include <iomanip>
#include "V3Global.h"
#include "V3Signed.h"
#include "V3Ast.h"
//######################################################################
// Signed class functions
class SignedVisitor : public AstNVisitor {
private:
// NODE STATE/TYPES
// STATE
int m_taskDepth; // Recursion check
bool m_paramsOnly; // Computing parameter value; limit operation
// METHODS - special type detection
bool backRequiresUnsigned(AstNode* nodep) {
// The spec doesn't state this, but if you have an array select where the selection
// index is NOT wide enough, you do not sign extend, but always zero extend.
return (nodep->castArraySel()
|| nodep->castSel());
}
// VISITORS
//========
// Signed: Output explicit by user, Lhs either
virtual void visit(AstSigned* nodep, AstNUser*) { signed_Os_Ix(nodep); }
virtual void visit(AstUnsigned* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
//========
// Signed: Output unsigned, Operands either
virtual void visit(AstSel* nodep, AstNUser*) { signed_Ou_Ix(nodep); } //See backRequiresUnsigned
virtual void visit(AstAttrOf* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstCountOnes* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstCLog2* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstPslBool* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstTime* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
//
virtual void visit(AstRedAnd* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstRedOr* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstRedXnor* nodep, AstNUser*){ signed_Ou_Ix(nodep); }
virtual void visit(AstRedXor* nodep,AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstIsUnknown* nodep,AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstOneHot* nodep,AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstOneHot0* nodep,AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstFEof* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstFGetC* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstFGetS* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstFScanF* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstSScanF* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstTestPlusArgs* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstValuePlusArgs* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
//
virtual void visit(AstConcat* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstReplicate* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstRange* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
// ... One presumes these are unsigned out, though the spec doesn't say
virtual void visit(AstLogNot* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstLogAnd* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstLogOr* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstLogIf* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstLogIff* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstBufIf1* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
// ... These shouldn't matter, just make unsigned
virtual void visit(AstScopeName* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstText* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstUCFunc* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
// ... These comparisons don't care about inbound types
// ... (Though they should match. We don't check.)
virtual void visit(AstEq* 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(AstNeqCase* nodep, AstNUser*){ signed_Ou_Ix(nodep); }
virtual void visit(AstNeqWild* nodep, AstNUser*){ signed_Ou_Ix(nodep); }
// ... Opaque returns, so arbitrary
virtual void visit(AstCvtPackString* nodep, AstNUser*){ signed_Ou_Ix(nodep); }
//========
// Signed: Output signed
virtual void visit(AstRand* nodep, AstNUser*) { signed_Os_Ix(nodep); }
//=======
// Signed: Output signed iff LHS signed; unary operator
virtual void visit(AstNot* nodep, AstNUser*) { signed_Olhs(nodep); }
virtual void visit(AstUnaryMin* nodep, AstNUser*) { signed_Olhs(nodep); }
virtual void visit(AstShiftL* nodep, AstNUser*) { signed_Olhs(nodep); }
virtual void visit(AstShiftR* nodep, AstNUser*) { signed_Olhs(nodep); }
// Signed: Output signed iff LHS signed; binary operator
// Note by contrast, bit extract selects are unsigned
virtual void visit(AstArraySel* nodep, AstNUser*) { signed_Olhs(nodep); } //See backRequiresUnsigned
//=======
// Signed: Output signed iff LHS & RHS signed; binary operator
virtual void visit(AstAnd* nodep, AstNUser*) { signed_OlhsAndRhs(nodep); }
virtual void visit(AstOr* nodep, AstNUser*) { signed_OlhsAndRhs(nodep); }
virtual void visit(AstXnor* nodep, AstNUser*) { signed_OlhsAndRhs(nodep); }
virtual void visit(AstXor* nodep, AstNUser*) { signed_OlhsAndRhs(nodep); }
virtual void visit(AstSub* nodep, AstNUser*) { signed_OlhsAndRhs(nodep); }
virtual void visit(AstAdd* nodep, AstNUser*) { signed_OlhsAndRhs(nodep); }
//=======
// Signed: Output signed iff RHS & THS signed
virtual void visit(AstNodeCond* nodep, AstNUser*) { signed_OrhsAndThs(nodep); }
//=======
// These have proper signedness set when they were created.
virtual void visit(AstReturn* nodep, AstNUser*) { nodep->iterateChildren(*this); }
virtual void visit(AstNodeDType* nodep, AstNUser*) { nodep->iterateChildren(*this); }
// Inherit from others
virtual void visit(AstVar* nodep, AstNUser*) {
// Avoid recursion; can't use user() as they're all full, and anyhow this is often called
if (nodep->didSigning()) return;
nodep->didSigning(true);
nodep->iterateChildren(*this);
nodep->signedFrom(nodep->dtypep());
}
virtual void visit(AstNodeVarRef* nodep, AstNUser*) {
nodep->varp()->iterate(*this);
nodep->signedFrom(nodep->varp());
}
virtual void visit(AstEnumItemRef* nodep, AstNUser*) {
nodep->itemp()->iterate(*this);
nodep->signedFrom(nodep->itemp());
}
virtual void visit(AstCast* nodep, AstNUser*) {
nodep->lhsp()->iterate(*this);
nodep->dtypep()->iterate(*this);
nodep->signedFrom(nodep->dtypep());
}
virtual void visit(AstConst* nodep, AstNUser*) {
// The node got setup with the signed state of the node.
// However a later operation may have changed the node->signed w/o changing
// the number's sign. So we don't: nodep->isSigned(nodep->num().isSigned());
}
virtual void visit(AstNodeFTask* nodep, AstNUser*) {
// Avoid recursion; can't use user() as they're all full, and anyhow this is often called
if (nodep->didSigning()) return;
nodep->didSigning(true);
nodep->iterateChildren(*this);
if (nodep->fvarp()) {
nodep->signedFrom(nodep->fvarp()); // Which will get it from fvarp()->dtypep()
}
}
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (nodep->taskp()) nodep->taskp()->iterate(*this);
nodep->signedFrom(nodep->taskp());
}
virtual void visit(AstRefDType* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (nodep->defp()) nodep->defp()->iterate(*this);
nodep->signedFrom(nodep->skipRefp());
}
virtual void visit(AstNodeIf* nodep, AstNUser*) {
if (!nodep->castGenIf()) { // for m_paramsOnly
nodep->ifsp()->iterateAndNext(*this);
nodep->elsesp()->iterateAndNext(*this);
}
nodep->condp()->iterateAndNext(*this);
}
virtual void visit(AstPin* nodep, AstNUser*) {
// Same as above taskref argument.
nodep->iterateChildren(*this);
}
// VISITORS - Special
virtual void visit(AstSFormatF* nodep, AstNUser*) {
nodep->iterateChildren(*this);
//
UINFO(9," Display in "<<nodep->text()<<endl);
string dispout = "";
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;
} else if (inPct && isdigit(ch)) {
} else if (tolower(inPct)) {
inPct = false;
switch (tolower(ch)) {
case '%': break; // %% - just output a %
case 'm': break; // %m - auto insert "name"
case 'd': { // Convert decimal to either 'd' or 'u'
if (argp && argp->isSigned()) { // Convert it
ch = '~';
}
if (argp) argp=argp->nextp();
break;
}
default: // Most operators, just move to next argument
if (argp) argp=argp->nextp();
break;
} // switch
}
dispout += ch;
}
nodep->text(dispout);
UINFO(9," Display out "<<nodep->text()<<endl);
}
// VISITORS - These need to be changed to different op types
// Uniop
virtual void visit(AstExtend* nodep, AstNUser*) {
signed_Olhs(nodep);
if (nodep->isSigned() && !backRequiresUnsigned(nodep->backp())) {
replaceWithSignedVersion(nodep, new AstExtendS (nodep->fileline(), nodep->lhsp()->unlinkFrBack())); nodep=NULL;
}
}
virtual void visit(AstExtendS* nodep, AstNUser*) {
signed_Olhs(nodep);
if (!(nodep->isSigned() && !backRequiresUnsigned(nodep->backp()))) {
replaceWithSignedVersion(nodep, new AstExtend (nodep->fileline(), nodep->lhsp()->unlinkFrBack())); nodep=NULL;
}
}
// Biop
virtual void visit(AstPow* nodep, AstNUser*) {
// Pow is special, output sign only depends on LHS sign
signed_Olhs(nodep);
if (nodep->isSigned()) {
replaceWithSignedVersion(nodep, new AstPowS (nodep->fileline(), nodep->lhsp()->unlinkFrBack(), nodep->rhsp()->unlinkFrBack())); nodep=NULL;
}
}
virtual void visit(AstPowS* nodep, AstNUser*) {
// Pow is special, output sign only depends on LHS sign
signed_Olhs(nodep);
if (!nodep->isSigned()) {
replaceWithSignedVersion(nodep, new AstPow (nodep->fileline(), nodep->lhsp()->unlinkFrBack(), nodep->rhsp()->unlinkFrBack())); nodep=NULL;
}
}
// These have different node types, as they operate differently
// Must add to case statement below,
virtual void visit(AstGt* nodep, AstNUser*) { checkReplace_Ou_FlavLhsAndRhs(nodep); }
virtual void visit(AstGtS* nodep, AstNUser*) { checkReplace_Ou_FlavLhsAndRhs(nodep); }
virtual void visit(AstGte* nodep, AstNUser*) { checkReplace_Ou_FlavLhsAndRhs(nodep); }
virtual void visit(AstGteS* nodep, AstNUser*) { checkReplace_Ou_FlavLhsAndRhs(nodep); }
virtual void visit(AstLt* nodep, AstNUser*) { checkReplace_Ou_FlavLhsAndRhs(nodep); }
virtual void visit(AstLtS* nodep, AstNUser*) { checkReplace_Ou_FlavLhsAndRhs(nodep); }
virtual void visit(AstLte* nodep, AstNUser*) { checkReplace_Ou_FlavLhsAndRhs(nodep); }
virtual void visit(AstLteS* nodep, AstNUser*) { checkReplace_Ou_FlavLhsAndRhs(nodep); }
// Need replacements; output matches input sign
virtual void visit(AstDiv* nodep, AstNUser*) { checkReplace_OlhsAndRhs(nodep); }
virtual void visit(AstDivS* nodep, AstNUser*) { checkReplace_OlhsAndRhs(nodep); }
virtual void visit(AstModDiv* nodep, AstNUser*) { checkReplace_OlhsAndRhs(nodep); }
virtual void visit(AstModDivS* nodep, AstNUser*) { checkReplace_OlhsAndRhs(nodep); }
virtual void visit(AstMul* nodep, AstNUser*) { checkReplace_OlhsAndRhs(nodep); }
virtual void visit(AstMulS* nodep, AstNUser*) { checkReplace_OlhsAndRhs(nodep); }
// ShiftRS converts to ShiftR, but not vice-versa
virtual void visit(AstShiftRS* nodep, AstNUser*) { checkReplace_Olhs(nodep); }
void checkReplace_Ou_FlavLhsAndRhs(AstNodeBiop* nodep) {
// For compares, the output of the comparison is unsigned.
// However, we need the appropriate type of compare selected by RHS & LHS
signed_Ou_Ix(nodep);
checkReplace(nodep, nodep->lhsp()->isSigned() && nodep->rhsp()->isSigned());
}
void checkReplace_Olhs(AstNodeBiop* nodep) {
signed_Olhs(nodep);
checkReplace(nodep, nodep->isSigned());
}
void checkReplace_OlhsAndRhs(AstNodeBiop* nodep) {
signed_OlhsAndRhs(nodep);
checkReplace(nodep, nodep->isSigned());
}
void checkReplace(AstNodeBiop* nodep, bool signedFlavorNeeded) {
if (signedFlavorNeeded != nodep->signedFlavor()) {
AstNode* lhsp = nodep->lhsp()->unlinkFrBack();
AstNode* rhsp = nodep->rhsp()->unlinkFrBack();
AstNode* newp = NULL;
// Given a signed/unsigned node type, create the opposite type
switch (nodep->type()) {
case AstType::atGT: newp = new AstGtS (nodep->fileline(), lhsp, rhsp); break;
case AstType::atGTS: newp = new AstGt (nodep->fileline(), lhsp, rhsp); break;
case AstType::atGTE: newp = new AstGteS (nodep->fileline(), lhsp, rhsp); break;
case AstType::atGTES: newp = new AstGte (nodep->fileline(), lhsp, rhsp); break;
case AstType::atLT: newp = new AstLtS (nodep->fileline(), lhsp, rhsp); break;
case AstType::atLTS: newp = new AstLt (nodep->fileline(), lhsp, rhsp); break;
case AstType::atLTE: newp = new AstLteS (nodep->fileline(), lhsp, rhsp); break;
case AstType::atLTES: newp = new AstLte (nodep->fileline(), lhsp, rhsp); break;
case AstType::atDIV: newp = new AstDivS (nodep->fileline(), lhsp, rhsp); break;
case AstType::atDIVS: newp = new AstDiv (nodep->fileline(), lhsp, rhsp); break;
case AstType::atMODDIV: newp = new AstModDivS (nodep->fileline(), lhsp, rhsp); break;
case AstType::atMODDIVS: newp = new AstModDiv (nodep->fileline(), lhsp, rhsp); break;
case AstType::atMUL: newp = new AstMulS (nodep->fileline(), lhsp, rhsp); break;
case AstType::atMULS: newp = new AstMul (nodep->fileline(), lhsp, rhsp); break;
case AstType::atSHIFTRS: newp = new AstShiftR (nodep->fileline(), lhsp, rhsp); break;
default:
nodep->v3fatalSrc("Node needs sign change, but bad case: "<<nodep<<endl);
break;
}
replaceWithSignedVersion(nodep,newp);
}
}
// VISITORS - defaults
virtual void visit(AstNodeMath* nodep, AstNUser*) {
nodep->v3fatalSrc("Visit function missing? Signedness unknown for this node: "<<nodep);
nodep->iterateChildren(*this);
}
virtual void visit(AstNode* nodep, AstNUser*) {
nodep->iterateChildren(*this);
}
// COMMON SCHEMES
// Signed: Output signed, Lhs/Rhs/etc either
void signed_Os_Ix(AstNode* nodep) {
nodep->iterateChildren(*this);
nodep->isSigned(true);
}
// Signed: Output unsigned, Lhs/Rhs/etx either
void signed_Ou_Ix(AstNode* nodep) {
nodep->iterateChildren(*this);
nodep->isSigned(false);
}
// Signed: Output signed iff LHS signed; unary operator
void signed_Olhs(AstNodeUniop* nodep) {
nodep->iterateChildren(*this);
nodep->isSigned(nodep->lhsp()->isSigned());
}
// Signed: Output signed iff LHS signed; binary operator
void signed_Olhs(AstNodeBiop* nodep) {
nodep->iterateChildren(*this);
nodep->isSigned(nodep->lhsp()->isSigned());
}
// Signed: Output signed iff LHS signed; select operator
void signed_Olhs(AstSel* nodep) {
nodep->iterateChildren(*this);
nodep->isSigned(nodep->fromp()->isSigned());
}
// Signed: Output signed iff LHS & RHS signed; binary operator
void signed_OlhsAndRhs(AstNodeBiop* nodep) {
nodep->iterateChildren(*this);
nodep->isSigned(nodep->lhsp()->isSigned() && nodep->rhsp()->isSigned());
}
// Signed: Output signed iff RHS & THS signed
void signed_OrhsAndThs(AstNodeTriop* nodep) {
nodep->iterateChildren(*this);
nodep->isSigned(nodep->rhsp()->isSigned() && nodep->thsp()->isSigned());
}
void replaceWithSignedVersion(AstNode* nodep, AstNode* newp) {
UINFO(6," Replace "<<nodep<<" w/ "<<newp<<endl);
nodep->replaceWith(newp);
newp->widthSignedFrom(nodep);
pushDeletep(nodep); nodep=NULL;
}
public:
// CONSTRUCTORS
SignedVisitor(bool paramsOnly) {
m_paramsOnly = paramsOnly;
m_taskDepth = 0;
}
virtual ~SignedVisitor() {}
AstNode* mainAcceptEdit(AstNode* nodep) {
return nodep->acceptSubtreeReturnEdits(*this);
}
};
//######################################################################
// Signed class functions
/// Remove all $signed, $unsigned, we're done with them.
class SignedRemoveVisitor : public AstNVisitor {
private:
// VISITORS
virtual void visit(AstSigned* nodep, AstNUser*) {
replaceWithSignedVersion(nodep, nodep->lhsp()->unlinkFrBack()); nodep=NULL;
}
virtual void visit(AstUnsigned* nodep, AstNUser*) {
replaceWithSignedVersion(nodep, nodep->lhsp()->unlinkFrBack()); nodep=NULL;
}
virtual void visit(AstNode* nodep, AstNUser*) {
nodep->iterateChildren(*this);
}
void replaceWithSignedVersion(AstNode* nodep, AstNode* newp) {
UINFO(6," Replace "<<nodep<<" w/ "<<newp<<endl);
nodep->replaceWith(newp);
newp->widthSignedFrom(nodep);
pushDeletep(nodep); nodep=NULL;
}
public:
// CONSTRUCTORS
SignedRemoveVisitor() {}
virtual ~SignedRemoveVisitor() {}
AstNode* mainAcceptEdit(AstNode* nodep) {
return nodep->acceptSubtreeReturnEdits(*this);
}
};
//######################################################################
// Top Signed class
void V3Signed::signedAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
(void)signedParamsEdit(nodep);
}
AstNode* V3Signed::signedParamsEdit(AstNode* nodep) {
// Only called from V3Width::widthParamsEdit
UINFO(4,__FUNCTION__<<": "<<endl);
SignedVisitor visitor (true);
nodep = visitor.mainAcceptEdit(nodep);
SignedRemoveVisitor rvisitor;
nodep = rvisitor.mainAcceptEdit(nodep);
return nodep;
}
-40
View File
@@ -1,40 +0,0 @@
// -*- C++ -*-
//*************************************************************************
// DESCRIPTION: Verilator: Signed/unsigned resolution
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2005-2011 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
//
// Verilator is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//*************************************************************************
#ifndef _V3SIGNED_H_
#define _V3SIGNED_H_ 1
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
//============================================================================
class V3Signed {
public:
static void signedAll(AstNetlist* nodep);
protected:
friend class V3Width; // Use widthParamsEdit instead of signedParamsEdit
static AstNode* signedParamsEdit(AstNode* nodep); // May replace nodep
};
#endif // Guard
+1042 -522
View File
File diff suppressed because it is too large Load Diff
-1
View File
@@ -34,7 +34,6 @@ public:
static void width(AstNetlist* nodep);
// Smaller step... Only do a single node for parameter propagation
static AstNode* widthParamsEdit(AstNode* nodep);
static AstNode* widthParamsEditIfNeed(AstNode* nodep);
// Final step... Mark all widths as equal
static void widthCommit(AstNetlist* nodep);
+103
View File
@@ -0,0 +1,103 @@
// -*- C++ -*-
//*************************************************************************
// DESCRIPTION: Verilator: Cleanup stage in V3Width
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
//
// Verilator is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//*************************************************************************
#ifndef _V3WIDTHCOMMIT_H_
#define _V3WIDTHCOMMIT_H_ 1
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
#ifndef _V3WIDTH_CPP_
# error "V3WidthCommit for V3Width internal use only"
#endif
//######################################################################
/// Remove all $signed, $unsigned, we're done with them.
class WidthRemoveVisitor : public AstNVisitor {
private:
// VISITORS
virtual void visit(AstSigned* nodep, AstNUser*) {
replaceWithSignedVersion(nodep, nodep->lhsp()->unlinkFrBack()); nodep=NULL;
}
virtual void visit(AstUnsigned* nodep, AstNUser*) {
replaceWithSignedVersion(nodep, nodep->lhsp()->unlinkFrBack()); nodep=NULL;
}
virtual void visit(AstNode* nodep, AstNUser*) {
nodep->iterateChildren(*this);
}
void replaceWithSignedVersion(AstNode* nodep, AstNode* newp) {
UINFO(6," Replace "<<nodep<<" w/ "<<newp<<endl);
nodep->replaceWith(newp);
newp->widthSignedFrom(nodep);
pushDeletep(nodep); nodep=NULL;
}
public:
// CONSTRUCTORS
WidthRemoveVisitor() {}
virtual ~WidthRemoveVisitor() {}
AstNode* mainAcceptEdit(AstNode* nodep) {
return nodep->acceptSubtreeReturnEdits(*this);
}
};
//######################################################################
class WidthCommitVisitor : public AstNVisitor {
// Now that all widthing is complete,
// Copy all width() to widthMin(). V3Const expects this
private:
// VISITORS
virtual void visit(AstConst* nodep, AstNUser*) {
nodep->width(nodep->width(),nodep->width());
if ((nodep->width() != nodep->num().width()) || !nodep->num().sized()) {
V3Number num (nodep->fileline(), nodep->width());
num.opAssign(nodep->num());
num.isSigned(nodep->isSigned());
AstNode* newp = new AstConst(nodep->fileline(), num);
nodep->replaceWith(newp);
//if (debug()>4) nodep->dumpTree(cout," fixConstSize_old: ");
//if (debug()>4) newp->dumpTree(cout," _new: ");
pushDeletep(nodep); nodep=NULL;
}
}
virtual void visit(AstNode* nodep, AstNUser*) {
nodep->width(nodep->width(),nodep->width());
nodep->iterateChildren(*this);
}
virtual void visit(AstNodePreSel* nodep, AstNUser*) {
// This check could go anywhere after V3Param
nodep->v3fatalSrc("Presels should have been removed before this point");
}
public:
// CONSTUCTORS
WidthCommitVisitor(AstNetlist* nodep) {
nodep->accept(*this);
}
virtual ~WidthCommitVisitor() {}
};
//######################################################################
#endif // Guard
+3 -3
View File
@@ -111,12 +111,12 @@ private:
// We must make sure sub gets sign of original value
AstNode* newp = new AstSub(lhsp->fileline(), lhsp,
new AstConst(lhsp->fileline(), AstConst::Unsized32(), rhs));
newp->signedFrom(lhsp);
newp->numericFrom(lhsp);
return newp;
} else { // rhs < 0;
AstNode* newp = new AstAdd(lhsp->fileline(), lhsp,
new AstConst(lhsp->fileline(), AstConst::Unsized32(), -rhs));
newp->signedFrom(lhsp);
newp->numericFrom(lhsp);
return newp;
}
}
@@ -126,7 +126,7 @@ private:
AstNode* newp = new AstSub(rhsp->fileline(),
new AstConst(rhsp->fileline(), AstConst::Unsized32(), lhs),
rhsp);
newp->signedFrom(rhsp); // Important as AstSub default is lhs's sign
newp->numericFrom(rhsp); // Important as AstSub default is lhs's sign
return newp;
}
-7
View File
@@ -74,7 +74,6 @@
#include "V3PreShell.h"
#include "V3Premit.h"
#include "V3Scope.h"
#include "V3Signed.h"
#include "V3Slice.h"
#include "V3Split.h"
#include "V3SplitAs.h"
@@ -168,9 +167,6 @@ void process () {
V3Width::width(v3Global.rootp());
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("width.tree"));
// Compute signed/unsigned
V3Signed::signedAll(v3Global.rootp());
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("signed.tree"));
V3Error::abortIfErrors();
// Commit to the widths we've chosen; Make widthMin==width
@@ -571,9 +567,6 @@ int main(int argc, char** argv, char** env) {
v3Global.opt.bin(argv[0]);
string argString = V3Options::argString(argc-1, argv+1);
v3Global.opt.parseOpts(new FileLine("COMMAND_LINE",0), argc-1, argv+1);
if (v3Global.opt.coverage() && !v3Global.opt.systemPerl() && !v3Global.opt.lintOnly()) {
v3fatal("Unsupported: Coverage analysis requires --sp output.");
}
if (!v3Global.opt.outFormatOk()
&& !v3Global.opt.preprocOnly()
&& !v3Global.opt.lintOnly()
+95 -22
View File
@@ -9,7 +9,7 @@ use Pod::Usage;
use strict;
use vars qw ($Debug $VERSION);
$VERSION = '3.202';
$VERSION = '3.307';
our $Self;
@@ -74,9 +74,10 @@ sub parameter {
sub process {
remove_outputs();
clean_input($Opt_Input, tmp_prefix().".y");
$Self->{bison_version} = bison_version_check();
my $supports_report = ($Self->{bison_version} >= 2.3);
my $supports_report = (bison_version_check() >= 2.3);
clean_input($Opt_Input, tmp_prefix().".y");
# Run bison
my $command = ($Opt_Yacc
@@ -100,11 +101,11 @@ sub process {
die "bisonpre: %Error: $Opt_Yacc version $v run failed due to errors\n";
}
clean_output(tmp_prefix().".output",output_prefix().".output", 1);
clean_output(tmp_prefix().".output",output_prefix().".output", 1,0);
warning_check(output_prefix().".output");
clean_output(tmp_prefix().".c", output_prefix().".c", 0);
clean_output(tmp_prefix().".h", output_prefix().".h", 0);
clean_output(tmp_prefix().".c", output_prefix().".c", 0,1);
clean_output(tmp_prefix().".h", output_prefix().".h", 0,1);
remove_tmp();
}
@@ -150,15 +151,17 @@ sub clean_output {
my $filename = shift;
my $outname = shift || $filename;
my $is_output = shift;
my $is_c = shift;
print " edit $filename $outname\n";
my $fh = IO::File->new("<$filename") or die "%Error: $! $filename\n";
my @lines = $fh->getlines;
$fh->close;
(my $basename = tmp_prefix().".y") =~ s!.*/!!;
(my $basename = tmp_prefix().".") =~ s!.*/!!;
$basename = quotemeta($basename);
(my $newbase = $Opt_Input) =~ s!.*/!!;
$newbase =~ s/\.y/./;
if ($is_output) {
my %state_line; my $l=0;
@@ -178,6 +181,28 @@ sub clean_output {
}
@lines = @out; @out = ();
}
if ($is_c) {
my %token_values;
my $in_en=0;
foreach my $line (@lines) {
$in_en=1 if $line =~ /enum\s+yytokentype/;
$in_en=0 if $line =~ /;/;
$token_values{$2} = $1 if $in_en && $line =~ /\b(\S+) = (\d+)/;
}
my @out;
foreach my $line (@lines) {
if ($line =~ /BISONPRE_TOKEN_NAMES/) {
push @out, $line;
foreach my $tv (sort keys %token_values) {
push @out, sprintf("\tcase %d: return \"%s\";\n",
$tv, $token_values{$tv});
}
next;
}
push @out, $line;
}
@lines = @out; @out = ();
}
$fh = IO::File->new(">$outname") or die "%Error: $! writing $outname\n";
foreach my $line (@lines) {
@@ -211,6 +236,7 @@ sub clean_input {
my $outname = shift || $filename; # Can == filename if desired
print " edit $filename $outname\n";
$Self->{filename} = $filename;
my $fh = IO::File->new("<$filename") or die "%Error: $! $filename\n";
my @lines = $fh->getlines;
$fh->close;
@@ -232,7 +258,7 @@ sub clean_input {
$section++;
if ($section==2) { $last_rule = undef; }
}
elsif ($line =~ s/^([a-zA-Z0-9_]+)<(\S+)>:/$1:/) {
elsif ($line =~ s/^([a-zA-Z0-9_]+)<(\S*)>:/$1:/) {
!$rules{$1}{name} or die "%Error: $filename:$l: Redeclaring '$1': $line\n";
$types{$2}{$1} = 1;
$rules{$1}{name} = $1;
@@ -272,6 +298,25 @@ sub clean_input {
#use Data::Dumper; print Dumper(\%rules);
# Replace BISONPRE_VERSION(ver,,...) with expanded list
{
my @linesin = @lines; @lines=(); my $l=0;
foreach my $line (@linesin) {
$l++;
if ($line =~ /BISONPRE_VERSION/) {
($line =~ /BISONPRE_VERSION\((\S+)\s*,\s*([^\),]+)\)\s*$/)
or die "%Error: $filename:$l: Bad form of BISONPRE_VERSION: $line\n";
my $ver=$1; my $cmd=$2;
if ($Self->{bison_version} >= $1) {
$line = $cmd."\n";
} else {
$line = "//NOP: $line";
}
}
push @lines, $line;
}
}
# Replace BISONPRE_NOT(type,...) with expanded list
{
my @linesin = @lines; @lines=(); my $l=0;
@@ -308,20 +353,7 @@ sub clean_input {
foreach my $line (@linesin) {
$l++;
if ($line =~ /BISONPRE_COPY/) {
($line =~ s/BISONPRE_COPY\((\S+)\s*,\s*{([^}]*)}\s*\)/{HERE}/)
or die "%Error: $filename:$l: Bad form of BISONPRE_NOT: $line\n";
my $rule = $1; my $code = $2;
$rules{$rule} or die "%Error: $filename:$l: Can't find definition for rule: $rule\n";
# Push it all onto one line to avoid error messages changing
my $insert = $rules{$rule}{rules_and_productions};
$insert =~ s/^\S+://g; # Strip rule name
#print "COPY code $code\n";
#print "COPY in $insert\n";
$_=$insert; eval("$code; \$_;"); $insert = $_;
#print "COPY out $insert\n";
while ($insert =~ s/[ \t\n]+\n/\n/go) {}
while ($insert =~ s/\n/ /go) {} # Optional - preserve line numbering
$line =~ s/{HERE}/$insert/;
$line = _bisonpre_copy($line,$l,0);
}
push @lines, $line;
}
@@ -346,6 +378,7 @@ sub clean_input {
if ($line =~ m!//BISONPRE_TYPES!) {
push @lines, $line;
foreach my $type (sort keys %types) {
next if !$type;
my $line = "%type<$type>\t";
foreach my $rule (sort keys %{$types{$type}}) {
$line.=" ".$rule;
@@ -372,6 +405,37 @@ sub clean_input {
$fh->close;
}
sub _bisonpre_copy {
my $text = shift;
my $l = shift;
my $depth = shift;
while ($text =~ /BISONPRE_COPY/) {
($text =~ s/BISONPRE_COPY(_ONCE)?\((\S+)\s*,\s*{([^}]*)}\s*\)/{HERE}/)
or die "%Error: $Self->{filename}:$l: Bad form of BISONPRE_NOT: $text\n";
my $once = $1; my $rule = $2; my $code = $3;
$Self->{rules}{$rule} or die "%Error: $Self->{filename}:$l: Can't find definition for rule: $rule\n";
if ($depth > 0 && $once) {
# _ONCE means don't inherit
$text =~ s/\|[ \t]+{HERE}//; # Don't OR in nothing
$text =~ s/{HERE}//;
} else {
# Push it all onto one line to avoid error messages changing
my $insert = $Self->{rules}{$rule}{rules_and_productions};
$insert =~ s/^\S+://g; # Strip rule name
# Recurse so BISONPRE under B
#print "COPY $l code $code\n";
#print "COPY $l in $insert\n";
$_=$insert; eval("$code; \$_;"); $insert = $_;
#print "COPY $l out $insert\n";
while ($insert =~ s/[ \t\n]+\n/\n/go) {}
while ($insert =~ s/\n/ /go) {} # Optional - preserve line numbering
$text =~ s/{HERE}/$insert/;
}
$depth++;
}
return $text;
}
#######################################################################
__END__
@@ -416,10 +480,19 @@ rule. The type will be inserted where /*BISONPRE_TYPES*/ is encountered.
Copy the rules and productions from the specified rule, filter through the
Perl code provided in the {} and insert here into the output file.
=item BISONPRE_COPY_ONCE(rule, {code})
As with BISONPRE_COPY, but if called from underneath another BISONPRE_COPY
rule, ignore it.
=item BISONPRE_NOT(token[, token...])
Create a rule that matches every token except for those specified.
=item BISONPRE_VERSION(ver, cmd)
If the bison version is >= the specified version, include the given command.
=back
=head1 ARGUMENTS
+1 -1
View File
@@ -25,7 +25,7 @@
//**********************************************************************
//**** Version and host name
#define DTVERSION "Verilator 3.813 2011/06/28"
#define DTVERSION "Verilator 3.820 2011/07/28"
//**********************************************************************
//**** Functions
+32 -8
View File
@@ -174,6 +174,7 @@ word [a-zA-Z0-9_]+
/* Extensions to Verilog set, some specified by PSL */
"$c"[0-9]* { FL; return yD_C; } /*Verilator only*/
/* System Tasks */
"$bitstoreal" { FL; return yD_BITSTOREAL; }
"$display" { FL; return yD_DISPLAY; }
"$fclose" { FL; return yD_FCLOSE; }
"$fdisplay" { FL; return yD_FDISPLAY; }
@@ -187,15 +188,18 @@ word [a-zA-Z0-9_]+
"$fullskew" { FL; return yaTIMINGSPEC; }
"$fwrite" { FL; return yD_FWRITE; }
"$hold" { FL; return yaTIMINGSPEC; }
"$itor" { FL; return yD_ITOR; }
"$nochange" { FL; return yaTIMINGSPEC; }
"$period" { FL; return yaTIMINGSPEC; }
"$random" { FL; return yD_RANDOM; }
"$readmemb" { FL; return yD_READMEMB; }
"$readmemh" { FL; return yD_READMEMH; }
"$realtime" { FL; return yD_TIME; }
"$realtime" { FL; return yD_REALTIME; }
"$realtobits" { FL; return yD_REALTOBITS; }
"$recovery" { FL; return yaTIMINGSPEC; }
"$recrem" { FL; return yaTIMINGSPEC; }
"$removal" { FL; return yaTIMINGSPEC; }
"$rtoi" { FL; return yD_RTOI; }
"$setup" { FL; return yaTIMINGSPEC; }
"$setuphold" { FL; return yaTIMINGSPEC; }
"$sformat" { FL; return yD_SFORMAT; }
@@ -261,6 +265,8 @@ word [a-zA-Z0-9_]+
"pulldown" { FL; return yPULLDOWN; }
"pullup" { FL; return yPULLUP; }
"rcmos" { FL; return yRCMOS; }
"real" { FL; return yREAL; }
"realtime" { FL; return yREALTIME; }
"reg" { FL; return yREG; }
"repeat" { FL; return yREPEAT; }
"rnmos" { FL; return yRNMOS; }
@@ -310,8 +316,6 @@ word [a-zA-Z0-9_]+
"medium" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
"pull0" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
"pull1" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
"real" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
"realtime" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
"release" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
"small" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
"strong0" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
@@ -478,12 +482,12 @@ word [a-zA-Z0-9_]+
<S05,S09>{
/* Keywords */
"assert" { FL; return yASSERT; }
"const" { FL; return yCONST__LEX; }
"cover" { FL; return yCOVER; }
"property" { FL; return yPROPERTY; }
/* Generic unsupported warnings */
"assume" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); }
"before" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); }
"const" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); }
"sequence" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); }
"union" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); }
"within" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); }
@@ -812,11 +816,11 @@ word [a-zA-Z0-9_]+
return yaINTNUM;
}
[0-9][_0-9]*(\.[_0-9]+)([eE][-+]?[_0-9]+)? {
FL; yylval.cdouble = 0; /* Only for delays, not used yet */
FL; yylval.cdouble = PARSEP->parseDouble(yytext, yyleng);
return yaFLOATNUM;
}
[0-9][_0-9]*(\.[_0-9]+)?([eE][-+]?[_0-9]+) {
FL; yylval.cdouble = 0; /* Only for delays, not used yet */
FL; yylval.cdouble = PARSEP->parseDouble(yytext, yyleng);
return yaFLOATNUM;
}
[0-9][_0-9]*(\.[_0-9]+)?(fs|ps|ns|us|ms|s|step) {
@@ -949,6 +953,21 @@ word [a-zA-Z0-9_]+
%%
int V3ParseImp::stateVerilogRecent() { return STATE_VERILOG_RECENT; }
double V3ParseImp::parseDouble(const char* textp, size_t length) {
char* strgp = new char[length+1];
char* dp=strgp;
for (const char* sp=textp; sp<(textp+length);) {
if (*sp != '_') *dp++ = *sp++;
else sp++;
}
*dp++ = '\0';
char* endp = strgp;
double d = strtod(strgp, &endp);
if ((endp-strgp) != length) { yyerrorf("Syntax error parsing real: %s",strgp); }
delete strgp;
return d;
}
int V3ParseImp::lexToken() {
// called from lexToBison, has a "this"
// Fetch next token from prefetch or real lexer
@@ -964,7 +983,8 @@ int V3ParseImp::lexToken() {
//yylval // Set by yylexThis()
}
// If a paren, read another
if (token == yGLOBAL__LEX
if (token == yCONST__LEX
|| token == yGLOBAL__LEX
// Never put yID_* here; below symbol table resolution would break
) {
if (debugFlex()) { cout<<" lexToken: reading ahead to find possible strength"<<endl; }
@@ -975,7 +995,11 @@ int V3ParseImp::lexToken() {
m_aheadVal = yylval;
yylval = curValue;
// Now potentially munge the current token
if (token == yGLOBAL__LEX) {
if (token == yCONST__LEX) {
//UNSUP if (nexttok == yREF) token = yCONST__REF;
token = yCONST__ETC;
}
else if (token == yGLOBAL__LEX) {
if (nexttok == yCLOCKING) token = yGLOBAL__CLOCKING;
else { token = yaID__LEX; yylval.strp = PARSEP->newString("global"); } // Avoid 2009 "global" conflicting with old code when we can
}
+36 -18
View File
@@ -274,6 +274,8 @@ class AstSenTree;
%token<fl> yCASEZ "casez"
%token<fl> yCHANDLE "chandle"
%token<fl> yCLOCKING "clocking"
%token<fl> yCONST__ETC "const"
%token<fl> yCONST__LEX "const-in-lex"
%token<fl> yCMOS "cmos"
%token<fl> yCONTEXT "context"
%token<fl> yCONTINUE "continue"
@@ -340,6 +342,8 @@ class AstSenTree;
%token<fl> yPULLUP "pullup"
%token<fl> yPURE "pure"
%token<fl> yRCMOS "rcmos"
%token<fl> yREAL "real"
%token<fl> yREALTIME "realtime"
%token<fl> yREG "reg"
%token<fl> yREPEAT "repeat"
%token<fl> yRETURN "return"
@@ -380,6 +384,7 @@ class AstSenTree;
%token<fl> yXOR "xor"
%token<fl> yD_BITS "$bits"
%token<fl> yD_BITSTOREAL "$bitstoreal"
%token<fl> yD_C "$c"
%token<fl> yD_CLOG2 "$clog2"
%token<fl> yD_COUNTONES "$countones"
@@ -398,11 +403,15 @@ class AstSenTree;
%token<fl> yD_FWRITE "$fwrite"
%token<fl> yD_INFO "$info"
%token<fl> yD_ISUNKNOWN "$isunknown"
%token<fl> yD_ITOR "$itor"
%token<fl> yD_ONEHOT "$onehot"
%token<fl> yD_ONEHOT0 "$onehot0"
%token<fl> yD_RANDOM "$random"
%token<fl> yD_READMEMB "$readmemb"
%token<fl> yD_READMEMH "$readmemh"
%token<fl> yD_REALTIME "$realtime"
%token<fl> yD_REALTOBITS "$realtobits"
%token<fl> yD_RTOI "$rtoi"
%token<fl> yD_SFORMAT "$sformat"
%token<fl> yD_SIGNED "$signed"
%token<fl> yD_SSCANF "$sscanf"
@@ -1065,6 +1074,12 @@ integer_vector_type<bdtypep>: // ==IEEE: integer_atom_type
| yREG { $$ = new AstBasicDType($1,AstBasicDTypeKwd::LOGIC); } // logic==reg
;
non_integer_type<bdtypep>: // ==IEEE: non_integer_type
yREAL { $$ = new AstBasicDType($1,AstBasicDTypeKwd::DOUBLE); }
| yREALTIME { $$ = new AstBasicDType($1,AstBasicDTypeKwd::DOUBLE); }
//UNSUP ySHORTREAL { $$ = new AstBasicDType($1,AstBasicDTypeKwd::FLOAT); }
;
signingE<signstate>: // IEEE: signing - plus empty
/*empty*/ { $$ = signedst_NOP; }
| signing { $$ = $1; }
@@ -1095,7 +1110,7 @@ simple_type<dtypep>: // ==IEEE: simple_type
// // IEEE: integer_type
integer_atom_type { $$ = $1; }
| integer_vector_type { $$ = $1; }
//UNSUP non_integer_type { $$ = $1; }
| non_integer_type { $$ = $1; }
// // IEEE: ps_type_identifier
// // IEEE: ps_parameter_identifier (presumably a PARAMETER TYPE)
| ps_type { $$ = $1; }
@@ -1118,7 +1133,7 @@ data_type<dtypep>: // ==IEEE: data_type
data_typeBasic<dtypep>: // IEEE: part of data_type
integer_vector_type signingE rangeListE { $1->setSignedState($2); $$ = GRAMMARP->addRange($1,$3,true); }
| integer_atom_type signingE { $1->setSignedState($2); $$ = $1; }
//UNSUP non_integer_type { UNSUP }
| non_integer_type { $$ = $1; }
;
data_typeNoRef<dtypep>: // ==IEEE: data_type, excluding class_type etc references
@@ -1269,23 +1284,24 @@ data_declarationVar<nodep>: // IEEE: part of data_declaration
;
data_declarationVarFront: // IEEE: part of data_declaration
// // Expanded: "constE yVAR lifetimeE data_type"
// // implicit_type expanded into /*empty*/ or "signingE rangeList"
constE yVAR lifetimeE data_type { /*VARRESET-in-ddVar*/ VARDTYPE($4); }
| constE yVAR lifetimeE { /*VARRESET-in-ddVar*/ VARDTYPE(new AstBasicDType($<fl>2, LOGIC_IMPLICIT)); }
| constE yVAR lifetimeE signingE rangeList { /*VARRESET-in-ddVar*/ VARDTYPE(GRAMMARP->addRange(new AstBasicDType($<fl>2, LOGIC_IMPLICIT, $4),$5,false)); }
/**/ yVAR lifetimeE data_type { /*VARRESET-in-ddVar*/ VARDTYPE($3); }
| /**/ yVAR lifetimeE { /*VARRESET-in-ddVar*/ VARDTYPE(new AstBasicDType($<fl>1, LOGIC_IMPLICIT)); }
| /**/ yVAR lifetimeE signingE rangeList { /*VARRESET-in-ddVar*/ VARDTYPE(GRAMMARP->addRange(new AstBasicDType($<fl>1, LOGIC_IMPLICIT, $3), $4,false)); }
//
// // implicit_type expanded into /*empty*/ or "signingE rangeList"
| yCONST__ETC yVAR lifetimeE data_type { /*VARRESET-in-ddVar*/ VARDTYPE(new AstConstDType($<fl>1, $4)); }
| yCONST__ETC yVAR lifetimeE { /*VARRESET-in-ddVar*/ VARDTYPE(new AstConstDType($<fl>1, new AstBasicDType($<fl>2, LOGIC_IMPLICIT))); }
| yCONST__ETC yVAR lifetimeE signingE rangeList { /*VARRESET-in-ddVar*/ VARDTYPE(new AstConstDType($<fl>1, GRAMMARP->addRange(new AstBasicDType($<fl>2, LOGIC_IMPLICIT, $4), $5,false))); }
//
// // Expanded: "constE lifetimeE data_type"
| /**/ data_type { /*VARRESET-in-ddVar*/ VARDTYPE($1); }
| /**/ lifetime data_type { /*VARRESET-in-ddVar*/ VARDTYPE($2); }
//UNSUP yCONST__ETC lifetimeE data_type { /*VARRESET-in-ddVar*/ VARDTYPE($3); }
| yCONST__ETC lifetimeE data_type { /*VARRESET-in-ddVar*/ VARDTYPE(new AstConstDType($<fl>1, $3)); }
// // = class_new is in variable_decl_assignment
;
constE: // IEEE: part of data_declaration
/* empty */ { }
//UNSUP yCONST__ETC { UNSUP }
;
implicit_typeE<dtypep>: // IEEE: part of *data_type_or_implicit
// // Also expanded in data_declaration
/* empty */ { $$ = NULL; }
@@ -1524,8 +1540,7 @@ delay_value: // ==IEEE:delay_value
delayExpr:
expr { }
// // Verilator doesn't support yaFLOATNUM/yaTIMENUM, so not in expr
| yaFLOATNUM { }
// // Verilator doesn't support yaTIMENUM, so not in expr
| yaTIMENUM { }
;
@@ -1710,8 +1725,6 @@ cellpinItemE<pinp>: // IEEE: named_port_connection + named_parameter_assignment
| expr { $$ = new AstPin($1->fileline(),PINNUMINC(),"",$1); }
//UNSUP expr ':' expr { }
//UNSUP expr ':' expr ':' expr { }
// // Floatnum should only occur with UDPs, but since ports aren't floats, it's legal to round always
| yaFLOATNUM { $$ = new AstPin($<fl>1,PINNUMINC(),"",new AstConst($<fl>1,AstConst::Unsized32(),(int)(($1<0)?($1-0.5):($1+0.5)))); }
;
//************************************************
@@ -1886,7 +1899,7 @@ statement_item<nodep>: // IEEE: statement_item
| statementVerilatorPragmas { $$ = $1; }
//
// // IEEE: disable_statement
//UNSUP yDISABLE idAny/*hierarchical_identifier-task_or_block*/ ';' { UNSUP }
| yDISABLE idAny/*hierarchical_identifier-task_or_block*/ ';' { $$ = new AstDisable($1,*$2); }
//UNSUP yDISABLE yFORK ';' { UNSUP }
// // IEEE: event_trigger
//UNSUP yP_MINUSGT hierarchical_identifier/*event*/ ';' { UNSUP }
@@ -2141,6 +2154,7 @@ system_f_call<nodep>: // IEEE: system_tf_call (as func)
//
| yD_BITS '(' expr ')' { $$ = new AstAttrOf($1,AstAttrType::EXPR_BITS,$3); }
| yD_BITS '(' data_type ')' { $$ = new AstAttrOf($1,AstAttrType::EXPR_BITS,$3); }
| yD_BITSTOREAL '(' expr ')' { $$ = new AstBitsToRealD($1,$3); }
| yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCFunc($1,$3)); }
| yD_CLOG2 '(' expr ')' { $$ = new AstCLog2($1,$3); }
| yD_COUNTONES '(' expr ')' { $$ = new AstCountOnes($1,$3); }
@@ -2150,10 +2164,14 @@ system_f_call<nodep>: // IEEE: system_tf_call (as func)
| yD_FSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstFScanF($1,*$5,$3,$6); }
| yD_SSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstSScanF($1,*$5,$3,$6); }
| yD_ISUNKNOWN '(' expr ')' { $$ = new AstIsUnknown($1,$3); }
| yD_ITOR '(' expr ')' { $$ = new AstIToRD($1,$3); }
| yD_ONEHOT '(' expr ')' { $$ = new AstOneHot($1,$3); }
| yD_ONEHOT0 '(' expr ')' { $$ = new AstOneHot0($1,$3); }
| yD_RANDOM '(' expr ')' { $1->v3error("Unsupported: Seeding $random doesn't map to C++, use $c(\"srand\")"); }
| yD_RANDOM parenE { $$ = new AstRand($1); }
| yD_REALTIME parenE { $$ = new AstTimeD($1); }
| yD_REALTOBITS '(' expr ')' { $$ = new AstRealToBits($1,$3); }
| yD_RTOI '(' expr ')' { $$ = new AstRToIS($1,$3); }
//| yD_SFORMATF '(' str commaEListE ')' { $$ = new AstSFormatF($1,*$3,false,$4); } // Have AST, just need testing and debug
| yD_SIGNED '(' expr ')' { $$ = new AstSigned($1,$3); }
| yD_STIME parenE { $$ = new AstSel($1,new AstTime($1),0,32); }
@@ -2374,7 +2392,7 @@ expr<nodep>: // IEEE: part of expression/constant_expression/primary
//
// // IEEE: unary_operator primary
'+' ~r~expr %prec prUNARYARITH { $$ = $2; }
| '-' ~r~expr %prec prUNARYARITH { $$ = new AstUnaryMin ($1,$2); }
| '-' ~r~expr %prec prUNARYARITH { $$ = new AstNegate ($1,$2); }
| '!' ~r~expr %prec prNEGATION { $$ = new AstLogNot ($1,$2); }
| '&' ~r~expr %prec prREDUCTION { $$ = new AstRedAnd ($1,$2); }
| '~' ~r~expr %prec prNEGATION { $$ = new AstNot ($1,$2); }
@@ -2452,7 +2470,7 @@ expr<nodep>: // IEEE: part of expression/constant_expression/primary
//
// // IEEE: primary_literal (minus string, which is handled specially)
| yaINTNUM { $$ = new AstConst($<fl>1,*$1); }
//UNSUP yaFLOATNUM { UNSUP }
| yaFLOATNUM { $$ = new AstConst($<fl>1,AstConst::RealDouble(),$1); }
//UNSUP yaTIMENUM { UNSUP }
| strAsInt~noStr__IGNORE~ { $$ = $1; }
//
+13 -6
View File
@@ -165,7 +165,7 @@ sub one_test {
if ($opt_stop) { die "%Error: --stop and errors found\n"; }
}
$leftcnt--;
print "==SUMMARY: Left $leftcnt Passed $okcnt Skipped $skcnt Failed $failcnt\n";
print STDERR "==SUMMARY: Left $leftcnt Passed $okcnt Skipped $skcnt Failed $failcnt\n";
},
)->ready();
}
@@ -336,6 +336,7 @@ sub new {
$self->{run_log_filename} ||= "$self->{obj_dir}/vlt_sim.log";
$self->{coverage_filename} ||= "$self->{obj_dir}/vlt_coverage.pl";
$self->{vcd_filename} ||= "$self->{obj_dir}/sim.vcd";
$self->{main_filename} ||= "$self->{obj_dir}/$self->{VM_PREFIX}__main.cpp";
($self->{top_filename} = $self->{pl_filename}) =~ s/\.pl$/\.v/;
if (!$self->{make_top_shell}) {
$self->{top_shell_filename} = $self->{top_filename};
@@ -536,6 +537,11 @@ sub compile {
return 1;
}
if (!$param{fails} && $param{verilator_make_gcc}
&& $param{make_main}) {
$self->_make_main();
}
$self->_run(logfile=>"$self->{obj_dir}/vlt_compile.log",
fails=>$param{fails},
expect=>$param{expect},
@@ -543,9 +549,6 @@ sub compile {
return 1 if $self->errors || $self->skips;
if (!$param{fails} && $param{verilator_make_gcc}) {
if ($param{make_main}) {
$self->_make_main();
}
if ($self->sp) {
$self->_sp_preproc(%param);
}
@@ -806,7 +809,7 @@ sub _make_main {
$self->_read_inputs();
my $filename = "$self->{obj_dir}/$self->{VM_PREFIX}__main.cpp";
my $filename = $self->{main_filename};
my $fh = IO::File->new(">$filename") or die "%Error: $! $filename,";
print $fh "// Test defines\n";
@@ -894,8 +897,12 @@ sub _make_main {
print $fh ' vl_fatal(__FILE__,__LINE__,"main", "%Error: Timeout; never got a $finish");',"\n";
print $fh " }\n";
print $fh " topp->final();\n";
print $fh " SpCoverage::write(\"",$self->{coverage_filename},"\");\n" if $self->{coverage};
if ($self->{coverage}) {
$fh->print("#if VM_COVERAGE\n");
$fh->print(" SpCoverage::write(\"",$self->{coverage_filename},"\");\n");
$fh->print("#endif //VM_COVERAGE\n");
}
if ($self->{trace}) {
$fh->print("#if VM_TRACE\n");
$fh->print(" if (tfp) tfp->close();\n");
+1 -1
View File
@@ -47,7 +47,7 @@ module t (/*AUTOARG*/
endcase
end
`ifdef NOT_YET_verilator
`ifdef NOT_YET_VERILATOR // Unsupported
// ambit synthesis one_hot "a, b_oh"
// cadence one_cold "a_l, b_oc_l"
`endif
+1 -1
View File
@@ -25,7 +25,7 @@ module t_case_huge_sub2 (/*AUTOARG*/
always @(/*AS*/index) begin
case (index[7:0])
`ifdef verilator
`ifdef VERILATOR // Harder test
8'h00: begin outa = $c("0"); end // Makes whole table non-optimizable
`else
8'h00: begin outa = 10'h0; end
-4
View File
@@ -2497,11 +2497,7 @@ module t_case_write1_tasks ();
endtask
task big_case;
`ifdef verilator
input [ 63:0] fd;
`else
input [ 31:0] fd;
`endif
input [ 31:0] foo;
reg [STRLEN*8: 1] foobar;
// verilator no_inline_task
-4
View File
@@ -10,11 +10,7 @@ module t_case_write2_tasks ();
// verilator lint_off WIDTH
// verilator lint_off CASEINCOMPLETE
`ifdef verilator
`define FD_BITS 63:0
`else
`define FD_BITS 31:0
`endif
parameter STRLEN = 78;
task ozonerab;
+1 -1
View File
@@ -86,7 +86,7 @@ module Test (/*AUTOARG*/
end
reg displayit;
`ifdef verilator
`ifdef VERILATOR // Harder test
initial displayit = $c1("0"); // Something that won't optimize away
`else
initial displayit = '0;
+2
View File
@@ -59,7 +59,9 @@ module t (/*AUTOARG*/
reg [7:0] cyc; initial cyc=0;
always @ (posedge clk) begin
`ifdef TEST_VERBOSE
$write("[%0t] rs %x cyc %d cg1f %x cnt %x cg %x\n",$time,reset_l,cyc,clkgate_e1f,count,countgated);
`endif
cyc <= cyc + 8'd1;
case (cyc)
8'd00: begin
+24
View File
@@ -0,0 +1,24 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
top_filename("t/t_cover_line.v");
compile (
verilator_flags2 => ['--cc --coverage-line'],
);
execute (
check_finished=>1,
);
# Read the input .v file and do any CHECK_COVER requests
inline_checks();
ok(1);
1;
+24
View File
@@ -0,0 +1,24 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
top_filename("t/t_cover_line.v");
compile (
verilator_flags2 => ['--sc --coverage-line'],
);
execute (
check_finished=>1,
);
# Read the input .v file and do any CHECK_COVER requests
inline_checks();
ok(1);
1;
@@ -7,6 +7,8 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
top_filename("t/t_cover_line.v");
compile (
verilator_flags2 => ['--sp --coverage-line'],
);
+4 -2
View File
@@ -19,10 +19,12 @@ execute (
[0] In top.v.sub2
[0] In top.v.sub2.subblock2
[0] Back \ Quote "
[0] %X=0c %D=12 %0X=c %0O=14 %B=001100
[0] %x=0c %d=12 %0x=c %0o=14 %b=001100
[0] %X=00c %0X=c %0O=14 %B=000001100
[0] %x=00c %0x=c %0o=14 %b=000001100
[0] %D= 12 %d= 12 %01d=12 %06d=000012 %6d= 12
[0] %x=00abbbbcccc %0x=abbbbcccc %o=00527356746314 %b=00000101010111011101110111100110011001100
[0] %x=00abc1234567812345678 %0x=abc1234567812345678 %o=012570110642547402215053170 %b=000001010101111000001001000110100010101100111100000010010001101000101011001111000
[0] %t= 0 %03t= 0 %0t=0
[0] %s=! %s= what! %s= hmmm!1234
[0] hello, from a very long string. Percent %s are literally substituted in.
+10 -4
View File
@@ -9,6 +9,7 @@ module t;
reg [31:0] str; initial str = "\000\277\021\n";
reg [47:0] str2; initial str2 = "\000what!";
reg [79:0] str3; initial str3 = "\000hmmm!1234";
reg [8:0] nine;
sub sub ();
sub2 sub2 ();
@@ -22,14 +23,19 @@ module t;
$display("[%0t] Back \\ Quote \"", $time); // Old bug when \" last on the line.
// Display formatting
$display("[%0t] %%X=%X %%D=%D %%0X=%0X %%0O=%0O %%B=%B", $time,
quad[5:0], quad[5:0], quad[5:0], quad[5:0], quad[5:0]);
$display("[%0t] %%x=%x %%d=%d %%0x=%0x %%0o=%0o %%b=%b", $time,
quad[5:0], quad[5:0], quad[5:0], quad[5:0], quad[5:0]);
nine = {3'd0,quad[5:0]};
$display("[%0t] %%X=%X %%0X=%0X %%0O=%0O %%B=%B", $time,
nine, nine, nine, nine);
$display("[%0t] %%x=%x %%0x=%0x %%0o=%0o %%b=%b", $time,
nine, nine, nine, nine);
$display("[%0t] %%D=%D %%d=%d %%01d=%01d %%06d=%06d %%6d=%6d", $time,
nine, nine, nine, nine, nine);
$display("[%0t] %%x=%x %%0x=%0x %%o=%o %%b=%b", $time,
quad, quad, quad, quad);
$display("[%0t] %%x=%x %%0x=%0x %%o=%o %%b=%b", $time,
wide, wide, wide, wide);
$display("[%0t] %%t=%t %%03t=%03t %%0t=%0t", $time,
$time, $time, $time);
$display;
// Not testing %0s, it does different things in different simulators
$display("[%0t] %%s=%s %%s=%s %%s=%s", $time,
+4 -2
View File
@@ -22,10 +22,12 @@ execute (
[0] In top.v.sub2
[0] In top.v.sub2.subblock2
[0] Back \ Quote "
[0] %X=0c %D=12 %0X=c %0O=14 %B=001100
[0] %x=0c %d=12 %0x=c %0o=14 %b=001100
[0] %X=00c %0X=c %0O=14 %B=000001100
[0] %x=00c %0x=c %0o=14 %b=000001100
[0] %D= 12 %d= 12 %01d=12 %06d=000012 %6d= 12
[0] %x=00abbbbcccc %0x=abbbbcccc %o=00527356746314 %b=00000101010111011101110111100110011001100
[0] %x=00abc1234567812345678 %0x=abc1234567812345678 %o=012570110642547402215053170 %b=000001010101111000001001000110100010101100111100000010010001101000101011001111000
[0] %t= 0 %03t= 0 %0t=0
[0] %s=! %s= what! %s= hmmm!1234
[0] hello, from a very long string. Percent %s are literally substituted in.
+39
View File
@@ -0,0 +1,39 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# 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
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
compile (
);
execute (
check_finished=>1,
expect=> quotemeta(
'[0] e=0.000000e+00 e1=0.000000e+00 e30=0e+00 e32=0.00e+00
[0] f=0.000000 f1=0.000000e+00 f30=0e+00 f32=0.00e+00
[0] g=0 g1=0.000000e+00 g30=0e+00 g32=0.00e+00
[0] e=1.000000e+00 e1=1.000000e+00 e30=1e+00 e32=1.00e+00
[0] f=1.000000 f1=1.000000e+00 f30=1e+00 f32=1.00e+00
[0] g=1 g1=1.000000e+00 g30=1e+00 g32=1.00e+00
[0] e=1.000000e-01 e1=1.000000e-01 e30=1e-01 e32=1.00e-01
[0] f=0.100000 f1=1.000000e-01 f30=1e-01 f32=1.00e-01
[0] g=0.1 g1=1.000000e-01 g30=1e-01 g32=1.00e-01
[0] e=1.234500e-15 e1=1.234500e-15 e30=1e-15 e32=1.23e-15
[0] f=0.000000 f1=1.234500e-15 f30=1e-15 f32=1.23e-15
[0] g=1.2345e-15 g1=1.234500e-15 g30=1e-15 g32=1.23e-15
[0] e=2.579000e+15 e1=2.579000e+15 e30=3e+15 e32=2.58e+15
[0] f=2579000000000000.000000 f1=2.579000e+15 f30=3e+15 f32=2.58e+15
[0] g=2.579e+15 g1=2.579000e+15 g30=3e+15 g32=2.58e+15
'),
);
ok(1);
1;
+37
View File
@@ -0,0 +1,37 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2003 by Wilson Snyder.
module t;
real n0; initial n0 = 0.0;
real n1; initial n1 = 1.0;
real n2; initial n2 = 0.1;
real n3; initial n3 = 1.2345e-15;
real n4; initial n4 = 2.579e+15;
initial begin
// Display formatting
$display("[%0t] e=%e e1=%1e e30=%3.0e e32=%3.2e", $time, n0,n0,n0,n0);
$display("[%0t] f=%f f1=%1e f30=%3.0e f32=%3.2e", $time, n0,n0,n0,n0);
$display("[%0t] g=%g g1=%1e g30=%3.0e g32=%3.2e", $time, n0,n0,n0,n0);
$display;
$display("[%0t] e=%e e1=%1e e30=%3.0e e32=%3.2e", $time, n1,n1,n1,n1);
$display("[%0t] f=%f f1=%1e f30=%3.0e f32=%3.2e", $time, n1,n1,n1,n1);
$display("[%0t] g=%g g1=%1e g30=%3.0e g32=%3.2e", $time, n1,n1,n1,n1);
$display;
$display("[%0t] e=%e e1=%1e e30=%3.0e e32=%3.2e", $time, n2,n2,n2,n2);
$display("[%0t] f=%f f1=%1e f30=%3.0e f32=%3.2e", $time, n2,n2,n2,n2);
$display("[%0t] g=%g g1=%1e g30=%3.0e g32=%3.2e", $time, n2,n2,n2,n2);
$display;
$display("[%0t] e=%e e1=%1e e30=%3.0e e32=%3.2e", $time, n3,n3,n3,n3);
$display("[%0t] f=%f f1=%1e f30=%3.0e f32=%3.2e", $time, n3,n3,n3,n3);
$display("[%0t] g=%g g1=%1e g30=%3.0e g32=%3.2e", $time, n3,n3,n3,n3);
$display;
$display("[%0t] e=%e e1=%1e e30=%3.0e e32=%3.2e", $time, n4,n4,n4,n4);
$display("[%0t] f=%f f1=%1e f30=%3.0e f32=%3.2e", $time, n4,n4,n4,n4);
$display("[%0t] g=%g g1=%1e g30=%3.0e g32=%3.2e", $time, n4,n4,n4,n4);
$write("*-* All Finished *-*\n");
$finish;
end
endmodule
+42
View File
@@ -0,0 +1,42 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# 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
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
top_filename("t/t_display_real.v");
compile (
v_flags2 => [$Self->{v3}?"-O0":""],
);
execute (
check_finished=>1,
expect=> quotemeta(
'[0] e=0.000000e+00 e1=0.000000e+00 e30=0e+00 e32=0.00e+00
[0] f=0.000000 f1=0.000000e+00 f30=0e+00 f32=0.00e+00
[0] g=0 g1=0.000000e+00 g30=0e+00 g32=0.00e+00
[0] e=1.000000e+00 e1=1.000000e+00 e30=1e+00 e32=1.00e+00
[0] f=1.000000 f1=1.000000e+00 f30=1e+00 f32=1.00e+00
[0] g=1 g1=1.000000e+00 g30=1e+00 g32=1.00e+00
[0] e=1.000000e-01 e1=1.000000e-01 e30=1e-01 e32=1.00e-01
[0] f=0.100000 f1=1.000000e-01 f30=1e-01 f32=1.00e-01
[0] g=0.1 g1=1.000000e-01 g30=1e-01 g32=1.00e-01
[0] e=1.234500e-15 e1=1.234500e-15 e30=1e-15 e32=1.23e-15
[0] f=0.000000 f1=1.234500e-15 f30=1e-15 f32=1.23e-15
[0] g=1.2345e-15 g1=1.234500e-15 g30=1e-15 g32=1.23e-15
[0] e=2.579000e+15 e1=2.579000e+15 e30=3e+15 e32=2.58e+15
[0] f=2579000000000000.000000 f1=2.579000e+15 f30=3e+15 f32=2.58e+15
[0] g=2.579e+15 g1=2.579000e+15 g30=3e+15 g32=2.58e+15
'),
);
ok(1);
1;
+5 -11
View File
@@ -11,7 +11,7 @@
`ifdef NC
`define NO_SHORTREAL
`endif
`ifdef VERILATOR
`ifdef VERILATOR // Unsupported
`define NO_SHORTREAL
`endif
@@ -39,9 +39,7 @@ module t ();
import "DPI-C" pure function longint dpii_f_longint (input longint i);
import "DPI-C" pure function chandle dpii_f_chandle (input chandle i);
import "DPI-C" pure function string dpii_f_string (input string i);
`ifndef VERILATOR
import "DPI-C" pure function real dpii_f_real (input real i);
`endif
`ifndef NO_SHORTREAL
import "DPI-C" pure function shortreal dpii_f_shortreal(input shortreal i);
`endif
@@ -53,9 +51,7 @@ module t ();
import "DPI-C" pure function void dpii_v_longint (input longint i, output longint o);
import "DPI-C" pure function void dpii_v_chandle (input chandle i, output chandle o);
import "DPI-C" pure function void dpii_v_string (input string i, output string o);
`ifndef VERILATOR
import "DPI-C" pure function void dpii_v_real (input real i, output real o);
`endif
`ifndef NO_SHORTREAL
import "DPI-C" pure function void dpii_v_shortreal(input shortreal i, output shortreal o);
`endif
@@ -93,9 +89,7 @@ module t ();
longint i_l, o_l;
chandle i_c, o_c;
string i_n, o_n;
`ifndef VERILATOR
real i_d, o_d;
`endif
`ifndef NO_SHORTREAL
shortreal i_f, o_f;
`endif
@@ -122,6 +116,10 @@ module t ();
i_y = {1'b1,wide[8-2:0]};
i_s = {1'b1,wide[16-2:0]};
i_l = {1'b1,wide[64-2:0]};
i_d = 32.1;
`ifndef NO_SHORTREAL
i_f = 30.2;
`endif
if (dpii_f_bit (i_b) !== ~i_b) $stop;
if (dpii_f_bit8 (i_b8) !== ~i_b8) $stop;
@@ -145,9 +143,7 @@ module t ();
if (dpii_f_longint (i_l) !== ~i_l) $stop;
if (dpii_f_chandle (i_c) !== i_c) $stop;
if (dpii_f_string (i_n) != i_n) $stop;
`ifndef VERILATOR
if (dpii_f_real (i_d) != i_d+1.5) $stop;
`endif
`ifndef NO_SHORTREAL
if (dpii_f_shortreal(i_f) != i_f+1.5) $stop;
`endif
@@ -159,9 +155,7 @@ module t ();
dpii_v_longint (i_l,o_l); if (o_l !== ~i_l) $stop;
dpii_v_chandle (i_c,o_c); if (o_c !== i_c) $stop;
dpii_v_string (i_n,o_n); if (o_n != i_n) $stop;
`ifndef VERILATOR
dpii_v_real (i_d,o_d); if (o_d != i_d+1.5) $stop;
`endif
`ifndef NO_SHORTREAL
dpii_v_shortreal(i_f,o_f); if (o_f != i_f+1.5) $stop;
`endif
+1 -1
View File
@@ -55,7 +55,7 @@ module t (/*AUTOARG*/
#error "`systemc_header didn't work"
#endif
bool m_did_ctor;
uint32_t my_function() {
vluint32_t my_function() {
if (!m_did_ctor) vl_fatal(__FILE__,__LINE__,__FILE__,"`systemc_ctor didn't work");
return 1;
}
+11 -2
View File
@@ -92,8 +92,17 @@ module t (/*AUTOARG*/
input [3:0] loop_continue;
integer i;
// Placeholder
return Test0(loop_stop,loop_break,loop_continue);
Test1 = 0;
begin : outer_block
for (i=1; i<20; i=i+1) begin : inner_block
Test1 = Test1 + 1;
// continue, IE jump to end-of-inner_block. Must be inside inner_block.
if (i[3:0] == loop_continue) disable inner_block;
// break, IE jump to end-of-outer_block. Must be inside outer_block.
if (i[3:0] == loop_break) disable outer_block;
Test1 = Test1 + i[15:0];
end : inner_block
end : outer_block
endfunction
function [15:0] Test2;
-2
View File
@@ -13,8 +13,6 @@ compile (
expect=>
q{%Error: t/t_func_bad.v:\d+: Too few arguments in function call to FUNC 'add'
%Error: t/t_func_bad.v:\d+: Too few arguments in function call to FUNC 'add'
%Error: t/t_func_bad.v:\d+: Too few arguments in function call to FUNC 'add'
%Error: t/t_func_bad.v:\d+: Too few arguments in function call to FUNC 'add'
%Error: t/t_func_bad.v:\d+: Too many arguments in function call to FUNC 'add'
%Error: t/t_func_bad.v:\d+: Too few arguments in function call to TASK 'x'
%Error: t/t_func_bad.v:\d+: Too few arguments in function call to TASK 'x'
+1 -1
View File
@@ -100,7 +100,7 @@ module tpub (
if (1'b1 != got_bool) $stop;
$c("publicGetLong(got_long);");
if (24'h11bca != got_long) $stop;
$c("{ uint64_t qq; publicGetQuad(qq); got_quad=qq; }");
$c("{ vluint64_t qq; publicGetQuad(qq); got_quad=qq; }");
if (60'haaaa_bbbb_cccc != got_quad) $stop;
$c("{ WData gw[3]; publicGetWide(gw); VL_ASSIGN_W(72,got_wide,gw); }");
if (72'hac_abca_aaaa_bbbb_1234 != got_wide) $stop;
+23
View File
@@ -0,0 +1,23 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
compile (
make_top_shell => 0,
make_main => 0,
v_flags2 => ["--lint-only -Wwarn-REALCVT"],
verilator_make_gcc => 0,
fails=>1,
expect=>
'%Warning-REALCVT: t/t_lint_realcvt_bad.v:\d+: Implicit conversion of real to integer
%Warning-REALCVT: Use .* to disable this message.
%Error: Exiting due to.*',
) if $Self->{v3};
ok(1);
1;
+11
View File
@@ -0,0 +1,11 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2011 by Wilson Snyder.
module sub;
integer i;
initial begin
i = 23.2;
end
endmodule
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# 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
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
compile (
);
execute (
check_finished=>1,
);
ok(1);
1;
+136
View File
@@ -0,0 +1,136 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// Copyright 2011 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
integer i;
reg [63:0] b;
real r, r2;
integer cyc=0;
realtime uninit;
initial if (uninit != 0.0) $stop;
initial begin
// rtoi truncates
if ($rtoi(36.7) != 36) $stop;
if ($rtoi(36.5) != 36) $stop;
if ($rtoi(36.4) != 36) $stop;
// casting rounds
if ((integer '(36.7)) != 37) $stop;
if ((integer '(36.5)) != 37) $stop;
if ((integer '(36.4)) != 36) $stop;
// assignment rounds
// verilator lint_off REALCVT
i = 36.7; if (i != 37) $stop;
i = 36.5; if (i != 37) $stop;
i = 36.4; if (i != 36) $stop;
r = 10'd38; if (r!=38.0) $stop;
// verilator lint_on REALCVT
// operators
if ((-(1.5)) != -1.5) $stop;
if ((+(1.5)) != 1.5) $stop;
if (((1.5)+(1.25)) != 2.75) $stop;
if (((1.5)-(1.25)) != 0.25) $stop;
if (((1.5)*(1.25)) != 1.875) $stop;
if (((1.5)/(1.25)) != 1.2) $stop;
//
if (((1.5)==(2)) != 1'b0) $stop; // note 2 becomes real 2.0
if (((1.5)!=(2)) != 1'b1) $stop;
if (((1.5)> (2)) != 1'b0) $stop;
if (((1.5)>=(2)) != 1'b0) $stop;
if (((1.5)< (2)) != 1'b1) $stop;
if (((1.5)<=(2)) != 1'b1) $stop;
if (((1.5)==(1.5)) != 1'b1) $stop;
if (((1.5)!=(1.5)) != 1'b0) $stop;
if (((1.5)> (1.5)) != 1'b0) $stop;
if (((1.5)>=(1.5)) != 1'b1) $stop;
if (((1.5)< (1.5)) != 1'b0) $stop;
if (((1.5)<=(1.5)) != 1'b1) $stop;
if (((1.6)==(1.5)) != 1'b0) $stop;
if (((1.6)!=(1.5)) != 1'b1) $stop;
if (((1.6)> (1.5)) != 1'b1) $stop;
if (((1.6)>=(1.5)) != 1'b1) $stop;
if (((1.6)< (1.5)) != 1'b0) $stop;
if (((1.6)<=(1.5)) != 1'b0) $stop;
//
if (((0.0)?(2.0):(1.1)) != 1.1) $stop;
if (((1.5)?(2.0):(1.1)) != 2.0) $stop;
//
if (!1.7) $stop;
if (!(!0.0)) $stop;
if (1.8 && 0.0) $stop;
if (!(1.8 || 0.0)) $stop;
//
i=0;
for (r=1.0; r<2.0; r=r+0.1) i++;
if (i!=10) $stop;
end
// 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;
if (cyc==0) begin
// Setup
end
else if (cyc<90) begin
if ($time != {32'h0, $rtoi($realtime)}) $stop;
if ($itor(cyc) != cyc) $stop;
//Unsup: if ((real `($time)) != $realtime) $stop;
r = $itor(cyc*2);
i = $rtoi(r);
if (i!=cyc*2) $stop;
//
r = $itor(cyc)/1.5;
b = $realtobits(r);
r2 = $bitstoreal(b);
if (r != r2) $stop;
//
// Trust the integer math as a comparison
r = $itor(cyc);
if ($rtoi(-r) != -cyc) $stop;
if ($rtoi(+r) != cyc) $stop;
if ($rtoi(r+2.0) != (cyc+2)) $stop;
if ($rtoi(r-2.0) != (cyc-2)) $stop;
if ($rtoi(r*2.0) != (cyc*2)) $stop;
if ($rtoi(r/2.0) != (cyc/2)) $stop;
r2 = (2.0/(r-60)); // When zero, result indeterminate, but no crash
//
r2 = $itor(cyc);
case (r)
(r2-1.0): $stop;
r2: ;
default: $stop;
endcase
//
r = $itor(cyc);
if ((r==50.0) != (cyc==50)) $stop;
if ((r!=50.0) != (cyc!=50)) $stop;
if ((r> 50.0) != (cyc> 50)) $stop;
if ((r>=50.0) != (cyc>=50)) $stop;
if ((r< 50.0) != (cyc< 50)) $stop;
if ((r<=50.0) != (cyc<=50)) $stop;
//
if ($rtoi((r-50.0) ? 10.0 : 20.0)
!= (((cyc-50)!=0) ? 10 : 20)) $stop;
//
if ((!(r-50.0)) != (!((cyc-50) != 0))) $stop;
end
else if (cyc==99) begin
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule
+2
View File
@@ -43,8 +43,10 @@ module t (/*AUTOARG*/
integer i;
initial begin
if ((-1 >>> 3) != -1) $stop; // Decimals are signed
// verilator lint_off WIDTH
if ((3'b111 >>> 3) != 0) $stop; // Based numbers are unsigned
if ((3'sb111 >>> 3) != -1) $stop; // Signed based numbers
// verilator lint_on WIDTH
if ( (3'sb000 > 3'sb000)) $stop;
if (!(3'sb000 > 3'sb111)) $stop;
if ( (3'sb111 > 3'sb000)) $stop;
+7 -4
View File
@@ -10,12 +10,15 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
unlink("$Self->{obj_dir}/t_sys_file_basic_test.log");
compile (
v_flags2 => ['+incdir+../include'],
);
v_flags2 => ['+incdir+../include',
# Build without cached objects, see bug363
"--exe ../$Self->{main_filename}"],
make_flags=>'MAKE_MAIN=0 VM_PARALLEL_BUILDS=0',
);
execute (
check_finished=>1,
);
check_finished=>1,
);
file_grep ("$Self->{obj_dir}/t_sys_file_basic_test.log",
qr/\[0\] hello v=12345667
+11
View File
@@ -16,6 +16,8 @@ module t;
reg [48*8:1] str;
reg [48*8:1] str2;
real r;
initial begin
n = 4'b1100;
q = 64'h1234_5678_abcd_0123;
@@ -29,6 +31,15 @@ module t;
`ifdef TEST_VERBOSE $display("str2=%0s",str2); `endif
if (str2 !== "n=1100 q= 2623536935500120647 w=hello-there12345") $stop;
$swrite(str2, "e=%e", r);
$swrite(str2, "e=%f", r);
$swrite(str2, "e=%g", r);
r = 0.01;
$swrite(str2, "e=%e f=%f g=%g", r, r, r);
`ifdef TEST_VERBOSE $display("str2=%0s",str2); `endif
if (str2 !== "e=1.000000e-02 f=0.010000 g=0.01") $stop;
$swrite(str2, "mod=%m");
`ifdef TEST_VERBOSE $display("str2=%0s",str2); `endif
`ifdef verilator
+2
View File
@@ -15,12 +15,14 @@ module t (/*AUTOARG*/
integer b_trace_off;
// verilator tracing_on
integer c_trace_on;
real r;
always @ (posedge clk) begin
if (cyc!=0) begin
cyc <= cyc + 1;
b_trace_off <= cyc;
c_trace_on <= b_trace_off;
r <= r + 0.1;
if (cyc==4) begin
if (c_trace_on != 2) $stop;
end
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# 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
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
compile (
);
execute (
check_finished=>1,
);
ok(1);
1;
+21
View File
@@ -0,0 +1,21 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2011 by Wilson Snyder.
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
const logic [2:0] five = 3'd5;
always @ (posedge clk) begin
if (five !== 3'd5) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule
+19
View File
@@ -0,0 +1,19 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2005 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
compile (
v_flags2 => ["--lint-only"],
fails=>1,
expect=>
'%Error: t/t_var_const_bad.v:\d+: Assigning to const variable: five
%Error: Exiting due to.*',
) if $Self->{v3};
ok(1);
1;
+22
View File
@@ -0,0 +1,22 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2011 by Wilson Snyder.
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
const logic [2:0] five = 3'd5;
always @ (posedge clk) begin
five = 3'd4;
if (five !== 3'd5) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule
+2 -2
View File
@@ -21,14 +21,14 @@ if ($Self->{v3}) {
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<uint32_t> \s+ i8;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<uint32_t> \s+ i16;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<uint32_t> \s+ i32;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<uint64_t> \s+ i64;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<vluint64_t> \s+ i64;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_bv<65>\s> \s+ i65;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<bool> \s+ o1;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<uint32_t> \s+ o8;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<uint32_t> \s+ o16;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<uint32_t> \s+ o32;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<uint64_t> \s+ o64;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<vluint64_t> \s+ o64;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_bv<65>\s> \s+ o65;/x);
}
+2 -2
View File
@@ -21,14 +21,14 @@ if ($Self->{v3}) {
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<uint8_t> \s+ i8;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<uint16_t> \s+ i16;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<uint32_t> \s+ i32;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<uint64_t> \s+ i64;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<vluint64_t> \s+ i64;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_in<sc_bv<65>\s> \s+ i65;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<bool> \s+ o1;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<uint8_t> \s+ o8;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<uint16_t> \s+ o16;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<uint32_t> \s+ o32;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<uint64_t> \s+ o64;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<vluint64_t> \s+ o64;/x);
file_grep ("$Self->{obj_dir}/$Self->{VM_PREFIX}.sp", qr/sc_out<sc_bv<65>\s> \s+ o65;/x);
}
+2 -2
View File
@@ -25,8 +25,8 @@ module t (/*AUTOARG*/);
// IEEE: non_integer_type
//UNSUP shortreal d_shortreal;
//UNSUP real d_real;
//UNSUP realtime d_realtime;
real d_real;
realtime d_realtime;
// Declarations using var
var byte v_b;
+78 -1
View File
@@ -28,6 +28,10 @@
// __FILE__ is too long
#define FILENM "t_vpi_var.cpp"
unsigned int main_time = false;
unsigned int callback_count = false;
unsigned int callback_count_half = false;
//======================================================================
@@ -72,6 +76,35 @@ public:
return __LINE__; \
}
int _mon_check_mcd() {
PLI_INT32 status;
PLI_UINT32 mcd;
PLI_BYTE8* filename = (PLI_BYTE8*)"mcd_open.tmp";
mcd = vpi_mcd_open(filename);
CHECK_RESULT_NZ(mcd);
{ // Check it got written
FILE* fp = fopen(filename,"r");
CHECK_RESULT_NZ(fp);
fclose(fp);
}
status = vpi_mcd_printf(mcd, (PLI_BYTE8*)"hello %s", "vpi_mcd_printf");
CHECK_RESULT(status, strlen("hello vpi_mcd_printf"));
status = vpi_mcd_flush(mcd);
CHECK_RESULT(status, 0);
status = vpi_mcd_close(mcd);
CHECK_RESULT(status, 0);
status = vpi_flush();
CHECK_RESULT(status, 0);
return 0;
}
int _mon_check_callbacks() {
t_cb_data cb_data;
cb_data.reason = cbEndOfSimulation;
@@ -87,6 +120,46 @@ int _mon_check_callbacks() {
return 0;
}
int _value_callback(p_cb_data cb_data) {
CHECK_RESULT(cb_data->value->value.integer+10, main_time);
callback_count++;
return 0;
}
int _value_callback_half(p_cb_data cb_data) {
CHECK_RESULT(cb_data->value->value.integer*2+10, main_time);
callback_count_half++;
return 0;
}
int _mon_check_value_callbacks() {
vpiHandle vh1 = vpi_handle_by_name((PLI_BYTE8*)"t.count", NULL);
CHECK_RESULT_NZ(vh1);
s_vpi_value v;
v.format = vpiIntVal;
vpi_get_value(vh1, &v);
t_cb_data cb_data;
cb_data.reason = cbValueChange;
cb_data.cb_rtn = _value_callback;
cb_data.obj = vh1;
cb_data.value = &v;
vpiHandle vh = vpi_register_cb(&cb_data);
CHECK_RESULT_NZ(vh);
vh1 = vpi_handle_by_name((PLI_BYTE8*)"t.half_count", NULL);
CHECK_RESULT_NZ(vh1);
cb_data.obj = vh1;
cb_data.cb_rtn = _value_callback_half;
vh = vpi_register_cb(&cb_data);
CHECK_RESULT_NZ(vh);
return 0;
}
int _mon_check_var() {
VlVpiHandle vh1 = vpi_handle_by_name((PLI_BYTE8*)"t.onebit", NULL);
CHECK_RESULT_NZ(vh1);
@@ -245,7 +318,9 @@ int _mon_check_quad() {
int mon_check() {
// Callback from initial block in monitor
if (int status = _mon_check_mcd()) return status;
if (int status = _mon_check_callbacks()) return status;
if (int status = _mon_check_value_callbacks()) return status;
if (int status = _mon_check_var()) return status;
if (int status = _mon_check_varlist()) return status;
if (int status = _mon_check_getput()) return status;
@@ -255,7 +330,6 @@ int mon_check() {
//======================================================================
unsigned int main_time = false;
double sc_time_stamp () {
return main_time;
@@ -288,12 +362,15 @@ int main(int argc, char **argv, char **env) {
while (sc_time_stamp() < sim_time && !Verilated::gotFinish()) {
main_time += 1;
topp->eval();
VerilatedVpi::callValueCbs();
topp->clk = !topp->clk;
//mon_do();
#if VM_TRACE
if (tfp) tfp->dump (main_time);
#endif
}
CHECK_RESULT(callback_count, 501);
CHECK_RESULT(callback_count_half, 250);
if (!Verilated::gotFinish()) {
vl_fatal(FILENM,__LINE__,"main", "%Error: Timeout; never got a $finish");
}
+14 -2
View File
@@ -19,6 +19,9 @@ module t (/*AUTOARG*/
reg [3:2][61:0] quads /*verilator public_flat_rw @(posedge clk) */;
reg [31:0] count /*verilator public_flat_rd */;
reg [31:0] half_count /*verilator public_flat_rd */;
integer status;
sub sub();
@@ -34,8 +37,17 @@ module t (/*AUTOARG*/
if (onebit != 1'b1) $stop;
if (quads[2] != 62'h12819213_abd31a1c) $stop;
if (quads[3] != 62'h1c77bb9b_3784ea09) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
always @(posedge clk) begin
count <= count + 2;
if (count[1])
half_count <= half_count + 2;
if (count == 1000) begin
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule
+9 -9
View File
@@ -60,11 +60,11 @@ int sc_main(int argc, char* argv[]) {
cout << "Defining Interconnect\n";
sc_signal<bool> reset_l;
sc_signal<bool> passed;
sc_signal<uint32_t> in_small;
sc_signal<uint64_t> in_quad;
sc_signal<vluint32_t> in_small;
sc_signal<vluint64_t> in_quad;
sc_signal<sc_bv<70> > in_wide;
sc_signal<uint32_t> out_small;
sc_signal<uint64_t> out_quad;
sc_signal<vluint32_t> out_small;
sc_signal<vluint64_t> out_quad;
sc_signal<sc_bv<70> > out_wide;
//==========
@@ -99,7 +99,7 @@ int sc_main(int argc, char* argv[]) {
//==========
// Waves
#if WAVES
#if VM_TRACE
// Before any evaluation, need to know to calculate those signals only used for tracing
Verilated::traceEverOn(true);
#endif
@@ -117,7 +117,7 @@ int sc_main(int argc, char* argv[]) {
//==========
// Waves
#if WAVES
#if VM_TRACE
cout << "Enabling waves...\n";
# ifdef SYSTEMPERL
SpTraceFile* tfp = new SpTraceFile;
@@ -135,7 +135,7 @@ int sc_main(int argc, char* argv[]) {
reset_l = 1;
while (VL_TIME_Q() < 60 && !passed && !Verilated::gotFinish()) {
#if WAVES
#if VM_TRACE
// Flush the wave files each cycle so we can immediately see the output
// Don't do this in "real" programs, do it in a abort() handler instead
if (tfp) tfp->flush();
@@ -156,7 +156,7 @@ int sc_main(int argc, char* argv[]) {
//==========
// Close Waves
#if WAVES
#if VM_TRACE
if (tfp) tfp->close();
#endif
@@ -168,7 +168,7 @@ int sc_main(int argc, char* argv[]) {
//==========
// Coverage analysis (since test passed)
mkdir("logs", 0777);
#ifdef SYSTEMPERL
#if VM_COVERAGE
SpCoverage::write(); // Writes logs/coverage.pl
#endif
+6 -6
View File
@@ -58,7 +58,7 @@ our $Raise_Weight_Max = 50;
'VREDXNOR'=> {weight=>1&&1, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(^~ %1)', },
'VREDXOR'=> {weight=>1&&1, width=>1, signed=>0, sc=>0, terminal=>0, v=>'(^ %1)', },
'VNOT'=> {weight=>1&&3, width=>0, sc=>1, terminal=>0, v=>'(~ %1)', },
'VUNARYMIN'=> {weight=>1&&2, width=>0, sc=>1, terminal=>0, v=>'(- %1)', },
'VNEGATE'=> {weight=>1&&2, width=>0, sc=>1, terminal=>0, v=>'(- %1)', },
'VCOUNTONES'=> {weight=>0&&2, width=>32, signed=>0, sc=>0, terminal=>0, v=>'\$countones(%1)', }, # No ncv support
'VONEHOT'=> {weight=>0&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'\$onehot(%1)', }, # No ncv support
'VONEHOT0'=> {weight=>0&&2, width=>1, signed=>0, sc=>0, terminal=>0, v=>'\$onehot0(%1)', }, # No ncv support
@@ -143,7 +143,7 @@ my %ops2 =
'VREDXOR'=> {pl=>'VREDXOR (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>0);'},
'VREDXNOR'=> {pl=>'VREDXNOR (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>0);'},
'VNOT'=> {pl=>'VNOT (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg);'},
'VUNARYMIN'=> {pl=>'VUNARYMIN(%tr,%1v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg);'},
'VNEGATE'=> {pl=>'VNEGATE (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>%tw,signed=>%tg);'},
'VCOUNTONES'=> {pl=>'VCOUNTONES(%tr,%1v);', rnd=>'%1r=gen_leaf(width=>0);'},
'VONEHOT'=> {pl=>'VONEHOT (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>0);'},
'VONEHOT0'=> {pl=>'VONEHOT0 (%tr,%1v);', rnd=>'%1r=gen_leaf(width=>0);'},
@@ -832,8 +832,8 @@ sub decl_text {
my $varref = $Vars{$var};
if ($Opt_Sc) {
(!$varref->{signed}) or die "%Error: No signed SystemC yet\n";
my $type = (( ($varref->{val}->Size == 32) && "uint32_t")
|| (($varref->{val}->Size == 64) && "uint64_t"));
my $type = (( ($varref->{val}->Size == 32) && "sc_dt::uint32")
|| (($varref->{val}->Size == 64) && "sc_dt::uint64"));
$type or die "%Error: Unknown Size ".$varref->{val}->Size,",";
return sprintf " %s<%s> %s; //=%s"
, $decl_with, $type, $var, $varref->{val}->to_Hex;
@@ -893,8 +893,8 @@ sub countones {
}
sub VLOGNOT { $_[0]{val} = makebool(($_[1]->is_empty)?1:0); }
sub VUNARYMIN { $_[0]{val} = my $o = newsized($_[1]); $o->Negate($_[1]); }
sub VLOGNOT { $_[0]{val} = makebool(($_[1]->is_empty)?1:0); }
sub VNEGATE { $_[0]{val} = my $o = newsized($_[1]); $o->Negate($_[1]); }
sub VCOUNTONES { $_[0]{val} = Bit::Vector->new_Dec(32,countones($_[1])); }
sub VONEHOT { $_[0]{val} = makebool((countones($_[1])==1)?1:0); }
sub VONEHOT0 { $_[0]{val} = makebool((countones($_[1])<=1)?1:0); }