mirror of
https://github.com/verilator/verilator.git
synced 2026-10-03 16:44:11 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
34e8de56bc | ||
|
|
8a7864ebaa | ||
|
|
9e5fb5467f | ||
|
|
fb34bf7222 | ||
|
|
4591f35b7c | ||
|
|
f0a06182ca | ||
|
|
d9e47a6293 | ||
|
|
a555f87705 | ||
|
|
826b997166 | ||
|
|
d34bc6f304 | ||
|
|
5771ea48ef | ||
|
|
a4f3199427 | ||
|
|
e6a43fc127 | ||
|
|
701bd38d01 | ||
|
|
1a8c8bec0d | ||
|
|
20aa21d4b6 | ||
|
|
8c6adeb85a | ||
|
|
09b7ba1317 | ||
|
|
0703843ac1 | ||
|
|
d962dfe48c | ||
|
|
d6884db439 | ||
|
|
fdcbedef8f | ||
|
|
8afd19648f |
@@ -3,6 +3,33 @@ 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.670 2008/07/23
|
||||
|
||||
** Add --x-assign=fast option, and make it the default.
|
||||
This chooses performance over reset debugging. See the manual.
|
||||
|
||||
** Add --autoflush, for flushing streams after $display. [Steve Tong]
|
||||
|
||||
** Add CASEZWITHX lint warning and if disabled fix handling of casez with Xs.
|
||||
|
||||
*** Add $feof, $fgetc, $fgets, $fflush, $fscanf, $sscanf. [Holger Waechtler]
|
||||
|
||||
*** Add $stime. [Holger Waechtler]
|
||||
|
||||
*** Add $random.
|
||||
|
||||
*** Add --Wfuture-, for improving forward compatibility.
|
||||
|
||||
**** Fix verilator_includer not being installed properly. [Holger Waechtler]
|
||||
|
||||
**** Fix IMPURE errors due to X-assignment temporary variables. [Steve Tong]
|
||||
|
||||
**** Fix "lvalue" errors with public functions; bug25. [CY Wang]
|
||||
|
||||
**** Add WIDTH warning to $fopen etc file descriptors.
|
||||
|
||||
**** Internal changes to how $displays get compiled and executed.
|
||||
|
||||
* Verilator 3.665 2008/06/25
|
||||
|
||||
**** Ignore "// verilator" comments alone on endif lines. [Rodney Sinclair]
|
||||
@@ -17,7 +44,7 @@ indicates the contributor was also the author of the fix; Thanks!
|
||||
|
||||
**** Fix compile errors under Fedora 9, GCC 4.3.0. [by Jeremy Bennett]
|
||||
|
||||
**** Fix Makefile to find headers/libraries under prefix. [by Holger_Waechtler]
|
||||
**** Fix Makefile to find headers/libraries under prefix. [by Holger Waechtler]
|
||||
|
||||
* Verilator 3.664 2008/05/08
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
/obj_dir/
|
||||
/obj_dbg/
|
||||
/obj_opt/
|
||||
/INCA_libs/
|
||||
/logs/
|
||||
Makefile
|
||||
src/Makefile_obj
|
||||
|
||||
+8
-2
@@ -117,6 +117,7 @@ DISTFILES_INC = $(INFOS) .gitignore COPYING *.in *.ac \
|
||||
test_verilated/vgen*.pl \
|
||||
test_regress/t/*.cpp \
|
||||
test_regress/t/*.h \
|
||||
test_regress/t/*.dat \
|
||||
test_regress/t/*.mem \
|
||||
test_regress/t/*.out \
|
||||
test_regress/t/*.pl \
|
||||
@@ -136,8 +137,10 @@ INST_PROJ_BIN_FILES = \
|
||||
|
||||
DISTFILES := $(DISTFILES_INC)
|
||||
|
||||
VL_INST_MAN_FILES = verilator.1
|
||||
|
||||
all: all_nomsg msg_test
|
||||
all_nomsg: verilator_exe
|
||||
all_nomsg: verilator_exe $(VL_INST_MAN_FILES)
|
||||
|
||||
.PHONY:verilator_exe
|
||||
verilator_exe verilator_bin verilator_bin_dbg:
|
||||
@@ -221,6 +224,8 @@ README: readme.texi
|
||||
# See uninstall also
|
||||
VL_INST_BIN_FILES = verilator verilator_bin verilator_bin_dbg \
|
||||
verilator_includer verilator_profcfunc
|
||||
# Some scripts go into both the search path and pkgdatadir,
|
||||
# so they can be found by the user, and under $VERILATOR_ROOT.
|
||||
installbin:
|
||||
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(bindir)
|
||||
( cd bin ; $(INSTALL_PROGRAM) verilator $(DESTDIR)$(bindir)/verilator )
|
||||
@@ -228,8 +233,9 @@ installbin:
|
||||
( cd bin ; $(INSTALL_PROGRAM) verilator_profcfunc $(DESTDIR)$(bindir)/verilator_profcfunc )
|
||||
( $(INSTALL_PROGRAM) verilator_bin $(DESTDIR)$(bindir)/verilator_bin )
|
||||
( $(INSTALL_PROGRAM) verilator_bin_dbg $(DESTDIR)$(bindir)/verilator_bin_dbg )
|
||||
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/bin
|
||||
( cd bin ; $(INSTALL_PROGRAM) verilator_includer $(DESTDIR)$(pkgdatadir)/bin/verilator_includer )
|
||||
|
||||
VL_INST_MAN_FILES = verilator.1
|
||||
installman:
|
||||
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(mandir)/man1
|
||||
for p in $(VL_INST_MAN_FILES) ; do \
|
||||
|
||||
+103
-23
@@ -177,6 +177,7 @@ descriptions in the next sections for more information.
|
||||
{file.c/cc/cpp} Optional C++ files to link in
|
||||
|
||||
--assert Enable all assertions
|
||||
--autoflush Flush streams after all $displays
|
||||
--bin <filename> Override Verilator binary
|
||||
--cc Create C++ output
|
||||
--compiler <compiler-name> Tune for specified C++ compiler
|
||||
@@ -223,6 +224,7 @@ descriptions in the next sections for more information.
|
||||
--underline-zero Zero signals with leading _'s
|
||||
-v <filename> Verilog library
|
||||
-Werror-<message> Convert warning to error
|
||||
-Wfuture-<message> Disable unknown message warnings
|
||||
-Wno-<message> Disable warning
|
||||
-x-assign <mode> Initially assign Xs to this value
|
||||
-y <dir> Directory to search for modules
|
||||
@@ -252,6 +254,14 @@ linking with make rules you write yourself.
|
||||
Enable all assertions, includes enabling the --psl flag. (If psl is not
|
||||
desired, but other assertions are, use --assert --nopsl.)
|
||||
|
||||
See also --x-assign; setting "--x-assign unique" may be desirable.
|
||||
|
||||
=item --autoflush
|
||||
|
||||
After every $display or $fdisplay, flush the output stream. This insures
|
||||
that messages will appear immediately but may reduce performance. Defaults
|
||||
off, which will buffer output as provided by the normal C stdio calls.
|
||||
|
||||
=item --bin I<filename>
|
||||
|
||||
Rarely needed. Override the default filename for Verilator itself. When a
|
||||
@@ -547,6 +557,14 @@ Convert the specified warning message into a error message. This is
|
||||
generally to discourage users from violating important site-wide rules, for
|
||||
example C<-Werror-NOUNOPTFLAT>.
|
||||
|
||||
=item -Wfuture-I<message>
|
||||
|
||||
Suppress unknown Verilator comments or warning messages with the given
|
||||
message code. This is used to allow code written with pragmas for a later
|
||||
version of Verilator to run under a older version; add -Wfuture- arguments
|
||||
for each message code or comment that the new version supports which the
|
||||
older version does not support.
|
||||
|
||||
=item -Wno-I<message>
|
||||
|
||||
Disable the specified warning message.
|
||||
@@ -554,9 +572,9 @@ Disable the specified warning message.
|
||||
=item -Wno-lint
|
||||
|
||||
Disable all lint related warning messages. This is equivelent to
|
||||
"-Wno-CASEINCOMPLETE -Wno-CASEOVERLAP -Wno-CASEX -Wno-CMPCONST
|
||||
-Wno-IMPLICIT -Wno-UNDRIVEN -Wno-UNSIGNED -Wno-UNUSED -Wno-VARHIDDEN
|
||||
-Wno-WIDTH".
|
||||
"-Wno-CASEINCOMPLETE -Wno-CASEOVERLAP -Wno-CASEX -Wno-CASEZWITHX
|
||||
-Wno-CMPCONST -Wno-IMPLICIT -Wno-UNDRIVEN -Wno-UNSIGNED -Wno-UNUSED
|
||||
-Wno-VARHIDDEN -Wno-WIDTH".
|
||||
|
||||
It is strongly recommended you cleanup your code rather than using this
|
||||
option, it is only intended to be use when running test-cases of code
|
||||
@@ -566,14 +584,18 @@ received from third parties.
|
||||
|
||||
=item -x-assign 1
|
||||
|
||||
=item -x-assign unique (default)
|
||||
=item -x-assign fast (default)
|
||||
|
||||
=item -x-assign unique
|
||||
|
||||
Controls the two-state value that is replaced when an assignment to X is
|
||||
encountered. -x-assign=0 converts all Xs to 0s, this is the fastest.
|
||||
-x-assign=1 converts all Xs to 1s, this is nearly as fast, but more likely
|
||||
to find reset bugs as active high logic will fire. The default,
|
||||
-x-assign=func will call a function to determine the value, this allows
|
||||
randomization of all Xs and is the slowest, but safest.
|
||||
encountered. -x-assign=fast, the default, converts all Xs to whatever is
|
||||
best for performance. -x-assign=0 converts all Xs to 0s, and is also fast.
|
||||
-x-assign=1 converts all Xs to 1s, this is nearly as fast as 0, but more
|
||||
likely to find reset bugs as active high logic will fire. -x-assign=unique
|
||||
will call a function to determine the value, this allows randomization of
|
||||
all Xs to find reset bugs and is the slowest, but safest for finding reset
|
||||
bugs in code.
|
||||
|
||||
=back
|
||||
|
||||
@@ -747,10 +769,10 @@ the test_sp directory in the distribution for an example.
|
||||
|
||||
=head1 BENCHMARKING & OPTIMIZATION
|
||||
|
||||
For best performance, run Verilator with the "-O3 -x-assign=0 --noassert"
|
||||
flags. The -O3 flag will require longer compile times, and -x-assign=0 may
|
||||
increase the risk of reset bugs in trade for performance; see the above
|
||||
documentation for these flags.
|
||||
For best performance, run Verilator with the "-O3 -x-assign=fast
|
||||
--noassert" flags. The -O3 flag will require longer compile times, and
|
||||
-x-assign=fast may increase the risk of reset bugs in trade for
|
||||
performance; see the above documentation for these flags.
|
||||
|
||||
Minor Verilog code changes can also give big wins. You should not have any
|
||||
UNOPTFLAT warnings from Verilator. Fixing these warnings can result in
|
||||
@@ -1298,10 +1320,9 @@ Wide variables over 64 bits cannot be function returns, to avoid exposing
|
||||
complexities. However, wide variables can be input/outputs; they will be
|
||||
passed as references to an array of 32 bit numbers.
|
||||
|
||||
This feature is still somewhat experimental. Generally, only the values of
|
||||
stored state (flops) should be written, as the model will NOT notice
|
||||
changes made to variables in these functions. (Same as when a signal is
|
||||
declared public.)
|
||||
Generally, only the values of stored state (flops) should be written, as
|
||||
the model will NOT notice changes made to variables in these functions.
|
||||
(Same as when a signal is declared public.)
|
||||
|
||||
=item /*verilator public_flat*/ (variable)
|
||||
|
||||
@@ -1535,8 +1556,8 @@ Verilator does not perform warning checking on uwires, it treats the uwire
|
||||
keyword as if it were the normal wire keyword.
|
||||
|
||||
=item $bits, $countones, $error, $fatal, $finish, $info, $isunknown,
|
||||
$onehot, $onehot0, $readmemb, $readmemh, $signed, $stop, $time, $unsigned,
|
||||
$warning.
|
||||
$onehot, $onehot0, $readmemb, $readmemh, $signed, $stime, $stop, $time,
|
||||
$unsigned, $warning.
|
||||
|
||||
Generally supported.
|
||||
|
||||
@@ -1554,7 +1575,7 @@ them with a $write with the appropriate format specifier.
|
||||
|
||||
The rarely used optional parameter to $finish and $stop is ignored.
|
||||
|
||||
=item $fopen, $fclose, $fdisplay, $fwrite
|
||||
=item $fopen, $fclose, $fdisplay, $feof, $fflush, $fgetc, $fgets, $fscanf, $fwrite
|
||||
|
||||
File descriptors passed to the file PLI calls must be file descriptors, not
|
||||
MCDs, which includes the mode parameter to $fopen being mandatory.
|
||||
@@ -1564,11 +1585,22 @@ 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
|
||||
|
||||
Only integer formats are supported; %e, %f, %m, %r, %v, and %z are not
|
||||
supported.
|
||||
|
||||
=item $fullskew, $hold, $nochange, $period, $recovery, $recrem, $removal,
|
||||
$setup, $setuphold, $skew, $timeskew, $width
|
||||
|
||||
All specify blocks and timing checks are ignored.
|
||||
|
||||
=item $random
|
||||
|
||||
$random does not support the optional argument to set the seed. Use the
|
||||
srand function in C to accomplish this, and note there is only one random
|
||||
number generator (not one per module).
|
||||
|
||||
=item $readmemb, $readmemh
|
||||
|
||||
Read memory commands should work properly. Note Verilator and the Verilog
|
||||
@@ -1653,6 +1685,16 @@ L<http://www.sunburst-design.com/papers/CummingsSNUG1999Boston_FullParallelCase_
|
||||
Ignoring this warning will only suppress the lint check, it will simulate
|
||||
correctly.
|
||||
|
||||
=item CASEWITHX
|
||||
|
||||
Warns that a case statement contains a constant with a C<x>. Verilator is
|
||||
two-state so interpret such items as always false. Note a common error is
|
||||
to use a C<X> in a case or casez statement item; often what the user
|
||||
instead insteaded is to use a casez with C<?>.
|
||||
|
||||
Ignoring this warning will only suppress the lint check, it will simulate
|
||||
correctly.
|
||||
|
||||
=item CMPCONST
|
||||
|
||||
Warns that you are comparing a value in a way that will always be constant.
|
||||
@@ -2129,11 +2171,49 @@ uses one large symbol table, as that results in 2-3 less assembly
|
||||
instructions for each signal access. This makes the execution time 10-15%
|
||||
faster, but can result in more compilations when something changes.
|
||||
|
||||
=item How do I access functions/tasks in C?
|
||||
|
||||
Write a Verilog function or task with input/outputs that match what you
|
||||
want to call in with C. Then mark that function public.
|
||||
|
||||
Verilog inputs of one bit become C++ bool inputs. Inputs 32 bits or
|
||||
smaller become C uint32_t inputs, 64-32 bits become C uint64_t inputs, and
|
||||
wider signals become arrays of 32 bits. Outputs are passed as references
|
||||
to bool, uint32_t, uint64_t or uint32_t[] arrays.
|
||||
|
||||
Signals wider than 64 bits are passed as an array of 32-bit uint32_t's.
|
||||
Thus to read bits 31:0, access signal[0], and for bits 63:32, access
|
||||
signal[1]. Unused bits (for example bit numbers 65-96 of a 65 bit vector)
|
||||
will always be zero. if you change the value you must make sure to pack
|
||||
zeros in the unused bits or core-dumps may result. (Because Verilator
|
||||
strips array bound checks where it believes them to be unnecessary.)
|
||||
|
||||
In the SYSTEMC example above, if you had in our.v:
|
||||
|
||||
task publicSetBool;
|
||||
// verilator public
|
||||
input in_bool;
|
||||
var_bool = in_bool;
|
||||
endtask
|
||||
|
||||
From the sc_main.cpp file, you'd then:
|
||||
|
||||
#include "Vour.h"
|
||||
#include "Vour_our.h"
|
||||
top->v.publicSetBool(value);
|
||||
|
||||
See additional notes under the /*verilator public*/ section.
|
||||
|
||||
=item How do I access signals in C?
|
||||
|
||||
First, declare the signals you will be accessing with a /*verilator
|
||||
public*/ comment before the closing semicolon. Then scope into the C++
|
||||
class to read the value of the signal, as you would any other member variable.
|
||||
The best thing is to make a Verilator public task or function accessor that
|
||||
can read or write that signal, as described in the previous FAQ. This will
|
||||
allow Verilator to better optimize the model.
|
||||
|
||||
If you really want raw access to the signals, declare the signals you will
|
||||
be accessing with a /*verilator public*/ comment before the closing
|
||||
semicolon. Then scope into the C++ class to read the value of the signal,
|
||||
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
|
||||
|
||||
+462
-91
@@ -23,8 +23,7 @@
|
||||
//=========================================================================
|
||||
|
||||
#include "verilated.h"
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <cctype>
|
||||
|
||||
#define VL_VALUE_STRING_MAX_WIDTH 1024 ///< Max static char array for VL_VALUE_STRING
|
||||
|
||||
@@ -80,23 +79,43 @@ IData VL_RAND32() {
|
||||
#endif
|
||||
}
|
||||
|
||||
IData VL_RAND_RESET_I(int outBits) {
|
||||
IData VL_RANDOM_I(int obits) {
|
||||
return VL_RAND32() & VL_MASK_I(obits);
|
||||
}
|
||||
|
||||
QData VL_RANDOM_Q(int obits) {
|
||||
QData data = ((QData)VL_RAND32()<<VL_ULL(32)) | (QData)VL_RAND32();
|
||||
return data & VL_MASK_Q(obits);
|
||||
}
|
||||
|
||||
WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp) {
|
||||
for (int i=0; i<VL_WORDS_I(obits); i++) {
|
||||
if (i<(VL_WORDS_I(obits)-1)) {
|
||||
outwp[i] = VL_RAND32();
|
||||
} else {
|
||||
outwp[i] = VL_RAND32() & VL_MASK_I(obits);
|
||||
}
|
||||
}
|
||||
return outwp;
|
||||
}
|
||||
|
||||
IData VL_RAND_RESET_I(int obits) {
|
||||
if (Verilated::randReset()==0) return 0;
|
||||
IData data = ~0;
|
||||
if (Verilated::randReset()!=1) { // if 2, randomize
|
||||
data = VL_RAND32();
|
||||
data = VL_RANDOM_I(obits);
|
||||
}
|
||||
if (outBits<32) data &= VL_MASK_I(outBits);
|
||||
if (obits<32) data &= VL_MASK_I(obits);
|
||||
return data;
|
||||
}
|
||||
|
||||
QData VL_RAND_RESET_Q(int outBits) {
|
||||
QData VL_RAND_RESET_Q(int obits) {
|
||||
if (Verilated::randReset()==0) return 0;
|
||||
QData data = VL_ULL(~0);
|
||||
if (Verilated::randReset()!=1) { // if 2, randomize
|
||||
data = ((QData)VL_RAND32()<<VL_ULL(32)) | (QData)VL_RAND32();
|
||||
data = VL_RANDOM_Q(obits);
|
||||
}
|
||||
if (outBits<64) data &= VL_MASK_Q(outBits);
|
||||
if (obits<64) data &= VL_MASK_Q(obits);
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -119,94 +138,351 @@ WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp) {
|
||||
//===========================================================================
|
||||
// Formatting
|
||||
|
||||
const char* VL_VALUE_FORMATTED_Q(int obits, char fmt, bool drop0, QData ld) {
|
||||
// Convert value into %b/%o/%x/%s/%u/%d formatted string
|
||||
// Note uses a single buffer; presumes only one call per printf
|
||||
static VL_THREAD char str[VL_VALUE_STRING_MAX_WIDTH];
|
||||
char* strp = &str[0];
|
||||
int lsb=obits-1;
|
||||
if (drop0) while (lsb && !VL_BITISSET_Q(ld,lsb)) lsb--;
|
||||
switch (fmt) {
|
||||
case 'd':
|
||||
sprintf(str,"%lld",(vlsint64_t)(VL_EXTENDS_QQ(obits,obits,ld)));
|
||||
return str;
|
||||
case 'u':
|
||||
sprintf(str,"%llu",ld);
|
||||
return str;
|
||||
case 's':
|
||||
for (; lsb>=0; lsb--) {
|
||||
lsb = (lsb / 8) * 8; // Next digit
|
||||
IData charval = (ld>>VL_BITBIT_Q(lsb)) & 0xff;
|
||||
*strp++ = (charval==0)?' ':charval;
|
||||
// Do a va_arg returning a quad, assuming input argument is anything less than wide
|
||||
#define _VL_VA_ARG_Q(ap, bits) (((bits) <= VL_WORDSIZE) ? va_arg(ap,IData) : va_arg(ap,QData))
|
||||
|
||||
void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
||||
// Format a Verilog $write style format into the output list
|
||||
// The format must be pre-processed (and lower cased) by Verilator
|
||||
// Arguments are in "width, arg-value (or WDataIn* if wide)" form
|
||||
//
|
||||
// Note uses a single buffer internally; presumes only one usage per printf
|
||||
// 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];
|
||||
bool inPct = false;
|
||||
bool widthSet = false;
|
||||
int width = 0;
|
||||
const char* pos = formatp;
|
||||
for (; *pos; ++pos) {
|
||||
if (!inPct && pos[0]=='%') {
|
||||
inPct = true;
|
||||
widthSet = false;
|
||||
width = 0;
|
||||
} else if (!inPct) { // Normal text
|
||||
// Fast-forward to next escape and add to output
|
||||
const char *ep = pos;
|
||||
while (ep[0] && ep[0]!='%') ep++;
|
||||
if (ep != pos) {
|
||||
output += string(pos, ep-pos);
|
||||
pos += ep-pos-1;
|
||||
}
|
||||
} else { // Format character
|
||||
inPct = false;
|
||||
char fmt = pos[0];
|
||||
switch (fmt) {
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
inPct = true; // Get more digits
|
||||
widthSet = true;
|
||||
width = width*10 + (fmt - '0');
|
||||
break;
|
||||
case '%':
|
||||
output += '%';
|
||||
break;
|
||||
case 'S': { // "C" string
|
||||
const char* cstrp = va_arg(ap, const char*);
|
||||
output += cstrp;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// Deal with all read-and-print somethings
|
||||
const int lbits = va_arg(ap, int);
|
||||
QData ld = 0;
|
||||
WDataInP lwp;
|
||||
if (lbits <= VL_QUADSIZE) {
|
||||
WData qlwp[2];
|
||||
ld = _VL_VA_ARG_Q(ap, lbits);
|
||||
VL_SET_WQ(qlwp,ld);
|
||||
lwp = qlwp;
|
||||
} else {
|
||||
lwp = va_arg(ap,WDataInP);
|
||||
ld = lwp[0];
|
||||
if (fmt == 'u' || fmt == 'd') fmt = 'x'; // Not supported, but show something
|
||||
}
|
||||
int lsb=lbits-1;
|
||||
if (widthSet && width==0) while (lsb && !VL_BITISSET_W(lwp,lsb)) lsb--;
|
||||
switch (fmt) {
|
||||
case 'c': {
|
||||
IData charval = ld & 0xff;
|
||||
output += charval;
|
||||
break;
|
||||
}
|
||||
case 's':
|
||||
for (; lsb>=0; lsb--) {
|
||||
lsb = (lsb / 8) * 8; // Next digit
|
||||
IData charval = (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 0xff;
|
||||
output += (charval==0)?' ':charval;
|
||||
}
|
||||
break;
|
||||
case 'd': { // Signed decimal
|
||||
int digits=sprintf(tmp,"%lld",(vlsint64_t)(VL_EXTENDS_QQ(lbits,lbits,ld)));
|
||||
int needmore = width-digits;
|
||||
if (needmore>0) output.append(needmore,' '); // Pre-pad spaces
|
||||
output += tmp;
|
||||
break;
|
||||
}
|
||||
case 'u': { // Unsigned decimal
|
||||
int digits=sprintf(tmp,"%llu",ld);
|
||||
int needmore = width-digits;
|
||||
if (needmore>0) output.append(needmore,' '); // Pre-pad spaces
|
||||
output += tmp;
|
||||
break;
|
||||
}
|
||||
case 'b':
|
||||
for (; lsb>=0; lsb--) {
|
||||
output += ((lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 1) + '0';
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
for (; lsb>=0; lsb--) {
|
||||
lsb = (lsb / 3) * 3; // Next digit
|
||||
// Octal numbers may span more than one wide word,
|
||||
// so we need to grab each bit separately and check for overrun
|
||||
// Octal is rare, so we'll do it a slow simple way
|
||||
output += ('0'
|
||||
+ ((VL_BITISSETLIMIT_W(lwp, lbits, lsb+0)) ? 1 : 0)
|
||||
+ ((VL_BITISSETLIMIT_W(lwp, lbits, lsb+1)) ? 2 : 0)
|
||||
+ ((VL_BITISSETLIMIT_W(lwp, lbits, lsb+2)) ? 4 : 0));
|
||||
}
|
||||
break;
|
||||
case 'x':
|
||||
for (; lsb>=0; lsb--) {
|
||||
lsb = (lsb / 4) * 4; // Next digit
|
||||
IData charval = (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 0xf;
|
||||
output += "0123456789abcdef"[charval];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
string msg = string("%%Error: Unknown _vl_vsformat code: ")+pos[0]+"\n";
|
||||
vl_fatal(__FILE__,__LINE__,"",msg.c_str());
|
||||
break;
|
||||
} // switch
|
||||
}
|
||||
} // switch
|
||||
}
|
||||
*strp++ = '\0';
|
||||
return str;
|
||||
case 'b':
|
||||
for (; lsb>=0; lsb--) {
|
||||
*strp++ = ((ld>>VL_BITBIT_Q(lsb)) & 1) + '0';
|
||||
}
|
||||
*strp++ = '\0';
|
||||
return str;
|
||||
case 'o':
|
||||
for (; lsb>=0; lsb--) {
|
||||
lsb = (lsb / 3) * 3; // Next digit
|
||||
*strp++ = ((ld>>VL_BITBIT_Q(lsb)) & 7) + '0';
|
||||
}
|
||||
*strp++ = '\0';
|
||||
return str;
|
||||
default:
|
||||
for (; lsb>=0; lsb--) {
|
||||
lsb = (lsb / 4) * 4; // Next digit
|
||||
IData charval = (ld>>VL_BITBIT_Q(lsb)) & 0xf;
|
||||
*strp++ = (charval + ((charval < 10) ? '0':('a'-10)));
|
||||
}
|
||||
*strp++ = '\0';
|
||||
return str;
|
||||
}
|
||||
*strp++ = '\0';
|
||||
return str;
|
||||
}
|
||||
|
||||
const char* VL_VALUE_FORMATTED_W(int obits, char fmt, bool drop0, WDataInP lwp) {
|
||||
// Convert value into %b/%o/%x/%s/%u/%d formatted string
|
||||
// Note uses a single buffer; presumes only one call per printf
|
||||
static VL_THREAD char str[VL_VALUE_STRING_MAX_WIDTH];
|
||||
char* strp = &str[0];
|
||||
int lsb=obits-1;
|
||||
if (drop0) while (lsb && !VL_BITISSET_W(lwp,lsb)) lsb--;
|
||||
switch (fmt) {
|
||||
case 's':
|
||||
for (; lsb>=0; lsb--) {
|
||||
lsb = (lsb / 8) * 8; // Next digit
|
||||
IData charval = (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 0xff;
|
||||
*strp++ = (charval==0)?' ':charval;
|
||||
}
|
||||
*strp++ = '\0';
|
||||
return str;
|
||||
case 'b':
|
||||
for (; lsb>=0; lsb--) {
|
||||
*strp++ = ((lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 1) + '0';
|
||||
}
|
||||
*strp++ = '\0';
|
||||
return str;
|
||||
case 'o':
|
||||
for (; lsb>=0; lsb--) {
|
||||
lsb = (lsb / 3) * 3; // Next digit
|
||||
*strp++ = ((lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 7) + '0';
|
||||
}
|
||||
*strp++ = '\0';
|
||||
return str;
|
||||
default:
|
||||
for (; lsb>=0; lsb--) {
|
||||
lsb = (lsb / 4) * 4; // Next digit
|
||||
IData charval = (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 0xf;
|
||||
*strp++ = (charval + ((charval < 10) ? '0':('a'-10)));
|
||||
}
|
||||
*strp++ = '\0';
|
||||
return str;
|
||||
static inline bool _vl_vsss_eof(FILE* fp, int& floc) {
|
||||
return fp ? feof(fp) : (floc<0);
|
||||
}
|
||||
static inline void _vl_vsss_advance(FILE* fp, int& floc) {
|
||||
if (fp) fgetc(fp);
|
||||
else floc -= 8;
|
||||
}
|
||||
static inline int _vl_vsss_peek(FILE* fp, int& floc, WDataInP fromp) {
|
||||
// Get a character without advancing
|
||||
if (fp) {
|
||||
int data = fgetc(fp);
|
||||
if (data == EOF) return EOF;
|
||||
ungetc(data,fp);
|
||||
return data;
|
||||
} else {
|
||||
if (floc < 0) return EOF;
|
||||
floc = floc & ~7; // Align to closest character
|
||||
int data = (fromp[VL_BITWORD_I(floc)] >> VL_BITBIT_I(floc)) & 0xff;
|
||||
return data;
|
||||
}
|
||||
*strp++ = '\0';
|
||||
return str;
|
||||
}
|
||||
static inline void _vl_vsss_skipspace(FILE* fp, int& floc, WDataInP fromp) {
|
||||
while (1) {
|
||||
int c = _vl_vsss_peek(fp, floc, fromp);
|
||||
if (c==EOF || !isspace(c)) return;
|
||||
_vl_vsss_advance(fp, floc);
|
||||
}
|
||||
}
|
||||
static inline void _vl_vsss_read(FILE* fp, int& floc, WDataInP fromp,
|
||||
char* tmpp, const char* acceptp) {
|
||||
// Read into tmp, consisting of characters from acceptp list
|
||||
char* cp = tmpp;
|
||||
while (1) {
|
||||
int c = _vl_vsss_peek(fp, floc, fromp);
|
||||
if (c==EOF || isspace(c)) break;
|
||||
if (acceptp!=NULL // String - allow anything
|
||||
&& NULL==strchr(acceptp, c)) break;
|
||||
if (acceptp!=NULL) c = tolower(c); // Non-strings we'll simplify
|
||||
*cp++ = c;
|
||||
_vl_vsss_advance(fp, floc);
|
||||
}
|
||||
*cp++ = '\0';
|
||||
//VL_PRINTF("\t_read got='%s'\n", tmpp);
|
||||
}
|
||||
static inline void _vl_vsss_setbit(WDataOutP owp, int obits, int lsb, int nbits, IData ld) {
|
||||
for (; nbits && lsb<obits; nbits--, lsb++, ld>>=1) {
|
||||
VL_ASSIGNBIT_WI(0, lsb, owp, ld & 1);
|
||||
}
|
||||
}
|
||||
|
||||
IData _vl_vsscanf(FILE* fp, // If a fscanf
|
||||
int fbits, WDataInP fromp, // Else if a sscanf
|
||||
const char* formatp, va_list ap) {
|
||||
// Read a Verilog $sscanf/$fscanf style format into the output list
|
||||
// The format must be pre-processed (and lower cased) by Verilator
|
||||
// Arguments are in "width, arg-value (or WDataIn* if wide)" form
|
||||
static VL_THREAD char tmp[VL_VALUE_STRING_MAX_WIDTH];
|
||||
int floc = fbits - 1;
|
||||
IData got = 0;
|
||||
bool inPct = false;
|
||||
const char* pos = formatp;
|
||||
for (; *pos && !_vl_vsss_eof(fp,floc); ++pos) {
|
||||
//VL_PRINTF("_vlscan fmt='%c' floc=%d file='%c'\n", pos[0], floc, _vl_vsss_peek(fp,floc,fromp));
|
||||
if (!inPct && pos[0]=='%') {
|
||||
inPct = true;
|
||||
} else if (!inPct && isspace(pos[0])) { // Format spaces
|
||||
while (isspace(pos[1])) pos++;
|
||||
_vl_vsss_skipspace(fp,floc,fromp);
|
||||
} else if (!inPct) { // Expected Format
|
||||
_vl_vsss_skipspace(fp,floc,fromp);
|
||||
int c = _vl_vsss_peek(fp,floc,fromp);
|
||||
if (c != pos[0]) goto done;
|
||||
else _vl_vsss_advance(fp,floc);
|
||||
} else { // Format character
|
||||
// Skip loading spaces
|
||||
inPct = false;
|
||||
char fmt = pos[0];
|
||||
switch (fmt) {
|
||||
case '%': {
|
||||
int c = _vl_vsss_peek(fp,floc,fromp);
|
||||
if (c != '%') goto done;
|
||||
else _vl_vsss_advance(fp,floc);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// Deal with all read-and-scan somethings
|
||||
// Note LSBs are preserved if there's an overflow
|
||||
const int obits = va_arg(ap, int);
|
||||
int lsb = 0;
|
||||
WData qowp[2];
|
||||
WDataOutP owp = qowp;
|
||||
if (obits > VL_QUADSIZE) {
|
||||
owp = va_arg(ap,WDataOutP);
|
||||
}
|
||||
for (int i=0; i<VL_WORDS_I(obits); i++) owp[i] = 0;
|
||||
switch (fmt) {
|
||||
case 'c': {
|
||||
int c = _vl_vsss_peek(fp,floc,fromp);
|
||||
if (c==EOF) goto done;
|
||||
else _vl_vsss_advance(fp,floc);
|
||||
owp[0] = c;
|
||||
break;
|
||||
}
|
||||
case 's': {
|
||||
_vl_vsss_skipspace(fp,floc,fromp);
|
||||
_vl_vsss_read(fp,floc,fromp, tmp, NULL);
|
||||
if (!tmp[0]) goto done;
|
||||
int pos = strlen(tmp)-1;
|
||||
for (int i=0; i<obits && pos>=0; pos--) {
|
||||
_vl_vsss_setbit(owp,obits,lsb, 8, tmp[pos]); lsb+=8;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'd': { // Signed decimal
|
||||
_vl_vsss_skipspace(fp,floc,fromp);
|
||||
_vl_vsss_read(fp,floc,fromp, tmp, "0123456789+-xz?_");
|
||||
if (!tmp[0]) goto done;
|
||||
vlsint64_t ld;
|
||||
sscanf(tmp,"%lld",&ld);
|
||||
VL_SET_WQ(owp,ld);
|
||||
break;
|
||||
}
|
||||
case 'u': { // Unsigned decimal
|
||||
_vl_vsss_skipspace(fp,floc,fromp);
|
||||
_vl_vsss_read(fp,floc,fromp, tmp, "0123456789+-xz?_");
|
||||
if (!tmp[0]) goto done;
|
||||
QData ld;
|
||||
sscanf(tmp,"%llu",&ld);
|
||||
VL_SET_WQ(owp,ld);
|
||||
break;
|
||||
}
|
||||
case 'b': {
|
||||
_vl_vsss_skipspace(fp,floc,fromp);
|
||||
_vl_vsss_read(fp,floc,fromp, tmp, "01xz?_");
|
||||
if (!tmp[0]) goto done;
|
||||
int pos = strlen(tmp)-1;
|
||||
for (int i=0; i<obits && pos>=0; pos--) {
|
||||
switch(tmp[pos]) {
|
||||
case 'x': case 'z': case '?': //FALLTHRU
|
||||
case '0': lsb++; break;
|
||||
case '1': _vl_vsss_setbit(owp,obits,lsb, 1, 1); lsb++; break;
|
||||
case '_': break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'o': {
|
||||
_vl_vsss_skipspace(fp,floc,fromp);
|
||||
_vl_vsss_read(fp,floc,fromp, tmp, "01234567xz?_");
|
||||
if (!tmp[0]) goto done;
|
||||
int pos = strlen(tmp)-1;
|
||||
for (int i=0; i<obits && pos>=0; pos--) {
|
||||
switch(tmp[pos]) {
|
||||
case 'x': case 'z': case '?': //FALLTHRU
|
||||
case '0': lsb+=3; break;
|
||||
case '1': _vl_vsss_setbit(owp,obits,lsb, 3, 1); lsb+=3; break;
|
||||
case '2': _vl_vsss_setbit(owp,obits,lsb, 3, 2); lsb+=3; break;
|
||||
case '3': _vl_vsss_setbit(owp,obits,lsb, 3, 3); lsb+=3; break;
|
||||
case '4': _vl_vsss_setbit(owp,obits,lsb, 3, 4); lsb+=3; break;
|
||||
case '5': _vl_vsss_setbit(owp,obits,lsb, 3, 5); lsb+=3; break;
|
||||
case '6': _vl_vsss_setbit(owp,obits,lsb, 3, 6); lsb+=3; break;
|
||||
case '7': _vl_vsss_setbit(owp,obits,lsb, 3, 7); lsb+=3; break;
|
||||
case '_': break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'x': {
|
||||
_vl_vsss_skipspace(fp,floc,fromp);
|
||||
_vl_vsss_read(fp,floc,fromp, tmp, "0123456789abcdefxz?_");
|
||||
if (!tmp[0]) goto done;
|
||||
int pos = strlen(tmp)-1;
|
||||
for (int i=0; i<obits && pos>=0; pos--) {
|
||||
switch(tmp[pos]) {
|
||||
case 'x': case 'z': case '?': //FALLTHRU
|
||||
case '0': lsb+=4; break;
|
||||
case '1': _vl_vsss_setbit(owp,obits,lsb, 4, 1); lsb+=4; break;
|
||||
case '2': _vl_vsss_setbit(owp,obits,lsb, 4, 2); lsb+=4; break;
|
||||
case '3': _vl_vsss_setbit(owp,obits,lsb, 4, 3); lsb+=4; break;
|
||||
case '4': _vl_vsss_setbit(owp,obits,lsb, 4, 4); lsb+=4; break;
|
||||
case '5': _vl_vsss_setbit(owp,obits,lsb, 4, 5); lsb+=4; break;
|
||||
case '6': _vl_vsss_setbit(owp,obits,lsb, 4, 6); lsb+=4; break;
|
||||
case '7': _vl_vsss_setbit(owp,obits,lsb, 4, 7); lsb+=4; break;
|
||||
case '8': _vl_vsss_setbit(owp,obits,lsb, 4, 8); lsb+=4; break;
|
||||
case '9': _vl_vsss_setbit(owp,obits,lsb, 4, 9); lsb+=4; break;
|
||||
case 'a': _vl_vsss_setbit(owp,obits,lsb, 4, 10); lsb+=4; break;
|
||||
case 'b': _vl_vsss_setbit(owp,obits,lsb, 4, 11); lsb+=4; break;
|
||||
case 'c': _vl_vsss_setbit(owp,obits,lsb, 4, 12); lsb+=4; break;
|
||||
case 'd': _vl_vsss_setbit(owp,obits,lsb, 4, 13); lsb+=4; break;
|
||||
case 'e': _vl_vsss_setbit(owp,obits,lsb, 4, 14); lsb+=4; break;
|
||||
case 'f': _vl_vsss_setbit(owp,obits,lsb, 4, 15); lsb+=4; break;
|
||||
case '_': break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
string msg = string("%%Error: Unknown _vl_vsscanf code: ")+pos[0]+"\n";
|
||||
vl_fatal(__FILE__,__LINE__,"",msg.c_str());
|
||||
break;
|
||||
} // switch
|
||||
|
||||
got++;
|
||||
// Reload data if non-wide (if wide, we put it in the right place directly)
|
||||
if (obits <= VL_BYTESIZE) {
|
||||
CData* p = va_arg(ap,CData*); *p = owp[0];
|
||||
} else if (obits <= VL_SHORTSIZE) {
|
||||
SData* p = va_arg(ap,SData*); *p = owp[0];
|
||||
} else if (obits <= VL_WORDSIZE) {
|
||||
IData* p = va_arg(ap,IData*); *p = owp[0];
|
||||
} else if (obits <= VL_QUADSIZE) {
|
||||
QData* p = va_arg(ap,QData*); *p = VL_SET_QW(owp);
|
||||
}
|
||||
}
|
||||
} // switch
|
||||
}
|
||||
}
|
||||
done:
|
||||
return got;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
@@ -228,6 +504,40 @@ void _VL_VINT_TO_STRING(int obits, char* destoutp, WDataInP sourcep) {
|
||||
while (isspace(*(destp-1)) && destp>destoutp) *--destp = '\0'; // Drop trailing spaces
|
||||
}
|
||||
|
||||
void _VL_STRING_TO_VINT(int obits, void* destp, int srclen, const char* srcp) {
|
||||
// Convert C string to Verilog format
|
||||
int bytes = VL_BYTES_I(obits);
|
||||
char* op = ((char*)(destp));
|
||||
if (srclen > bytes) srclen = bytes; // Don't overflow destination
|
||||
int i;
|
||||
for (i=0; i<srclen; i++) { *op++ = srcp[srclen-1-i]; }
|
||||
for (; i<bytes; i++) { *op++ = 0; }
|
||||
}
|
||||
|
||||
IData VL_FGETS_IXQ(int obits, void* destp, QData fpq) {
|
||||
FILE* fp = VL_CVT_Q_FP(fpq);
|
||||
if (VL_UNLIKELY(!fp)) return 0;
|
||||
|
||||
// The string needs to be padded with 0's in unused spaces in front of
|
||||
// any read data. This means we can't know in what location the first
|
||||
// character will finally live, so we need to copy. Yuk.
|
||||
IData bytes = VL_BYTES_I(obits);
|
||||
char buffer[bytes];
|
||||
|
||||
// We don't use fgets, as we must read \0s.
|
||||
IData got = 0;
|
||||
char* cp = buffer;
|
||||
while (got < bytes) {
|
||||
int c = getc(fp);
|
||||
if (c==EOF) break;
|
||||
*cp++ = c; got++;
|
||||
if (c=='\n') break;
|
||||
}
|
||||
|
||||
_VL_STRING_TO_VINT(obits, destp, got, buffer);
|
||||
return got;
|
||||
}
|
||||
|
||||
QData VL_FOPEN_QI(QData filename, IData mode) {
|
||||
IData fnw[2]; VL_SET_WQ(fnw, filename);
|
||||
return VL_FOPEN_WI(2, fnw, mode);
|
||||
@@ -240,6 +550,67 @@ QData VL_FOPEN_WI(int fnwords, WDataInP filenamep, IData mode) {
|
||||
return VL_CVT_FP_Q(fopen(filenamez,modez));
|
||||
}
|
||||
|
||||
void VL_WRITEF(const char* formatp, ...) {
|
||||
va_list ap;
|
||||
va_start(ap,formatp);
|
||||
string output;
|
||||
_vl_vsformat(output, formatp, ap);
|
||||
va_end(ap);
|
||||
|
||||
// Users can redefine VL_PRINTF if they wish.
|
||||
VL_PRINTF("%s", output.c_str());
|
||||
}
|
||||
|
||||
void VL_FWRITEF(QData fpq, const char* formatp, ...) {
|
||||
FILE* fp = VL_CVT_Q_FP(fpq);
|
||||
if (VL_UNLIKELY(!fp)) return;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap,formatp);
|
||||
string output;
|
||||
_vl_vsformat(output, formatp, ap);
|
||||
va_end(ap);
|
||||
|
||||
fputs(output.c_str(), fp);
|
||||
}
|
||||
|
||||
IData VL_FSCANF_IX(QData fpq, const char* formatp, ...) {
|
||||
FILE* fp = VL_CVT_Q_FP(fpq);
|
||||
if (VL_UNLIKELY(!fp)) return 0;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap,formatp);
|
||||
IData got = _vl_vsscanf(fp, 0, NULL, formatp, ap);
|
||||
va_end(ap);
|
||||
return got;
|
||||
}
|
||||
|
||||
IData VL_SSCANF_IIX(int lbits, IData ld, const char* formatp, ...) {
|
||||
IData fnw[2]; VL_SET_WI(fnw, ld);
|
||||
|
||||
va_list ap;
|
||||
va_start(ap,formatp);
|
||||
IData got = _vl_vsscanf(NULL, lbits, fnw, formatp, ap);
|
||||
va_end(ap);
|
||||
return got;
|
||||
}
|
||||
IData VL_SSCANF_IQX(int lbits, QData ld, const char* formatp, ...) {
|
||||
IData fnw[2]; VL_SET_WQ(fnw, ld);
|
||||
|
||||
va_list ap;
|
||||
va_start(ap,formatp);
|
||||
IData got = _vl_vsscanf(NULL, lbits, fnw, formatp, ap);
|
||||
va_end(ap);
|
||||
return got;
|
||||
}
|
||||
IData VL_SSCANF_IWX(int lbits, WDataInP lwp, const char* formatp, ...) {
|
||||
va_list ap;
|
||||
va_start(ap,formatp);
|
||||
IData got = _vl_vsscanf(NULL, lbits, lwp, formatp, ap);
|
||||
va_end(ap);
|
||||
return got;
|
||||
}
|
||||
|
||||
void VL_READMEM_Q(bool hex, int width, int depth, int array_lsb, int,
|
||||
QData ofilename, void* memp, IData start, IData end) {
|
||||
IData fnw[2]; VL_SET_WQ(fnw, ofilename);
|
||||
|
||||
+25
-14
@@ -29,11 +29,11 @@
|
||||
|
||||
#include "verilatedos.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <cassert>
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
@@ -179,21 +179,21 @@ extern void vl_fatal (const char* filename, int linenum, const char* hier,
|
||||
const char* msg);
|
||||
|
||||
//=========================================================================
|
||||
// Extern functions -- Init time only, so slow is fine
|
||||
// Extern functions -- Slow path
|
||||
|
||||
extern IData VL_RANDOM_I(int obits); ///< Randomize a signal
|
||||
extern QData VL_RANDOM_Q(int obits); ///< Randomize a signal
|
||||
extern WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp); ///< Randomize a signal
|
||||
|
||||
/// Init time only, so slow is fine
|
||||
extern IData VL_RAND_RESET_I(int obits); ///< Random reset a signal
|
||||
extern QData VL_RAND_RESET_Q(int obits); ///< Random reset a signal
|
||||
extern WDataOutP VL_RAND_RESET_W(int obits, WDataOutP outwp); ///< Random reset a signal
|
||||
extern WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp); ///< Zero reset a signal
|
||||
|
||||
/// Return string with formated Verilog value
|
||||
extern const char* VL_VALUE_FORMATTED_W(int obits, char fmt, bool drop0, WDataInP lwp);
|
||||
extern const char* VL_VALUE_FORMATTED_Q(int obits, char fmt, bool drop0, QData ld);
|
||||
inline const char* VL_VALUE_FORMATTED_I(int obits, char fmt, bool drop0, IData ld) {
|
||||
return VL_VALUE_FORMATTED_Q(obits,fmt,drop0,ld);
|
||||
}
|
||||
|
||||
/// File I/O
|
||||
extern IData VL_FGETS_IXQ(int sbits, void* strgp, QData fpq);
|
||||
|
||||
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); }
|
||||
@@ -206,6 +206,14 @@ inline void VL_READMEM_I(bool hex, int width, int depth, int array_lsb, int fnwo
|
||||
IData ofilename, void* memp, IData start, IData end) {
|
||||
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 IData VL_FSCANF_IX(QData fpq, 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, ...);
|
||||
|
||||
//=========================================================================
|
||||
// Base macros
|
||||
|
||||
@@ -213,9 +221,12 @@ inline void VL_READMEM_I(bool hex, int width, int depth, int array_lsb, int fnwo
|
||||
#define VL_BITISSET_I(data,bit) (data & (VL_UL(1)<<VL_BITBIT_I(bit)))
|
||||
#define VL_BITISSET_Q(data,bit) (data & (VL_ULL(1)<<VL_BITBIT_Q(bit)))
|
||||
#define VL_BITISSET_W(data,bit) (data[VL_BITWORD_I(bit)] & (VL_UL(1)<<VL_BITBIT_I(bit)))
|
||||
#define VL_BITISSETLIMIT_W(data,width,bit) (((bit)<(width)) && data[VL_BITWORD_I(bit)] & (VL_UL(1)<<VL_BITBIT_I(bit)))
|
||||
|
||||
/// Create two 32-bit words from quadword
|
||||
#define VL_SET_WQ(decl,data) { decl[0]=(data); decl[1]=((data)>>VL_WORDSIZE); }
|
||||
#define VL_SET_WQ(owp,data) { owp[0]=(data); owp[1]=((data)>>VL_WORDSIZE); }
|
||||
#define VL_SET_WI(owp,data) { owp[0]=(data); owp[1]=0; }
|
||||
#define VL_SET_QW(lwp) ( ((QData)(lwp[0])) | ((QData)(lwp[1])<<((QData)(VL_WORDSIZE)) ))
|
||||
|
||||
// Use a union to avoid cast-to-different-size warnings
|
||||
/// Return FILE* from QData
|
||||
|
||||
@@ -110,10 +110,14 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
||||
//=========================================================================
|
||||
// Integer size macros
|
||||
|
||||
#define VL_BYTESIZE 8 ///< Bits in a byte
|
||||
#define VL_SHORTSIZE 16 ///< Bits in a short
|
||||
#define VL_WORDSIZE 32 ///< Bits in a word
|
||||
#define VL_QUADSIZE 64 ///< Bits in a quadword
|
||||
#define VL_WORDSIZE_LOG2 5 ///< log2(VL_WORDSIZE)
|
||||
|
||||
/// Bytes this number of bits needs (1 bit=1 byte)
|
||||
#define VL_BYTES_I(nbits) (((nbits)+(VL_BYTESIZE-1))/VL_BYTESIZE)
|
||||
/// Words this number of bits needs (1 bit=1 word)
|
||||
#define VL_WORDS_I(nbits) (((nbits)+(VL_WORDSIZE-1))/VL_WORDSIZE)
|
||||
|
||||
|
||||
+5
-1
@@ -46,6 +46,10 @@ export OBJCACHE_JOBS := -j $(shell objcache --jobs "$(OBJCACHE_HOSTS)")
|
||||
export OBJCACHE := @objcache --read --write
|
||||
endif
|
||||
|
||||
UNDER_GIT = $(wildcard ../.git)
|
||||
|
||||
#*********************************************************************
|
||||
|
||||
obj_opt:
|
||||
mkdir $@
|
||||
obj_dbg:
|
||||
@@ -71,7 +75,7 @@ dbg: ../verilator_bin_dbg
|
||||
|
||||
prefiles::
|
||||
|
||||
ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users
|
||||
ifneq ($(UNDER_GIT),) # If local git tree... Else don't burden users
|
||||
prefiles:: config_rev.h
|
||||
# This output goes into srcdir, as we need to distribute it as part of the kit.
|
||||
config_rev.h: config_rev.pl ../.git/index
|
||||
|
||||
+2
-2
@@ -32,8 +32,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
|
||||
+2
-2
@@ -29,8 +29,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
+2
-2
@@ -20,8 +20,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <map>
|
||||
#include <iomanip>
|
||||
|
||||
+2
-2
@@ -23,8 +23,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <map>
|
||||
#include <iomanip>
|
||||
|
||||
+2
-2
@@ -18,8 +18,8 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <memory>
|
||||
|
||||
+24
-5
@@ -197,7 +197,8 @@ public:
|
||||
TRIWIRE,
|
||||
BLOCKTEMP,
|
||||
MODULETEMP,
|
||||
STMTTEMP
|
||||
STMTTEMP,
|
||||
XTEMP
|
||||
};
|
||||
enum en m_e;
|
||||
inline AstVarType () {};
|
||||
@@ -209,7 +210,7 @@ public:
|
||||
"?","GPARAM","LPARAM","GENVAR",
|
||||
"INTEGER","INPUT","OUTPUT","INOUT",
|
||||
"SUPPLY0","SUPPLY1","WIRE","IMPLICIT","REG","TRIWIRE",
|
||||
"BLOCKTEMP","MODULETEMP","STMTTEMP"};
|
||||
"BLOCKTEMP","MODULETEMP","STMTTEMP","XTEMP"};
|
||||
return names[m_e];};
|
||||
};
|
||||
inline bool operator== (AstVarType lhs, AstVarType rhs) { return (lhs.m_e == rhs.m_e); }
|
||||
@@ -250,6 +251,25 @@ public:
|
||||
|
||||
//######################################################################
|
||||
|
||||
class AstCaseType {
|
||||
public:
|
||||
enum en {
|
||||
CASE,
|
||||
CASEX,
|
||||
CASEZ
|
||||
};
|
||||
enum en m_e;
|
||||
inline AstCaseType () {};
|
||||
inline AstCaseType (en _e) : m_e(_e) {};
|
||||
explicit inline AstCaseType (int _e) : m_e(static_cast<en>(_e)) {};
|
||||
operator en () const { return m_e; };
|
||||
};
|
||||
inline bool operator== (AstCaseType lhs, AstCaseType rhs) { return (lhs.m_e == rhs.m_e); }
|
||||
inline bool operator== (AstCaseType lhs, AstCaseType::en rhs) { return (lhs.m_e == rhs); }
|
||||
inline bool operator== (AstCaseType::en lhs, AstCaseType rhs) { return (lhs == rhs.m_e); }
|
||||
|
||||
//######################################################################
|
||||
|
||||
class AstDisplayType {
|
||||
public:
|
||||
enum en {
|
||||
@@ -651,7 +671,6 @@ public:
|
||||
virtual bool same(AstNode* otherp) const { return true; }
|
||||
virtual bool maybePointedTo() const { return false; } // Another AstNode* may have a pointer into this node, other then normal front/back/etc.
|
||||
virtual bool broken() const { return false; }
|
||||
virtual bool emitWordForm() { return false; }
|
||||
|
||||
// INVOKERS
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) = 0;
|
||||
@@ -682,7 +701,7 @@ struct AstNodeMath : public AstNode {
|
||||
virtual ~AstNodeMath() {}
|
||||
// METHODS
|
||||
virtual string emitVerilog() = 0; /// Format string for verilog writing; see V3EmitV
|
||||
virtual string emitOperator() = 0;
|
||||
virtual string emitC() = 0;
|
||||
virtual string emitSimpleOperator() { return ""; }
|
||||
virtual bool cleanOut() = 0; // True if output has extra upper bits zero
|
||||
};
|
||||
@@ -784,7 +803,7 @@ struct AstNodeCond : public AstNodeTriop {
|
||||
AstNode* expr1p() const { return op2p()->castNode(); } // op2 = If true...
|
||||
AstNode* expr2p() const { return op3p()->castNode(); } // op3 = If false...
|
||||
virtual string emitVerilog() { return "%k(%l %k? %r %k: %t)"; }
|
||||
virtual string emitOperator() { return "VL_COND"; }
|
||||
virtual string emitC() { return "VL_COND_%nq%lq%rq%tq(%nw,%lw,%rw,%tw, %P, %li, %ri, %ti)"; }
|
||||
virtual bool cleanOut() { return false; } // clean if e1 & e2 clean
|
||||
virtual bool cleanLhs() { return true; }
|
||||
virtual bool cleanRhs() { return false; } virtual bool cleanThs() { return false; } // Propagates up
|
||||
|
||||
+2
-2
@@ -20,8 +20,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <vector>
|
||||
|
||||
+232
-114
@@ -53,7 +53,7 @@ public:
|
||||
uint32_t asInt() const { return num().asInt(); }
|
||||
vluint64_t asQuad() const { return num().asQuad(); }
|
||||
virtual string emitVerilog() { V3ERROR_NA; return ""; } // Implemented specially
|
||||
virtual string emitOperator() { V3ERROR_NA; return ""; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual bool cleanOut() { return true; }
|
||||
virtual V3Hash sameHash() const { return V3Hash(num().asHash()); }
|
||||
virtual bool same(AstNode* samep) const {
|
||||
@@ -81,7 +81,7 @@ struct AstRange : public AstNode {
|
||||
int msbConst() const { AstConst* constp=msbp()->castConst(); return (constp?constp->asInt():0); }
|
||||
int lsbConst() const { AstConst* constp=lsbp()->castConst(); return (constp?constp->asInt():0); }
|
||||
int elementsConst() const { return msbConst()-lsbConst()+1; }
|
||||
virtual string emitOperator() { V3ERROR_NA; return ""; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(AstNode* samep) const { return true; }
|
||||
};
|
||||
@@ -100,7 +100,7 @@ struct AstArraySel : public AstNodeSel {
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) {
|
||||
V3ERROR_NA; /* How can from be a const? */ }
|
||||
virtual string emitVerilog() { return "%k(%l%k[%r])"; }
|
||||
virtual string emitOperator() { V3ERROR_NA; return ""; }
|
||||
virtual string emitC() { return "%li%k[%ri]"; }
|
||||
virtual bool cleanOut() { return true; }
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
@@ -133,7 +133,7 @@ struct AstWordSel : public AstNodeSel {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& from, const V3Number& bit) { V3ERROR_NA; }
|
||||
virtual string emitVerilog() { return "%k(%l[%r])"; } // Not %k, as usually it's a small constant rhsp
|
||||
virtual string emitOperator() { V3ERROR_NA; return ""; }
|
||||
virtual string emitC() { return "%li[%ri]"; } // Not %k, as usually it's a small constant rhsp
|
||||
virtual bool cleanOut() { return true; }
|
||||
virtual bool cleanLhs() { return true; } virtual bool cleanRhs() { return true; }
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
@@ -206,7 +206,10 @@ struct AstSel : public AstNodeTriop {
|
||||
virtual void numberOperate(V3Number& out, const V3Number& from, const V3Number& bit, const V3Number& width) {
|
||||
out.opRange(from, bit.asInt()+width.asInt()-1, bit.asInt()); }
|
||||
virtual string emitVerilog() { V3ERROR_NA; return ""; } // Implemented specially
|
||||
virtual string emitOperator() { V3ERROR_NA; return ""; }
|
||||
virtual string emitC() {
|
||||
return this->widthp()->isOne()
|
||||
? "VL_BITSEL_%nq%lq%rq%tq(%nw,%lw,%rw,%tw, %P, %li, %ri)"
|
||||
: "VL_SEL_%nq%lq%rq%tq(%nw,%lw,%rw,%tw, %P, %li, %ri, %ti)"; }
|
||||
virtual bool cleanOut() { return false; }
|
||||
virtual bool cleanLhs() { return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool cleanThs() {return true;}
|
||||
@@ -332,9 +335,10 @@ public:
|
||||
bool isSignal() const { return (varType()==AstVarType::WIRE || varType()==AstVarType::IMPLICIT
|
||||
|| varType()==AstVarType::REG || varType()==AstVarType::INTEGER); }
|
||||
bool isTemp() const { return (varType()==AstVarType::BLOCKTEMP || varType()==AstVarType::MODULETEMP
|
||||
|| varType()==AstVarType::STMTTEMP); }
|
||||
|| varType()==AstVarType::STMTTEMP || varType()==AstVarType::XTEMP); }
|
||||
bool isStatementTemp() const { return (varType()==AstVarType::STMTTEMP); }
|
||||
bool isMovableToBlock() const { return (varType()==AstVarType::BLOCKTEMP || isFuncLocal()); }
|
||||
bool isPure() const { return (varType()==AstVarType::XTEMP); }
|
||||
bool isParam() const { return (varType()==AstVarType::LPARAM || varType()==AstVarType::GPARAM); }
|
||||
bool isGParam() const { return (varType()==AstVarType::GPARAM); }
|
||||
bool isGenVar() const { return (varType()==AstVarType::GENVAR); }
|
||||
@@ -531,7 +535,7 @@ public:
|
||||
&& varp()->name()==samep->castVarRef()->varp()->name()); }
|
||||
virtual int instrCount() const { return widthInstrs()*(lvalue()?1:instrCountLd()); }
|
||||
virtual string emitVerilog() { V3ERROR_NA; return ""; } // Implemented specially
|
||||
virtual string emitOperator() { V3ERROR_NA; return ""; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual bool cleanOut() { return true; }
|
||||
};
|
||||
|
||||
@@ -559,7 +563,7 @@ public:
|
||||
string inlinedDots() const { return m_inlinedDots; }
|
||||
void inlinedDots(const string& flag) { m_inlinedDots = flag; }
|
||||
virtual string emitVerilog() { V3ERROR_NA; return ""; }
|
||||
virtual string emitOperator() { V3ERROR_NA; return ""; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual bool cleanOut() { return true; }
|
||||
virtual int instrCount() const { return widthInstrs(); }
|
||||
virtual V3Hash sameHash() const { return V3Hash(V3Hash(varp()),V3Hash(dotted())); }
|
||||
@@ -792,7 +796,7 @@ public:
|
||||
virtual V3Hash sameHash() const { return V3Hash(m_expect); }
|
||||
virtual bool same(AstNode* samep) const { return expect() == samep->castParseRef()->expect(); }
|
||||
virtual string emitVerilog() { V3ERROR_NA; return ""; }
|
||||
virtual string emitOperator() { V3ERROR_NA; return ""; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
AstParseRefExp expect() const { return m_expect; }
|
||||
// op1 = Components
|
||||
AstNode* lhsp() const { return op1p(); } // op1 = List of statements
|
||||
@@ -808,7 +812,7 @@ struct AstDot : public AstNode {
|
||||
virtual AstNode* clone() { return new AstDot(*this);}
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual string emitVerilog() { V3ERROR_NA; return ""; }
|
||||
virtual string emitOperator() { V3ERROR_NA; return ""; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
AstNode* lhsp() const { return op1p(); }
|
||||
AstNode* rhsp() const { return op2p(); }
|
||||
};
|
||||
@@ -1191,11 +1195,11 @@ struct AstCase : public AstNodeCase {
|
||||
// exprp Children: MATHs
|
||||
// casesp Children: CASEITEMs
|
||||
private:
|
||||
bool m_casex; // True if casex instead of normal case.
|
||||
AstCaseType m_casex; // 0=case, 1=casex, 2=casez
|
||||
bool m_fullPragma; // Synthesis full_case
|
||||
bool m_parallelPragma; // Synthesis parallel_case
|
||||
public:
|
||||
AstCase(FileLine* fileline, bool casex, AstNode* exprp, AstNode* casesp)
|
||||
AstCase(FileLine* fileline, AstCaseType casex, AstNode* exprp, AstNode* casesp)
|
||||
: AstNodeCase(fileline, exprp, casesp) {
|
||||
m_casex=casex;
|
||||
m_fullPragma=false; m_parallelPragma=false;
|
||||
@@ -1204,11 +1208,14 @@ public:
|
||||
virtual AstType type() const { return AstType::CASE;}
|
||||
virtual AstNode* clone() { return new AstCase(*this); }
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual string verilogKwd() const { return casex()?"casex":"case"; }
|
||||
bool casex() const { return m_casex; }
|
||||
virtual string verilogKwd() const { return casez()?"casez":casex()?"casex":"case"; }
|
||||
virtual bool same(AstNode* samep) const {
|
||||
return m_casex==samep->castCase()->m_casex; }
|
||||
bool casex() const { return m_casex==AstCaseType::CASEX; }
|
||||
bool casez() const { return m_casex==AstCaseType::CASEZ; }
|
||||
bool fullPragma() const { return m_fullPragma; }
|
||||
bool parallelPragma() const { return m_parallelPragma; }
|
||||
void fullPragma(bool flag) { m_fullPragma=flag; }
|
||||
bool parallelPragma() const { return m_parallelPragma; }
|
||||
void parallelPragma(bool flag) { m_parallelPragma=flag; }
|
||||
};
|
||||
|
||||
@@ -1323,6 +1330,101 @@ struct AstFOpen : public AstNodeStmt {
|
||||
AstNode* modep() const { return op3p(); }
|
||||
};
|
||||
|
||||
struct AstFFlush : public AstNodeStmt {
|
||||
// Parents: stmtlist
|
||||
// Children: file which must be a varref
|
||||
AstFFlush(FileLine* fileline, AstNode* filep)
|
||||
: AstNodeStmt (fileline) {
|
||||
setNOp2p(filep);
|
||||
}
|
||||
virtual ~AstFFlush() {}
|
||||
virtual AstType type() const { return AstType::FFLUSH;}
|
||||
virtual AstNode* clone() { return new AstFFlush(*this); }
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual string verilogKwd() const { return "$fflush"; };
|
||||
virtual bool isGateOptimizable() const { return false; }
|
||||
virtual bool isPredictOptimizable() const { return false; }
|
||||
virtual bool isSplittable() const { return false; }
|
||||
virtual bool isOutputter() const { return true; }
|
||||
virtual bool isUnlikely() const { return true; }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(AstNode* samep) const { return true; }
|
||||
AstNode* filep() const { return op2p(); }
|
||||
void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); }
|
||||
};
|
||||
|
||||
struct AstFScanF : public AstNodeMath {
|
||||
// Parents: expr
|
||||
// Children: file which must be a varref
|
||||
// Children: varrefs to load
|
||||
private:
|
||||
string m_text;
|
||||
public:
|
||||
AstFScanF(FileLine* fileline, const string& text, AstNode* filep, AstNode* exprsp)
|
||||
: AstNodeMath (fileline), m_text(text) {
|
||||
addNOp1p(exprsp);
|
||||
setNOp2p(filep);
|
||||
}
|
||||
virtual ~AstFScanF() {}
|
||||
virtual AstType type() const { return AstType::FSCANF;}
|
||||
virtual AstNode* clone() { return new AstFScanF(*this); }
|
||||
virtual string name() const { return m_text; }
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual string verilogKwd() const { return "$fscanf"; }
|
||||
virtual string emitVerilog() { V3ERROR_NA; return ""; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual bool isGateOptimizable() const { return false; }
|
||||
virtual bool isPredictOptimizable() const { return false; }
|
||||
virtual bool isSplittable() const { return false; } // SPECIAL: has 'visual' ordering
|
||||
virtual bool isOutputter() const { return true; } // SPECIAL: makes output
|
||||
virtual bool cleanOut() { return false; }
|
||||
virtual V3Hash sameHash() const { return V3Hash(text()); }
|
||||
virtual bool same(AstNode* samep) const {
|
||||
return text()==samep->castFScanF()->text(); }
|
||||
AstNode* exprsp() const { return op1p()->castNode(); } // op1 = Expressions to output
|
||||
void exprsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to output
|
||||
string text() const { return m_text; } // * = Text to display
|
||||
void text(const string& text) { m_text=text; }
|
||||
AstNode* filep() const { return op2p(); }
|
||||
void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); }
|
||||
};
|
||||
|
||||
struct AstSScanF : public AstNodeMath {
|
||||
// Parents: expr
|
||||
// Children: file which must be a varref
|
||||
// Children: varrefs to load
|
||||
private:
|
||||
string m_text;
|
||||
public:
|
||||
AstSScanF(FileLine* fileline, const string& text, AstNode* fromp, AstNode* exprsp)
|
||||
: AstNodeMath (fileline), m_text(text) {
|
||||
addNOp1p(exprsp);
|
||||
setOp2p(fromp);
|
||||
}
|
||||
virtual ~AstSScanF() {}
|
||||
virtual AstType type() const { return AstType::SSCANF;}
|
||||
virtual AstNode* clone() { return new AstSScanF(*this); }
|
||||
virtual string name() const { return m_text; }
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual string verilogKwd() const { return "$sscanf"; }
|
||||
virtual string emitVerilog() { V3ERROR_NA; return ""; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual bool isGateOptimizable() const { return false; }
|
||||
virtual bool isPredictOptimizable() const { return false; }
|
||||
virtual bool isSplittable() const { return false; } // SPECIAL: has 'visual' ordering
|
||||
virtual bool isOutputter() const { return true; } // SPECIAL: makes output
|
||||
virtual bool cleanOut() { return false; }
|
||||
virtual V3Hash sameHash() const { return V3Hash(text()); }
|
||||
virtual bool same(AstNode* samep) const {
|
||||
return text()==samep->castSScanF()->text(); }
|
||||
AstNode* exprsp() const { return op1p()->castNode(); } // op1 = Expressions to output
|
||||
void exprsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to output
|
||||
string text() const { return m_text; } // * = Text to display
|
||||
void text(const string& text) { m_text=text; }
|
||||
AstNode* fromp() const { return op2p(); }
|
||||
void fromp(AstNode* nodep) { setOp2p(nodep); }
|
||||
};
|
||||
|
||||
struct AstReadMem : public AstNodeStmt {
|
||||
private:
|
||||
bool m_isHex; // readmemh, not readmemb
|
||||
@@ -1451,9 +1553,8 @@ struct AstChangeXor : public AstNodeBiComAsv {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opChangeXor(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l ^ %r)"; }
|
||||
virtual string emitOperator() { return "VL_CHANGEXOR"; }
|
||||
virtual string emitC() { return "VL_CHANGEXOR_%li(%lw, %P, %li, %ri)"; }
|
||||
virtual string emitSimpleOperator() { return "^"; }
|
||||
virtual bool emitWordForm() { return true; }
|
||||
virtual bool cleanOut() {return false;} // Lclean && Rclean
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
@@ -1745,14 +1846,21 @@ struct AstScopeName : public AstNode {
|
||||
|
||||
struct AstRand : public AstNodeTermop {
|
||||
// Return a random number, based upon width()
|
||||
AstRand(FileLine* fl, int wwidth) : AstNodeTermop(fl) {
|
||||
width(wwidth,wwidth); }
|
||||
private:
|
||||
bool m_reset; // Random reset, versus always random
|
||||
public:
|
||||
AstRand(FileLine* fl, int wwidth, bool reset) : AstNodeTermop(fl) {
|
||||
width(wwidth,wwidth); m_reset=reset; }
|
||||
AstRand(FileLine* fl) : AstNodeTermop(fl), m_reset(false) { }
|
||||
virtual ~AstRand() {}
|
||||
virtual AstType type() const { return AstType::RAND;}
|
||||
virtual AstNode* clone() { return new AstRand(*this); }
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual string emitVerilog() { return "$random"; }
|
||||
virtual string emitOperator() { return "VL_RAND_RESET"; }
|
||||
virtual string emitC() {
|
||||
return (m_reset ?
|
||||
"VL_RAND_RESET_%nq(%nw, %P)"
|
||||
:"VL_RANDOM_%nq(%nw, %P)"); }
|
||||
virtual bool cleanOut() { return true; }
|
||||
virtual bool isGateOptimizable() const { return false; }
|
||||
virtual bool isPredictOptimizable() const { return false; }
|
||||
@@ -1769,7 +1877,7 @@ struct AstTime : public AstNodeTermop {
|
||||
virtual AstNode* clone() { return new AstTime(*this); }
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual string emitVerilog() { return "$time"; }
|
||||
virtual string emitOperator() { return "VL_TIME"; }
|
||||
virtual string emitC() { return "VL_TIME_%nq()"; }
|
||||
virtual bool cleanOut() { return true; }
|
||||
virtual bool isGateOptimizable() const { return false; }
|
||||
virtual bool isPredictOptimizable() const { return false; }
|
||||
@@ -1791,7 +1899,7 @@ public:
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual bool cleanOut() { return false; }
|
||||
virtual string emitVerilog() { V3ERROR_NA; return ""; } // Implemented specially
|
||||
virtual string emitOperator() { V3ERROR_NA; return ""; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
AstNode* bodysp() const { return op1p()->castNode(); } // op1= expressions to print
|
||||
virtual bool isSplittable() const { return false; } // SPECIAL: User may order w/other sigs
|
||||
virtual bool isOutputter() const { return true; }
|
||||
@@ -1815,8 +1923,7 @@ struct AstUnaryMin : public AstNodeUniop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opUnaryMin(lhs); }
|
||||
virtual string emitVerilog() { return "%k(- %l)"; }
|
||||
virtual string emitOperator() { return "VL_UNARYMIN"; }
|
||||
virtual bool emitWordForm() { return true; }
|
||||
virtual string emitC() { return "VL_UNARYMIN_%lq(%lW, %P, %li)"; }
|
||||
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return true;}
|
||||
};
|
||||
@@ -1829,7 +1936,7 @@ struct AstRedAnd : public AstNodeUniop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedAnd(lhs); }
|
||||
virtual string emitVerilog() { return "%k(& %l)"; }
|
||||
virtual string emitOperator() { return "VL_REDAND"; }
|
||||
virtual string emitC() { return "VL_REDAND_%nq%lq(%nw,%lw, %P, %li)"; }
|
||||
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;}
|
||||
};
|
||||
@@ -1842,8 +1949,7 @@ struct AstRedOr : public AstNodeUniop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedOr(lhs); }
|
||||
virtual string emitVerilog() { return "%k(| %l)"; }
|
||||
virtual string emitOperator() { return "VL_REDOR"; }
|
||||
virtual bool emitWordForm() { return true; }
|
||||
virtual string emitC() { return "VL_REDOR_%lq(%lW, %P, %li)"; }
|
||||
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;}
|
||||
};
|
||||
@@ -1856,8 +1962,7 @@ struct AstRedXor : public AstNodeUniop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedXor(lhs); }
|
||||
virtual string emitVerilog() { return "%k(^ %l)"; }
|
||||
virtual string emitOperator() { return "VL_REDXOR"; }
|
||||
virtual bool emitWordForm() { return true; }
|
||||
virtual string emitC() { return "VL_REDXOR_%lq(%lW, %P, %li)"; }
|
||||
virtual bool cleanOut() {return false;}
|
||||
virtual bool cleanLhs() {return (lhsp()->width()!=1 && lhsp()->width()!=2 && lhsp()->width()!=4
|
||||
&& lhsp()->width()!=8 && lhsp()->width()!=16);}
|
||||
@@ -1874,8 +1979,7 @@ struct AstRedXnor : public AstNodeUniop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedXnor(lhs); }
|
||||
virtual string emitVerilog() { return "%k(~^ %l)"; }
|
||||
virtual string emitOperator() { v3fatalSrc("REDXNOR should have became REDXOR"); return ""; }
|
||||
virtual bool emitWordForm() { return true; }
|
||||
virtual string emitC() { v3fatalSrc("REDXNOR should have became REDXOR"); return ""; }
|
||||
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;}
|
||||
virtual int instrCount() const { return 1+V3Number::log2b(width()); }
|
||||
@@ -1890,7 +1994,7 @@ struct AstLogNot : public AstNodeUniop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opLogNot(lhs); }
|
||||
virtual string emitVerilog() { return "%k(! %l)"; }
|
||||
virtual string emitOperator() { return "VL_LOGNOT"; }
|
||||
virtual string emitC() { return "VL_LOGNOT_%nq%lq(%nw,%lw, %P, %li)"; }
|
||||
virtual string emitSimpleOperator() { return "!"; }
|
||||
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;}
|
||||
@@ -1904,9 +2008,8 @@ struct AstNot : public AstNodeUniop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opNot(lhs); }
|
||||
virtual string emitVerilog() { return "%k(~ %l)"; }
|
||||
virtual string emitOperator() { return "VL_NOT"; }
|
||||
virtual string emitC() { return "VL_NOT_%lq(%lW, %P, %li)"; }
|
||||
virtual string emitSimpleOperator() { return "~"; }
|
||||
virtual bool emitWordForm() { return true; }
|
||||
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return true;}
|
||||
};
|
||||
@@ -1919,7 +2022,7 @@ struct AstExtend : public AstNodeUniop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); }
|
||||
virtual string emitVerilog() { return "%l"; }
|
||||
virtual string emitOperator() { return "VL_EXTEND"; }
|
||||
virtual string emitC() { return "VL_EXTEND_%nq%lq(%nw,%lw, %P, %li)"; }
|
||||
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} // Because the EXTEND operator self-casts
|
||||
virtual int instrCount() const { return 0; }
|
||||
@@ -1933,7 +2036,7 @@ struct AstExtendS : public AstNodeUniop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opExtendS(lhs); }
|
||||
virtual string emitVerilog() { return "%l"; }
|
||||
virtual string emitOperator() { return "VL_EXTENDS"; }
|
||||
virtual string emitC() { return "VL_EXTENDS_%nq%lq(%nw,%lw, %P, %li)"; }
|
||||
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} // Because the EXTEND operator self-casts
|
||||
virtual int instrCount() const { return 0; }
|
||||
@@ -1950,7 +2053,7 @@ struct AstSigned : public AstNodeUniop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); out.isSigned(false); }
|
||||
virtual string emitVerilog() { return "%k$signed(%l)"; }
|
||||
virtual string emitOperator() { V3ERROR_NA; return ""; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;} // Eliminated before matters
|
||||
virtual bool sizeMattersLhs() {return true;} // Eliminated before matters
|
||||
virtual int instrCount() const { return 0; }
|
||||
@@ -1966,7 +2069,7 @@ struct AstUnsigned : public AstNodeUniop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); out.isSigned(false); }
|
||||
virtual string emitVerilog() { return "%k$unsigned(%l)"; }
|
||||
virtual string emitOperator() { V3ERROR_NA; return ""; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;} // Eliminated before matters
|
||||
virtual bool sizeMattersLhs() {return true;} // Eliminated before matters
|
||||
virtual int instrCount() const { return 0; }
|
||||
@@ -1979,8 +2082,7 @@ struct AstCLog2 : public AstNodeUniop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opCLog2(lhs); }
|
||||
virtual string emitVerilog() { return "%k$clog2(%l)"; }
|
||||
virtual bool emitWordForm() { return true; }
|
||||
virtual string emitOperator() { return "VL_CLOG2"; }
|
||||
virtual string emitC() { return "VL_CLOG2_%lq(%lW, %P, %li)"; }
|
||||
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;}
|
||||
virtual int instrCount() const { return widthInstrs()*16; }
|
||||
@@ -1994,8 +2096,7 @@ struct AstCountOnes : public AstNodeUniop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opCountOnes(lhs); }
|
||||
virtual string emitVerilog() { return "%k$countones(%l)"; }
|
||||
virtual bool emitWordForm() { return true; }
|
||||
virtual string emitOperator() { return "VL_COUNTONES"; }
|
||||
virtual string emitC() { return "VL_COUNTONES_%lq(%lW, %P, %li)"; }
|
||||
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;}
|
||||
virtual int instrCount() const { return widthInstrs()*16; }
|
||||
@@ -2010,7 +2111,7 @@ struct AstIsUnknown : public AstNodeUniop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opIsUnknown(lhs); }
|
||||
virtual string emitVerilog() { return "%k$isunknown(%l)"; }
|
||||
virtual string emitOperator() { V3ERROR_NA; return ""; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return false;}
|
||||
};
|
||||
@@ -2024,8 +2125,7 @@ struct AstOneHot : public AstNodeUniop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opOneHot(lhs); }
|
||||
virtual string emitVerilog() { return "%k$onehot(%l)"; }
|
||||
virtual bool emitWordForm() { return true; }
|
||||
virtual string emitOperator() { return "VL_ONEHOT"; }
|
||||
virtual string emitC() { return "VL_ONEHOT_%lq(%lW, %P, %li)"; }
|
||||
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;}
|
||||
virtual int instrCount() const { return widthInstrs()*4; }
|
||||
@@ -2040,8 +2140,7 @@ struct AstOneHot0 : public AstNodeUniop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opOneHot0(lhs); }
|
||||
virtual string emitVerilog() { return "%k$onehot0(%l)"; }
|
||||
virtual bool emitWordForm() { return true; }
|
||||
virtual string emitOperator() { return "VL_ONEHOT0"; }
|
||||
virtual string emitC() { return "VL_ONEHOT0_%lq(%lW, %P, %li)"; }
|
||||
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;}
|
||||
virtual int instrCount() const { return widthInstrs()*3; }
|
||||
@@ -2066,7 +2165,7 @@ public:
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); }
|
||||
virtual string emitVerilog() { return "%k$_CAST(%l)"; }
|
||||
virtual string emitOperator() { return "VL_CAST"; }
|
||||
virtual string emitC() { return "VL_CAST_%nq%lq(%nw,%lw, %P, %li)"; }
|
||||
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} // Special cased in V3Cast
|
||||
virtual V3Hash sameHash() const { return V3Hash(size()); }
|
||||
@@ -2076,6 +2175,37 @@ public:
|
||||
int size() const { return m_size; }
|
||||
};
|
||||
|
||||
struct AstFEof : public AstNodeUniop {
|
||||
AstFEof(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {}
|
||||
virtual ~AstFEof() {}
|
||||
virtual AstType type() const { return AstType::FEOF;}
|
||||
virtual AstNode* clone() { return new AstFEof(*this); }
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { V3ERROR_NA; }
|
||||
virtual string emitVerilog() { return "%k$feof(%l)"; }
|
||||
virtual string emitC() { return "(%li ? feof(VL_CVT_Q_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; }
|
||||
AstNode* filep() const { return lhsp(); }
|
||||
};
|
||||
|
||||
struct AstFGetC : public AstNodeUniop {
|
||||
AstFGetC(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {}
|
||||
virtual ~AstFGetC() {}
|
||||
virtual AstType type() const { return AstType::FEOF;}
|
||||
virtual AstNode* clone() { return new AstFGetC(*this); }
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { V3ERROR_NA; }
|
||||
virtual string emitVerilog() { return "%k$fgetc(%l)"; }
|
||||
// Non-existant filehandle returns EOF
|
||||
virtual string emitC() { return "(%li ? fgetc(VL_CVT_Q_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; }
|
||||
AstNode* filep() const { return lhsp(); }
|
||||
};
|
||||
|
||||
//======================================================================
|
||||
// Binary ops
|
||||
|
||||
@@ -2088,7 +2218,7 @@ struct AstLogOr : public AstNodeBiComAsv {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLogOr(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %k|| %r)"; }
|
||||
virtual string emitOperator() { return "VL_LOGOR"; }
|
||||
virtual string emitC() { return "VL_LOGOR_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
virtual string emitSimpleOperator() { return "||"; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
@@ -2104,7 +2234,7 @@ struct AstLogAnd : public AstNodeBiComAsv {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLogAnd(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %k&& %r)"; }
|
||||
virtual string emitOperator() { return "VL_LOGAND"; }
|
||||
virtual string emitC() { return "VL_LOGAND_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
virtual string emitSimpleOperator() { return "&&"; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
@@ -2120,7 +2250,7 @@ struct AstLogIf : public AstNodeBiop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { V3ERROR_NA; }
|
||||
virtual string emitVerilog() { return "%k(%l %k-> %r)"; }
|
||||
virtual string emitOperator() { return "VL_LOGIF"; }
|
||||
virtual string emitC() { return "VL_LOGIF_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
virtual string emitSimpleOperator() { return "->"; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
@@ -2136,7 +2266,7 @@ struct AstLogIff : public AstNodeBiCom {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { V3ERROR_NA; }
|
||||
virtual string emitVerilog() { return "%k(%l %k<-> %r)"; }
|
||||
virtual string emitOperator() { return "VL_LOGIFF"; }
|
||||
virtual string emitC() { return "VL_LOGIFF_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
virtual string emitSimpleOperator() { return "<->"; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
@@ -2152,9 +2282,8 @@ struct AstOr : public AstNodeBiComAsv {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opOr(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %k| %r)"; }
|
||||
virtual string emitOperator() { return "VL_OR"; }
|
||||
virtual string emitC() { return "VL_OR_%lq(%lW, %P, %li, %ri)"; }
|
||||
virtual string emitSimpleOperator() { return "|"; }
|
||||
virtual bool emitWordForm() { return true; }
|
||||
virtual bool cleanOut() {V3ERROR_NA; return false;} // Lclean && Rclean
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
@@ -2168,9 +2297,8 @@ struct AstAnd : public AstNodeBiComAsv {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opAnd(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %k& %r)"; }
|
||||
virtual string emitOperator() { return "VL_AND"; }
|
||||
virtual string emitC() { return "VL_AND_%lq(%lW, %P, %li, %ri)"; }
|
||||
virtual string emitSimpleOperator() { return "&"; }
|
||||
virtual bool emitWordForm() { return true; }
|
||||
virtual bool cleanOut() {V3ERROR_NA; return false;} // Lclean || Rclean
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
@@ -2184,9 +2312,8 @@ struct AstXor : public AstNodeBiComAsv {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opXor(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %k^ %r)"; }
|
||||
virtual string emitOperator() { return "VL_XOR"; }
|
||||
virtual string emitC() { return "VL_XOR_%lq(%lW, %P, %li, %ri)"; }
|
||||
virtual string emitSimpleOperator() { return "^"; }
|
||||
virtual bool emitWordForm() { return true; }
|
||||
virtual bool cleanOut() {return false;} // Lclean && Rclean
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
@@ -2200,9 +2327,8 @@ struct AstXnor : public AstNodeBiComAsv {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opXnor(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %k^ ~ %r)"; }
|
||||
virtual string emitOperator() { return "VL_XNOR"; }
|
||||
virtual string emitC() { return "VL_XNOR_%lq(%lW, %P, %li, %ri)"; }
|
||||
virtual string emitSimpleOperator() { return "^ ~"; }
|
||||
virtual bool emitWordForm() { return true; }
|
||||
virtual bool cleanOut() {return false;}
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
|
||||
@@ -2216,9 +2342,8 @@ struct AstEq : public AstNodeBiCom {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opEq(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %k== %r)"; }
|
||||
virtual string emitOperator() { return "VL_EQ"; }
|
||||
virtual string emitC() { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; }
|
||||
virtual string emitSimpleOperator() { return "=="; }
|
||||
virtual bool emitWordForm() { return true; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
@@ -2232,9 +2357,8 @@ struct AstNeq : public AstNodeBiCom {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opNeq(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %k!= %r)"; }
|
||||
virtual string emitOperator() { return "VL_NEQ"; }
|
||||
virtual string emitC() { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; }
|
||||
virtual string emitSimpleOperator() { return "!="; }
|
||||
virtual bool emitWordForm() { return true; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
@@ -2248,9 +2372,8 @@ struct AstLt : public AstNodeBiop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLt(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %k< %r)"; }
|
||||
virtual string emitOperator() { return "VL_LT"; }
|
||||
virtual string emitC() { return "VL_LT_%lq(%lW, %P, %li, %ri)"; }
|
||||
virtual string emitSimpleOperator() { return "<"; }
|
||||
virtual bool emitWordForm() { return true; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
@@ -2264,9 +2387,8 @@ struct AstLtS : public AstNodeBiop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLtS(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %k< %r)"; }
|
||||
virtual string emitOperator() { return "VL_LTS"; }
|
||||
virtual string emitC() { return "VL_LTS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
virtual string emitSimpleOperator() { return ""; }
|
||||
virtual bool emitWordForm() { return false; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
@@ -2281,9 +2403,8 @@ struct AstGt : public AstNodeBiop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGt(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %k> %r)"; }
|
||||
virtual string emitOperator() { return "VL_GT"; }
|
||||
virtual string emitC() { return "VL_GT_%lq(%lW, %P, %li, %ri)"; }
|
||||
virtual string emitSimpleOperator() { return ">"; }
|
||||
virtual bool emitWordForm() { return true; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
@@ -2297,9 +2418,8 @@ struct AstGtS : public AstNodeBiop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGtS(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %k> %r)"; }
|
||||
virtual string emitOperator() { return "VL_GTS"; }
|
||||
virtual string emitC() { return "VL_GTS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
virtual string emitSimpleOperator() { return ""; }
|
||||
virtual bool emitWordForm() { return false; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
@@ -2314,9 +2434,8 @@ struct AstGte : public AstNodeBiop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGte(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %k>= %r)"; }
|
||||
virtual string emitOperator() { return "VL_GTE"; }
|
||||
virtual string emitC() { return "VL_GTE_%lq(%lW, %P, %li, %ri)"; }
|
||||
virtual string emitSimpleOperator() { return ">="; }
|
||||
virtual bool emitWordForm() { return true; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
@@ -2330,9 +2449,8 @@ struct AstGteS : public AstNodeBiop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGteS(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %k>= %r)"; }
|
||||
virtual string emitOperator() { return "VL_GTES"; }
|
||||
virtual string emitC() { return "VL_GTES_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
virtual string emitSimpleOperator() { return ""; }
|
||||
virtual bool emitWordForm() { return false; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
@@ -2347,9 +2465,8 @@ struct AstLte : public AstNodeBiop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLte(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %k<= %r)"; }
|
||||
virtual string emitOperator() { return "VL_LTE"; }
|
||||
virtual string emitC() { return "VL_LTE_%lq(%lW, %P, %li, %ri)"; }
|
||||
virtual string emitSimpleOperator() { return "<="; }
|
||||
virtual bool emitWordForm() { return true; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
@@ -2363,9 +2480,8 @@ struct AstLteS : public AstNodeBiop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLteS(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %k<= %r)"; }
|
||||
virtual string emitOperator() { return "VL_LTES"; }
|
||||
virtual string emitC() { return "VL_LTES_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
virtual string emitSimpleOperator() { return ""; }
|
||||
virtual bool emitWordForm() { return false; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
@@ -2382,7 +2498,7 @@ struct AstShiftL : public AstNodeBiop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opShiftL(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %k<< %r)"; }
|
||||
virtual string emitOperator() { return "VL_SHIFTL"; }
|
||||
virtual string emitC() { return "VL_SHIFTL_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
virtual string emitSimpleOperator() { return "<<"; }
|
||||
virtual bool cleanOut() {return false;}
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return true;}
|
||||
@@ -2399,7 +2515,7 @@ struct AstShiftR : public AstNodeBiop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opShiftR(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %k>> %r)"; }
|
||||
virtual string emitOperator() { return "VL_SHIFTR"; }
|
||||
virtual string emitC() { return "VL_SHIFTR_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
virtual string emitSimpleOperator() { return ">>"; }
|
||||
virtual bool cleanOut() {return false;}
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
@@ -2416,7 +2532,7 @@ struct AstShiftRS : public AstNodeBiop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opShiftRS(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %k>>> %r)"; }
|
||||
virtual string emitOperator() { return "VL_SHIFTRS"; }
|
||||
virtual string emitC() { return "VL_SHIFTRS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
virtual string emitSimpleOperator() { return ""; }
|
||||
virtual bool cleanOut() {return false;}
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
@@ -2432,9 +2548,8 @@ struct AstAdd : public AstNodeBiComAsv {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opAdd(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %k+ %r)"; }
|
||||
virtual string emitOperator() { return "VL_ADD"; }
|
||||
virtual string emitC() { return "VL_ADD_%lq(%lW, %P, %li, %ri)"; }
|
||||
virtual string emitSimpleOperator() { return "+"; }
|
||||
virtual bool emitWordForm() { return true; }
|
||||
virtual bool cleanOut() {return false;}
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
|
||||
@@ -2448,9 +2563,8 @@ struct AstSub : public AstNodeBiop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opSub(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %k- %r)"; }
|
||||
virtual string emitOperator() { return "VL_SUB"; }
|
||||
virtual string emitC() { return "VL_SUB_%lq(%lW, %P, %li, %ri)"; }
|
||||
virtual string emitSimpleOperator() { return "-"; }
|
||||
virtual bool emitWordForm() { return true; }
|
||||
virtual bool cleanOut() {return false;}
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
|
||||
@@ -2464,9 +2578,8 @@ struct AstMul : public AstNodeBiComAsv {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opMul(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %k* %r)"; }
|
||||
virtual string emitOperator() { return "VL_MUL"; }
|
||||
virtual string emitC() { return "VL_MUL_%lq(%lW, %P, %li, %ri)"; }
|
||||
virtual string emitSimpleOperator() { return "*"; }
|
||||
virtual bool emitWordForm() { return true; }
|
||||
virtual bool cleanOut() {return false;}
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
|
||||
@@ -2481,9 +2594,8 @@ struct AstMulS : public AstNodeBiComAsv {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opMulS(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %k* %r)"; }
|
||||
virtual string emitOperator() { return "VL_MULS"; }
|
||||
virtual string emitC() { return "VL_MULS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
virtual string emitSimpleOperator() { return ""; }
|
||||
virtual bool emitWordForm() { return false; }
|
||||
virtual bool cleanOut() {return false;}
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
|
||||
@@ -2499,8 +2611,7 @@ struct AstDiv : public AstNodeBiop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opDiv(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %k/ %r)"; }
|
||||
virtual string emitOperator() { return "VL_DIV"; }
|
||||
virtual bool emitWordForm() { return true; }
|
||||
virtual string emitC() { return "VL_DIV_%lq(%lW, %P, %li, %ri)"; }
|
||||
virtual bool cleanOut() {return false;}
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
|
||||
@@ -2515,8 +2626,7 @@ struct AstDivS : public AstNodeBiop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opDivS(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %k/ %r)"; }
|
||||
virtual string emitOperator() { return "VL_DIVS"; }
|
||||
virtual bool emitWordForm() { return false; }
|
||||
virtual string emitC() { return "VL_DIVS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
virtual bool cleanOut() {return false;}
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
|
||||
@@ -2532,8 +2642,7 @@ struct AstModDiv : public AstNodeBiop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opModDiv(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %k%% %r)"; }
|
||||
virtual string emitOperator() { return "VL_MODDIV"; }
|
||||
virtual bool emitWordForm() { return true; }
|
||||
virtual string emitC() { return "VL_MODDIV_%lq(%lW, %P, %li, %ri)"; }
|
||||
virtual bool cleanOut() {return false;}
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
|
||||
@@ -2548,8 +2657,7 @@ struct AstModDivS : public AstNodeBiop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opModDivS(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %k%% %r)"; }
|
||||
virtual string emitOperator() { return "VL_MODDIVS"; }
|
||||
virtual bool emitWordForm() { return false; }
|
||||
virtual string emitC() { return "VL_MODDIVS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
virtual bool cleanOut() {return false;}
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
|
||||
@@ -2565,8 +2673,7 @@ struct AstPow : public AstNodeBiop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opPow(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %k** %r)"; }
|
||||
virtual string emitOperator() { return "VL_POW"; }
|
||||
virtual bool emitWordForm() { return false; }
|
||||
virtual string emitC() { return "VL_POW_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
virtual bool cleanOut() {return false;}
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return false;}
|
||||
@@ -2581,8 +2688,7 @@ struct AstPowS : public AstNodeBiop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opPowS(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %k** %r)"; }
|
||||
virtual string emitOperator() { return "VL_POWS"; }
|
||||
virtual bool emitWordForm() { return false; }
|
||||
virtual string emitC() { return "VL_POWS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
virtual bool cleanOut() {return false;}
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return false;}
|
||||
@@ -2598,9 +2704,8 @@ struct AstEqCase : public AstNodeBiCom {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opCaseEq(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %k=== %r)"; }
|
||||
virtual string emitOperator() { return "VL_EQ"; } // Until have 4 state anyways
|
||||
virtual string emitC() { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; }
|
||||
virtual string emitSimpleOperator() { return "=="; }
|
||||
virtual bool emitWordForm() { return true; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
@@ -2614,9 +2719,8 @@ struct AstNeqCase : public AstNodeBiCom {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opCaseNeq(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %k!== %r)"; }
|
||||
virtual string emitOperator() { return "VL_NEQ"; } // Until have 4 state anyways
|
||||
virtual string emitC() { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; }
|
||||
virtual string emitSimpleOperator() { return "!="; }
|
||||
virtual bool emitWordForm() { return true; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
@@ -2631,9 +2735,8 @@ struct AstEqWild : public AstNodeBiop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opWildEq(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %k==? %r)"; }
|
||||
virtual string emitOperator() { return "VL_EQ"; } // Until have 4 state anyways
|
||||
virtual string emitC() { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; }
|
||||
virtual string emitSimpleOperator() { return "=="; }
|
||||
virtual bool emitWordForm() { return true; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
@@ -2647,9 +2750,8 @@ struct AstNeqWild : public AstNodeBiop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opWildNeq(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %k!=? %r)"; }
|
||||
virtual string emitOperator() { return "VL_NEQ"; } // Until have 4 state anyways
|
||||
virtual string emitC() { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; }
|
||||
virtual string emitSimpleOperator() { return "!="; }
|
||||
virtual bool emitWordForm() { return true; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
@@ -2665,7 +2767,7 @@ struct AstConcat : public AstNodeBiop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual string emitVerilog() { return "%k{%l, %k%r}"; }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opConcat(lhs,rhs); }
|
||||
virtual string emitOperator() { return "VL_CONCAT"; }
|
||||
virtual string emitC() { return "VL_CONCAT_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
@@ -2681,12 +2783,28 @@ struct AstReplicate : public AstNodeBiop {
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opRepl(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k{%l{%k%r}}"; }
|
||||
virtual string emitOperator() { return "VL_REPLICATE"; }
|
||||
virtual string emitC() { return "VL_REPLICATE_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
virtual bool cleanOut() {return false;}
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
virtual int instrCount() const { return widthInstrs()*2; }
|
||||
};
|
||||
struct AstFGetS : public AstNodeBiop {
|
||||
AstFGetS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {}
|
||||
virtual ~AstFGetS() {}
|
||||
virtual AstType type() const { return AstType::FEOF;}
|
||||
virtual AstNode* clone() { return new AstFGetS(*this); }
|
||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { V3ERROR_NA; }
|
||||
virtual string emitVerilog() { return "%k$fgets(%l,%r)"; }
|
||||
virtual string emitC() { return "VL_FGETS_%nqX%rq(%lw, %P, &(%li), %ri)"; }
|
||||
virtual bool cleanOut() {return false;}
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
virtual int instrCount() const { return widthInstrs()*64; }
|
||||
AstNode* strgp() const { return lhsp(); }
|
||||
AstNode* filep() const { return rhsp(); }
|
||||
};
|
||||
|
||||
//======================================================================
|
||||
// SysVerilog assertions
|
||||
@@ -3155,7 +3273,7 @@ struct AstCMath : public AstNodeMath {
|
||||
virtual bool isPredictOptimizable() const { return false; }
|
||||
virtual bool cleanOut() { return true; }
|
||||
virtual string emitVerilog() { V3ERROR_NA; return ""; } // Implemented specially
|
||||
virtual string emitOperator() { V3ERROR_NA; return ""; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(AstNode* samep) const { return true; }
|
||||
};
|
||||
|
||||
+2
-2
@@ -28,8 +28,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
|
||||
+2
-2
@@ -26,8 +26,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <map>
|
||||
|
||||
|
||||
+2
-2
@@ -27,8 +27,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
|
||||
+49
-20
@@ -39,8 +39,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
|
||||
@@ -73,7 +73,7 @@ private:
|
||||
}
|
||||
|
||||
// Check for X/Z in non-casex statements
|
||||
if (!nodep->castCase() || !nodep->castCase()->casex()) {
|
||||
{
|
||||
m_caseExprp = nodep;
|
||||
nodep->exprp()->accept(*this);
|
||||
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
|
||||
@@ -83,11 +83,18 @@ private:
|
||||
}
|
||||
}
|
||||
virtual void visit(AstConst* nodep, AstNUser*) {
|
||||
// See also neverItem
|
||||
if (m_caseExprp && nodep->num().isFourState()) {
|
||||
if (m_caseExprp->castGenCase()) {
|
||||
nodep->v3error("Use of x/? constant in generate case statement, (no such thing as 'generate casez')");
|
||||
} else if (m_caseExprp->castCase() && m_caseExprp->castCase()->casex()) {
|
||||
// Don't sweat it, we already complained about casex in general
|
||||
} else if (m_caseExprp->castCase() && m_caseExprp->castCase()->casez()) {
|
||||
if (nodep->num().isUnknown()) {
|
||||
nodep->v3warn(CASEWITHX, "Use of x constant in casez statement, (perhaps intended ?/z in constant)");
|
||||
}
|
||||
} else {
|
||||
nodep->v3error("Use of x/? constant in case statement, (perhaps intended casex/casez)");
|
||||
nodep->v3warn(CASEWITHX, "Use of x/? constant in case statement, (perhaps intended casex/casez)");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -152,20 +159,24 @@ private:
|
||||
//if (debug()>=9) icondp->dumpTree(cout," caseitem: ");
|
||||
AstConst* iconstp = icondp->castConst();
|
||||
if (!iconstp) nodep->v3fatalSrc("above 'can't parse' should have caught this\n");
|
||||
V3Number nummask (itemp->fileline(), iconstp->width());
|
||||
nummask.opBitsNonX(iconstp->num());
|
||||
uint32_t mask = nummask.asInt();
|
||||
V3Number numval (itemp->fileline(), iconstp->width());
|
||||
numval.opBitsOne(iconstp->num());
|
||||
uint32_t val = numval.asInt();
|
||||
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) {
|
||||
if ((i & mask) == val) {
|
||||
if (!m_valueItem[i]) {
|
||||
m_valueItem[i] = itemp;
|
||||
} else if (!itemp->ignoreOverlap() && !bitched) {
|
||||
itemp->v3warn(CASEOVERLAP,"Case values overlap (example pattern 0x"<<hex<<i<<")");
|
||||
bitched = true;
|
||||
m_caseNoOverlapsAllCovered = false;
|
||||
if (neverItem(nodep, iconstp)) {
|
||||
// X in casez can't ever be executed
|
||||
} else {
|
||||
V3Number nummask (itemp->fileline(), iconstp->width());
|
||||
nummask.opBitsNonX(iconstp->num());
|
||||
uint32_t mask = nummask.asInt();
|
||||
V3Number numval (itemp->fileline(), iconstp->width());
|
||||
numval.opBitsOne(iconstp->num());
|
||||
uint32_t val = numval.asInt();
|
||||
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) {
|
||||
if ((i & mask) == val) {
|
||||
if (!m_valueItem[i]) {
|
||||
m_valueItem[i] = itemp;
|
||||
} else if (!itemp->ignoreOverlap() && !bitched) {
|
||||
itemp->v3warn(CASEOVERLAP,"Case values overlap (example pattern 0x"<<hex<<i<<")");
|
||||
bitched = true;
|
||||
m_caseNoOverlapsAllCovered = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -296,8 +307,15 @@ private:
|
||||
AstNode* and1p;
|
||||
AstNode* and2p;
|
||||
AstConst* iconstp = icondp->castConst();
|
||||
if (iconstp && iconstp->num().isFourState()
|
||||
&& nodep->casex()) {
|
||||
if (iconstp && neverItem(nodep, iconstp)) {
|
||||
// X in casez can't ever be executed
|
||||
icondp->deleteTree(); icondp=NULL; iconstp=NULL;
|
||||
// For simplicity, make expression that is not equal, and let later
|
||||
// optimizations remove it
|
||||
and1p = new AstConst(itemp->fileline(), V3Number(itemp->fileline(),1,0));
|
||||
and2p = new AstConst(itemp->fileline(), V3Number(itemp->fileline(),1,1));
|
||||
} else if (iconstp && iconstp->num().isFourState()
|
||||
&& (nodep->casex() || nodep->casez())) {
|
||||
V3Number nummask (itemp->fileline(), iconstp->width());
|
||||
nummask.opBitsNonX(iconstp->num());
|
||||
V3Number numval (itemp->fileline(), iconstp->width());
|
||||
@@ -394,6 +412,17 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
bool neverItem(AstCase* casep, AstConst* itemp) {
|
||||
// Xs in case or casez are impossible due to two state simulations
|
||||
if (casep->casex()) {
|
||||
} else if (casep->casez()) {
|
||||
if (itemp->num().isUnknown()) return true;
|
||||
} else {
|
||||
if (itemp->num().isFourState()) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstCase* nodep, AstNUser*) {
|
||||
V3Case::caseLint(nodep);
|
||||
|
||||
+2
-2
@@ -43,8 +43,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
+2
-2
@@ -32,8 +32,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
|
||||
+2
-2
@@ -29,8 +29,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
+2
-2
@@ -33,8 +33,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
+2
-2
@@ -36,8 +36,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
+2
-2
@@ -26,8 +26,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <map>
|
||||
|
||||
|
||||
+2
-2
@@ -30,8 +30,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <map>
|
||||
|
||||
|
||||
+2
-2
@@ -25,8 +25,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
+2
-2
@@ -53,8 +53,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
|
||||
+2
-2
@@ -29,8 +29,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
@@ -26,8 +26,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
+2
-2
@@ -28,8 +28,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <map>
|
||||
|
||||
|
||||
+260
-203
@@ -20,10 +20,10 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
#include <cmath>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
@@ -78,10 +78,10 @@ public:
|
||||
//int debug() { return 9; }
|
||||
|
||||
// METHODS
|
||||
void displayEmit(AstDisplay* nodep);
|
||||
string displayFormat(AstNode* widthNode, string in,
|
||||
char fmtLetter, bool padZero, bool reallyString);
|
||||
void displayArg(AstDisplay* dispp, AstNode** elistp, string fmt, char fmtLetter);
|
||||
void displayNode(AstNode* nodep, const string& vformat, AstNode* exprsp, bool isScan);
|
||||
void displayEmit(AstNode* nodep, bool isScan);
|
||||
void displayArg(AstNode* dispp, AstNode** elistp, bool isScan,
|
||||
string vfmt, char fmtLetter);
|
||||
|
||||
void emitVarDecl(AstVar* nodep, const string& prefixIfImp);
|
||||
typedef enum {EVL_IO, EVL_SIG, EVL_TEMP, EVL_STATIC, EVL_ALL} EisWhich;
|
||||
@@ -91,7 +91,8 @@ public:
|
||||
void emitIQW(AstNode* nodep) {
|
||||
puts (nodep->isWide()?"W":(nodep->isQuad()?"Q":"I"));
|
||||
}
|
||||
void emitOpName(AstNode* nodep, const string& name);
|
||||
void emitOpName(AstNode* nodep, const string& format,
|
||||
AstNode* lhsp, AstNode* rhsp, AstNode* thsp);
|
||||
|
||||
string cFuncArgs(AstCFunc* nodep) {
|
||||
// Return argument list for given C function
|
||||
@@ -230,7 +231,23 @@ public:
|
||||
nodep->lhsp()->iterateAndNext(*this);
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstDisplay* nodep, AstNUser*); // BELOW
|
||||
virtual void visit(AstDisplay* nodep, AstNUser*) {
|
||||
string text = nodep->text();
|
||||
if (nodep->addNewline()) text += "\\n";
|
||||
displayNode(nodep, text, nodep->exprsp(), false);
|
||||
}
|
||||
virtual void visit(AstFScanF* nodep, AstNUser*) {
|
||||
displayNode(nodep, nodep->text(), nodep->exprsp(), true);
|
||||
}
|
||||
virtual void visit(AstSScanF* nodep, AstNUser*) {
|
||||
displayNode(nodep, nodep->text(), nodep->exprsp(), true);
|
||||
}
|
||||
|
||||
void checkMaxWords(AstNode* nodep) {
|
||||
if (nodep->widthWords() > VL_TO_STRING_MAX_WORDS) {
|
||||
nodep->v3error("String of "<<nodep->width()<<" bits exceeds hardcoded limit VL_TO_STRING_MAX_WORDS in verilatedos.h\n");
|
||||
}
|
||||
}
|
||||
virtual void visit(AstFOpen* nodep, AstNUser*) {
|
||||
nodep->filep()->iterateAndNext(*this);
|
||||
puts(" = VL_FOPEN_");
|
||||
@@ -242,9 +259,7 @@ public:
|
||||
puts(cvtToStr(nodep->filenamep()->widthWords()));
|
||||
putbs(", ");
|
||||
}
|
||||
if (nodep->filenamep()->widthWords() > VL_TO_STRING_MAX_WORDS) {
|
||||
nodep->v3error("String of "<<nodep->filenamep()->width()<<" bits exceeds hardcoded limit VL_TO_STRING_MAX_WORDS in verilatedos.h\n");
|
||||
}
|
||||
checkMaxWords(nodep->filenamep());
|
||||
nodep->filenamep()->iterateAndNext(*this);
|
||||
putbs(", ");
|
||||
nodep->modep()->iterateAndNext(*this);
|
||||
@@ -271,9 +286,7 @@ public:
|
||||
puts(cvtToStr(array_lsb));
|
||||
putbs(",");
|
||||
puts(cvtToStr(nodep->filenamep()->widthWords()));
|
||||
if (nodep->filenamep()->widthWords() > VL_TO_STRING_MAX_WORDS) {
|
||||
nodep->v3error("String of "<<nodep->filenamep()->width()<<" bits exceeds hardcoded limit VL_TO_STRING_MAX_WORDS in verilatedos.h\n");
|
||||
}
|
||||
checkMaxWords(nodep->filenamep());
|
||||
putbs(", ");
|
||||
nodep->filenamep()->iterateAndNext(*this);
|
||||
putbs(", ");
|
||||
@@ -292,6 +305,17 @@ public:
|
||||
nodep->filep()->iterateAndNext(*this); // For saftey, so user doesn't later WRITE with it.
|
||||
puts("=0; }\n");
|
||||
}
|
||||
virtual void visit(AstFFlush* nodep, AstNUser*) {
|
||||
if (!nodep->filep()) {
|
||||
puts("fflush (stdout);\n");
|
||||
} else {
|
||||
puts("if (");
|
||||
nodep->filep()->iterateAndNext(*this);
|
||||
puts(") { fflush (VL_CVT_Q_FP(");
|
||||
nodep->filep()->iterateAndNext(*this);
|
||||
puts(")); }\n");
|
||||
}
|
||||
}
|
||||
virtual void visit(AstWhile* nodep, AstNUser*) {
|
||||
nodep->precondsp()->iterateAndNext(*this);
|
||||
puts("while (");
|
||||
@@ -353,26 +377,24 @@ public:
|
||||
|
||||
// Operators
|
||||
virtual void visit(AstNodeTermop* nodep, AstNUser*) {
|
||||
emitOpName(nodep,nodep->emitOperator());
|
||||
puts(")");
|
||||
emitOpName(nodep, nodep->emitC(), NULL, NULL, NULL);
|
||||
}
|
||||
virtual void visit(AstNodeUniop* nodep, AstNUser*) {
|
||||
if (emitSimpleOk(nodep)) {
|
||||
putbs("("); puts(nodep->emitSimpleOperator()); puts(" ");
|
||||
nodep->lhsp()->iterateAndNext(*this); puts(")");
|
||||
} else {
|
||||
emitOpName(nodep,nodep->emitOperator());
|
||||
emitOpName(nodep, nodep->emitC(), nodep->lhsp(), NULL, NULL);
|
||||
}
|
||||
nodep->lhsp()->iterateAndNext(*this); puts(")");
|
||||
}
|
||||
virtual void visit(AstNodeBiop* nodep, AstNUser*) {
|
||||
if (emitSimpleOk(nodep)) {
|
||||
putbs("("); nodep->lhsp()->iterateAndNext(*this);
|
||||
puts(" "); putbs(nodep->emitSimpleOperator()); puts(" ");
|
||||
nodep->rhsp()->iterateAndNext(*this); puts(")");
|
||||
} else {
|
||||
emitOpName(nodep,nodep->emitOperator());
|
||||
nodep->lhsp()->iterateAndNext(*this); puts(", ");
|
||||
emitOpName(nodep, nodep->emitC(), nodep->lhsp(), nodep->rhsp(), NULL);
|
||||
}
|
||||
nodep->rhsp()->iterateAndNext(*this); puts(")");
|
||||
}
|
||||
virtual void visit(AstRedXor* nodep, AstNUser* vup) {
|
||||
if (nodep->lhsp()->isWide()) {
|
||||
@@ -404,10 +426,7 @@ public:
|
||||
virtual void visit(AstNodeCond* nodep, AstNUser*) {
|
||||
// Widths match up already, so we'll just use C++'s operator w/o any temps.
|
||||
if (nodep->expr1p()->isWide()) {
|
||||
emitOpName(nodep,nodep->emitOperator());
|
||||
nodep->condp()->iterateAndNext(*this); puts(", ");
|
||||
nodep->expr1p()->iterateAndNext(*this); puts(", ");
|
||||
nodep->expr2p()->iterateAndNext(*this); puts(")");
|
||||
emitOpName(nodep, nodep->emitC(), nodep->condp(), nodep->expr1p(), nodep->expr2p());
|
||||
} else {
|
||||
putbs("(");
|
||||
nodep->condp()->iterateAndNext(*this); putbs(" ? ");
|
||||
@@ -417,16 +436,7 @@ public:
|
||||
}
|
||||
virtual void visit(AstSel* nodep, AstNUser*) {
|
||||
// Note ASSIGN checks for this on a LHS
|
||||
if (nodep->widthp()->isOne()) {
|
||||
emitOpName(nodep,"VL_BITSEL");
|
||||
nodep->fromp()->iterateAndNext(*this); puts(", ");
|
||||
nodep->lsbp()->iterateAndNext(*this); puts(")");
|
||||
} else {
|
||||
emitOpName(nodep,"VL_SEL");
|
||||
nodep->fromp()->iterateAndNext(*this); puts(", ");
|
||||
nodep->lsbp()->iterateAndNext(*this); puts(", ");
|
||||
nodep->widthp()->iterateAndNext(*this); puts(")");
|
||||
}
|
||||
emitOpName(nodep, nodep->emitC(), nodep->fromp(), nodep->lsbp(), nodep->thsp());
|
||||
}
|
||||
virtual void visit(AstReplicate* nodep, AstNUser*) {
|
||||
if (nodep->lhsp()->widthMin() == 1 && !nodep->isWide()) {
|
||||
@@ -440,19 +450,11 @@ public:
|
||||
if (nodep->lhsp()) { puts(","+cvtToStr(nodep->lhsp()->widthMin())); }
|
||||
if (nodep->rhsp()) { puts(","+cvtToStr(nodep->rhsp()->widthMin())); }
|
||||
puts(",");
|
||||
nodep->lhsp()->iterateAndNext(*this); puts(", ");
|
||||
nodep->rhsp()->iterateAndNext(*this); puts(")");
|
||||
} else {
|
||||
emitOpName(nodep,nodep->emitOperator());
|
||||
emitOpName(nodep, nodep->emitC(), nodep->lhsp(), nodep->rhsp(), NULL);
|
||||
}
|
||||
nodep->lhsp()->iterateAndNext(*this); puts(", ");
|
||||
nodep->rhsp()->iterateAndNext(*this); puts(")");
|
||||
}
|
||||
virtual void visit(AstArraySel* nodep, AstNUser*) {
|
||||
nodep->fromp()->iterateAndNext(*this); putbs("[");
|
||||
nodep->bitp()->iterateAndNext(*this); puts("]");
|
||||
}
|
||||
virtual void visit(AstWordSel* nodep, AstNUser*) {
|
||||
nodep->fromp()->iterateAndNext(*this); puts("["); // Not putbs, as usually it's a small constant next
|
||||
nodep->bitp()->iterateAndNext(*this); puts("]");
|
||||
}
|
||||
// Terminals
|
||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||
@@ -852,33 +854,95 @@ bool EmitCStmts::emitSimpleOk(AstNodeMath* nodep) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void EmitCStmts::emitOpName(AstNode* nodep, const string& opname) {
|
||||
putbs(opname+"_");
|
||||
if (nodep->emitWordForm()) {
|
||||
emitIQW(nodep->op1p());
|
||||
puts("(");
|
||||
if (nodep->op1p()->isWide()) {
|
||||
puts(cvtToStr(nodep->op1p()->widthWords()));
|
||||
puts(", ");
|
||||
void EmitCStmts::emitOpName(AstNode* nodep, const string& format,
|
||||
AstNode* lhsp, AstNode* rhsp, AstNode* thsp) {
|
||||
// Look at emitOperator() format for term/uni/dual/triops,
|
||||
// and write out appropriate text.
|
||||
// %n* node
|
||||
// %nq emitIQW on the [node]
|
||||
// %nw width in bits
|
||||
// %nW width in words
|
||||
// %ni iterate
|
||||
// %l* lhsp - if appropriate, then second char as above
|
||||
// %r* rhsp - if appropriate, then second char as above
|
||||
// %t* thsp - if appropriate, then second char as above
|
||||
// %k Potential line break
|
||||
// %P Wide temporary name
|
||||
// , Commas suppressed if the previous field is suppressed
|
||||
string nextComma;
|
||||
bool needComma = false;
|
||||
#define COMMA { if (nextComma!="") { puts(nextComma); nextComma=""; } }
|
||||
|
||||
putbs("");
|
||||
for (string::const_iterator pos = format.begin(); pos != format.end(); ++pos) {
|
||||
if (pos[0]==',') {
|
||||
// Remember we need to add one, but don't do yet to avoid ",)"
|
||||
if (needComma) {
|
||||
if (pos[1]==' ') { nextComma=", "; }
|
||||
else nextComma = ",";
|
||||
needComma = false;
|
||||
}
|
||||
if (pos[1]==' ') { ++pos; } // Must do even if no nextComma
|
||||
}
|
||||
else if (pos[0]=='%') {
|
||||
++pos;
|
||||
bool detail = false;
|
||||
AstNode* detailp = NULL;
|
||||
switch (pos[0]) {
|
||||
case '%': puts("%"); break;
|
||||
case 'k': putbs(""); break;
|
||||
case 'n': detail = true; detailp = nodep; break;
|
||||
case 'l': detail = true; detailp = lhsp; break;
|
||||
case 'r': detail = true; detailp = rhsp; break;
|
||||
case 't': detail = true; detailp = thsp; break;
|
||||
case 'P':
|
||||
if (nodep->isWide()) {
|
||||
if (!m_wideTempRefp) nodep->v3fatalSrc("Wide Op w/ no temp, perhaps missing op in V3EmitC?");
|
||||
COMMA;
|
||||
puts(m_wideTempRefp->hiername());
|
||||
puts(m_wideTempRefp->varp()->name());
|
||||
m_wideTempRefp = NULL;
|
||||
needComma = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
nodep->v3fatalSrc("Unknown emitOperator format code: %"<<pos[0]);
|
||||
break;
|
||||
}
|
||||
if (detail) {
|
||||
// Get next letter of %[nlrt]
|
||||
++pos;
|
||||
switch (pos[0]) {
|
||||
case 'q': emitIQW(detailp); break;
|
||||
case 'w':
|
||||
COMMA;
|
||||
puts(cvtToStr(detailp->widthMin()));
|
||||
needComma = true;
|
||||
break;
|
||||
case 'W':
|
||||
if (lhsp->isWide()) {
|
||||
COMMA;
|
||||
puts(cvtToStr(lhsp->widthWords()));
|
||||
needComma = true;
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
COMMA;
|
||||
if (!detailp) { nodep->v3fatalSrc("emitOperator() references undef node"); }
|
||||
else detailp->iterateAndNext(*this);
|
||||
needComma = true;
|
||||
break;
|
||||
default:
|
||||
nodep->v3fatalSrc("Unknown emitOperator format code: %[nlrt]"<<pos[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Normal text
|
||||
if (pos[0] == ')') nextComma="";
|
||||
COMMA;
|
||||
string s; s+=pos[0]; puts(s);
|
||||
}
|
||||
} else {
|
||||
emitIQW(nodep);
|
||||
if (nodep->op1p()) { emitIQW(nodep->op1p()); }
|
||||
if (nodep->op2p()) { emitIQW(nodep->op2p()); }
|
||||
if (nodep->op3p()) { emitIQW(nodep->op3p()); }
|
||||
puts("(");
|
||||
puts(cvtToStr(nodep->widthMin()));
|
||||
if (nodep->op1p()) { puts(","+cvtToStr(nodep->op1p()->widthMin())); }
|
||||
if (nodep->op2p()) { puts(","+cvtToStr(nodep->op2p()->widthMin())); }
|
||||
if (nodep->op3p()) { puts(","+cvtToStr(nodep->op3p()->widthMin())); }
|
||||
if (nodep->op1p() || nodep->isWide()) puts(", ");
|
||||
}
|
||||
if (nodep->isWide()) {
|
||||
if (!m_wideTempRefp) nodep->v3fatalSrc("Wide Op w/ no temp, perhaps missing op in V3EmitC?");
|
||||
puts(m_wideTempRefp->hiername());
|
||||
puts(m_wideTempRefp->varp()->name());
|
||||
m_wideTempRefp = NULL;
|
||||
if (nodep->op1p()) puts(", ");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -888,13 +952,11 @@ void EmitCStmts::emitOpName(AstNode* nodep, const string& opname) {
|
||||
// We only do one display at once, so can just use static state
|
||||
|
||||
struct EmitDispState {
|
||||
bool m_wide; // Put out a wide func that needs string buffer
|
||||
string m_format; // "%s" and text from user
|
||||
vector<AstNode*> m_argsp; // Each argument to be printed
|
||||
vector<string> m_argsFunc; // Function before each argument to be printed
|
||||
EmitDispState() { clear(); }
|
||||
void clear() {
|
||||
m_wide = false;
|
||||
m_format = "";
|
||||
m_argsp.clear();
|
||||
m_argsFunc.clear();
|
||||
@@ -906,18 +968,40 @@ struct EmitDispState {
|
||||
}
|
||||
} emitDispState;
|
||||
|
||||
void EmitCStmts::displayEmit(AstDisplay* nodep) {
|
||||
if (emitDispState.m_format != "") {
|
||||
void EmitCStmts::displayEmit(AstNode* nodep, bool isScan) {
|
||||
if (emitDispState.m_format == ""
|
||||
&& nodep->castDisplay()) { // not fscanf etc, as they need to return value
|
||||
// NOP
|
||||
} else {
|
||||
// Format
|
||||
if (nodep->filep()) {
|
||||
puts("if (");
|
||||
nodep->filep()->iterate(*this); // Check if closed, to avoid core dump
|
||||
puts(") fprintf(VL_CVT_Q_FP(");
|
||||
nodep->filep()->iterate(*this);
|
||||
puts("),\"");
|
||||
bool isStmt;
|
||||
if (AstFScanF* dispp = nodep->castFScanF()) {
|
||||
isStmt = false;
|
||||
puts("VL_FSCANF_IX(");
|
||||
dispp->filep()->iterate(*this);
|
||||
puts(",");
|
||||
} else if (AstSScanF* dispp = nodep->castSScanF()) {
|
||||
isStmt = false;
|
||||
checkMaxWords(dispp->fromp());
|
||||
puts("VL_SSCANF_I"); emitIQW(dispp->fromp()); puts("X(");
|
||||
puts(cvtToStr(dispp->fromp()->widthMin()));
|
||||
puts(",");
|
||||
dispp->fromp()->iterate(*this);
|
||||
puts(",");
|
||||
} else if (AstDisplay* dispp = nodep->castDisplay()) {
|
||||
isStmt = true;
|
||||
if (dispp->filep()) {
|
||||
puts("VL_FWRITEF(");
|
||||
dispp->filep()->iterate(*this);
|
||||
puts(",");
|
||||
} else {
|
||||
puts("VL_WRITEF(");
|
||||
}
|
||||
} else {
|
||||
puts("VL_PRINTF(\"");
|
||||
isStmt = true;
|
||||
nodep->v3fatalSrc("Unknown displayEmit node type");
|
||||
}
|
||||
puts("\"");
|
||||
ofp()->putsNoTracking(emitDispState.m_format);
|
||||
puts("\"");
|
||||
// Arguments
|
||||
@@ -928,160 +1012,133 @@ void EmitCStmts::displayEmit(AstDisplay* nodep) {
|
||||
ofp()->indentInc();
|
||||
ofp()->putbs("");
|
||||
if (func!="") puts(func);
|
||||
if (argp) argp->iterate(*this);
|
||||
if (func!="") puts(")");
|
||||
if (argp) {
|
||||
if (isScan) puts("&(");
|
||||
argp->iterate(*this);
|
||||
if (isScan) puts(")");
|
||||
}
|
||||
ofp()->indentDec();
|
||||
}
|
||||
// End
|
||||
puts(");\n");
|
||||
puts(")");
|
||||
if (isStmt) puts(";\n");
|
||||
else puts(" ");
|
||||
// Prep for next
|
||||
emitDispState.clear();
|
||||
}
|
||||
}
|
||||
|
||||
string EmitCStmts::displayFormat(AstNode* widthNodep, string in,
|
||||
char fmtLetter, bool padZero, bool reallyString) {
|
||||
if (fmtLetter=='s') padZero = false;
|
||||
if (widthNodep && widthNodep->isWide()
|
||||
&& (fmtLetter=='d'||fmtLetter=='u')) {
|
||||
widthNodep->v3error("Unsupported: $display of dec format of > 64 bit results (use hex format instead)");
|
||||
}
|
||||
if (widthNodep && widthNodep->widthMin()>8 && fmtLetter=='c') {
|
||||
widthNodep->v3error("$display of char format of > 8 bit result");
|
||||
}
|
||||
string fmt;
|
||||
if (in == "") {
|
||||
// Size naturally
|
||||
if (widthNodep == NULL) fmt=""; // Out of args, will get error
|
||||
if (fmtLetter=='u' || fmtLetter=='d') { // Decimal. Spec says leading spaces, not zeros
|
||||
double mantissabits = widthNodep->widthMin() - ((fmtLetter=='d')?1:0);
|
||||
double maxval = pow(2.0, mantissabits);
|
||||
double dchars = log10(maxval)+1.0;
|
||||
if (fmtLetter=='d') dchars++; // space for sign
|
||||
int nchars = int(dchars);
|
||||
fmt=cvtToStr(nchars);
|
||||
} else if (fmtLetter!='s' && fmtLetter!='c') { // Strings/chars don't get padding
|
||||
int bitsPerChar = (fmtLetter=='b'?1 : fmtLetter=='o'?3 : 4);
|
||||
int nchars = (widthNodep->widthMin() + bitsPerChar-1)/bitsPerChar;
|
||||
if (padZero) fmt=(string)("0")+cvtToStr(nchars);
|
||||
else fmt=cvtToStr(nchars);
|
||||
}
|
||||
} else if (in == "0") {
|
||||
fmt=""; // No width
|
||||
} else {
|
||||
fmt=in;
|
||||
}
|
||||
return fmt;
|
||||
}
|
||||
|
||||
void EmitCStmts::displayArg(AstDisplay* dispp, AstNode** elistp, string fmt, char fmtLetter) {
|
||||
void EmitCStmts::displayArg(AstNode* dispp, AstNode** elistp, bool isScan,
|
||||
string vfmt, char fmtLetter) {
|
||||
// Print display argument, edits elistp
|
||||
if (!*elistp) {
|
||||
dispp->v3error("Missing arguments for $display format");
|
||||
AstNode* argp = *elistp;
|
||||
if (!argp) {
|
||||
// expectDisplay() checks this first, so internal error if found here
|
||||
dispp->v3error("Internal: Missing arguments for $display format");
|
||||
return;
|
||||
}
|
||||
if ((*elistp)->widthMin() > VL_VALUE_STRING_MAX_WIDTH) {
|
||||
if (argp->widthMin() > VL_VALUE_STRING_MAX_WIDTH) {
|
||||
dispp->v3error("Exceeded limit of 1024 bits for any display arguments");
|
||||
}
|
||||
|
||||
if ((*elistp)->isWide() // Have to use our own function for wide,
|
||||
|| fmtLetter=='s' // ... Verilog strings
|
||||
|| fmtLetter=='b' // ... binary, no printf %b in C
|
||||
|| fmtLetter=='d') { // ... Signed decimal
|
||||
// We use a single static string, so must only have one call per VL_PRINT
|
||||
if (emitDispState.m_wide) { displayEmit(dispp); }
|
||||
emitDispState.m_wide = true;
|
||||
string nfmt = displayFormat(*elistp, fmt, fmtLetter, false, true);
|
||||
string pfmt = "%"+nfmt+"s";
|
||||
string func = "VL_VALUE_FORMATTED_";
|
||||
func += ((*elistp)->isWide()) ? "W(" : ((*elistp)->isQuad()) ? "Q(" : "I(";
|
||||
func += (cvtToStr((*elistp)->widthMin())
|
||||
+",'"+fmtLetter+"'"
|
||||
+","+(fmt=="0"?"true":"false")+",");
|
||||
emitDispState.pushFormat(pfmt);
|
||||
emitDispState.pushArg(*elistp,func);
|
||||
} else {
|
||||
string func;
|
||||
string nfmt = displayFormat(*elistp, fmt, fmtLetter, true, false);
|
||||
// We don't need to check for fmtLetter=='d', as it is above.
|
||||
if ((*elistp)->isQuad() && (fmtLetter=='u'||fmtLetter=='o'||fmtLetter=='x')) {
|
||||
nfmt+="ll";
|
||||
func="(unsigned long long)("; // Must match %ull to avoid warnings
|
||||
}
|
||||
string pfmt = "%"+nfmt+fmtLetter;
|
||||
|
||||
emitDispState.pushFormat(pfmt);
|
||||
emitDispState.pushArg(*elistp,func);
|
||||
if (argp && argp->isWide()
|
||||
&& (fmtLetter=='d'||fmtLetter=='u')) {
|
||||
argp->v3error("Unsupported: "<<dispp->verilogKwd()<<" of dec format of > 64 bit results (use hex format instead)");
|
||||
}
|
||||
if (argp && argp->widthMin()>8 && fmtLetter=='c') {
|
||||
// Technically legal, but surely not what the user intended.
|
||||
argp->v3error(dispp->verilogKwd()<<" of char format of > 8 bit result");
|
||||
}
|
||||
|
||||
//string pfmt = "%"+displayFormat(argp, vfmt, fmtLetter)+fmtLetter;
|
||||
string pfmt;
|
||||
if ((fmtLetter=='u' || fmtLetter=='d')
|
||||
&& !isScan
|
||||
&& vfmt == "") { // Size decimal output. Spec says leading spaces, not zeros
|
||||
double mantissabits = argp->widthMin() - ((fmtLetter=='d')?1:0);
|
||||
double maxval = pow(2.0, mantissabits);
|
||||
double dchars = log10(maxval)+1.0;
|
||||
if (fmtLetter=='d') dchars++; // space for sign
|
||||
int nchars = int(dchars);
|
||||
pfmt = string("%") + cvtToStr(nchars) + fmtLetter;
|
||||
} else {
|
||||
pfmt = string("%") + vfmt + fmtLetter;
|
||||
}
|
||||
emitDispState.pushFormat(pfmt);
|
||||
emitDispState.pushArg(NULL,cvtToStr(argp->widthMin()));
|
||||
emitDispState.pushArg(argp,"");
|
||||
|
||||
// Next parameter
|
||||
*elistp = (*elistp)->nextp();
|
||||
}
|
||||
|
||||
void EmitCStmts::visit(AstDisplay* nodep, AstNUser*) {
|
||||
string vformat = nodep->text();
|
||||
AstNode* elistp = nodep->exprsp();
|
||||
void EmitCStmts::displayNode(AstNode* nodep, const string& vformat, AstNode* exprsp,
|
||||
bool isScan) {
|
||||
AstNode* elistp = exprsp;
|
||||
|
||||
// Convert Verilog display to C printf formats
|
||||
// "%0t" becomes "%d"
|
||||
emitDispState.clear();
|
||||
string fmt = "";
|
||||
string::iterator pos = vformat.begin();
|
||||
string vfmt = "";
|
||||
string::const_iterator pos = vformat.begin();
|
||||
bool inPct = false;
|
||||
for (; pos != vformat.end(); ++pos) {
|
||||
if (inPct && pos[0]=='%') {
|
||||
emitDispState.pushFormat("%%"); // We're printf'ing it, so need to quote the %
|
||||
inPct = false;
|
||||
} else if (pos[0]=='%') {
|
||||
//UINFO(1,"Parse '"<<*pos<<"' IP"<<inPct<<" List "<<(void*)(elistp)<<endl);
|
||||
if (!inPct && pos[0]=='%') {
|
||||
inPct = true;
|
||||
fmt = "";
|
||||
vfmt = "";
|
||||
} else if (!inPct) { // Normal text
|
||||
//char text[2]; text[0]=*pos; text[1]='\0';
|
||||
emitDispState.pushFormat(*pos);
|
||||
} else { // Format character
|
||||
if (isdigit(pos[0])) {
|
||||
inPct = false;
|
||||
switch (tolower(pos[0])) {
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
// Digits, like %5d, etc.
|
||||
fmt += pos[0];
|
||||
} else {
|
||||
inPct = false;
|
||||
switch (tolower(pos[0])) {
|
||||
// Special codes
|
||||
case '~': displayArg(nodep,&elistp,fmt,'d'); break; // Signed decimal
|
||||
// Spec: h d o b c l
|
||||
case 'b': displayArg(nodep,&elistp,fmt,'b'); break;
|
||||
case 'c': displayArg(nodep,&elistp,fmt,'c'); break;
|
||||
case 't':
|
||||
case 'd': displayArg(nodep,&elistp,fmt,'u'); break; // Unsigned decimal
|
||||
case 'o': displayArg(nodep,&elistp,fmt,'o'); break;
|
||||
case 'h':
|
||||
case 'x': displayArg(nodep,&elistp,fmt,'x'); break;
|
||||
case 's': displayArg(nodep,&elistp,fmt,'s'); break;
|
||||
case 'm': {
|
||||
emitDispState.pushFormat("%s");
|
||||
emitDispState.pushArg(NULL, "vlSymsp->name(");
|
||||
if (!nodep->scopeNamep()) nodep->v3fatalSrc("Display with %m but no AstScopeName");
|
||||
for (AstText* textp=nodep->scopeNamep()->scopeAttrp(); textp; textp=textp->nextp()->castText()) {
|
||||
emitDispState.pushFormat(textp->text());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'u':
|
||||
case 'z':
|
||||
case 'l':
|
||||
case 'v':
|
||||
nodep->v3error("Unsupported: $display format code: %"<<pos[0]);
|
||||
break;
|
||||
default:
|
||||
nodep->v3error("Unknown $display format code: %"<<pos[0]);
|
||||
break;
|
||||
vfmt += pos[0];
|
||||
inPct = true; // Get more digits
|
||||
break;
|
||||
case '%':
|
||||
emitDispState.pushFormat("%%"); // We're printf'ing it, so need to quote the %
|
||||
break;
|
||||
// Special codes
|
||||
case '~': displayArg(nodep,&elistp,isScan, vfmt,'d'); break; // Signed decimal
|
||||
// Spec: h d o b c l
|
||||
case 'b': displayArg(nodep,&elistp,isScan, vfmt,'b'); break;
|
||||
case 'c': displayArg(nodep,&elistp,isScan, vfmt,'c'); break;
|
||||
case 't':
|
||||
case 'd': displayArg(nodep,&elistp,isScan, vfmt,'u'); break; // Unsigned decimal
|
||||
case 'o': displayArg(nodep,&elistp,isScan, vfmt,'o'); break;
|
||||
case 'h':
|
||||
case 'x': displayArg(nodep,&elistp,isScan, vfmt,'x'); break;
|
||||
case 's': displayArg(nodep,&elistp,isScan, vfmt,'s'); break;
|
||||
case 'm': {
|
||||
emitDispState.pushFormat("%S");
|
||||
emitDispState.pushArg(NULL, "vlSymsp->name()");
|
||||
if (!nodep->castDisplay()) nodep->v3fatalSrc("Non-Display with %m");
|
||||
AstScopeName* scopenamep = nodep->castDisplay()->scopeNamep();
|
||||
if (!scopenamep) nodep->v3fatalSrc("Display with %m but no AstScopeName");
|
||||
for (AstText* textp=scopenamep->scopeAttrp(); textp; textp=textp->nextp()->castText()) {
|
||||
emitDispState.pushFormat(textp->text());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'u':
|
||||
case 'z':
|
||||
case 'l':
|
||||
case 'v':
|
||||
nodep->v3error("Unsupported: $display format code: %"<<pos[0]);
|
||||
break;
|
||||
default:
|
||||
nodep->v3error("Unknown $display format code: %"<<pos[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (elistp != NULL) {
|
||||
nodep->v3error("Extra arguments for $display format\n");
|
||||
// expectFormat also checks this, and should have found it first, so internal
|
||||
elistp->v3error("Internal: Extra arguments for $display format\n");
|
||||
}
|
||||
if (nodep->addNewline()) emitDispState.pushFormat("\\n");
|
||||
displayEmit(nodep);
|
||||
displayEmit(nodep, isScan);
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
|
||||
+3
-3
@@ -24,10 +24,10 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
#include <cmath>
|
||||
|
||||
#include "V3Global.h"
|
||||
#include "V3File.h"
|
||||
|
||||
@@ -20,10 +20,10 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
#include <cmath>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
|
||||
+3
-3
@@ -20,10 +20,10 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
#include <cmath>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
+3
-3
@@ -20,10 +20,10 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
#include <cmath>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
+24
-7
@@ -20,10 +20,10 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
#include <cmath>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
@@ -163,19 +163,30 @@ public:
|
||||
virtual void visit(AstCoverInc*, AstNUser*) {
|
||||
// N/A
|
||||
}
|
||||
virtual void visit(AstDisplay* nodep, AstNUser*) {
|
||||
|
||||
void visitNodeDisplay(AstNode* nodep, AstNode* filep, const string& text, AstNode* exprsp) {
|
||||
putbs(nodep->verilogKwd());
|
||||
putbs(" (");
|
||||
if (nodep->filep()) { nodep->filep()->iterateAndNext(*this); putbs(","); }
|
||||
if (filep) { filep->iterateAndNext(*this); putbs(","); }
|
||||
puts("\"");
|
||||
ofp()->putsNoTracking(nodep->text());
|
||||
ofp()->putsNoTracking(text);
|
||||
puts("\"");
|
||||
for (AstNode* expp=nodep->exprsp(); expp; expp = expp->nextp()) {
|
||||
for (AstNode* expp=exprsp; expp; expp = expp->nextp()) {
|
||||
puts(",");
|
||||
expp->iterateAndNext(*this);
|
||||
}
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstDisplay* nodep, AstNUser*) {
|
||||
visitNodeDisplay(nodep, nodep->filep(), nodep->text(), nodep->exprsp());
|
||||
}
|
||||
virtual void visit(AstFScanF* nodep, AstNUser*) {
|
||||
visitNodeDisplay(nodep, nodep->filep(), nodep->text(), nodep->exprsp());
|
||||
}
|
||||
virtual void visit(AstSScanF* nodep, AstNUser*) {
|
||||
visitNodeDisplay(nodep, nodep->fromp(), nodep->text(), nodep->exprsp());
|
||||
}
|
||||
|
||||
virtual void visit(AstFOpen* nodep, AstNUser*) {
|
||||
putbs(nodep->verilogKwd());
|
||||
putbs(" (");
|
||||
@@ -192,6 +203,12 @@ public:
|
||||
if (nodep->filep()) nodep->filep()->iterateChildren(*this);
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstFFlush* nodep, AstNUser*) {
|
||||
putbs(nodep->verilogKwd());
|
||||
putbs(" (");
|
||||
if (nodep->filep()) nodep->filep()->iterateChildren(*this);
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstReadMem* nodep, AstNUser*) {
|
||||
putbs(nodep->verilogKwd());
|
||||
putbs(" (");
|
||||
|
||||
+6
-3
@@ -18,8 +18,8 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <cstring>
|
||||
#include <set>
|
||||
#include "V3Error.h"
|
||||
@@ -261,6 +261,7 @@ void V3Error::abortIfWarnings() {
|
||||
|
||||
bool V3Error::isError(V3ErrorCode code) {
|
||||
if (code==V3ErrorCode::SUPPRESS) return false;
|
||||
else if (code==V3ErrorCode::INFO) return false;
|
||||
else if (code==V3ErrorCode::FATAL) return true;
|
||||
else if (code==V3ErrorCode::ERROR) return true;
|
||||
else if (code<V3ErrorCode::FIRST_WARN
|
||||
@@ -270,6 +271,7 @@ bool V3Error::isError(V3ErrorCode code) {
|
||||
|
||||
string V3Error::msgPrefix(V3ErrorCode code) {
|
||||
if (code==V3ErrorCode::SUPPRESS) return "-arning-suppressed: ";
|
||||
else if (code==V3ErrorCode::INFO) return "-Info: ";
|
||||
else if (code==V3ErrorCode::FATAL) return "%Error: ";
|
||||
else if (code==V3ErrorCode::ERROR) return "%Error: ";
|
||||
else if (isError(code)) return "%Error-"+(string)code.ascii()+": ";
|
||||
@@ -311,7 +313,8 @@ void V3Error::v3errorEnd (ostringstream& sstr) {
|
||||
if (sstr.str()[sstr.str().length()-1] != '\n') {
|
||||
cerr<<endl;
|
||||
}
|
||||
if (s_errorCode!=V3ErrorCode::SUPPRESS) {
|
||||
if (s_errorCode!=V3ErrorCode::SUPPRESS
|
||||
&& s_errorCode!=V3ErrorCode::INFO) {
|
||||
if (!s_describedEachWarn[s_errorCode]
|
||||
&& !s_pretendError[s_errorCode]) {
|
||||
s_describedEachWarn[s_errorCode] = true;
|
||||
|
||||
+7
-3
@@ -34,6 +34,7 @@ class V3ErrorCode {
|
||||
public:
|
||||
enum en {
|
||||
SUPPRESS, // Warning suppressed by user
|
||||
INFO, // General information out
|
||||
FATAL, // Kill the program
|
||||
ERROR, // General error out, can't suppress
|
||||
// Error codes:
|
||||
@@ -45,6 +46,7 @@ public:
|
||||
BLKANDNBLK, // Blocked and non-blocking assignments to same variable
|
||||
CASEINCOMPLETE, // Case statement has missing values
|
||||
CASEOVERLAP, // Case statements overlap
|
||||
CASEWITHX, // Case with X values
|
||||
CASEX, // Casex
|
||||
CMPCONST, // Comparison is constant due to limited range
|
||||
COMBDLY, // Combinatorial delayed assignment
|
||||
@@ -74,11 +76,11 @@ public:
|
||||
const char* ascii() const {
|
||||
const char* names[] = {
|
||||
// Leading spaces indicate it can't be disabled.
|
||||
" SUPPRESS", " FATAL", " ERROR",
|
||||
" SUPPRESS", " INFO", " FATAL", " ERROR",
|
||||
"MULTITOP", "TASKNSVAR",
|
||||
" FIRST_WARN",
|
||||
"BLKANDNBLK",
|
||||
"CASEINCOMPLETE", "CASEOVERLAP", "CASEX", "CMPCONST",
|
||||
"CASEINCOMPLETE", "CASEOVERLAP", "CASEWITHX", "CASEX", "CMPCONST",
|
||||
"COMBDLY", "STMTDLY", "GENCLK", "IMPLICIT", "IMPURE",
|
||||
"MULTIDRIVEN", "REDEFMACRO",
|
||||
"UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNSIGNED", "UNUSED",
|
||||
@@ -94,7 +96,8 @@ public:
|
||||
bool pretendError() const { return ( m_e==BLKANDNBLK || m_e==IMPURE); };
|
||||
// Warnings that are lint only
|
||||
bool lintError() const { return ( m_e==CASEINCOMPLETE || m_e==CASEOVERLAP
|
||||
|| m_e==CASEX || m_e==CMPCONST
|
||||
|| m_e==CASEWITHX || m_e==CASEX
|
||||
|| m_e==CMPCONST
|
||||
|| m_e==IMPLICIT
|
||||
|| m_e==UNDRIVEN || m_e==UNSIGNED
|
||||
|| m_e==UNUSED || m_e==VARHIDDEN
|
||||
@@ -159,6 +162,7 @@ inline void v3errorEnd(ostringstream& sstr) { V3Error::v3errorEnd(sstr); }
|
||||
|
||||
// These allow errors using << operators: v3error("foo"<<"bar");
|
||||
// Careful, you can't put () around msg, as you would in most macro definitions
|
||||
#define v3info(msg) v3errorEnd(((V3Error::v3errorPrep(V3ErrorCode::INFO)<<msg),V3Error::v3errorStr()));
|
||||
#define v3fatal(msg) v3errorEnd(((V3Error::v3errorPrep(V3ErrorCode::FATAL)<<msg),V3Error::v3errorStr()));
|
||||
#define v3error(msg) v3errorEnd(((V3Error::v3errorPrep(V3ErrorCode::ERROR)<<msg),V3Error::v3errorStr()));
|
||||
#define v3warn(code,msg) v3errorEnd(((V3Error::v3errorPrep(V3ErrorCode::code)<<msg),V3Error::v3errorStr()));
|
||||
|
||||
+2
-2
@@ -31,8 +31,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
+4
-3
@@ -20,7 +20,7 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdarg.h>
|
||||
#include <cstdarg>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
@@ -244,8 +244,9 @@ void V3File::createMakeDir() {
|
||||
// V3OutFile: A class for printing to a file, with automatic indentation of C++ code.
|
||||
|
||||
V3OutFile::V3OutFile(const string& filename)
|
||||
: m_lineno(1), m_column(0), m_nobreak(false), m_prependIndent(true), m_indentLevel(0)
|
||||
, m_declSAlign(0), m_declNSAlign(0), m_declPadNum(0) {
|
||||
: m_filename(filename), m_lineno(1), m_column(0)
|
||||
, m_nobreak(false), m_prependIndent(true), m_indentLevel(0)
|
||||
, m_declSAlign(0), m_declNSAlign(0), m_declPadNum(0) {
|
||||
if ((m_fp = V3File::new_fopen_w(filename.c_str())) == NULL) {
|
||||
v3fatal("Cannot write "<<filename);
|
||||
}
|
||||
|
||||
+5
-3
@@ -24,7 +24,7 @@
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include "V3Error.h"
|
||||
#include <stdio.h>
|
||||
#include <cstdio>
|
||||
#include <stack>
|
||||
#include <set>
|
||||
#include <fstream>
|
||||
@@ -87,6 +87,7 @@ public:
|
||||
private:
|
||||
// MEMBERS
|
||||
FILE* m_fp;
|
||||
string m_filename;
|
||||
int m_lineno;
|
||||
int m_column;
|
||||
int m_nobreak; // Basic operator or begin paren, don't break next
|
||||
@@ -120,8 +121,9 @@ public:
|
||||
bool tokenStart(const char* cp, const char* cmp);
|
||||
bool tokenEnd(const char* cp);
|
||||
void indentInc() { m_indentLevel += INDBLK; };
|
||||
void indentDec() { m_indentLevel -= INDBLK;
|
||||
UASSERT(m_indentLevel>=0,"Underflow of indentation\n");
|
||||
void indentDec() {
|
||||
m_indentLevel -= INDBLK;
|
||||
UASSERT(m_indentLevel>=0, ": "<<m_filename<<": Underflow of indentation\n");
|
||||
}
|
||||
void blockInc() { m_parenVec.push(m_indentLevel + INDBLK); }
|
||||
void blockDec() { if (!m_parenVec.empty()) m_parenVec.pop(); }
|
||||
|
||||
+2
-2
@@ -27,8 +27,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
#include <iomanip>
|
||||
|
||||
+2
-2
@@ -25,8 +25,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "V3Global.h"
|
||||
|
||||
+2
-2
@@ -21,8 +21,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
+2
-2
@@ -20,8 +20,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
+2
-2
@@ -20,8 +20,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
+2
-2
@@ -20,8 +20,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <stack>
|
||||
#include <map>
|
||||
|
||||
+2
-2
@@ -20,8 +20,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "V3Global.h"
|
||||
|
||||
+2
-2
@@ -27,8 +27,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
+2
-2
@@ -30,8 +30,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
+2
-2
@@ -27,8 +27,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
+2
-2
@@ -29,8 +29,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <map>
|
||||
|
||||
|
||||
+2
-2
@@ -30,8 +30,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "V3Global.h"
|
||||
|
||||
+2
-2
@@ -27,8 +27,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
|
||||
+2
-2
@@ -26,8 +26,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
|
||||
+2
-2
@@ -30,8 +30,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <cstring>
|
||||
#include <unistd.h>
|
||||
#include <map>
|
||||
|
||||
+65
-2
@@ -24,8 +24,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
@@ -108,6 +108,48 @@ private:
|
||||
}
|
||||
m_setRefLvalue = last_setRefLvalue;
|
||||
}
|
||||
virtual void visit(AstFFlush* nodep, AstNUser*) {
|
||||
bool last_setRefLvalue = m_setRefLvalue;
|
||||
{
|
||||
m_setRefLvalue = true;
|
||||
nodep->filep()->iterateAndNext(*this);
|
||||
}
|
||||
m_setRefLvalue = last_setRefLvalue;
|
||||
}
|
||||
virtual void visit(AstFGetC* nodep, AstNUser*) {
|
||||
bool last_setRefLvalue = m_setRefLvalue;
|
||||
{
|
||||
m_setRefLvalue = true;
|
||||
nodep->filep()->iterateAndNext(*this);
|
||||
}
|
||||
m_setRefLvalue = last_setRefLvalue;
|
||||
}
|
||||
virtual void visit(AstFGetS* nodep, AstNUser*) {
|
||||
bool last_setRefLvalue = m_setRefLvalue;
|
||||
{
|
||||
m_setRefLvalue = true;
|
||||
nodep->filep()->iterateAndNext(*this);
|
||||
nodep->strgp()->iterateAndNext(*this);
|
||||
}
|
||||
m_setRefLvalue = last_setRefLvalue;
|
||||
}
|
||||
virtual void visit(AstFScanF* nodep, AstNUser*) {
|
||||
bool last_setRefLvalue = m_setRefLvalue;
|
||||
{
|
||||
m_setRefLvalue = true;
|
||||
nodep->filep()->iterateAndNext(*this);
|
||||
nodep->exprsp()->iterateAndNext(*this);
|
||||
}
|
||||
m_setRefLvalue = last_setRefLvalue;
|
||||
}
|
||||
virtual void visit(AstSScanF* nodep, AstNUser*) {
|
||||
bool last_setRefLvalue = m_setRefLvalue;
|
||||
{
|
||||
m_setRefLvalue = true;
|
||||
nodep->exprsp()->iterateAndNext(*this);
|
||||
}
|
||||
m_setRefLvalue = last_setRefLvalue;
|
||||
}
|
||||
virtual void visit(AstReadMem* nodep, AstNUser*) {
|
||||
bool last_setRefLvalue = m_setRefLvalue;
|
||||
{
|
||||
@@ -157,6 +199,27 @@ private:
|
||||
nodep->iterateChildren(*this);
|
||||
m_ftaskp = NULL;
|
||||
}
|
||||
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
|
||||
AstNode* pinp = nodep->pinsp();
|
||||
AstNodeFTask* taskp = nodep->taskp();
|
||||
// We'll deal with mismatching pins later
|
||||
if (!taskp) return;
|
||||
for (AstNode* stmtp = taskp->stmtsp(); stmtp && pinp; stmtp=stmtp->nextp()) {
|
||||
if (AstVar* portp = stmtp->castVar()) {
|
||||
if (portp->isIO()) {
|
||||
if (portp->isInput()) {
|
||||
pinp->iterateAndNext(*this);
|
||||
} else { // Output or Inout
|
||||
m_setRefLvalue = true;
|
||||
pinp->iterateAndNext(*this);
|
||||
m_setRefLvalue = false;
|
||||
}
|
||||
// Advance pin
|
||||
pinp = pinp->nextp();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
// Default: Just iterate
|
||||
|
||||
+2
-2
@@ -25,8 +25,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
|
||||
+2
-2
@@ -28,8 +28,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
|
||||
+69
-3
@@ -29,8 +29,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
@@ -312,10 +312,48 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void expectFormat(AstNode* nodep, const string& format, AstNode* argp, bool isScan) {
|
||||
// Check display arguments
|
||||
bool inPct = false;
|
||||
for (const char* inp = format.c_str(); *inp; inp++) {
|
||||
char ch = tolower(*inp); // Breaks with iterators...
|
||||
if (!inPct && ch=='%') {
|
||||
inPct = true;
|
||||
} else if (inPct) {
|
||||
inPct = false;
|
||||
switch (ch) {
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
inPct = true;
|
||||
break;
|
||||
case '%': break; // %% - just output a %
|
||||
case 'm': // %m - auto insert "name"
|
||||
if (isScan) nodep->v3error("Unsupported: %m in $fscanf");
|
||||
break;
|
||||
default: // Most operators, just move to next argument
|
||||
if (!V3Number::displayedFmtLegal(ch)) {
|
||||
nodep->v3error("Unknown $display format code: %"<<ch);
|
||||
} else {
|
||||
if (!argp) {
|
||||
nodep->v3error("Missing arguments for $display format");
|
||||
} else {
|
||||
argp = argp->nextp();
|
||||
}
|
||||
}
|
||||
break;
|
||||
} // switch
|
||||
}
|
||||
}
|
||||
if (argp) {
|
||||
argp->v3error("Extra arguments for $display format\n");
|
||||
}
|
||||
}
|
||||
|
||||
void expectDescriptor(AstNode* nodep, AstNodeVarRef* filep) {
|
||||
if (!filep) nodep->v3error("Unsupported: $fopen/$fclose descriptor must be a simple variable");
|
||||
if (!filep) nodep->v3error("Unsupported: $fopen/$fclose/$f* descriptor must be a simple variable");
|
||||
if (filep && filep->varp()) filep->varp()->attrFileDescr(true);
|
||||
}
|
||||
|
||||
virtual void visit(AstFOpen* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
expectDescriptor(nodep, nodep->filep()->castNodeVarRef());
|
||||
@@ -324,9 +362,37 @@ private:
|
||||
nodep->iterateChildren(*this);
|
||||
expectDescriptor(nodep, nodep->filep()->castNodeVarRef());
|
||||
}
|
||||
virtual void visit(AstFEof* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
expectDescriptor(nodep, nodep->filep()->castNodeVarRef());
|
||||
}
|
||||
virtual void visit(AstFFlush* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (nodep->filep()) {
|
||||
expectDescriptor(nodep, nodep->filep()->castNodeVarRef());
|
||||
}
|
||||
}
|
||||
virtual void visit(AstFGetC* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
expectDescriptor(nodep, nodep->filep()->castNodeVarRef());
|
||||
}
|
||||
virtual void visit(AstFGetS* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
expectDescriptor(nodep, nodep->filep()->castNodeVarRef());
|
||||
}
|
||||
virtual void visit(AstFScanF* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
expectDescriptor(nodep, nodep->filep()->castNodeVarRef());
|
||||
expectFormat(nodep, nodep->text(), nodep->exprsp(), true);
|
||||
}
|
||||
virtual void visit(AstSScanF* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
expectFormat(nodep, nodep->text(), nodep->exprsp(), true);
|
||||
}
|
||||
virtual void visit(AstDisplay* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (nodep->filep()) expectDescriptor(nodep, nodep->filep()->castNodeVarRef());
|
||||
expectFormat(nodep, nodep->text(), nodep->exprsp(), false);
|
||||
if (!m_assertp
|
||||
&& (nodep->displayType() == AstDisplayType::INFO
|
||||
|| nodep->displayType() == AstDisplayType::WARNING
|
||||
|
||||
+2
-2
@@ -28,8 +28,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
|
||||
|
||||
+2
-2
@@ -25,8 +25,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
+36
-16
@@ -20,9 +20,9 @@
|
||||
|
||||
#include <config_build.h>
|
||||
#include "verilatedos.h"
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
#include "V3Number.h"
|
||||
@@ -143,14 +143,14 @@ V3Number::V3Number (FileLine* fileline, const char* sourcep) {
|
||||
olen++;
|
||||
break;
|
||||
}
|
||||
case 'z': {
|
||||
case 'z': case '?': {
|
||||
if (olen) m_fileline->v3error("Multi-digit X/Z/? not legal in decimal constant: "<<*cp);
|
||||
if (!m_sized) m_fileline->v3error("Unsized X/Z/? not legal in decimal constant: "<<*cp);
|
||||
olen++;
|
||||
setAllBitsZ();
|
||||
break;
|
||||
}
|
||||
case 'x': case '?': {
|
||||
case 'x': {
|
||||
if (olen) m_fileline->v3error("Multi-digit X/Z/? not legal in decimal constant: "<<*cp);
|
||||
if (!m_sized) m_fileline->v3error("Unsized X/Z/? not legal in decimal constant: "<<*cp);
|
||||
olen++;
|
||||
@@ -181,9 +181,8 @@ V3Number::V3Number (FileLine* fileline, const char* sourcep) {
|
||||
switch(tolower(*cp)) {
|
||||
case '0': setBit(obit++, 0); break;
|
||||
case '1': setBit(obit++, 1); break;
|
||||
case 'z': setBit(obit++, 'z'); break;
|
||||
case 'x': case '?':
|
||||
setBit(obit++, 'x'); break;
|
||||
case 'z': case '?': setBit(obit++, 'z'); break;
|
||||
case 'x': setBit(obit++, 'x'); break;
|
||||
case '_': break;
|
||||
default:
|
||||
m_fileline->v3error("Illegal character in binary constant: "<<*cp);
|
||||
@@ -202,8 +201,9 @@ V3Number::V3Number (FileLine* fileline, const char* sourcep) {
|
||||
case '5': setBit(obit++, 1); setBit(obit++, 0); setBit(obit++, 1); break;
|
||||
case '6': setBit(obit++, 0); setBit(obit++, 1); setBit(obit++, 1); break;
|
||||
case '7': setBit(obit++, 1); setBit(obit++, 1); setBit(obit++, 1); break;
|
||||
case 'z': setBit(obit++, 'z'); setBit(obit++, 'z'); setBit(obit++, 'z'); break;
|
||||
case 'x': case '?':
|
||||
case 'z': case '?':
|
||||
setBit(obit++, 'z'); setBit(obit++, 'z'); setBit(obit++, 'z'); break;
|
||||
case 'x':
|
||||
setBit(obit++, 'x'); setBit(obit++, 'x'); setBit(obit++, 'x'); break;
|
||||
case '_': break;
|
||||
default:
|
||||
@@ -230,8 +230,9 @@ V3Number::V3Number (FileLine* fileline, const char* sourcep) {
|
||||
case 'd': setBit(obit++,1); setBit(obit++,0); setBit(obit++,1); setBit(obit++,1); break;
|
||||
case 'e': setBit(obit++,0); setBit(obit++,1); setBit(obit++,1); setBit(obit++,1); break;
|
||||
case 'f': setBit(obit++,1); setBit(obit++,1); setBit(obit++,1); setBit(obit++,1); break;
|
||||
case 'z': setBit(obit++,'z'); setBit(obit++,'z'); setBit(obit++,'z'); setBit(obit++,'z'); break;
|
||||
case 'x': case '?':
|
||||
case 'z': case '?':
|
||||
setBit(obit++,'z'); setBit(obit++,'z'); setBit(obit++,'z'); setBit(obit++,'z'); break;
|
||||
case 'x':
|
||||
setBit(obit++,'x'); setBit(obit++,'x'); setBit(obit++,'x'); setBit(obit++,'x'); break;
|
||||
case '_': break;
|
||||
default:
|
||||
@@ -345,6 +346,22 @@ string V3Number::ascii(bool prefixed, bool cleanVerilog) const {
|
||||
return out.str();
|
||||
}
|
||||
|
||||
bool V3Number::displayedFmtLegal(char format) {
|
||||
// Is this a valid format letter?
|
||||
switch (tolower(format)) {
|
||||
case 'b': return true;
|
||||
case 'c': return true;
|
||||
case 'd': return true; // Unsigned decimal
|
||||
case 'h': return true;
|
||||
case 'o': return true;
|
||||
case 's': return true;
|
||||
case 't': return true;
|
||||
case 'x': return true;
|
||||
case '~': return true; // Signed decimal
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
string V3Number::displayed(const string& vformat) const {
|
||||
string::const_iterator pos = vformat.begin();
|
||||
UASSERT(pos != vformat.end() && pos[0]=='%', "display with non format argument "<<*this);
|
||||
@@ -506,6 +523,12 @@ bool V3Number::isEqAllOnes(int optwidth) const {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool V3Number::isUnknown() const {
|
||||
for(int bit=0; bit<width(); bit++) {
|
||||
if (bitIsX(bit)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int V3Number::minWidth() const {
|
||||
for(int bit=width()-1; bit>0; bit--) {
|
||||
@@ -609,10 +632,7 @@ V3Number& V3Number::opCountOnes (const V3Number& lhs) {
|
||||
return *this;
|
||||
}
|
||||
V3Number& V3Number::opIsUnknown (const V3Number& lhs) {
|
||||
for(int bit=0; bit<lhs.width(); bit++) {
|
||||
if (lhs.bitIsX(bit)) return setSingleBits(1);
|
||||
}
|
||||
return setSingleBits(0);
|
||||
return setSingleBits(lhs.isUnknown());
|
||||
}
|
||||
V3Number& V3Number::opOneHot (const V3Number& lhs) {
|
||||
if (lhs.isFourState()) return setAllBitsX();
|
||||
|
||||
@@ -119,6 +119,7 @@ public:
|
||||
// ACCESSORS
|
||||
string ascii(bool prefixed=true, bool cleanVerilog=false) const;
|
||||
string displayed(const string& format) const;
|
||||
static bool displayedFmtLegal(char format); // Is this a valid format letter?
|
||||
int width() const { return m_width; }
|
||||
int minWidth() const; // Minimum width that can represent this number (~== log2(num)+1)
|
||||
bool sized() const { return m_sized; }
|
||||
@@ -133,6 +134,7 @@ public:
|
||||
bool isCaseEq(const V3Number& rhsp) const; // operator==
|
||||
void width(int width, bool sized=true);
|
||||
void isSigned(bool ssigned) { m_signed=ssigned; }
|
||||
bool isUnknown() const;
|
||||
uint32_t asInt() const;
|
||||
vlsint32_t asSInt() const;
|
||||
vluint64_t asQuad() const;
|
||||
|
||||
@@ -26,8 +26,8 @@
|
||||
|
||||
#include <config_build.h>
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <algorithm>
|
||||
#include "V3Number.h"
|
||||
|
||||
|
||||
+21
-2
@@ -95,6 +95,15 @@ void V3Options::addCppFile(const string& filename) {
|
||||
m_cppFiles.insert(filename);
|
||||
}
|
||||
}
|
||||
void V3Options::addFuture(const string& flag) {
|
||||
if (m_futures.find(flag) == m_futures.end()) {
|
||||
m_futures.insert(flag);
|
||||
}
|
||||
}
|
||||
bool V3Options::isFuture(const string& flag) const {
|
||||
return m_futures.find(flag) != m_futures.end();
|
||||
}
|
||||
|
||||
void V3Options::addLibraryFile(const string& filename) {
|
||||
if (m_libraryFiles.find(filename) == m_libraryFiles.end()) {
|
||||
m_libraryFiles.insert(filename);
|
||||
@@ -563,6 +572,7 @@ void V3Options::parseOptsList(FileLine* fl, int argc, char** argv) {
|
||||
else if ( onoff (sw, "-MMD", flag/*ref*/) ) { m_makeDepend = flag; }
|
||||
else if ( onoff (sw, "-MP", flag/*ref*/) ) { m_makePhony = flag; }
|
||||
else if ( onoff (sw, "-assert", flag/*ref*/) ) { m_assert = flag; m_psl = flag; }
|
||||
else if ( onoff (sw, "-autoflush", flag/*ref*/) ) { m_autoflush = flag; }
|
||||
else if ( !strcmp (sw, "-cc") ) { m_outFormatOk = true; m_systemC = false; m_systemPerl = false; }
|
||||
else if ( onoff (sw, "-coverage", flag/*ref*/) ) { coverage(flag); }
|
||||
else if ( onoff (sw, "-coverage-line", flag/*ref*/) ){ m_coverageLine = flag; }
|
||||
@@ -645,11 +655,18 @@ void V3Options::parseOptsList(FileLine* fl, int argc, char** argv) {
|
||||
string msg = sw+strlen("-Werror-");
|
||||
V3ErrorCode code (msg.c_str());
|
||||
if (code == V3ErrorCode::ERROR) {
|
||||
fl->v3fatal("Unknown warning specified: "<<sw);
|
||||
if (!isFuture(msg)) {
|
||||
fl->v3fatal("Unknown warning specified: "<<sw);
|
||||
}
|
||||
} else {
|
||||
V3Error::pretendError(code, true);
|
||||
}
|
||||
}
|
||||
else if ( !strncmp (sw, "-Wfuture-",strlen("-Wfuture-")) ) {
|
||||
string msg = sw+strlen("-Wfuture-");
|
||||
// Note it may not be a future option, but one that is currently implemented.
|
||||
addFuture(msg);
|
||||
}
|
||||
else if ( !strcmp (sw, "-bin") && (i+1)<argc ) {
|
||||
shift; m_bin = argv[i];
|
||||
}
|
||||
@@ -685,6 +702,7 @@ void V3Options::parseOptsList(FileLine* fl, int argc, char** argv) {
|
||||
shift;
|
||||
if (!strcmp (argv[i], "0")) { m_xAssign="0"; }
|
||||
else if (!strcmp (argv[i], "1")) { m_xAssign="1"; }
|
||||
else if (!strcmp (argv[i], "fast")) { m_xAssign="fast"; }
|
||||
else if (!strcmp (argv[i], "unique")) { m_xAssign="unique"; }
|
||||
else {
|
||||
fl->v3fatal("Unknown setting for --x-assign: "<<argv[i]);
|
||||
@@ -792,6 +810,7 @@ void V3Options::parseOptsFile(FileLine* fl, const string& filename) {
|
||||
V3Options::V3Options() {
|
||||
m_impp = new V3OptionsImp;
|
||||
|
||||
m_autoflush = false;
|
||||
m_coverageLine = false;
|
||||
m_coverageUser = false;
|
||||
m_debugCheck = false;
|
||||
@@ -830,7 +849,7 @@ V3Options::V3Options() {
|
||||
m_makeDir = "obj_dir";
|
||||
m_bin = "";
|
||||
m_flags = "";
|
||||
m_xAssign = "unique";
|
||||
m_xAssign = "fast";
|
||||
|
||||
m_language = V3LangCode::mostRecent();
|
||||
|
||||
|
||||
+8
-1
@@ -79,6 +79,7 @@ class V3Options {
|
||||
V3OptionsImp* m_impp; // Slow hidden options
|
||||
|
||||
V3StringSet m_cppFiles; // argument: C++ files to link against
|
||||
V3StringSet m_futures; // argument: -Wfuture- list
|
||||
V3StringSet m_libraryFiles; // argument: Verilog -v files
|
||||
V3StringList m_vFiles; // argument: Verilog files to read
|
||||
|
||||
@@ -86,6 +87,7 @@ class V3Options {
|
||||
bool m_makeDepend; // main switch: -MMD
|
||||
bool m_makePhony; // main switch: -MP
|
||||
bool m_assert; // main switch: --assert
|
||||
bool m_autoflush; // main switch: --autoflush
|
||||
bool m_coverageLine; // main switch: --coverage-block
|
||||
bool m_coverageUser; // main switch: --coverage-func
|
||||
bool m_debugCheck; // main switch: --debug-check
|
||||
@@ -150,9 +152,10 @@ class V3Options {
|
||||
private:
|
||||
// METHODS
|
||||
void addArg(const string& incdir);
|
||||
void addDefine(const string& defline);
|
||||
void addFuture(const string& flag);
|
||||
void addIncDir(const string& incdir);
|
||||
void addLibExt(const string& libext);
|
||||
void addDefine(const string& defline);
|
||||
void optimize(int level);
|
||||
void coverage(bool flag) { m_coverageLine = m_coverageUser = flag; }
|
||||
bool onoff(const char* sw, const char* arg, bool& flag);
|
||||
@@ -182,6 +185,7 @@ class V3Options {
|
||||
bool skipIdentical() const { return m_skipIdentical; }
|
||||
bool stats() const { return m_stats; }
|
||||
bool assertOn() const { return m_assert; } // assertOn as "assert" may be defined
|
||||
bool autoflush() const { return m_autoflush; }
|
||||
bool coverage() const { return m_coverageUser || m_coverageLine; }
|
||||
bool coverageLine() const { return m_coverageLine; }
|
||||
bool coverageUser() const { return m_coverageUser; }
|
||||
@@ -217,11 +221,14 @@ class V3Options {
|
||||
string modPrefix() const { return m_modPrefix; }
|
||||
string topModule() const { return m_topModule; }
|
||||
string xAssign() const { return m_xAssign; }
|
||||
|
||||
const V3StringSet& cppFiles() const { return m_cppFiles; }
|
||||
const V3StringSet& libraryFiles() const { return m_libraryFiles; }
|
||||
const V3StringList& vFiles() const { return m_vFiles; }
|
||||
const V3LangCode& language() const { return m_language; }
|
||||
|
||||
bool isFuture(const string& flag) const;
|
||||
|
||||
// ACCESSORS (optimization options)
|
||||
bool oAcycSimp() const { return m_oAcycSimp; }
|
||||
bool oCase() const { return m_oCase; }
|
||||
|
||||
+2
-2
@@ -88,8 +88,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
+2
-2
@@ -30,8 +30,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
+2
-2
@@ -21,8 +21,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <fstream>
|
||||
#include <stack>
|
||||
|
||||
+2
-2
@@ -20,8 +20,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
+25
-2
@@ -23,12 +23,15 @@
|
||||
// For each wide OP, make a a temporary variable with the wide value
|
||||
// For each deep expression, assign expression to temporary.
|
||||
//
|
||||
// Each display (independant transformation; here as Premit is a good point)
|
||||
// If autoflush, insert a flush
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
@@ -264,6 +267,26 @@ private:
|
||||
checkNode(nodep);
|
||||
}
|
||||
|
||||
// Autoflush
|
||||
virtual void visit(AstDisplay* nodep, AstNUser* vup) {
|
||||
startStatement(nodep);
|
||||
nodep->iterateChildren(*this);
|
||||
m_stmtp = NULL;
|
||||
if (v3Global.opt.autoflush()) {
|
||||
AstNode* searchp = nodep->nextp();
|
||||
while (searchp && searchp->castComment()) searchp = searchp->nextp();
|
||||
if (searchp
|
||||
&& searchp->castDisplay()
|
||||
&& nodep->filep()->sameTree(searchp->castDisplay()->filep())) {
|
||||
// There's another display next; we can just wait to flush
|
||||
} else {
|
||||
UINFO(4,"Autoflush "<<nodep<<endl);
|
||||
nodep->addNextHere(new AstFFlush(nodep->fileline(),
|
||||
nodep->filep()->cloneTree(true)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------
|
||||
// Default: Just iterate
|
||||
virtual void visit(AstVar* nodep, AstNUser*) {} // Don't hit varrefs under vars
|
||||
|
||||
+5
-2
@@ -20,8 +20,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <fstream>
|
||||
|
||||
@@ -181,6 +181,9 @@ void V3Read::lexFile(const string& modname) {
|
||||
bool V3Read::optPsl() {
|
||||
return v3Global.opt.psl();
|
||||
}
|
||||
bool V3Read::optFuture(const string& flag) {
|
||||
return v3Global.opt.isFuture(flag);
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// Lex internal functions
|
||||
|
||||
@@ -56,6 +56,7 @@ protected:
|
||||
friend class V3PreShellImp;
|
||||
int yylexThis();
|
||||
static bool optPsl();
|
||||
static bool optFuture(const string& flag);
|
||||
static void ppline (const char* text);
|
||||
static void incLineno() { s_readp->fileline()->incLineno(); }
|
||||
static void verilatorCmtLint(const char* text, bool on);
|
||||
|
||||
+2
-2
@@ -27,8 +27,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
#include <iomanip>
|
||||
|
||||
+2
-2
@@ -36,8 +36,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
|
||||
+11
-2
@@ -30,8 +30,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <map>
|
||||
#include <iomanip>
|
||||
@@ -80,6 +80,11 @@ private:
|
||||
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(AstConcat* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
|
||||
virtual void visit(AstReplicate* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
|
||||
@@ -102,6 +107,10 @@ private:
|
||||
virtual void visit(AstNeqCase* nodep, AstNUser*){ signed_Ou_Ix(nodep); }
|
||||
virtual void visit(AstNeqWild* 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); }
|
||||
|
||||
+2
-2
@@ -51,8 +51,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
+2
-2
@@ -27,8 +27,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
+2
-2
@@ -20,8 +20,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <map>
|
||||
#include <iomanip>
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <map>
|
||||
#include <iomanip>
|
||||
|
||||
+2
-2
@@ -28,8 +28,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
+2
-2
@@ -23,8 +23,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <map>
|
||||
|
||||
|
||||
+3
-3
@@ -27,10 +27,10 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
#include <cmath>
|
||||
#include <deque>
|
||||
|
||||
#include "V3Global.h"
|
||||
|
||||
+4
-3
@@ -29,8 +29,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <map>
|
||||
|
||||
@@ -208,7 +208,8 @@ private:
|
||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (nodep->varp()->user4p() != m_curVxp) {
|
||||
if (m_curVxp->pure()) {
|
||||
if (m_curVxp->pure()
|
||||
&& !nodep->varp()->isPure()) {
|
||||
m_curVxp->impure(nodep);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -48,8 +48,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
||||
+2
-2
@@ -26,8 +26,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "V3Global.h"
|
||||
|
||||
+5
-4
@@ -33,8 +33,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
|
||||
@@ -191,10 +191,11 @@ private:
|
||||
UINFO(4," -> "<<newp<<endl);
|
||||
} else {
|
||||
// Make a Vxrand variable
|
||||
// We use the special XTEMP type so it doesn't break pure functions
|
||||
string newvarname = ((string)"__Vxrand__"
|
||||
+cvtToStr(m_modp->varNumGetInc()));
|
||||
AstVar* newvarp
|
||||
= new AstVar (nodep->fileline(), AstVarType::MODULETEMP, newvarname,
|
||||
= new AstVar (nodep->fileline(), AstVarType::XTEMP, newvarname,
|
||||
new AstRange(nodep->fileline(), nodep->width()-1, 0));
|
||||
m_statUnkVars++;
|
||||
AstNRelinker replaceHandle;
|
||||
@@ -212,7 +213,7 @@ private:
|
||||
new AstAnd(nodep->fileline(),
|
||||
new AstConst(nodep->fileline(),numbx),
|
||||
new AstRand(nodep->fileline(),
|
||||
nodep->width())))));
|
||||
nodep->width(), true)))));
|
||||
// Add inits in front of other statement.
|
||||
// In the future, we should stuff the initp into the module's constructor.
|
||||
AstNode* afterp = m_modp->stmtsp()->unlinkFrBackWithNext();
|
||||
|
||||
+2
-2
@@ -30,8 +30,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
+54
-3
@@ -45,8 +45,8 @@
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "V3Global.h"
|
||||
@@ -362,6 +362,11 @@ private:
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstRand* nodep, AstNUser* vup) {
|
||||
if (vup->c()->prelim()) {
|
||||
nodep->width(32,32); // Says the spec
|
||||
}
|
||||
}
|
||||
virtual void visit(AstTime* nodep, AstNUser*) {
|
||||
nodep->width(64,64);
|
||||
}
|
||||
@@ -558,7 +563,10 @@ private:
|
||||
nodep->iterateChildren(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||
}
|
||||
virtual void visit(AstDisplay* nodep, AstNUser*) {
|
||||
if (nodep->filep()) nodep->filep()->iterateAndNext(*this,WidthVP(64,64,BOTH).p());
|
||||
if (nodep->filep()) {
|
||||
nodep->filep()->iterateAndNext(*this,WidthVP(64,64,BOTH).p());
|
||||
widthCheck(nodep,"file_descriptor (see docs)",nodep->filep(),64,64);
|
||||
}
|
||||
// Just let all arguments seek their natural sizes
|
||||
nodep->iterateChildren(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||
}
|
||||
@@ -566,9 +574,52 @@ private:
|
||||
nodep->filep()->iterateAndNext(*this,WidthVP(64,64,BOTH).p());
|
||||
nodep->filenamep()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||
nodep->modep()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||
widthCheck(nodep,"file_descriptor (see docs)",nodep->filep(),64,64);
|
||||
}
|
||||
virtual void visit(AstFClose* nodep, AstNUser*) {
|
||||
nodep->filep()->iterateAndNext(*this,WidthVP(64,64,BOTH).p());
|
||||
widthCheck(nodep,"file_descriptor (see docs)",nodep->filep(),64,64);
|
||||
}
|
||||
virtual void visit(AstFEof* nodep, AstNUser*) {
|
||||
nodep->filep()->iterateAndNext(*this,WidthVP(64,64,BOTH).p());
|
||||
nodep->width(1,1);
|
||||
widthCheck(nodep,"file_descriptor (see docs)",nodep->filep(),64,64);
|
||||
}
|
||||
virtual void visit(AstFFlush* nodep, AstNUser*) {
|
||||
if (nodep->filep()) {
|
||||
nodep->filep()->iterateAndNext(*this,WidthVP(64,64,BOTH).p());
|
||||
widthCheck(nodep,"file_descriptor (see docs)",nodep->filep(),64,64);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstFGetC* nodep, AstNUser* vup) {
|
||||
nodep->filep()->iterateAndNext(*this,WidthVP(64,64,BOTH).p());
|
||||
if (vup->c()->prelim()) {
|
||||
nodep->width(32,8);
|
||||
}
|
||||
widthCheck(nodep,"file_descriptor (see docs)",nodep->filep(),64,64);
|
||||
}
|
||||
virtual void visit(AstFGetS* nodep, AstNUser* vup) {
|
||||
nodep->filep()->iterateAndNext(*this,WidthVP(64,64,BOTH).p());
|
||||
nodep->strgp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||
if (vup->c()->prelim()) {
|
||||
nodep->width(32,32);
|
||||
}
|
||||
widthCheck(nodep,"file_descriptor (see docs)",nodep->filep(),64,64);
|
||||
}
|
||||
virtual void visit(AstFScanF* nodep, AstNUser* vup) {
|
||||
nodep->filep()->iterateAndNext(*this,WidthVP(64,64,BOTH).p());
|
||||
nodep->exprsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||
if (vup->c()->prelim()) {
|
||||
nodep->width(32,32);
|
||||
}
|
||||
widthCheck(nodep,"file_descriptor (see docs)",nodep->filep(),64,64);
|
||||
}
|
||||
virtual void visit(AstSScanF* nodep, AstNUser* vup) {
|
||||
nodep->fromp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||
nodep->exprsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||
if (vup->c()->prelim()) {
|
||||
nodep->width(32,32);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstReadMem* nodep, AstNUser*) {
|
||||
nodep->filenamep()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||
|
||||
@@ -307,6 +307,8 @@ void process () {
|
||||
V3Gate::gateAll(v3Global.rootp());
|
||||
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("gate.tree"));
|
||||
// V3Gate calls constant propagation itself.
|
||||
} else {
|
||||
v3info("Command Line disabled gate optimization with -Og/-O0. This may cause ordering problems.");
|
||||
}
|
||||
|
||||
// Remove unused vars
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
//**********************************************************************
|
||||
//**** Version and host name
|
||||
|
||||
#define DTVERSION "Verilator 3.665 2008/06/25"
|
||||
#define DTVERSION "Verilator 3.670 2008/07/23"
|
||||
|
||||
//**********************************************************************
|
||||
//**** Functions
|
||||
@@ -83,7 +83,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <stdio.h>
|
||||
#include <cstdio>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
+25
-2
@@ -54,7 +54,9 @@ void V3Read::verilatorCmtLint(const char* textp, bool warnOff) {
|
||||
string::size_type pos;
|
||||
if ((pos=msg.find("*")) != string::npos) { msg.erase(pos); }
|
||||
if (!(V3Read::fileline()->warnOff(msg, warnOff))) {
|
||||
yyerrorf("Unknown verilator lint message code: %s, in %s",msg.c_str(), textp);
|
||||
if (!V3Read::optFuture(msg)) {
|
||||
yyerrorf("Unknown verilator lint message code: %s, in %s",msg.c_str(), textp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +73,20 @@ void V3Read::verilatorCmtLintRestore() {
|
||||
}
|
||||
|
||||
void V3Read::verilatorCmtBad(const char* textp) {
|
||||
yyerrorf("Unknown verilator comment: %s",textp);
|
||||
string cmtparse = textp;
|
||||
if (cmtparse.substr(0,strlen("/*verilator")) == "/*verilator") {
|
||||
cmtparse.replace(0,strlen("/*verilator"), "");
|
||||
}
|
||||
while (isspace(cmtparse[0])) {
|
||||
cmtparse.replace(0,1, "");
|
||||
}
|
||||
string cmtname;
|
||||
for (int i=0; isalnum(cmtparse[i]); i++) {
|
||||
cmtname += cmtparse[i];
|
||||
}
|
||||
if (!V3Read::optFuture(cmtname)) {
|
||||
yyerrorf("Unknown verilator comment: %s",textp);
|
||||
}
|
||||
}
|
||||
|
||||
// See V3Read.cpp
|
||||
@@ -132,13 +147,19 @@ escid \\[^ \t\f\r\n]+
|
||||
"$display" {yylval.fileline = CRELINE(); return yD_DISPLAY;}
|
||||
"$fclose" {yylval.fileline = CRELINE(); return yD_FCLOSE;}
|
||||
"$fdisplay" {yylval.fileline = CRELINE(); return yD_FDISPLAY;}
|
||||
"$feof" {yylval.fileline = CRELINE(); return yD_FEOF;}
|
||||
"$fflush" {yylval.fileline = CRELINE(); return yD_FFLUSH;}
|
||||
"$fgetc" {yylval.fileline = CRELINE(); return yD_FGETC;}
|
||||
"$fgets" {yylval.fileline = CRELINE(); return yD_FGETS;}
|
||||
"$finish" {yylval.fileline = CRELINE(); return yD_FINISH;}
|
||||
"$fopen" {yylval.fileline = CRELINE(); return yD_FOPEN;}
|
||||
"$fscanf" {yylval.fileline = CRELINE(); return yD_FSCANF;}
|
||||
"$fullskew" {yylval.fileline = CRELINE(); return yaTIMINGSPEC;}
|
||||
"$fwrite" {yylval.fileline = CRELINE(); return yD_FWRITE;}
|
||||
"$hold" {yylval.fileline = CRELINE(); return yaTIMINGSPEC;}
|
||||
"$nochange" {yylval.fileline = CRELINE(); return yaTIMINGSPEC;}
|
||||
"$period" {yylval.fileline = CRELINE(); return yaTIMINGSPEC;}
|
||||
"$random" {yylval.fileline = CRELINE(); return yD_RANDOM;}
|
||||
"$readmemb" {yylval.fileline = CRELINE(); return yD_READMEMB;}
|
||||
"$readmemh" {yylval.fileline = CRELINE(); return yD_READMEMH;}
|
||||
"$realtime" {yylval.fileline = CRELINE(); return yD_TIME;}
|
||||
@@ -148,6 +169,8 @@ escid \\[^ \t\f\r\n]+
|
||||
"$setup" {yylval.fileline = CRELINE(); return yaTIMINGSPEC;}
|
||||
"$setuphold" {yylval.fileline = CRELINE(); return yaTIMINGSPEC;}
|
||||
"$skew" {yylval.fileline = CRELINE(); return yaTIMINGSPEC;}
|
||||
"$sscanf" {yylval.fileline = CRELINE(); return yD_SSCANF;}
|
||||
"$stime" {yylval.fileline = CRELINE(); return yD_STIME;}
|
||||
"$stop" {yylval.fileline = CRELINE(); return yD_STOP;}
|
||||
"$time" {yylval.fileline = CRELINE(); return yD_TIME;}
|
||||
"$timeskew" {yylval.fileline = CRELINE(); return yaTIMINGSPEC;}
|
||||
|
||||
+38
-5
@@ -20,7 +20,7 @@
|
||||
//*************************************************************************
|
||||
|
||||
%{
|
||||
#include <stdio.h>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstdarg>
|
||||
#include <cstring>
|
||||
@@ -226,16 +226,24 @@ class AstSenTree;
|
||||
%token<fileline> yD_FATAL "$fatal"
|
||||
%token<fileline> yD_FCLOSE "$fclose"
|
||||
%token<fileline> yD_FDISPLAY "$fdisplay"
|
||||
%token<fileline> yD_FEOF "$feof"
|
||||
%token<fileline> yD_FFLUSH "$fflush"
|
||||
%token<fileline> yD_FGETC "$fgetc"
|
||||
%token<fileline> yD_FGETS "$fgets"
|
||||
%token<fileline> yD_FINISH "$finish"
|
||||
%token<fileline> yD_FOPEN "$fopen"
|
||||
%token<fileline> yD_FSCANF "$fscanf"
|
||||
%token<fileline> yD_FWRITE "$fwrite"
|
||||
%token<fileline> yD_INFO "$info"
|
||||
%token<fileline> yD_ISUNKNOWN "$isunknown"
|
||||
%token<fileline> yD_ONEHOT "$onehot"
|
||||
%token<fileline> yD_ONEHOT0 "$onehot0"
|
||||
%token<fileline> yD_RANDOM "$random"
|
||||
%token<fileline> yD_READMEMB "$readmemb"
|
||||
%token<fileline> yD_READMEMH "$readmemh"
|
||||
%token<fileline> yD_SIGNED "$signed"
|
||||
%token<fileline> yD_SSCANF "$sscanf"
|
||||
%token<fileline> yD_STIME "$stime"
|
||||
%token<fileline> yD_STOP "$stop"
|
||||
%token<fileline> yD_TIME "$time"
|
||||
%token<fileline> yD_UNSIGNED "$unsigned"
|
||||
@@ -424,6 +432,7 @@ class AstSenTree;
|
||||
%type<assignwp> gateBuf gateNot gateAnd gateNand gateOr gateNor gateXor gateXnor
|
||||
%type<nodep> gateAndPinList gateOrPinList gateXorPinList
|
||||
%type<nodep> commaEListE
|
||||
%type<nodep> commaVRDListE vrdList
|
||||
|
||||
%type<nodep> pslStmt pslDir pslDirOne pslProp
|
||||
%type<nodep> pslDecl
|
||||
@@ -895,6 +904,9 @@ stmt: ';' { $$ = NULL; }
|
||||
| '{' concIdList '}' '=' delayE expr ';' { $$ = new AstAssign($4,$2,$6); }
|
||||
| yD_C '(' cStrList ')' ';' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCStmt($1,$3)); }
|
||||
| yD_FCLOSE '(' varRefDotBit ')' ';' { $$ = new AstFClose($1, $3); }
|
||||
| yD_FFLUSH ';' { $1->v3error("Unsupported: $fflush of all handles does not map to C++.\n"); }
|
||||
| yD_FFLUSH '(' ')' ';' { $1->v3error("Unsupported: $fflush of all handles does not map to C++.\n"); }
|
||||
| yD_FFLUSH '(' varRefDotBit ')' ';' { $$ = new AstFClose($1, $3); }
|
||||
| yD_FINISH parenE ';' { $$ = new AstFinish($1); }
|
||||
| yD_FINISH '(' expr ')' ';' { $$ = new AstFinish($1); }
|
||||
| yD_STOP parenE ';' { $$ = new AstStop($1); }
|
||||
@@ -940,9 +952,9 @@ stateCaseForIf: caseStmt caseAttrE caseListE yENDCASE { $$ = $1; if ($3) $1->add
|
||||
| yDO stmtBlock yWHILE '(' expr ')' { $$ = $2->cloneTree(true); $$->addNext(new AstWhile($1,$5,$2));}
|
||||
;
|
||||
|
||||
caseStmt: yCASE '(' expr ')' { $$ = V3Parse::s_caseAttrp = new AstCase($1,false,$3,NULL); }
|
||||
| yCASEX '(' expr ')' { $$ = V3Parse::s_caseAttrp = new AstCase($1,true,$3,NULL); $1->v3warn(CASEX,"Suggest casez (with ?'s) in place of casex (with X's)\n"); }
|
||||
| yCASEZ '(' expr ')' { $$ = V3Parse::s_caseAttrp = new AstCase($1,true,$3,NULL); }
|
||||
caseStmt: yCASE '(' expr ')' { $$ = V3Parse::s_caseAttrp = new AstCase($1,AstCaseType::CASE,$3,NULL); }
|
||||
| yCASEX '(' expr ')' { $$ = V3Parse::s_caseAttrp = new AstCase($1,AstCaseType::CASEX,$3,NULL); $1->v3warn(CASEX,"Suggest casez (with ?'s) in place of casex (with X's)\n"); }
|
||||
| yCASEZ '(' expr ')' { $$ = V3Parse::s_caseAttrp = new AstCase($1,AstCaseType::CASEZ,$3,NULL); }
|
||||
;
|
||||
|
||||
caseAttrE: /*empty*/ { }
|
||||
@@ -1076,10 +1088,19 @@ exprNoStr: expr yP_OROR expr { $$ = new AstLogOr ($2,$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); }
|
||||
| yD_FEOF '(' expr ')' { $$ = new AstFEof($1,$3); }
|
||||
| yD_FGETC '(' expr ')' { $$ = new AstFGetC($1,$3); }
|
||||
| yD_FGETS '(' varRefDotBit ',' expr ')' { $$ = new AstFGetS($1,$3,$5); }
|
||||
| yD_FSCANF '(' expr ',' yaSTRING commaVRDListE ')' { $$ = new AstFScanF($1,*$5,$3,$6); }
|
||||
| yD_SSCANF '(' expr ',' yaSTRING commaVRDListE ')' { $$ = new AstSScanF($1,*$5,$3,$6); }
|
||||
| yD_ISUNKNOWN '(' expr ')' { $$ = new AstIsUnknown($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\")\n"); }
|
||||
| yD_RANDOM '(' ')' { $$ = new AstRand($1); }
|
||||
| yD_RANDOM { $$ = new AstRand($1); }
|
||||
| yD_SIGNED '(' expr ')' { $$ = new AstSigned($1,$3); }
|
||||
| yD_STIME { $$ = new AstSel($1,new AstTime($1),0,32); }
|
||||
| yD_TIME { $$ = new AstTime($1); }
|
||||
| yD_UNSIGNED '(' expr ')' { $$ = new AstUnsigned($1,$3); }
|
||||
|
||||
@@ -1122,6 +1143,14 @@ commaEListE: /* empty */ { $$ = NULL; }
|
||||
| ',' exprList { $$ = $2; }
|
||||
;
|
||||
|
||||
vrdList: varRefDotBit { $$ = $1; }
|
||||
| vrdList ',' varRefDotBit { $$ = $1;$1->addNext($3); }
|
||||
;
|
||||
|
||||
commaVRDListE: /* empty */ { $$ = NULL; }
|
||||
| ',' vrdList { $$ = $2; }
|
||||
;
|
||||
|
||||
//************************************************
|
||||
// Gate declarations
|
||||
|
||||
@@ -1453,8 +1482,12 @@ string V3Parse::deQuote(FileLine* fileline, string text) {
|
||||
}
|
||||
} else {
|
||||
if (octal_digits) {
|
||||
fileline->v3error("Non-three digit octal escape code (\\###)");
|
||||
// Spec allows 1-3 digits
|
||||
octal_digits = 0;
|
||||
quoted = false;
|
||||
newtext += octal_val;
|
||||
--cp; // Backup to reprocess terminating character as non-escaped
|
||||
continue;
|
||||
}
|
||||
quoted = false;
|
||||
if (*cp == 'n') newtext += '\n';
|
||||
|
||||
@@ -325,9 +325,11 @@ sub compile {
|
||||
}
|
||||
if ($param{v3}) {
|
||||
$opt_gdb="gdbrun" if defined $opt_gdb;
|
||||
unshift @{$param{verilator_flags}}, "--gdb $opt_gdb" if $opt_gdb;
|
||||
unshift @{$param{verilator_flags}}, "--debug" if $::Debug;
|
||||
# unshift @{$param{verilator_flags}}, "--trace";
|
||||
my @verilator_flags = @{$param{verilator_flags}};
|
||||
unshift @verilator_flags, "--gdb $opt_gdb" if $opt_gdb;
|
||||
unshift @verilator_flags, "--debug" if $::Debug;
|
||||
unshift @verilator_flags, "--x-assign unique"; # More likely to be buggy
|
||||
# unshift @verilator_flags, "--trace";
|
||||
if (defined $opt_optimize) {
|
||||
my $letters = "";
|
||||
if ($opt_optimize =~ /[a-zA-Z]/) {
|
||||
@@ -336,15 +338,15 @@ sub compile {
|
||||
foreach my $l ('a'..'z') {
|
||||
$letters .= ((rand() > 0.5) ? $l : uc $l);
|
||||
}
|
||||
unshift @{$param{verilator_flags}}, "--trace" if rand() > 0.5;
|
||||
unshift @{$param{verilator_flags}}, "--coverage" if rand() > 0.5;
|
||||
unshift @verilator_flags, "--trace" if rand() > 0.5;
|
||||
unshift @verilator_flags, "--coverage" if rand() > 0.5;
|
||||
}
|
||||
unshift @{$param{verilator_flags}}, "--O".$letters;
|
||||
unshift @verilator_flags, "--O".$letters;
|
||||
}
|
||||
|
||||
my @v3args = ("perl","../bin/verilator",
|
||||
"--prefix ".$self->{VM_PREFIX},
|
||||
@{$param{verilator_flags}},
|
||||
@verilator_flags,
|
||||
@{$param{verilator_flags2}},
|
||||
@{$param{v_flags}},
|
||||
@{$param{v_flags2}},
|
||||
|
||||
@@ -9,7 +9,7 @@ if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
|
||||
$golden_out ||= "t/$Last_Self->{name}.out";
|
||||
|
||||
compile (
|
||||
v_flags2 => [$Last_Self->{v3}?"--stats --O3 -x-assign 0":""],
|
||||
v_flags2 => [$Last_Self->{v3}?"--stats --O3 -x-assign fast":""],
|
||||
);
|
||||
|
||||
execute (
|
||||
|
||||
@@ -9,7 +9,7 @@ if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
|
||||
$golden_out ||= "t/$Last_Self->{name}.out";
|
||||
|
||||
compile (
|
||||
v_flags2 => [$Last_Self->{v3}?"--stats --O3 -x-assign 0":""],
|
||||
v_flags2 => [$Last_Self->{v3}?"--stats --O3 -x-assign fast":""],
|
||||
);
|
||||
|
||||
execute (
|
||||
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003-2007 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# General Public License or the Perl Artistic License.
|
||||
|
||||
compile (
|
||||
v_flags2 => ["--x-assign 0"],
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user