mirror of
https://github.com/verilator/verilator.git
synced 2026-10-03 08:33:21 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2433848408 | ||
|
|
e602f7febc | ||
|
|
f607b32938 | ||
|
|
c7a088faa5 | ||
|
|
30f6c0e105 | ||
|
|
38b9fa7b93 | ||
|
|
39a31fc17f | ||
|
|
899a7df14a | ||
|
|
7a8c425103 | ||
|
|
0e8ce59022 | ||
|
|
77ac76a158 | ||
|
|
8108b97050 | ||
|
|
a1c3491dea | ||
|
|
8bba96a84e | ||
|
|
6cd9b25a53 | ||
|
|
0431b1909c | ||
|
|
907665e2e8 | ||
|
|
61e8836fbd | ||
|
|
0e921b5dff | ||
|
|
7ef37d6e17 | ||
|
|
dce227684a | ||
|
|
158e112752 | ||
|
|
ec992c7f5e | ||
|
|
e7d63c7644 | ||
|
|
6464e8fee6 | ||
|
|
047d66a657 | ||
|
|
55c23360d9 | ||
|
|
c378d32c85 | ||
|
|
3d9540c58c | ||
|
|
39724eb916 | ||
|
|
48dddd4ae7 | ||
|
|
9c00fd10de | ||
|
|
9309d0b00f | ||
|
|
038b5d32a3 | ||
|
|
706920ba19 | ||
|
|
39492a0726 | ||
|
|
df1170fea9 | ||
|
|
f0e1d204fa | ||
|
|
8ece0a8a5f | ||
|
|
1373b81e7c | ||
|
|
d3601dd561 | ||
|
|
f685cf1d0c | ||
|
|
d5fcf0c153 | ||
|
|
5f9810070d | ||
|
|
923efa004b | ||
|
|
869e8eab3c | ||
|
|
b51d197117 | ||
|
|
e4f0a8952c | ||
|
|
072ee425f4 | ||
|
|
a4c2819be2 | ||
|
|
2a274f9c19 |
@@ -12,6 +12,7 @@
|
||||
*.pdf
|
||||
/Makefile
|
||||
README
|
||||
TAGS
|
||||
autom4te.cache
|
||||
config.cache
|
||||
config.status
|
||||
|
||||
@@ -3,6 +3,55 @@ 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.843 2012/12/01
|
||||
|
||||
*** Add +1364-1995ext and similar language options, bug532. [Jeremy Bennett]
|
||||
|
||||
**** Fix mis-optimized identical submodule subtract, bug581. [Charlie Brej]
|
||||
|
||||
**** Fix crash on dotted references into dead modules, bug583. [Jeremy Bennett]
|
||||
|
||||
**** Fix compile issues on MSVCC, bug571, bug577. [Amir Gonnen]
|
||||
|
||||
**** Fix --debug overriding preceding --dump-treei, bug580. [Jeremy Bennett]
|
||||
|
||||
|
||||
* Verilator 3.842 2012/11/03
|
||||
|
||||
**** Add -x-initial-edge, bug570. [Jeremy Bennett]
|
||||
|
||||
**** Fix parameter pins interspersed with cells broke in 3.840. [Bernard Deadman]
|
||||
|
||||
**** Fix large shift error on large shift constants. [David Welch]
|
||||
|
||||
**** Fix $display mangling on GCC 4.7 and speed up, msg927, bug373, bug574. [R Diez]
|
||||
|
||||
**** Fix array of struct references giving false error, bug566. [Julius Baxter]
|
||||
|
||||
**** Fix missing var access functions when no DPI, bug572. [Amir Gonnen]
|
||||
|
||||
**** Fix name collision on unnamed blocks, bug567. [Chandan Egbert]
|
||||
|
||||
**** Fix name collision on task inputs, bug569. [Chandan Egbert]
|
||||
|
||||
|
||||
* Verilator 3.841 2012/09/03
|
||||
|
||||
*** Add --savable to support model save/restore. [Jeremy Bennett]
|
||||
|
||||
*** Support '{} assignment pattern on structures, part of bug355.
|
||||
|
||||
**** Fix double-deep parameter cell WIDTHs, bug541. [Hiroki Honda]
|
||||
|
||||
**** Fix imports under multiple instantiated cells, bug542. [Alex Solomatnikov]
|
||||
|
||||
**** Fix defparam in generate broke in 3.840, bug543. [Alex Solomatnikov]
|
||||
|
||||
**** Fix duplicate begin error broke in 3.840, bug548. [Alex Solomatnikov]
|
||||
|
||||
**** Fix triangle symbol resolution error broke in 3.840, bug550. [Ted Campbell]
|
||||
|
||||
|
||||
* Verilator 3.840 2012/07/31 Beta
|
||||
|
||||
** Rewrote tristate handling; supports tri0, tri1, tristate bit selects,
|
||||
|
||||
@@ -36,3 +36,5 @@ nodist/
|
||||
/vc_hdrs.h$
|
||||
/csrc/
|
||||
doxygen-doc/.*
|
||||
TAGS
|
||||
.*~
|
||||
|
||||
+191
-32
@@ -241,6 +241,11 @@ descriptions in the next sections for more information.
|
||||
{file.c/cc/cpp} Optional C++ files to compile in
|
||||
{file.a/o/so} Optional C++ files to link in
|
||||
|
||||
+1364-1995ext+<ext> Use Verilog 1995 with file extension <ext>
|
||||
+1364-2001ext+<ext> Use Verilog 2001 with file extension <ext>
|
||||
+1364-2005ext+<ext> Use Verilog 2005 with file extension <ext>
|
||||
+1800-2005ext+<ext> Use SystemVerilog 2005 with file extension <ext>
|
||||
+1800-2009ext+<ext> Use SystemVerilog 2009 with file extension <ext>
|
||||
--assert Enable all assertions
|
||||
--autoflush Flush streams after all $displays
|
||||
--bbox-sys Blackbox unknown $system calls
|
||||
@@ -261,6 +266,7 @@ descriptions in the next sections for more information.
|
||||
--debug-check Enable debugging assertions
|
||||
--debugi <level> Enable debugging at a specified level
|
||||
--debugi-<srcfile> <level> Enable debugging a source file at a level
|
||||
--default-language <lang> Default language to parse
|
||||
+define+<var>+<value> Set preprocessor define
|
||||
--dump-tree Enable dumping .tree files
|
||||
--dump-treei <level> Enable dumping .tree files at a level
|
||||
@@ -279,7 +285,7 @@ descriptions in the next sections for more information.
|
||||
--inline-mult <value> Tune module inlining
|
||||
-LDFLAGS <flags> Linker pre-object flags for makefile
|
||||
-LDLIBS <flags> Linker library flags for makefile
|
||||
--language <lang> Language standard to parse
|
||||
--language <lang> Default language standard to parse
|
||||
+libext+<ext>+[ext]... Extensions for finding modules
|
||||
--lint-only Lint, but do not make output
|
||||
--MMD Create .d dependency files
|
||||
@@ -303,10 +309,12 @@ descriptions in the next sections for more information.
|
||||
--private Debugging; see docs
|
||||
--psl Enable PSL parsing
|
||||
--public Debugging; see docs
|
||||
--savable Enable model save-restore
|
||||
--sc Create SystemC output
|
||||
--sp Create SystemPerl output
|
||||
--stats Create statistics file
|
||||
-sv Enable SystemVerilog parsing
|
||||
+systemverilogext+<ext> Synonym for +1800-2009ext+<ext>
|
||||
--top-module <topname> Name of top level input module
|
||||
--trace Enable waveform creation
|
||||
--trace-depth <levels> Depth of tracing
|
||||
@@ -319,13 +327,16 @@ descriptions in the next sections for more information.
|
||||
--unused-regexp <regexp> Tune UNUSED lint signals
|
||||
-V Verbose version and config
|
||||
-v <filename> Verilog library
|
||||
+verilog1995ext+<ext> Synonym for +1364-1995ext+<ext>
|
||||
+verilog2001ext+<ext> Synonym for +1364-2001ext+<ext>
|
||||
-Werror-<message> Convert warning to error
|
||||
-Wfuture-<message> Disable unknown message warnings
|
||||
-Wno-<message> Disable warning
|
||||
-Wno-lint Disable all lint warnings
|
||||
-Wno-style Disable all style warnings
|
||||
-Wno-fatal Disable fatal exit on warnings
|
||||
-x-assign <mode> Initially assign Xs to this value
|
||||
--x-assign <mode> Initially assign Xs to this value
|
||||
--x-initial-edge Enable initial X->0 and X->1 edge triggers
|
||||
-y <dir> Directory to search for modules
|
||||
|
||||
|
||||
@@ -353,18 +364,56 @@ this way, Verilator will include a make rule that uses these files when
|
||||
linking the I<module> executable. This generally is only useful when used
|
||||
with the --exe option.
|
||||
|
||||
=item +1364-1995ext+I<ext>
|
||||
|
||||
=item +1364-2001ext+I<ext>
|
||||
|
||||
=item +1364-2005ext+I<ext>
|
||||
|
||||
=item +1800-2005ext+I<ext>
|
||||
|
||||
=item +1800-2009ext+I<ext>
|
||||
|
||||
Specifies the language standard to be used with a specific filename
|
||||
extension, I<ext>.
|
||||
|
||||
For compatibility with other simulators, see also the synonyms
|
||||
C<+verilog1995ext+>I<ext>, C<+verilog2001ext+>I<ext>, and
|
||||
C<+systemverilogext+>I<ext>.
|
||||
|
||||
For any source file, the language specified by these options takes
|
||||
precedence over any language specified by the C<--default-language> or
|
||||
C<--language> options.
|
||||
|
||||
These options take effect in the order they are encountered. Thus the
|
||||
following would use Verilog 1995 for C<a.v> and Verilog 2001 for C<b.v>.
|
||||
|
||||
verilator ... +1364-1995ext+v a.v +1364-2001ext+v b.v
|
||||
|
||||
These flags are only recommended for legacy mixed language designs, as the
|
||||
preferable option is to edit the code to repair new keywords, or add
|
||||
appropriate C<`begin_keywords>.
|
||||
|
||||
B<Note> C<`begin_keywords> is a SystemVerilog construct, which specifies
|
||||
I<only> which the set of keywords is to be recognized. Whatever set is
|
||||
chosen, the semantics will be those of SystemVerilog. By contrast
|
||||
C<+1364-1995ext+> etc. specify both the syntax I<and> semantics to be used.
|
||||
|
||||
=item --assert
|
||||
|
||||
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.
|
||||
See also --x-assign and --x-initial-edge; setting "--x-assign unique"
|
||||
and/or "--x-initial-edge" 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.
|
||||
that messages will appear immediately but may reduce performance; for best
|
||||
performance call "fflush(stdout)" occasionally in the main C loop.
|
||||
Defaults off, which will buffer output as provided by the normal C stdio
|
||||
calls.
|
||||
|
||||
=item --bbox-sys
|
||||
|
||||
@@ -524,6 +573,7 @@ Rarely needed. Enable internal debugging assertion checks, without
|
||||
changing debug verbosity. Enabled automatically when --debug specified.
|
||||
|
||||
=item --debugi <level>
|
||||
|
||||
=item --debugi-<srcfile> <level>
|
||||
|
||||
Rarely needed - for developer use. Set internal debugging level globally
|
||||
@@ -531,6 +581,25 @@ to the specified debug level (1-10) or set the specified source file to the
|
||||
specified level. Higher levels produce more detailed messages (plain
|
||||
C<--debug> is equivalent to C<--debugi 4>).
|
||||
|
||||
=item --default-language I<value>
|
||||
|
||||
Select the language to be used by default when first processing each
|
||||
Verilog file. The language value must be "1364-1995", "1364-2001",
|
||||
"1364-2005", "1800-2005" or "1800-2009".
|
||||
|
||||
Any language associated with a particular file extension (see the various
|
||||
+I<lang>ext+ options) will be used in preference to the language specified
|
||||
by --default-language.
|
||||
|
||||
The --default-language flag is only recommended for legacy code using the
|
||||
same language in all source files, as the preferable option is to edit the
|
||||
code to repair new keywords, or add appropriate C<`begin_keywords>. For
|
||||
legacy mixed language designs, the various +I<lang>ext+ options should be
|
||||
used.
|
||||
|
||||
If no language is specified, either by this flag or +I<lang>ext+ options,
|
||||
then the latest SystemVerilog language (IEEE 1800-2009) is used.
|
||||
|
||||
=item +define+I<var>+I<value>
|
||||
|
||||
Defines the given preprocessor symbol. Same as -D; +define is fairly
|
||||
@@ -544,7 +613,7 @@ the Verilator Internals manual. --dump-tree is enabled automatically with
|
||||
--debug, so "--debug --no-dump-tree" may be useful if the dump files are
|
||||
large and not desired.
|
||||
|
||||
=item --dump-treei
|
||||
=item --dump-treei <level>
|
||||
|
||||
Rarely needed. Enable writing .tree debug files with a specific dumping
|
||||
level, 0 disbles dumps and is equivelent to "--no-dump-tree". Level 9
|
||||
@@ -640,15 +709,8 @@ in the Make variable LDLIBS, not LDFLAGS.)
|
||||
|
||||
=item --language I<value>
|
||||
|
||||
Select the language to be used when first processing each Verilog file.
|
||||
The language value must be "1364-1995", "1364-2001", "1364-2001",
|
||||
"1364-2005", "1800-2005", "VAMS-2.3". Verilator also allows the
|
||||
non-standard "1800+VAMS" to allow both the full SystemVerilog and
|
||||
Verilog-AMS keywords.
|
||||
|
||||
The --language flag is only recommended for legacy code, as the preferable
|
||||
option is to edit the code to repair new keywords, or add appropriate
|
||||
`begin_keywords.
|
||||
A synonym for C<--default-langauge>, for compatibility with other tools and
|
||||
earlier versions of Verilator.
|
||||
|
||||
=item +libext+I<ext>+I<ext>...
|
||||
|
||||
@@ -816,6 +878,27 @@ inlining. This will also turn off inlining as if all modules had a
|
||||
/*verilator public_module*/, unless the module specifically enabled it with
|
||||
/*verilator inline_module*/.
|
||||
|
||||
=item --savable
|
||||
|
||||
Enable including save and restore functions in the generated model.
|
||||
|
||||
The user code must create a VerilatedSerialize or VerilatedDeserialze
|
||||
object then calling the << or >> operators on the generated model and any
|
||||
other data the process needs saved/restored. For example:
|
||||
|
||||
void save_model(const char* filenamep) {
|
||||
VerilatedSave os;
|
||||
os.open(filenamep);
|
||||
os << main_time; // user code must save the timestamp, etc
|
||||
os << *topp;
|
||||
}
|
||||
void restore_model(const char* filenamep) {
|
||||
VerilatedRestore os;
|
||||
os.open(filenamep);
|
||||
os >> main_time;
|
||||
os >> *topp;
|
||||
}
|
||||
|
||||
=item --sc
|
||||
|
||||
Specifies SystemC output mode; see also --cc and -sp.
|
||||
@@ -834,6 +917,10 @@ Specifies SystemVerilog language features should be enabled; equivalent to
|
||||
"--language 1800-2005". This option is selected by default, it exists for
|
||||
compatibility with other simulators.
|
||||
|
||||
=item +systemverilogext+I<ext>
|
||||
|
||||
A synonym for C<+1800-2009ext+>I<ext>.
|
||||
|
||||
=item --top-module I<topname>
|
||||
|
||||
When the input Verilog contains more than one top level module, specifies
|
||||
@@ -909,6 +996,12 @@ Read the filename as a Verilog library. Any modules in the file may be
|
||||
used to resolve cell instantiations in the top level module, else ignored.
|
||||
Note -v is fairly standard across Verilog tools.
|
||||
|
||||
=item +verilog1995ext+I<ext>
|
||||
|
||||
=item +verilog2001ext+I<ext>
|
||||
|
||||
Synonyms for C<+1364-1995ext+>I<ext> and C<+1364-2001ext+>I<ext> respectively
|
||||
|
||||
=item -Wall
|
||||
|
||||
Enable all warnings, including code style warnings that are normally
|
||||
@@ -978,29 +1071,63 @@ Enable all code style related warning messages. This is equivalent to
|
||||
-Wwarn-PINNOCONNECT -Wwarn-SYNCASYNCNET -Wwarn-UNDRIVEN -Wwarn-UNUSED
|
||||
-Wwarn-VARHIDDEN".
|
||||
|
||||
=item -x-assign 0
|
||||
=item --x-assign 0
|
||||
|
||||
=item -x-assign 1
|
||||
=item --x-assign 1
|
||||
|
||||
=item -x-assign fast (default)
|
||||
=item --x-assign fast (default)
|
||||
|
||||
=item -x-assign unique
|
||||
=item --x-assign unique
|
||||
|
||||
Controls the two-state value that is replaced when an assignment to X is
|
||||
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
|
||||
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.
|
||||
|
||||
If using -x-assign unique, you may want to seed your random number
|
||||
If using --x-assign unique, you may want to seed your random number
|
||||
generator such that each regression run gets a different randomization
|
||||
sequence. Use the system's srand48() or for Windows srand() function to do
|
||||
this. You'll probably also want to print any seeds selected, and code to
|
||||
enable rerunning with that same seed so you can reproduce bugs.
|
||||
|
||||
B<Note.> This option applies only to variables which are explicitly assigned
|
||||
to X in the Verilog source code. Initial values of clocks are set to 0 unless
|
||||
--x-initial-edge is specified. Initial values of all other state holding
|
||||
variables are set as though --x-assign unique had been specified.
|
||||
|
||||
=item --x-initial-edge
|
||||
|
||||
Enables emulation of event driven simulators which generally trigger an
|
||||
edge on a transition from X to 1 (C<posedge>) or X to 0 (C<negedge>). Thus
|
||||
the following code, where C<rst_n> is uninitialized would set C<res_n> to
|
||||
C<1'b1> when C<rst_n> is first set to zero:
|
||||
|
||||
reg res_n = 1'b0;
|
||||
|
||||
always @(negedge rst_n) begin
|
||||
if (rst_n == 1'b0) begin
|
||||
res_n <= 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
In Verilator, by default, uninitialized clocks are given a value of zero,
|
||||
so the above C<always> block would not trigger.
|
||||
|
||||
While it is not good practice, there are some designs that rely on X
|
||||
E<rarr> 0 triggering a C<negedge>, particularly in reset sequences. Using
|
||||
--x-initial-edge with Verilator will replicate this behaviour. It will also
|
||||
ensure that X E<rarr> 1 triggers a C<posedge>.
|
||||
|
||||
B<Note.> Some users have reported that using this option can affect
|
||||
convergence, and that it may be necessary to use --converge-limit to
|
||||
increase the number of convergence iterations. This may be another
|
||||
indication of problems with the modelled design that should be addressed.
|
||||
|
||||
=item -y I<dir>
|
||||
|
||||
Add the directory to the list of directories that should be searched for
|
||||
@@ -1036,6 +1163,7 @@ We'll compile this example into C++.
|
||||
Verilated::commandArgs(argc, argv);
|
||||
Vour* top = new Vour;
|
||||
while (!Verilated::gotFinish()) { top->eval(); }
|
||||
delete top;
|
||||
exit(0);
|
||||
}
|
||||
EOF
|
||||
@@ -1103,6 +1231,7 @@ This is an example similar to the above, but using SystemPerl.
|
||||
top = new Vour("top"); // SP_CELL (top, Vour);
|
||||
top->clk(clk); // SP_PIN (top, clk, clk);
|
||||
while (!Verilated::gotFinish()) { sc_start(1, SC_NS); }
|
||||
delete top;
|
||||
exit(0);
|
||||
}
|
||||
EOF
|
||||
@@ -1159,9 +1288,9 @@ the test_sp directory in the distribution for an example.
|
||||
|
||||
=head1 BENCHMARKING & OPTIMIZATION
|
||||
|
||||
For best performance, run Verilator with the "-O3 -x-assign=fast
|
||||
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
|
||||
--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
|
||||
@@ -1176,8 +1305,10 @@ C++ compiler and size of your CPU's caches.
|
||||
By default, the lib/verilated.mk file has optimization turned off. This is
|
||||
for the benefit of new users, as it improves compile times at the cost of
|
||||
runtimes. To add optimization as the default, set one of three variables,
|
||||
OPT, OPT_FAST, or OPT_SLOW in lib/verilated.mk. Or, just for one run, pass
|
||||
them on the command line to make:
|
||||
OPT, OPT_FAST, or OPT_SLOW lib/verilated.mk. Or, use the -CFLAGS and/or
|
||||
-LDFLAGS option on the verilator command line to pass the flags directly to
|
||||
the compiler or linker. Or, just for one run, pass them on the command
|
||||
line to make:
|
||||
|
||||
make OPT_FAST="-O2" -f Vour.mk Vour__ALL.a
|
||||
|
||||
@@ -1188,7 +1319,9 @@ rarely, yet take a long time to compile with optimization on. OPT
|
||||
specifies overall optimization and affects all compiles, including those
|
||||
OPT_FAST and OPT_SLOW affect. For best results, use OPT="-O2", and link
|
||||
with "-static". Nearly the same results can be had with much better
|
||||
compile times with OPT_FAST="-O1 -fstrict-aliasing".
|
||||
compile times with OPT_FAST="-O1 -fstrict-aliasing". Higher optimization
|
||||
such as "-O3" may help, but gcc compile times may be excessive under O3 on
|
||||
even medium sized designs.
|
||||
|
||||
Unfortunately, using the optimizer with SystemC files can result in
|
||||
compiles taking several minutes. (The SystemC libraries have many little
|
||||
@@ -1202,6 +1335,11 @@ If you will be running many simulations on a single compile, investigate
|
||||
feedback driven compilation. With GCC, using -fprofile-arcs, then
|
||||
-fbranch-probabilities will yield another 15% or so.
|
||||
|
||||
Modern compilers also support link-time optimization (LTO), which can help
|
||||
especially if you link in DPI code. To enable LTO on GCC, pass "-flto" in
|
||||
both compilation and link. Note LTO may cause excessive compile times on
|
||||
large designs.
|
||||
|
||||
You may uncover further tuning possibilities by profiling the Verilog code.
|
||||
Use Verilator's --profile-cfuncs, then GCC's -g -pg. You can then run
|
||||
either oprofile or gprof to see where in the C++ code the time is spent.
|
||||
@@ -1401,6 +1539,7 @@ example:
|
||||
|
||||
top->final(); // Done simulating
|
||||
// // (Though this example doesn't get here)
|
||||
delete top;
|
||||
}
|
||||
|
||||
Note signals are read and written as member variables of the lower module.
|
||||
@@ -2242,7 +2381,7 @@ from a four state simulator. An === comparison to X will always be false,
|
||||
so that Verilog code which checks for uninitialized logic will not fire.
|
||||
|
||||
Assigning a variable to a X will actually assign the variable to a random
|
||||
value (see the -x-assign switch.) Thus if the value is actually used, the
|
||||
value (see the --x-assign switch.) Thus if the value is actually used, the
|
||||
random value should cause downstream errors. Integers also randomize, even
|
||||
though the Verilog 2001 specification says they initialize to zero.
|
||||
|
||||
@@ -2254,6 +2393,18 @@ following runs have it initialize them randomly. If the results match,
|
||||
reset works. (Note this is what the hardware will really do.) In
|
||||
practice, just setting all variables to one at startup finds most problems.
|
||||
|
||||
B<Note.> --x-assign applies to variables explicitly initialized or assigned to
|
||||
X. Unititialized clocks are initialized to zero, while all other state holding
|
||||
variables are initialized to a random value.
|
||||
|
||||
Event driven simulators will generally trigger an edge on a transition from X
|
||||
to 1 (C<posedge>) or X to 0 (C<negedge>). However, by default, since clocks
|
||||
are initialized to zero, Verilator will not trigger an initial negedge. Some
|
||||
code (particulary for reset) may rely on X->0 triggering an edge. Verilator
|
||||
provides a switch (see --x-initial-edge) to enable this behavior. Comparing
|
||||
runs with and without this switch will find such problems.
|
||||
|
||||
|
||||
=head2 Tri/Inout
|
||||
|
||||
Verilator converts some simple tristate structures into two state. Pullup,
|
||||
@@ -2374,6 +2525,12 @@ Increment/decrement can only be used as standalone statements or in for
|
||||
loops. They cannot be used as side effect operators inside more complicate
|
||||
expressions ("a = b++;").
|
||||
|
||||
=item '{} operator
|
||||
|
||||
Assignment patterns with order based, default, constant integer (array) or
|
||||
member identifier (struct/union) keys are supported. Data type keys and
|
||||
keys which are computed from a constant expression are not supported.
|
||||
|
||||
=item cast operator
|
||||
|
||||
Casting is supported only between simple scalar types, signed and unsigned,
|
||||
@@ -3566,9 +3723,11 @@ Major concepts by Paul Wasson and Duane Galbi.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<verilator_profcfunc>, L<systemperl>, L<vcoverage>, L<make>
|
||||
L<verilator_profcfunc>, L<systemperl>, L<vcoverage>, L<make>,
|
||||
|
||||
And internals.txt in the distribution.
|
||||
L<verilator --help> which is the source for this document,
|
||||
|
||||
and internals.txt in the distribution.
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
+3
-1
@@ -4,7 +4,9 @@
|
||||
# redistribute it and/or modify it under the terms of either the GNU Lesser
|
||||
# General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||
|
||||
AC_INIT([Verilator],[3.840 2012-07-31])
|
||||
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
|
||||
#AC_INIT([Verilator],[#.### devel])
|
||||
AC_INIT([Verilator],[3.843 2012-12-01])
|
||||
AC_CONFIG_HEADER(src/config_build.h)
|
||||
AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk)
|
||||
|
||||
|
||||
+29
-14
@@ -33,14 +33,10 @@
|
||||
// Global variables
|
||||
|
||||
// Slow path variables
|
||||
int Verilated::s_randReset = 0;
|
||||
VerilatedVoidCb Verilated::s_flushCb = NULL;
|
||||
|
||||
// Keep below together in one cache line
|
||||
int Verilated::s_debug = 0;
|
||||
bool Verilated::s_calcUnusedSigs = false;
|
||||
bool Verilated::s_gotFinish = false;
|
||||
bool Verilated::s_assertOn = true;
|
||||
Verilated::Serialized Verilated::s_s;
|
||||
VL_THREAD const VerilatedScope* Verilated::t_dpiScopep = NULL;
|
||||
VL_THREAD const char* Verilated::t_dpiFilename = "";
|
||||
VL_THREAD int Verilated::t_dpiLineno = 0;
|
||||
@@ -81,6 +77,17 @@ void vl_fatal (const char* filename, int linenum, const char* hier, const char*
|
||||
}
|
||||
#endif
|
||||
|
||||
//===========================================================================
|
||||
// Overall class init
|
||||
|
||||
Verilated::Serialized::Serialized() {
|
||||
s_randReset = 0;
|
||||
s_debug = 0;
|
||||
s_calcUnusedSigs = false;
|
||||
s_gotFinish = false;
|
||||
s_assertOn = true;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// Random reset -- Only called at init time, so don't inline.
|
||||
|
||||
@@ -301,7 +308,7 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
||||
const char *ep = pos;
|
||||
while (ep[0] && ep[0]!='%') ep++;
|
||||
if (ep != pos) {
|
||||
output += string(pos, ep-pos);
|
||||
output.append(pos, ep-pos);
|
||||
pos += ep-pos-1;
|
||||
}
|
||||
} else { // Format character
|
||||
@@ -346,9 +353,9 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
||||
// Deal with all read-and-print somethings
|
||||
const int lbits = va_arg(ap, int);
|
||||
QData ld = 0;
|
||||
WData qlwp[2];
|
||||
WDataInP lwp;
|
||||
if (lbits <= VL_QUADSIZE) {
|
||||
WData qlwp[2];
|
||||
ld = _VL_VA_ARG_Q(ap, lbits);
|
||||
VL_SET_WQ(qlwp,ld);
|
||||
lwp = qlwp;
|
||||
@@ -750,9 +757,10 @@ void VL_FCLOSE_I(IData fdi) {
|
||||
}
|
||||
|
||||
void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...) {
|
||||
VL_STATIC_OR_THREAD string output; // static only for speed
|
||||
output = "";
|
||||
va_list ap;
|
||||
va_start(ap,formatp);
|
||||
string output;
|
||||
_vl_vsformat(output, formatp, ap);
|
||||
va_end(ap);
|
||||
|
||||
@@ -760,9 +768,10 @@ void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...) {
|
||||
}
|
||||
|
||||
string VL_SFORMATF_NX(const char* formatp, ...) {
|
||||
VL_STATIC_OR_THREAD string output; // static only for speed
|
||||
output = "";
|
||||
va_list ap;
|
||||
va_start(ap,formatp);
|
||||
string output;
|
||||
_vl_vsformat(output, formatp, ap);
|
||||
va_end(ap);
|
||||
|
||||
@@ -770,9 +779,10 @@ string VL_SFORMATF_NX(const char* formatp, ...) {
|
||||
}
|
||||
|
||||
void VL_WRITEF(const char* formatp, ...) {
|
||||
VL_STATIC_OR_THREAD string output; // static only for speed
|
||||
output = "";
|
||||
va_list ap;
|
||||
va_start(ap,formatp);
|
||||
string output;
|
||||
_vl_vsformat(output, formatp, ap);
|
||||
va_end(ap);
|
||||
|
||||
@@ -781,12 +791,13 @@ void VL_WRITEF(const char* formatp, ...) {
|
||||
}
|
||||
|
||||
void VL_FWRITEF(IData fpi, const char* formatp, ...) {
|
||||
VL_STATIC_OR_THREAD string output; // static only for speed
|
||||
output = "";
|
||||
FILE* fp = VL_CVT_I_FP(fpi);
|
||||
if (VL_UNLIKELY(!fp)) return;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap,formatp);
|
||||
string output;
|
||||
_vl_vsformat(output, formatp, ap);
|
||||
va_end(ap);
|
||||
|
||||
@@ -949,13 +960,13 @@ IData VL_SYSTEM_IW(int lhswords, WDataInP filenamep) {
|
||||
}
|
||||
|
||||
IData VL_TESTPLUSARGS_I(const char* formatp) {
|
||||
string match = VerilatedImp::argPlusMatch(formatp);
|
||||
const string& match = VerilatedImp::argPlusMatch(formatp);
|
||||
if (match == "") return 0;
|
||||
else return 1;
|
||||
}
|
||||
|
||||
IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rwp) {
|
||||
string match = VerilatedImp::argPlusMatch(prefixp);
|
||||
const string& match = VerilatedImp::argPlusMatch(prefixp);
|
||||
const char* dp = match.c_str() + 1 /*leading + */ + strlen(prefixp);
|
||||
if (match == "") return 0;
|
||||
VL_ZERO_RESET_W(rbits, rwp);
|
||||
@@ -991,7 +1002,7 @@ IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rw
|
||||
}
|
||||
|
||||
const char* vl_mc_scan_plusargs(const char* prefixp) {
|
||||
string match = VerilatedImp::argPlusMatch(prefixp);
|
||||
const string& match = VerilatedImp::argPlusMatch(prefixp);
|
||||
static VL_THREAD char outstr[VL_VALUE_STRING_MAX_WIDTH];
|
||||
if (match == "") return NULL;
|
||||
strncpy(outstr, match.c_str()+strlen(prefixp)+1, // +1 to skip the "+"
|
||||
@@ -1056,6 +1067,10 @@ void Verilated::commandArgs(int argc, const char** argv) {
|
||||
VerilatedImp::commandArgs(argc,argv);
|
||||
}
|
||||
|
||||
const char* Verilated::commandArgsPlusMatch(const char* prefixp) {
|
||||
return VerilatedImp::argPlusMatch(prefixp).c_str();
|
||||
}
|
||||
|
||||
void Verilated::scopesDump() {
|
||||
VerilatedImp::scopesDump();
|
||||
}
|
||||
|
||||
+23
-16
@@ -219,14 +219,18 @@ struct Verilated {
|
||||
// MEMBERS
|
||||
private:
|
||||
// Slow path variables
|
||||
static int s_randReset; ///< Random reset: 0=all 0s, 1=all 1s, 2=random
|
||||
static VerilatedVoidCb s_flushCb; ///< Flush callback function
|
||||
|
||||
// Fast path
|
||||
static int s_debug; ///< See accessors... only when VL_DEBUG set
|
||||
static bool s_calcUnusedSigs; ///< Waves file on, need all signals calculated
|
||||
static bool s_gotFinish; ///< A $finish statement executed
|
||||
static bool s_assertOn; ///< Assertions are enabled
|
||||
static struct Serialized { // All these members serialized/deserialized
|
||||
// Slow path
|
||||
int s_randReset; ///< Random reset: 0=all 0s, 1=all 1s, 2=random
|
||||
// Fast path
|
||||
int s_debug; ///< See accessors... only when VL_DEBUG set
|
||||
bool s_calcUnusedSigs; ///< Waves file on, need all signals calculated
|
||||
bool s_gotFinish; ///< A $finish statement executed
|
||||
bool s_assertOn; ///< Assertions are enabled
|
||||
Serialized();
|
||||
} s_s;
|
||||
|
||||
static VL_THREAD const VerilatedScope* t_dpiScopep; ///< DPI context scope
|
||||
static VL_THREAD const char* t_dpiFilename; ///< DPI context filename
|
||||
@@ -241,29 +245,29 @@ public:
|
||||
/// 0 = Set to zeros
|
||||
/// 1 = Set all bits to one
|
||||
/// 2 = Randomize all bits
|
||||
static void randReset(int val) { s_randReset=val; }
|
||||
static int randReset() { return s_randReset; } ///< Return randReset value
|
||||
static void randReset(int val) { s_s.s_randReset=val; }
|
||||
static int randReset() { return s_s.s_randReset; } ///< Return randReset value
|
||||
|
||||
/// Enable debug of internal verilated code
|
||||
static inline void debug(int level) { s_debug = level; }
|
||||
static inline void debug(int level) { s_s.s_debug = level; }
|
||||
#ifdef VL_DEBUG
|
||||
static inline int debug() { return s_debug; } ///< Return debug value
|
||||
static inline int debug() { return s_s.s_debug; } ///< Return debug value
|
||||
#else
|
||||
static inline int debug() { return 0; } ///< Constant 0 debug, so C++'s optimizer rips up
|
||||
#endif
|
||||
/// Enable calculation of unused signals
|
||||
static void calcUnusedSigs(bool flag) { s_calcUnusedSigs=flag; }
|
||||
static bool calcUnusedSigs() { return s_calcUnusedSigs; } ///< Return calcUnusedSigs value
|
||||
static void calcUnusedSigs(bool flag) { s_s.s_calcUnusedSigs=flag; }
|
||||
static bool calcUnusedSigs() { return s_s.s_calcUnusedSigs; } ///< Return calcUnusedSigs value
|
||||
/// Did the simulation $finish?
|
||||
static void gotFinish(bool flag) { s_gotFinish=flag; }
|
||||
static bool gotFinish() { return s_gotFinish; } ///< Return if got a $finish
|
||||
static void gotFinish(bool flag) { s_s.s_gotFinish=flag; }
|
||||
static bool gotFinish() { return s_s.s_gotFinish; } ///< Return if got a $finish
|
||||
/// Allow traces to at some point be enabled (disables some optimizations)
|
||||
static void traceEverOn(bool flag) {
|
||||
if (flag) { calcUnusedSigs(flag); }
|
||||
}
|
||||
/// Enable/disable assertions
|
||||
static void assertOn(bool flag) { s_assertOn=flag; }
|
||||
static bool assertOn() { return s_assertOn; }
|
||||
static void assertOn(bool flag) { s_s.s_assertOn=flag; }
|
||||
static bool assertOn() { return s_s.s_assertOn; }
|
||||
/// Flush callback for VCD waves
|
||||
static void flushCb(VerilatedVoidCb cb);
|
||||
static void flushCall() { if (s_flushCb) (*s_flushCb)(); }
|
||||
@@ -271,6 +275,7 @@ public:
|
||||
/// Record command line arguments, for retrieval by $test$plusargs/$value$plusargs
|
||||
static void commandArgs(int argc, const char** argv);
|
||||
static void commandArgs(int argc, char** argv) { commandArgs(argc,(const char**)argv); }
|
||||
static const char* commandArgsPlusMatch(const char* prefixp);
|
||||
|
||||
/// For debugging, print text list of all scope names with
|
||||
/// dpiImport/Export context. This function may change in future
|
||||
@@ -292,6 +297,8 @@ public:
|
||||
static const char* dpiFilenamep() { return t_dpiFilename; }
|
||||
static int dpiLineno() { return t_dpiLineno; }
|
||||
static int exportFuncNum(const char* namep);
|
||||
static size_t serializedSize() { return sizeof(s_s); }
|
||||
static void* serializedPtr() { return &s_s; }
|
||||
};
|
||||
|
||||
//=========================================================================
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@
|
||||
`define _VERILATED_V_ 1
|
||||
|
||||
// Hide verilator pragmas from other tools
|
||||
`ifdef verilator `else
|
||||
`ifdef VERILATOR `else
|
||||
`define coverage_block_off
|
||||
`endif
|
||||
|
||||
|
||||
@@ -55,7 +55,9 @@ class VerilatedImp {
|
||||
// MEMBERS
|
||||
static VerilatedImp s_s; ///< Static Singleton; One and only static this
|
||||
|
||||
ArgVec m_argVec; ///< Argument list
|
||||
// Nothing here is save-restored; users expected to re-register appropriately
|
||||
|
||||
ArgVec m_argVec; ///< Argument list (NOT save-restored, may want different results)
|
||||
bool m_argVecLoaded; ///< Ever loaded argument list
|
||||
UserMap m_userMap; ///< Map of <(scope,userkey), userData>
|
||||
ScopeNameMap m_nameMap; ///< Map of <scope_name, scope pointer>
|
||||
|
||||
@@ -0,0 +1,231 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//=============================================================================
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2001-2012 by Wilson Snyder. This program is free software;
|
||||
// you can redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||
//
|
||||
// This is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
//
|
||||
//=============================================================================
|
||||
///
|
||||
/// \file
|
||||
/// \brief C++ Tracing in VCD Format
|
||||
///
|
||||
/// AUTHOR: Wilson Snyder
|
||||
///
|
||||
//=============================================================================
|
||||
|
||||
#include "verilatedos.h"
|
||||
#include "verilated.h"
|
||||
#include "verilated_save.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <cerrno>
|
||||
|
||||
#if defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
|
||||
# include <io.h>
|
||||
#else
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifndef O_LARGEFILE // For example on WIN32
|
||||
# define O_LARGEFILE 0
|
||||
#endif
|
||||
#ifndef O_NONBLOCK
|
||||
# define O_NONBLOCK 0
|
||||
#endif
|
||||
|
||||
// CONSTANTS
|
||||
static const char* VLTSAVE_HEADER_STR = "verilatorsave01\n"; ///< Value of first bytes of each file
|
||||
static const char* VLTSAVE_TRAILER_STR = "vltsaved"; ///< Value of last bytes of each file
|
||||
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
// Searalization
|
||||
|
||||
bool VerilatedDeserialize::readDiffers (const void* __restrict datap, size_t size) {
|
||||
bufferCheck();
|
||||
const vluint8_t* __restrict dp = (const vluint8_t* __restrict)datap;
|
||||
vluint8_t miss = 0;
|
||||
while (size--) {
|
||||
miss |= (*dp++ ^ *m_cp++);
|
||||
}
|
||||
return (miss!=0);
|
||||
}
|
||||
|
||||
VerilatedDeserialize& VerilatedDeserialize::readAssert (const void* __restrict datap, size_t size) {
|
||||
if (VL_UNLIKELY(readDiffers(datap,size))) {
|
||||
string msg = (string)"Can't deserialize save-restore file as was made from different model";
|
||||
vl_fatal(filename().c_str(), 0, "", msg.c_str());
|
||||
close();
|
||||
}
|
||||
return *this; // For function chaining
|
||||
}
|
||||
|
||||
void VerilatedSerialize::header() {
|
||||
VerilatedSerialize& os = *this; // So can cut and paste standard << code below
|
||||
assert((strlen(VLTSAVE_HEADER_STR) & 7) == 0); // Keep aligned
|
||||
os.write(VLTSAVE_HEADER_STR, strlen(VLTSAVE_HEADER_STR));
|
||||
|
||||
// Verilated doesn't do it itself, as if we're not using save/restore
|
||||
// it doesn't need to compile this stuff in
|
||||
os.write(Verilated::serializedPtr(), Verilated::serializedSize());
|
||||
}
|
||||
|
||||
void VerilatedDeserialize::header() {
|
||||
VerilatedDeserialize& os = *this; // So can cut and paste standard >> code below
|
||||
if (VL_UNLIKELY(os.readDiffers(VLTSAVE_HEADER_STR, strlen(VLTSAVE_HEADER_STR)))) {
|
||||
string msg = (string)"Can't deserialize; file has wrong header signature";
|
||||
vl_fatal(filename().c_str(), 0, "", msg.c_str());
|
||||
close();
|
||||
}
|
||||
os.read(Verilated::serializedPtr(), Verilated::serializedSize());
|
||||
}
|
||||
|
||||
void VerilatedSerialize::trailer() {
|
||||
VerilatedSerialize& os = *this; // So can cut and paste standard << code below
|
||||
assert((strlen(VLTSAVE_TRAILER_STR) & 7) == 0); // Keep aligned
|
||||
os.write(VLTSAVE_TRAILER_STR, strlen(VLTSAVE_TRAILER_STR));
|
||||
}
|
||||
|
||||
void VerilatedDeserialize::trailer() {
|
||||
VerilatedDeserialize& os = *this; // So can cut and paste standard >> code below
|
||||
if (VL_UNLIKELY(os.readDiffers(VLTSAVE_TRAILER_STR, strlen(VLTSAVE_TRAILER_STR)))) {
|
||||
string msg = (string)"Can't deserialize; file has wrong end-of-file signature";
|
||||
vl_fatal(filename().c_str(), 0, "", msg.c_str());
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
// Opening/Closing
|
||||
|
||||
void VerilatedSave::open (const char* filenamep) {
|
||||
if (isOpen()) return;
|
||||
VL_DEBUG_IF(VL_PRINTF("-vltSave: opening save file %s\n",filenamep););
|
||||
|
||||
if (filenamep[0]=='|') {
|
||||
assert(0); // Not supported yet.
|
||||
} else {
|
||||
m_fd = ::open (filenamep, O_CREAT|O_WRONLY|O_TRUNC|O_LARGEFILE|O_NONBLOCK
|
||||
, 0666);
|
||||
if (m_fd<0) {
|
||||
// User code can check isOpen()
|
||||
m_isOpen = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_isOpen = true;
|
||||
m_filename = filenamep;
|
||||
m_cp = m_bufp;
|
||||
header();
|
||||
}
|
||||
|
||||
void VerilatedRestore::open (const char* filenamep) {
|
||||
if (isOpen()) return;
|
||||
VL_DEBUG_IF(VL_PRINTF("-vltRestore: opening restore file %s\n",filenamep););
|
||||
|
||||
if (filenamep[0]=='|') {
|
||||
assert(0); // Not supported yet.
|
||||
} else {
|
||||
m_fd = ::open (filenamep, O_CREAT|O_RDONLY|O_LARGEFILE
|
||||
, 0666);
|
||||
if (m_fd<0) {
|
||||
// User code can check isOpen()
|
||||
m_isOpen = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_isOpen = true;
|
||||
m_filename = filenamep;
|
||||
m_cp = m_bufp;
|
||||
m_endp = m_bufp;
|
||||
header();
|
||||
}
|
||||
|
||||
void VerilatedSave::close () {
|
||||
if (!isOpen()) return;
|
||||
trailer();
|
||||
flush();
|
||||
m_isOpen = false;
|
||||
::close(m_fd); // May get error, just ignore it
|
||||
}
|
||||
|
||||
void VerilatedRestore::close () {
|
||||
if (!isOpen()) return;
|
||||
trailer();
|
||||
flush();
|
||||
m_isOpen = false;
|
||||
::close(m_fd); // May get error, just ignore it
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// Buffer management
|
||||
|
||||
void VerilatedSave::flush() {
|
||||
if (VL_UNLIKELY(!isOpen())) return;
|
||||
vluint8_t* wp = m_bufp;
|
||||
while (1) {
|
||||
ssize_t remaining = (m_cp - wp);
|
||||
if (remaining==0) break;
|
||||
errno = 0;
|
||||
ssize_t got = ::write (m_fd, wp, remaining);
|
||||
if (got>0) {
|
||||
wp += got;
|
||||
} else if (got < 0) {
|
||||
if (errno != EAGAIN && errno != EINTR) {
|
||||
// write failed, presume error (perhaps out of disk space)
|
||||
string msg = string(__FUNCTION__)+": "+strerror(errno);
|
||||
vl_fatal("",0,"",msg.c_str());
|
||||
close();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_cp = m_bufp; // Reset buffer
|
||||
}
|
||||
|
||||
void VerilatedRestore::fill() {
|
||||
if (VL_UNLIKELY(!isOpen())) return;
|
||||
// Move remaining characters down to start of buffer. (No memcpy, overlaps allowed)
|
||||
vluint8_t* rp = m_bufp;
|
||||
for (vluint8_t* sp=m_cp; rp < m_endp;) *rp++ = *sp++; // Overlaps
|
||||
m_endp = m_bufp + (m_endp - m_cp);
|
||||
m_cp = m_bufp; // Reset buffer
|
||||
// Read into buffer starting at m_endp
|
||||
while (1) {
|
||||
ssize_t remaining = (m_bufp+bufferSize() - m_endp);
|
||||
if (remaining==0) break;
|
||||
errno = 0;
|
||||
ssize_t got = ::read (m_fd, m_endp, remaining);
|
||||
if (got>0) {
|
||||
m_endp += got;
|
||||
} else if (got < 0) {
|
||||
if (errno != EAGAIN && errno != EINTR) {
|
||||
// write failed, presume error (perhaps out of disk space)
|
||||
string msg = string(__FUNCTION__)+": "+strerror(errno);
|
||||
vl_fatal("",0,"",msg.c_str());
|
||||
close();
|
||||
break;
|
||||
}
|
||||
} else { // got==0, EOF
|
||||
// Fill buffer from here to end with NULLs so reader's don't need to check eof each character.
|
||||
while (m_endp < m_bufp+bufferSize()) *m_endp++ = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// Serialization of types
|
||||
|
||||
|
||||
@@ -0,0 +1,234 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//=============================================================================
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2012-2012 by Wilson Snyder. This program is free software;
|
||||
// you can redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||
//
|
||||
// This is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
//
|
||||
//=============================================================================
|
||||
///
|
||||
/// \file
|
||||
/// \brief Save-restore serialization of verilated modules
|
||||
///
|
||||
/// AUTHOR: Wilson Snyder
|
||||
///
|
||||
//=============================================================================
|
||||
|
||||
#ifndef _VERILATED_SAVE_C_H_
|
||||
#define _VERILATED_SAVE_C_H_ 1
|
||||
|
||||
#include "verilatedos.h"
|
||||
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedSerialBase - internal base class for common code between VerilatedSerialize and VerilatedDeserialize
|
||||
|
||||
class VerilatedSerialBase {
|
||||
protected:
|
||||
// MEMBERS
|
||||
// For speed, keep m_cp as the first member of this structure
|
||||
vluint8_t* m_cp; ///< Current pointer into m_bufp buffer
|
||||
vluint8_t* m_bufp; ///< Output buffer
|
||||
bool m_isOpen; ///< True indicates open file/stream
|
||||
string m_filename;
|
||||
|
||||
inline static size_t bufferSize() { return 256*1024; } // See below for slack calculation
|
||||
inline static size_t bufferInsertSize() { return 16*1024; }
|
||||
|
||||
// CREATORS
|
||||
VerilatedSerialBase() {
|
||||
m_isOpen = false;
|
||||
m_bufp = new vluint8_t [bufferSize()];
|
||||
m_cp = m_bufp;
|
||||
}
|
||||
public:
|
||||
// CREATORS
|
||||
virtual ~VerilatedSerialBase() {
|
||||
close();
|
||||
if (m_bufp) { delete m_bufp; m_bufp=NULL; }
|
||||
}
|
||||
// METHODS
|
||||
bool isOpen() const { return m_isOpen; }
|
||||
string filename() const { return m_filename; }
|
||||
virtual void close() { flush(); }
|
||||
virtual void flush() {}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedSerialize - convert structures to a stream representation
|
||||
|
||||
class VerilatedSerialize : public VerilatedSerialBase {
|
||||
protected:
|
||||
virtual void close() { flush(); }
|
||||
virtual void flush() {}
|
||||
void header();
|
||||
void trailer();
|
||||
public:
|
||||
// CREATORS
|
||||
VerilatedSerialize() {}
|
||||
virtual ~VerilatedSerialize() { close(); }
|
||||
// METHODS
|
||||
VerilatedSerialize& bufferCheck() {
|
||||
// Flush the write buffer if there's not enough space left for new information
|
||||
// We only call this once per vector, so we need enough slop for a very wide "b###" line
|
||||
if (VL_UNLIKELY(m_cp > (m_bufp+(bufferSize()-bufferInsertSize())))) {
|
||||
flush();
|
||||
}
|
||||
return *this; // For function chaining
|
||||
}
|
||||
inline VerilatedSerialize& write (const void* __restrict datap, size_t size) {
|
||||
const vluint8_t* __restrict dp = (const vluint8_t* __restrict)datap;
|
||||
while (size) {
|
||||
bufferCheck();
|
||||
size_t blk = size; if (blk>bufferInsertSize()) blk = bufferInsertSize();
|
||||
const vluint8_t* __restrict maxp = dp + blk;
|
||||
while (dp < maxp) *m_cp++ = *dp++;
|
||||
size -= blk;
|
||||
}
|
||||
return *this; // For function chaining
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedDeserial - load structures from a stream representation
|
||||
|
||||
class VerilatedDeserialize : public VerilatedSerialBase {
|
||||
protected:
|
||||
vluint8_t* m_endp; ///< Last valid byte in m_bufp buffer
|
||||
virtual void fill() = 0;
|
||||
void header();
|
||||
void trailer();
|
||||
public:
|
||||
// CREATORS
|
||||
VerilatedDeserialize() {}
|
||||
virtual ~VerilatedDeserialize() { close(); }
|
||||
// METHODS
|
||||
inline VerilatedDeserialize& read (void* __restrict datap, size_t size) {
|
||||
vluint8_t* __restrict dp = (vluint8_t* __restrict)datap;
|
||||
while (size) {
|
||||
bufferCheck();
|
||||
size_t blk = size; if (blk>bufferInsertSize()) blk = bufferInsertSize();
|
||||
const vluint8_t* __restrict maxp = dp + blk;
|
||||
while (dp < maxp) *dp++ = *m_cp++;
|
||||
size -= blk;
|
||||
}
|
||||
return *this; // For function chaining
|
||||
}
|
||||
// Read a datum and compare with expected value
|
||||
bool readDiffers (const void* __restrict datap, size_t size);
|
||||
VerilatedDeserialize& readAssert (const void* __restrict datap, size_t size);
|
||||
VerilatedDeserialize& readAssert (vluint64_t data) { return readAssert(&data, sizeof(data)); }
|
||||
VerilatedDeserialize& bufferCheck() {
|
||||
// Flush the write buffer if there's not enough space left for new information
|
||||
// We only call this once per vector, so we need enough slop for a very wide "b###" line
|
||||
if (VL_UNLIKELY((m_cp+bufferInsertSize()) > m_endp)) {
|
||||
fill();
|
||||
}
|
||||
return *this; // For function chaining
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedSave - serialize to a file
|
||||
|
||||
class VerilatedSave : public VerilatedSerialize {
|
||||
private:
|
||||
int m_fd; ///< File descriptor we're writing to
|
||||
|
||||
public:
|
||||
// CREATORS
|
||||
VerilatedSave() {}
|
||||
virtual ~VerilatedSave() { close(); }
|
||||
// METHODS
|
||||
void open(const char* filenamep); ///< Open the file; call isOpen() to see if errors
|
||||
void open(const string& filename) { open(filename.c_str()); }
|
||||
virtual void close();
|
||||
virtual void flush();
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedRestore - deserialize from a file
|
||||
|
||||
class VerilatedRestore : public VerilatedDeserialize {
|
||||
private:
|
||||
int m_fd; ///< File descriptor we're writing to
|
||||
|
||||
public:
|
||||
// CREATORS
|
||||
VerilatedRestore() {}
|
||||
virtual ~VerilatedRestore() { close(); }
|
||||
|
||||
// METHODS
|
||||
void open(const char* filenamep); ///< Open the file; call isOpen() to see if errors
|
||||
void open(const string& filename) { open(filename.c_str()); }
|
||||
virtual void close();
|
||||
virtual void flush() {}
|
||||
virtual void fill();
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
|
||||
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, vluint64_t& rhs) {
|
||||
return os.write(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, vluint64_t& rhs){
|
||||
return os.read(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, vluint32_t& rhs) {
|
||||
return os.write(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, vluint32_t& rhs) {
|
||||
return os.read(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, vluint16_t& rhs) {
|
||||
return os.write(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, vluint16_t& rhs) {
|
||||
return os.read(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, vluint8_t& rhs) {
|
||||
return os.write(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, vluint8_t& rhs) {
|
||||
return os.read(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, bool& rhs) {
|
||||
return os.write(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, bool& rhs) {
|
||||
return os.read(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, double& rhs) {
|
||||
return os.write(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, double& rhs) {
|
||||
return os.read(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, float& rhs) {
|
||||
return os.write(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, float& rhs) {
|
||||
return os.read(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, string& rhs) {
|
||||
vluint32_t len=rhs.length();
|
||||
os<<len;
|
||||
return os.write(rhs.data(), len);
|
||||
}
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, string& rhs) {
|
||||
vluint32_t len;
|
||||
os>>len;
|
||||
rhs.resize(len);
|
||||
return os.read((void*)rhs.data(), len);
|
||||
}
|
||||
|
||||
#endif // guard
|
||||
@@ -182,7 +182,7 @@ public:
|
||||
vluint32_t entSize() const { return m_entSize; }
|
||||
virtual const char* name() { return m_varp->name(); }
|
||||
virtual const char* fullname() {
|
||||
static VL_THREAD string out;
|
||||
VL_STATIC_OR_THREAD string out;
|
||||
out = string(m_scopep->name())+"."+name();
|
||||
return out.c_str();
|
||||
}
|
||||
@@ -207,7 +207,7 @@ public:
|
||||
virtual ~VerilatedVpioVarIndex() {}
|
||||
static inline VerilatedVpioVarIndex* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioVarIndex*>((VerilatedVpio*)h); }
|
||||
virtual const char* fullname() {
|
||||
static VL_THREAD string out;
|
||||
VL_STATIC_OR_THREAD string out;
|
||||
char num[20]; sprintf(num,"%d",m_index);
|
||||
out = string(scopep()->name())+"."+name()+"["+num+"]";
|
||||
return out.c_str();
|
||||
|
||||
@@ -78,8 +78,12 @@
|
||||
# else
|
||||
# error "Unsupported compiler for VL_THREADED: No thread-local declarator"
|
||||
# endif
|
||||
# define VL_STATIC_OR_THREAD ///< Static if unthreaded, as some strings can be faster
|
||||
// ///< if non-dynamic and can't do "static VL_THREAD string"
|
||||
#else
|
||||
# define VL_THREAD ///< Storage class for thread-local storage
|
||||
# define VL_STATIC_OR_THREAD static ///< Static if unthreaded, as some strings can be faster
|
||||
// ///< if non-dynamic and can't do "static VL_THREAD string"
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
@@ -36,18 +36,22 @@ typedef signed __int8 int8_t;
|
||||
#endif
|
||||
|
||||
/* Use to export a symbol from application */
|
||||
#ifndef DPI_DLLISPEC
|
||||
#if defined (_MSC_VER)
|
||||
#define DPI_DLLISPEC __declspec(dllimport)
|
||||
#else
|
||||
#define DPI_DLLISPEC
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Use to import a symbol into application */
|
||||
#ifndef DPI_DLLESPEC
|
||||
#if defined (_MSC_VER)
|
||||
#define DPI_DLLESPEC __declspec(dllexport)
|
||||
#else
|
||||
#define DPI_DLLESPEC
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Use to mark a function as external */
|
||||
#ifndef DPI_EXTERN
|
||||
|
||||
+180
-35
@@ -14,32 +14,6 @@ the first for reference for developers and debugging problems.
|
||||
|
||||
See also the Verilator internals presentation at http://www.veripool.org.
|
||||
|
||||
=head1 ADDING A NEW FEATURE
|
||||
|
||||
Generally what would you do to add a new feature?
|
||||
|
||||
=over 4
|
||||
|
||||
File a bug (if there isn't already) so others know what you're working on.
|
||||
|
||||
Make a testcase in the test_regress/t/t_EXAMPLE format, see TESTING Below.
|
||||
|
||||
If grammar changes are needed, look at the git version of VerilogPerl's
|
||||
src/VParseGrammar.y, as this grammar supports the full SystemVerilog
|
||||
language and has a lot of back-and-forth with Verilator's grammar. Copy
|
||||
the appropriate rules to src/verilog.y and modify the productions.
|
||||
|
||||
If a new Ast type is needed, add it to V3AstNodes.h.
|
||||
|
||||
Now you can run "test_regress/t/t_{new testcase}.pl --debug" and it'll
|
||||
probably fail but you'll see a test_regress/obj_dir/t_{newtestcase}/*.tree
|
||||
file which you can examine to see if the parsing worked. See also the
|
||||
sections below on debugging.
|
||||
|
||||
Modify the later visitor functions to process the new feature as needed.
|
||||
|
||||
=back
|
||||
|
||||
=head1 CODE FLOWS
|
||||
|
||||
=head2 Verilator Flow
|
||||
@@ -93,6 +67,10 @@ Verilator finally writes the C++ modules.
|
||||
|
||||
=head2 Key Classes Used in the Verilator Flow
|
||||
|
||||
=over 4
|
||||
|
||||
=item C<AstNode>
|
||||
|
||||
The AST is represented at the top level by the class C<AstNode>. This abstract
|
||||
class has derived classes for the individual components (e.g. C<AstGenerate>
|
||||
for a generate block) or groups of components (e.g. C<AstNodeFTask> for
|
||||
@@ -119,11 +97,64 @@ are at the top of the tree.
|
||||
By convention, each function/method uses the variable C<nodep> as a pointer
|
||||
to the C<AstNode> currently being processed.
|
||||
|
||||
=item C<AstNVistor>
|
||||
|
||||
The passes are implemented by AST visitor classes (see L</Visitor
|
||||
Functions>). These are implemented by subclasses of the abstract class,
|
||||
C<AstNVisitor>. Each pass creates an instance of the visitor class, which
|
||||
in turn implements a method to perform the pass.
|
||||
|
||||
=item C<V3Graph>
|
||||
|
||||
A number of passes use graph algorithms, and the class C<V3Graph> is provided
|
||||
to represent those graphs. Graphs are directed, and algorithms are provided to
|
||||
manipulate the graphs and to output them in I<GraphViz> dot format (see
|
||||
L<http://www.graphviz.org/>). C<V3Graph.h> provides documentation of this
|
||||
class.
|
||||
|
||||
=item C<V3GraphVertex>
|
||||
|
||||
This is the base class for vertices in a graph. Vertices have an associated
|
||||
C<fanout>, C<color> and C<rank>, which may be used in algorithms for ordering
|
||||
the graph. A generic C<user>/C<userp> member variable is also provided.
|
||||
|
||||
Virtual methods are provided to specify the name, color, shape and style to be
|
||||
used in dot output. Typically users provided derived classes from
|
||||
C<V3GraphVertex> which will reimplement these methods.
|
||||
|
||||
Iterators are provided to access in and out edges. Typically these are used in
|
||||
the form:
|
||||
|
||||
for (V3GraphEdge *edgep = vertexp->inBeginp();
|
||||
edgep;
|
||||
edgep = edgep->inNextp()) {
|
||||
|
||||
=item C<V3GraphEdge>
|
||||
|
||||
This is the base class for directed edges between pairs of vertices. Edges
|
||||
have an associated C<weight> and may also be made C<cutable>. A generic
|
||||
C<user>/C<userp> member variable is also provided.
|
||||
|
||||
Accessors, C<fromp> and C<top> return the "from" and "to" vertices
|
||||
respectively.
|
||||
|
||||
Virtual methods are provided to specify the label, color and style to be
|
||||
used in dot output. Typically users provided derived classes from
|
||||
C<V3GraphEdge> which will reimplement these methods.
|
||||
|
||||
=item C<V3GraphAlg>
|
||||
|
||||
This is the base class for graph algorithms. It implements a C<bool> method,
|
||||
C<followEdge> which algorithms can use to decide whether an edge is
|
||||
followed. This method returns true if the graph edge has weight greater than
|
||||
one and a user function, C<edgeFuncp> (supplied in the constructor) returns
|
||||
C<true>.
|
||||
|
||||
A number of predefined derived algorithm classes and access methods are
|
||||
provided and documented in C<V3GraphAlg.cpp>.
|
||||
|
||||
=back
|
||||
|
||||
=head2 Verilated Flow
|
||||
|
||||
The evaluation loop outputted by Verilator is designed to allow a single
|
||||
@@ -178,16 +209,15 @@ TREEOP macro.
|
||||
|
||||
The original C++ source code is transformed into C++ code in the C<obj_opt>
|
||||
and C<obj_dbg> sub-directories (the former for the optimized version of
|
||||
verilator, the latter for the debug version). So for example C<V3Const.cpp>
|
||||
Verilator, the latter for the debug version). So for example C<V3Const.cpp>
|
||||
into C<V3Const__gen.cpp>.
|
||||
|
||||
=head2 Visitor Functions
|
||||
|
||||
The verilator uses the I<Visitor> design pattern to implement its
|
||||
refinement and optimization passes. This allows separation of the pass
|
||||
algorithm from the AST on which it operates. Wikipedia provides an
|
||||
introduction to the concept at
|
||||
L<http://en.wikipedia.org/wiki/Visitor_pattern>.
|
||||
Verilator uses the I<Visitor> design pattern to implement its refinement
|
||||
and optimization passes. This allows separation of the pass algorithm from
|
||||
the AST on which it operates. Wikipedia provides an introduction to the
|
||||
concept at L<http://en.wikipedia.org/wiki/Visitor_pattern>.
|
||||
|
||||
As noted above, all visitors are derived classes of C<AstNvisitor>. All
|
||||
derived classes of C<AstNode> implement the C<accept> method, which takes
|
||||
@@ -339,7 +369,75 @@ AST.
|
||||
To write a test see the BUGS section of the Verilator primary manual, and
|
||||
the documentation in:
|
||||
|
||||
test_regress/t/driver.pl --help
|
||||
test_regress/t/driver.pl --help
|
||||
|
||||
It is important to add tests for failures as well as success (for example to
|
||||
check that an error message is correctly triggered).
|
||||
|
||||
Tests that fail should by convenition have the suffix C<_bad> in their name,
|
||||
and include C<fails =E<gt> 1> in either their C<compile> or C<execute> step as
|
||||
appropriate.
|
||||
|
||||
Developers will also want to configure with two extra flags:
|
||||
|
||||
=over 4
|
||||
|
||||
=item --enable-ccwarn
|
||||
|
||||
Causes the build to stop on warnings as well as errors. A good way to
|
||||
ensure no sloppy code gets added, however it can be painful when it comes
|
||||
to testing, since third party code used in the tests (e.g. SystemC) may not
|
||||
be warning free.
|
||||
|
||||
=item --enable-longtests
|
||||
|
||||
In addition to the standard C, SystemC and SystemPerl tests also run the
|
||||
tests in the C<test_vcs>, C<test_verilated> and C<test_regress> directories
|
||||
when using I<make test>. This is disabled by default as SystemC/SystemPerl
|
||||
installation problems would otherwise falsely indicate a Verilator problem.
|
||||
|
||||
=back
|
||||
|
||||
When enabling the long tests, some additional PERL modules are needed, which
|
||||
you can install using cpan.
|
||||
|
||||
cpan install Unix::Processors
|
||||
|
||||
There are some traps to avoid when running regression tests
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
The regression tests will assume that you have a version of SystemPerl to
|
||||
match. Typically if working on Verilator from git, also use SystemPerl from
|
||||
git.
|
||||
|
||||
=item *
|
||||
|
||||
When checking the MANIFEST, the test will barf on unexpected code in the
|
||||
Verilator tree. So make sure to keep any such code outside the tree.
|
||||
|
||||
=item *
|
||||
|
||||
Not all Linux systems install Perldoc by default. This is needed for the
|
||||
I<--help> option to Verilator, and also for regression testing. This can be
|
||||
installed using cpan:
|
||||
|
||||
cpan install Pod::Perldoc
|
||||
|
||||
Many Linux systems also offer a standard package for this. Red
|
||||
Hat/Fedora/Centos offer I<perl-Pod-Perldoc>, while Debian/Ubuntu/Linux Mint
|
||||
offer I<perl-doc>.
|
||||
|
||||
=item *
|
||||
|
||||
Running regression may exhaust resources on some Linux systems, particularly
|
||||
file handles and user processes. Increase these to respectively 16,384 and
|
||||
4,096. The method of doing this is system dependent, but on Fedora Linux it
|
||||
would require editing the C</etc/security/limits.conf> file as root.
|
||||
|
||||
=back
|
||||
|
||||
=head1 DEBUGGING
|
||||
|
||||
@@ -376,6 +474,9 @@ algorithmic stage. An example:
|
||||
|
||||
=over 4
|
||||
|
||||
The following summarizes the above example dump, with more detail on each
|
||||
field in the section below.
|
||||
|
||||
"1:2:" indicates the hierarchy of the C<VAR> is the C<op2p> pointer under
|
||||
the C<MODULE>, which in turn is the C<op1p> pointer under the C<NETLIST>
|
||||
|
||||
@@ -439,7 +540,7 @@ Of the form C<< <ennnn> >> or C<< <ennnn#> >> , where C<nnnn> is the number
|
||||
of the last edit to modify this node. The trailing C<#> indicates the node
|
||||
has been edited since the last tree dump (which typically means in the last
|
||||
refinement or optimization pass). GDB can watch for this, see L</Debugging
|
||||
with GDB> below.
|
||||
with GDB>.
|
||||
|
||||
=item Source file and line
|
||||
|
||||
@@ -498,7 +599,7 @@ under gdb and break when an error is hit or the program is about to exit.
|
||||
You can also use --debug --gdbbt to just backtrace and then exit gdb. To
|
||||
debug the Verilated executable, use --gdbsim.
|
||||
|
||||
If you wish to start verilator under GDB (or another debugger), then you
|
||||
If you wish to start Verilator under GDB (or another debugger), then you
|
||||
can use --debug and look at the underlying invocation of verilator_dgb. For
|
||||
example
|
||||
|
||||
@@ -548,6 +649,50 @@ backtrace. You will typically see a frame sequence something like
|
||||
visit()
|
||||
...
|
||||
|
||||
=head1 ADDING A NEW FEATURE
|
||||
|
||||
Generally what would you do to add a new feature?
|
||||
|
||||
=over 4
|
||||
|
||||
=item 1.
|
||||
|
||||
File a bug (if there isn't already) so others know what you're working on.
|
||||
|
||||
=item 2.
|
||||
|
||||
Make a testcase in the test_regress/t/t_EXAMPLE format, see L<TESTING>.
|
||||
|
||||
=item 3.
|
||||
|
||||
If grammar changes are needed, look at the git version of VerilogPerl's
|
||||
src/VParseGrammar.y, as this grammar supports the full SystemVerilog
|
||||
language and has a lot of back-and-forth with Verilator's grammar. Copy
|
||||
the appropriate rules to src/verilog.y and modify the productions.
|
||||
|
||||
=item 4.
|
||||
|
||||
If a new Ast type is needed, add it to V3AstNodes.h.
|
||||
|
||||
=back
|
||||
|
||||
Now you can run "test_regress/t/t_{new testcase}.pl --debug" and it'll
|
||||
probably fail but you'll see a test_regress/obj_dir/t_{newtestcase}/*.tree
|
||||
file which you can examine to see if the parsing worked. See also the
|
||||
sections above on debugging.
|
||||
|
||||
Modify the later visitor functions to process the new feature as needed.
|
||||
|
||||
=head2 Adding a new pass
|
||||
|
||||
For more substantial changes you may need to add a new pass. The simplest way
|
||||
to do this is to copy the C<.cpp> and C<.h> files from an existing
|
||||
pass. You'll need to add a call into your pass from the C<process()> function
|
||||
in C<src/verilator.cpp>.
|
||||
|
||||
To get your pass to build you'll need to add its binary filename to the list
|
||||
in C<src/Makefile_obj.in> and reconfigure.
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
The latest version is available from L<http://www.veripool.org/>.
|
||||
|
||||
@@ -219,6 +219,7 @@ RAW_OBJS = \
|
||||
V3SplitAs.o \
|
||||
V3Stats.o \
|
||||
V3StatsReport.o \
|
||||
V3String.o \
|
||||
V3Subst.o \
|
||||
V3Table.o \
|
||||
V3Task.o \
|
||||
|
||||
+50
-4
@@ -1135,10 +1135,17 @@ struct AstVarRef : public AstNodeVarRef {
|
||||
ASTNODE_NODE_FUNCS(VarRef, VARREF)
|
||||
virtual void dump(ostream& str);
|
||||
virtual V3Hash sameHash() const { return V3Hash(V3Hash(varp()->name()),V3Hash(hiername())); }
|
||||
virtual bool same(AstNode* samep) const {
|
||||
if (varScopep()) return varScopep()==samep->castVarRef()->varScopep();
|
||||
else return (hiername()==samep->castVarRef()->hiername()
|
||||
&& varp()->name()==samep->castVarRef()->varp()->name()); }
|
||||
virtual bool same(AstNode* samep) const { return same(samep->castVarRef()); }
|
||||
inline bool same(AstVarRef* samep) const {
|
||||
if (varScopep()) return (varScopep()==samep->varScopep()
|
||||
&& lvalue()==samep->lvalue());
|
||||
else return (hiername()==samep->hiername()
|
||||
&& varp()->name()==samep->varp()->name()
|
||||
&& lvalue()==samep->lvalue()); }
|
||||
inline bool sameNoLvalue(AstVarRef* samep) const {
|
||||
if (varScopep()) return (varScopep()==samep->varScopep());
|
||||
else return (hiername()==samep->hiername()
|
||||
&& varp()->name()==samep->varp()->name()); }
|
||||
virtual int instrCount() const { return widthInstrs()*(lvalue()?1:instrCountLd()); }
|
||||
virtual string emitVerilog() { V3ERROR_NA; return ""; } // Implemented specially
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
@@ -3905,6 +3912,45 @@ struct AstFGetS : public AstNodeBiop {
|
||||
AstNode* filep() const { return rhsp(); }
|
||||
};
|
||||
|
||||
struct AstPattern : public AstNodeMath {
|
||||
// Verilog '{a,b,c,d...}
|
||||
// Parents: AstNodeAssign, AstPattern, ...
|
||||
// Children: expression, AstPattern, AstPatReplicate
|
||||
AstPattern(FileLine* fl, AstNode* itemsp) : AstNodeMath(fl) {
|
||||
addNOp1p(itemsp);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(Pattern, PATTERN)
|
||||
virtual string emitVerilog() { V3ERROR_NA; return ""; } // Implemented specially
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { V3ERROR_NA; }
|
||||
virtual string emitC() { V3ERROR_NA; return "";}
|
||||
virtual string emitSimpleOperator() { V3ERROR_NA; return "";}
|
||||
virtual bool cleanOut() {V3ERROR_NA; return "";}
|
||||
virtual int instrCount() const { return widthInstrs(); }
|
||||
AstNode* itemsp() const { return op1p(); } // op1 = AstPatReplicate, AstPatMember, etc
|
||||
};
|
||||
struct AstPatMember : public AstNodeMath {
|
||||
// Verilog '{a} or '{a{b}}
|
||||
// Parents: AstPattern
|
||||
// Children: expression, AstPattern, replication count
|
||||
private:
|
||||
bool m_default;
|
||||
public:
|
||||
AstPatMember(FileLine* fl, AstNode* lhsp, AstNode* keyp, AstNode* repp) : AstNodeMath(fl) {
|
||||
setOp1p(lhsp), setNOp2p(keyp), setNOp3p(repp); m_default = false; }
|
||||
ASTNODE_NODE_FUNCS(PatMember, PATMEMBER)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { V3ERROR_NA; }
|
||||
virtual string emitVerilog() { return lhsp()?"%f{%r{%k%l}}":"%l"; }
|
||||
virtual string emitC() { V3ERROR_NA; return "";}
|
||||
virtual string emitSimpleOperator() { V3ERROR_NA; return "";}
|
||||
virtual bool cleanOut() {V3ERROR_NA; return "";}
|
||||
virtual int instrCount() const { return widthInstrs()*2; }
|
||||
AstNode* lhsp() const { return op1p(); } // op1 = expression to assign or another AstPattern
|
||||
AstNode* keyp() const { return op2p(); } // op2 = assignment key (Const, id Text)
|
||||
AstNode* repp() const { return op3p(); } // op3 = replication count, or NULL for count 1
|
||||
bool isDefault() const { return m_default; }
|
||||
void isDefault(bool flag) { m_default = flag; }
|
||||
};
|
||||
|
||||
//======================================================================
|
||||
// SysVerilog assertions
|
||||
|
||||
|
||||
+6
-3
@@ -134,9 +134,11 @@ private:
|
||||
if (m_unnamedScope=="") m_unnamedScope = ident;
|
||||
else m_unnamedScope = m_unnamedScope + "__DOT__"+ident;
|
||||
// Create CellInline for dotted var resolution
|
||||
AstCellInline* inlinep = new AstCellInline(nodep->fileline(),
|
||||
m_unnamedScope, "__BEGIN__");
|
||||
m_modp->addInlinesp(inlinep); // Must be parsed before any AstCells
|
||||
if (!m_ftaskp) {
|
||||
AstCellInline* inlinep = new AstCellInline(nodep->fileline(),
|
||||
m_unnamedScope, "__BEGIN__");
|
||||
m_modp->addInlinesp(inlinep); // Must be parsed before any AstCells
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,6 +186,7 @@ private:
|
||||
virtual void visit(AstScopeName* nodep, AstNUser*) {
|
||||
// If there's a %m in the display text, we add a special node that will contain the name()
|
||||
// Similar code in V3Inline
|
||||
if (nodep->user1SetOnce()) return; // Don't double-add text's
|
||||
if (m_namedScope != "") {
|
||||
// To keep correct visual order, must add before other Text's
|
||||
AstNode* afterp = nodep->scopeAttrp();
|
||||
|
||||
+1
-1
@@ -83,7 +83,7 @@ private:
|
||||
if (vscp->user1p()) return ((AstVarScope*)vscp->user1p());
|
||||
AstVar* varp = vscp->varp();
|
||||
if (!varp->width1()) varp->v3error("Unsupported: Clock edge on non-single bit signal: "<<varp->prettyName());
|
||||
string newvarname = ((string)"__Vclklast__"+vscp->scopep()->nameDotless()+"__"+varp->shortName());
|
||||
string newvarname = ((string)"__Vclklast__"+vscp->scopep()->nameDotless()+"__"+varp->name());
|
||||
AstVar* newvarp = new AstVar (vscp->fileline(), AstVarType::MODULETEMP, newvarname, VFlagLogicPacked(), 1);
|
||||
m_modp->addStmtp(newvarp);
|
||||
AstVarScope* newvscp = new AstVarScope(vscp->fileline(), m_scopep, newvarp);
|
||||
|
||||
+2
-1
@@ -25,6 +25,7 @@
|
||||
#include <set>
|
||||
|
||||
#include "V3Global.h"
|
||||
#include "V3String.h"
|
||||
#include "V3Config.h"
|
||||
|
||||
//######################################################################
|
||||
@@ -89,7 +90,7 @@ class V3ConfigIgnores {
|
||||
it = m_ignFiles.find(filename);
|
||||
// Make new list for this file of all matches
|
||||
for (IgnFiles::iterator fnit = m_ignWilds.begin(); fnit != m_ignWilds.end(); ++fnit) {
|
||||
if (V3Options::wildmatch(filename.c_str(), fnit->first.c_str())) {
|
||||
if (VString::wildmatch(filename.c_str(), fnit->first.c_str())) {
|
||||
for (IgnLines::iterator lit = fnit->second.begin(); lit != fnit->second.end(); ++lit) {
|
||||
it->second.insert(*lit);
|
||||
}
|
||||
|
||||
+4
-5
@@ -415,8 +415,7 @@ private:
|
||||
// Avoid comparing widthMin's, which results in lost optimization attempts
|
||||
// If cleanup sameTree to be smarter, this can be restored.
|
||||
//return node1p->sameTree(node2p);
|
||||
return node1p->castVarRef()->varp() == node2p->castVarRef()->varp()
|
||||
&& node1p->castVarRef()->lvalue() == node2p->castVarRef()->lvalue();
|
||||
return node1p->same(node2p);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@@ -431,7 +430,7 @@ private:
|
||||
AstVarRef* elsevarp = elsep->lhsp()->castVarRef();
|
||||
if (!ifvarp || !elsevarp) return false;
|
||||
if (ifvarp->isWide()) return false; // Would need temporaries, so not worth it
|
||||
if (ifvarp->varp() != elsevarp->varp()) return false;
|
||||
if (!ifvarp->sameTree(elsevarp)) return false;
|
||||
return true;
|
||||
}
|
||||
bool operandIfIf(AstNodeIf* nodep) {
|
||||
@@ -776,7 +775,7 @@ private:
|
||||
AstSel* sel2p = nextp->lhsp()->castSel(); if (!sel2p) return false;
|
||||
AstVarRef* varref1p = sel1p->fromp()->castVarRef(); if (!varref1p) return false;
|
||||
AstVarRef* varref2p = sel2p->fromp()->castVarRef(); if (!varref2p) return false;
|
||||
if (varref1p->varp() != varref2p->varp()) return false;
|
||||
if (!varref1p->sameTree(varref2p)) return false;
|
||||
AstConst* con1p = sel1p->lsbp()->castConst(); if (!con1p) return false;
|
||||
AstConst* con2p = sel2p->lsbp()->castConst(); if (!con2p) return false;
|
||||
// We need to make sure there's no self-references involved in either
|
||||
@@ -827,7 +826,7 @@ private:
|
||||
bool replaceNodeAssign(AstNodeAssign* nodep) {
|
||||
if (nodep->lhsp()->castVarRef()
|
||||
&& nodep->rhsp()->castVarRef()
|
||||
&& nodep->lhsp()->sameTree(nodep->rhsp())
|
||||
&& nodep->lhsp()->castVarRef()->sameNoLvalue(nodep->rhsp()->castVarRef())
|
||||
&& !nodep->castAssignDly()) {
|
||||
// X = X. Quite pointless, though X <= X may override another earlier assignment
|
||||
if (nodep->castAssignW()) {
|
||||
|
||||
+104
-3
@@ -29,6 +29,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include "V3Global.h"
|
||||
#include "V3String.h"
|
||||
#include "V3EmitC.h"
|
||||
#include "V3EmitCBase.h"
|
||||
|
||||
@@ -842,6 +843,7 @@ class EmitCImp : EmitCStmts {
|
||||
void emitCoverageDecl(AstNodeModule* modp);
|
||||
void emitCoverageImp(AstNodeModule* modp);
|
||||
void emitDestructorImp(AstNodeModule* modp);
|
||||
void emitSavableImp(AstNodeModule* modp);
|
||||
void emitTextSection(AstType type);
|
||||
void emitIntFuncDecls(AstNodeModule* modp);
|
||||
// High level
|
||||
@@ -1366,7 +1368,16 @@ void EmitCImp::emitVarResets(AstNodeModule* modp) {
|
||||
puts(varp->name());
|
||||
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
|
||||
if (zeroit) {
|
||||
puts(" = 0;\n");
|
||||
// We want to force an initial edge on uninitialized clocks (from 'X' to
|
||||
// whatever the first value is). Since the class is instantiated before
|
||||
// initial blocks are evaluated, this should not clash with any initial
|
||||
// block settings. Clocks are always BIT datatypes, so zeroit is true.
|
||||
if (v3Global.opt.xInitialEdge()
|
||||
&& (0 == varp->name().find("__Vclklast__"))) {
|
||||
puts(" = 1;\n");
|
||||
} else {
|
||||
puts(" = 0;\n");
|
||||
}
|
||||
} else {
|
||||
puts(" = VL_RAND_RESET_");
|
||||
emitIQW(varp);
|
||||
@@ -1436,7 +1447,7 @@ void EmitCImp::emitCoverageImp(AstNodeModule* modp) {
|
||||
// compatible, and have a common wrapper.
|
||||
puts("void "+modClassName(m_modp)+"::__vlCoverInsert(uint32_t* countp, bool enable, const char* filenamep, int lineno, int column,\n");
|
||||
puts( "const char* hierp, const char* pagep, const char* commentp) {\n");
|
||||
puts( "static uint32_t fake_zero_count = 0;\n");
|
||||
puts( "static uint32_t fake_zero_count = 0;\n"); // static doesn't need save-restore as constant
|
||||
puts( "if (!enable) countp = &fake_zero_count;\n"); // Used for second++ instantiation of identical bin
|
||||
puts( "*countp = 0;\n");
|
||||
puts( "SP_COVER_INSERT(countp,");
|
||||
@@ -1459,6 +1470,79 @@ void EmitCImp::emitDestructorImp(AstNodeModule* modp) {
|
||||
puts("}\n");
|
||||
}
|
||||
|
||||
void EmitCImp::emitSavableImp(AstNodeModule* modp) {
|
||||
if (v3Global.opt.savable() ) {
|
||||
puts("\n// Savable\n");
|
||||
for (int de=0; de<2; ++de) {
|
||||
string classname = de ? "VerilatedDeserialize" : "VerilatedSerialize";
|
||||
string funcname = de ? "__Vdeserialize" : "__Vserialize";
|
||||
string writeread = de ? "read" : "write";
|
||||
string op = de ? ">>" : "<<";
|
||||
puts("void "+modClassName(modp)+"::"+funcname+"("+classname+"& os) {\n");
|
||||
// Place a computed checksum to insure proper structure save/restore formatting
|
||||
// OK if this hash includes some things we won't dump, since just looking for loading the wrong model
|
||||
VHashFnv hash;
|
||||
for (AstNode* nodep=modp->stmtsp(); nodep; nodep = nodep->nextp()) {
|
||||
if (AstVar* varp = nodep->castVar()) {
|
||||
hash.hash(varp->name());
|
||||
hash.hash(varp->dtypep()->width());
|
||||
}
|
||||
}
|
||||
ofp()->printf( "vluint64_t __Vcheckval = VL_ULL(0x%" VL_PRI64 "x);\n",
|
||||
hash.value());
|
||||
if (de) {
|
||||
puts("os.readAssert(__Vcheckval);\n");
|
||||
} else {
|
||||
puts("os<<__Vcheckval;\n");
|
||||
}
|
||||
|
||||
// Save all members
|
||||
if (v3Global.opt.inhibitSim()) puts("os"+op+"__Vm_inhibitSim;\n");
|
||||
for (AstNode* nodep=modp->stmtsp(); nodep; nodep = nodep->nextp()) {
|
||||
if (AstVar* varp = nodep->castVar()) {
|
||||
if (varp->isIO() && modp->isTop() && optSystemC()) {
|
||||
// System C top I/O doesn't need loading, as the lower level subinst code does it.
|
||||
}
|
||||
else if (varp->isParam()) {}
|
||||
else if (varp->isStatic() && varp->isConst()) {}
|
||||
else {
|
||||
int vects = 0;
|
||||
// This isn't very robust and may need cleanup for other data types
|
||||
for (AstArrayDType* arrayp=varp->dtypeSkipRefp()->castArrayDType(); arrayp;
|
||||
arrayp = arrayp->subDTypep()->skipRefp()->castArrayDType()) {
|
||||
int vecnum = vects++;
|
||||
if (arrayp->msb() < arrayp->lsb()) varp->v3fatalSrc("Should have swapped msb & lsb earlier.");
|
||||
string ivar = string("__Vi")+cvtToStr(vecnum);
|
||||
// MSVC++ pre V7 doesn't support 'for (int ...)', so declare in sep block
|
||||
puts("{ int __Vi"+cvtToStr(vecnum)+"="+cvtToStr(0)+";");
|
||||
puts(" for (; "+ivar+"<"+cvtToStr(arrayp->elementsConst()));
|
||||
puts("; ++"+ivar+") {\n");
|
||||
}
|
||||
if (varp->basicp() && (varp->basicp()->keyword() == AstBasicDTypeKwd::STRING
|
||||
|| !varp->basicp()->isWide())) {
|
||||
puts("os"+op+varp->name());
|
||||
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
|
||||
puts(";\n");
|
||||
} else {
|
||||
puts("os."+writeread+"(&"+varp->name());
|
||||
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
|
||||
puts(",sizeof("+varp->name());
|
||||
for (int v=0; v<vects; ++v) puts( "[__Vi"+cvtToStr(v)+"]");
|
||||
puts("));\n");
|
||||
}
|
||||
for (int v=0; v<vects; ++v) puts( "}}\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (modp->isTop()) { // Save the children
|
||||
puts( "__VlSymsp->"+funcname+"(os);\n");
|
||||
}
|
||||
puts("}\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EmitCImp::emitStaticDecl(AstNodeModule* modp) {
|
||||
// Need implementation here. Be careful of alignment code; needs to be uniquified
|
||||
// with module name to avoid multiple symbols.
|
||||
@@ -1675,8 +1759,12 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
|
||||
} else {
|
||||
puts("#include \"verilated.h\"\n");
|
||||
}
|
||||
if (v3Global.opt.savable()) {
|
||||
puts("#include \"verilated_save.h\"\n");
|
||||
}
|
||||
if (v3Global.opt.coverage()) {
|
||||
puts("#include \"SpCoverage.h\"\n");
|
||||
if (v3Global.opt.savable()) v3error("--coverage and --savable not supported together");
|
||||
}
|
||||
if (v3Global.needHInlines()) { // Set by V3EmitCInlines; should have been called before us
|
||||
puts("#include \""+topClassName()+"__Inlines.h\"\n");
|
||||
@@ -1842,10 +1930,22 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
|
||||
puts("static void traceFull ("+v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code);\n");
|
||||
puts("static void traceChg ("+v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code);\n");
|
||||
}
|
||||
if (v3Global.opt.savable()) {
|
||||
puts("void __Vserialize(VerilatedSerialize& os);\n");
|
||||
puts("void __Vdeserialize(VerilatedDeserialize& os);\n");
|
||||
puts("\n");
|
||||
}
|
||||
|
||||
puts("} VL_ATTR_ALIGNED(64);\n");
|
||||
puts("} VL_ATTR_ALIGNED(128);\n");
|
||||
puts("\n");
|
||||
|
||||
// Save/restore
|
||||
if (v3Global.opt.savable() && modp->isTop()) {
|
||||
puts("inline VerilatedSerialize& operator<<(VerilatedSerialize& os, "+modClassName(modp)+"& rhs) {rhs.__Vserialize(os); return os;}\n");
|
||||
puts("inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, "+modClassName(modp)+"& rhs) {rhs.__Vdeserialize(os); return os;}\n");
|
||||
puts("\n");
|
||||
}
|
||||
|
||||
// finish up h-file
|
||||
if (!optSystemPerl()) {
|
||||
puts("#endif /*guard*/\n");
|
||||
@@ -1893,6 +1993,7 @@ void EmitCImp::emitImp(AstNodeModule* modp) {
|
||||
emitCtorImp(modp);
|
||||
emitConfigureImp(modp);
|
||||
emitDestructorImp(modp);
|
||||
emitSavableImp(modp);
|
||||
emitCoverageImp(modp);
|
||||
}
|
||||
|
||||
|
||||
+30
-3
@@ -115,8 +115,8 @@ class EmitCSyms : EmitCBaseVisitor {
|
||||
AstScope* scopep = it->first; AstNodeModule* smodp = it->second;
|
||||
for (vector<ModVarPair>::iterator it = m_modVars.begin(); it != m_modVars.end(); ++it) {
|
||||
AstNodeModule* modp = it->first;
|
||||
AstVar* varp = it->second;
|
||||
if (modp == smodp) {
|
||||
AstVar* varp = it->second;
|
||||
// Need to split the module + var name into the original-ish full scope and variable name under that scope.
|
||||
// The module instance name is included later, when we know the scopes this module is under
|
||||
string whole = scopep->name()+"__DOT__"+varp->name();
|
||||
@@ -204,7 +204,8 @@ class EmitCSyms : EmitCBaseVisitor {
|
||||
}
|
||||
virtual void visit(AstVar* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (nodep->isSigUserRdPublic()) {
|
||||
if (nodep->isSigUserRdPublic()
|
||||
&& !nodep->isParam()) { // The VPI functions require a pointer to allow modification, but parameters are constants
|
||||
m_modVars.push_back(make_pair(m_modp, nodep));
|
||||
}
|
||||
}
|
||||
@@ -339,8 +340,13 @@ void EmitCSyms::emitSymHdr() {
|
||||
puts("\n// METHODS\n");
|
||||
puts("inline const char* name() { return __Vm_namep; }\n");
|
||||
puts("inline bool getClearActivity() { bool r=__Vm_activity; __Vm_activity=false; return r;}\n");
|
||||
if (v3Global.opt.savable() ) {
|
||||
puts("void __Vserialize(VerilatedSerialize& os);\n");
|
||||
puts("void __Vdeserialize(VerilatedDeserialize& os);\n");
|
||||
}
|
||||
puts("\n");
|
||||
puts("} VL_ATTR_ALIGNED(64);\n");
|
||||
puts("\n");
|
||||
puts("#endif /*guard*/\n");
|
||||
}
|
||||
|
||||
@@ -498,7 +504,28 @@ void EmitCSyms::emitSymImp() {
|
||||
}
|
||||
|
||||
puts("}\n");
|
||||
puts("\n");
|
||||
|
||||
if (v3Global.opt.savable() ) {
|
||||
puts("\n");
|
||||
for (int de=0; de<2; ++de) {
|
||||
string classname = de ? "VerilatedDeserialize" : "VerilatedSerialize";
|
||||
string funcname = de ? "__Vdeserialize" : "__Vserialize";
|
||||
string op = de ? ">>" : "<<";
|
||||
puts("void "+symClassName()+"::"+funcname+"("+classname+"& os) {\n");
|
||||
puts( "// LOCAL STATE\n");
|
||||
// __Vm_namep presumably already correct
|
||||
puts( "os"+op+"__Vm_activity;\n");
|
||||
puts( "os"+op+"__Vm_didInit;\n");
|
||||
puts( "// SUBCELL STATE\n");
|
||||
for (vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end(); ++it) {
|
||||
AstScope* scopep = it->first; AstNodeModule* modp = it->second;
|
||||
if (!modp->isTop()) {
|
||||
puts( scopep->nameDotless()+"."+funcname+"(os);\n");
|
||||
}
|
||||
}
|
||||
puts("}\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
|
||||
@@ -80,6 +80,9 @@ public:
|
||||
if (v3Global.dpi()) {
|
||||
putMakeClassEntry(of, "verilated_dpi.cpp");
|
||||
}
|
||||
if (v3Global.opt.savable()) {
|
||||
putMakeClassEntry(of, "verilated_save.cpp");
|
||||
}
|
||||
if (v3Global.opt.systemPerl()) {
|
||||
putMakeClassEntry(of, "Sp.cpp"); // Note Sp.cpp includes SpTraceVcdC
|
||||
}
|
||||
|
||||
+3
-2
@@ -29,6 +29,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include "V3Global.h"
|
||||
#include "V3String.h"
|
||||
#include "V3EmitXml.h"
|
||||
#include "V3EmitCBase.h"
|
||||
|
||||
@@ -64,12 +65,12 @@ class EmitXmlFileVisitor : public EmitCBaseVisitor {
|
||||
|
||||
// XML methods
|
||||
void outputTag(AstNode* nodep, string tag) {
|
||||
if (tag=="") tag = V3Options::downcase(nodep->typeName());
|
||||
if (tag=="") tag = VString::downcase(nodep->typeName());
|
||||
puts("<"+tag+" "+nodep->fileline()->xml());
|
||||
if (nodep->name()!="") { puts(" name="); putsQuoted(nodep->prettyName()); }
|
||||
}
|
||||
void outputChildrenEnd(AstNode* nodep, string tag) {
|
||||
if (tag=="") tag = V3Options::downcase(nodep->typeName());
|
||||
if (tag=="") tag = VString::downcase(nodep->typeName());
|
||||
if (nodep->op1p() || nodep->op2p() || nodep->op3p() || nodep->op4p()) {
|
||||
puts(">\n");
|
||||
nodep->iterateChildren(*this);
|
||||
|
||||
+19
-4
@@ -80,22 +80,33 @@ const string FileLineSingleton::filenameLetters(int no) {
|
||||
return op;
|
||||
}
|
||||
|
||||
//! Convert filenames to a filenameno
|
||||
|
||||
//! This lets us assign a nice small identifier for debug messages, but more
|
||||
//! importantly lets us use a 4 byte int instead of 8 byte pointer in every
|
||||
//! FileLine.
|
||||
|
||||
//! We associate a language with each source file, so we also set the default
|
||||
//! for this.
|
||||
int FileLineSingleton::nameToNumber(const string& filename) {
|
||||
// Convert filenames to a filenameno
|
||||
// This lets us assign a nice small identifier for debug messages, but more
|
||||
// importantly lets us use a 4 byte int instead of 8 byte pointer in every FileLine.
|
||||
FileNameNumMap::const_iterator iter = m_namemap.find(filename);
|
||||
if (VL_LIKELY(iter != m_namemap.end())) return iter->second;
|
||||
int num = m_names.size();
|
||||
m_names.push_back(filename);
|
||||
m_languages.push_back(V3LangCode::mostRecent());
|
||||
m_namemap.insert(make_pair(filename,num));
|
||||
return num;
|
||||
}
|
||||
|
||||
//! Support XML output
|
||||
|
||||
//! Experimental. Updated to also put out the language.
|
||||
void FileLineSingleton::fileNameNumMapDumpXml(ostream& os) {
|
||||
os<<"<files>\n";
|
||||
for (FileNameNumMap::const_iterator it = m_namemap.begin(); it != m_namemap.end(); ++it) {
|
||||
os<<"<file id=\""<<filenameLetters(it->second)<<"\" filename=\""<<it->first<<"\"/>\n";
|
||||
os<<"<file id=\""<<filenameLetters(it->second)
|
||||
<<"\" filename=\""<<it->first
|
||||
<<"\" language=\""<<numberToLang(it->second).ascii()<<"\"/>\n";
|
||||
}
|
||||
os<<"</files>\n";
|
||||
}
|
||||
@@ -170,6 +181,10 @@ FileLine* FileLine::copyOrSameFileLine() {
|
||||
return newp;
|
||||
}
|
||||
|
||||
void FileLine::updateLanguage () {
|
||||
language(v3Global.opt.fileLanguage(filename()));
|
||||
}
|
||||
|
||||
const string FileLine::filebasename() const {
|
||||
string name = filename();
|
||||
string::size_type pos;
|
||||
|
||||
+19
-3
@@ -30,6 +30,8 @@
|
||||
#include <set>
|
||||
#include <deque>
|
||||
|
||||
#include "V3LangCode.h"
|
||||
|
||||
//######################################################################
|
||||
|
||||
class V3ErrorCode {
|
||||
@@ -271,12 +273,18 @@ inline uint32_t cvtToHash(const void* vp) {
|
||||
|
||||
class FileLine;
|
||||
|
||||
//! Singleton class with tables of per-file data.
|
||||
|
||||
//! This singleton class contains tables of data that are unchanging in each
|
||||
//! source file (each with its own unique filename number).
|
||||
class FileLineSingleton {
|
||||
// TYPES
|
||||
typedef map<string,int> FileNameNumMap;
|
||||
typedef map<string,V3LangCode> FileLangNumMap;
|
||||
// MEMBERS
|
||||
FileNameNumMap m_namemap; // filenameno for each filename
|
||||
deque<string> m_names; // filename text for each filenameno
|
||||
deque<V3LangCode> m_languages; // language for each filenameno
|
||||
// COSNTRUCTORS
|
||||
FileLineSingleton() { }
|
||||
~FileLineSingleton() { }
|
||||
@@ -285,17 +293,22 @@ protected:
|
||||
// METHODS
|
||||
int nameToNumber(const string& filename);
|
||||
const string numberToName(int filenameno) const { return m_names[filenameno]; }
|
||||
void clear() { m_namemap.clear(); m_names.clear(); }
|
||||
const V3LangCode numberToLang(int filenameno) const { return m_languages[filenameno]; }
|
||||
void numberToLang(int filenameno, const V3LangCode l) { m_languages[filenameno] = l; }
|
||||
void clear() { m_namemap.clear(); m_names.clear(); m_languages.clear(); }
|
||||
void fileNameNumMapDumpXml(ostream& os);
|
||||
static const string filenameLetters(int fileno);
|
||||
};
|
||||
|
||||
//! File and line number of an object, mostly for error reporting
|
||||
|
||||
//! This class is instantiated for every source code line (potentially
|
||||
//! millions). To save space, per-file information (e.g. filename, source
|
||||
//! language is held in tables in the FileLineSingleton class.
|
||||
class FileLine {
|
||||
// File and line number of an object, mostly for error reporting
|
||||
int m_lineno;
|
||||
int m_filenameno;
|
||||
bitset<V3ErrorCode::_ENUM_MAX> m_warnOn;
|
||||
// Consider moving opt.language() into here, so can know language per-node
|
||||
|
||||
private:
|
||||
struct EmptySecret {};
|
||||
@@ -315,6 +328,7 @@ protected:
|
||||
friend class V3PreLex;
|
||||
friend class V3PreProcImp;
|
||||
void lineno(int num) { m_lineno = num; }
|
||||
void language (V3LangCode lang) { singleton().numberToLang(m_filenameno, lang); }
|
||||
void filename(const string& name) { m_filenameno = singleton().nameToNumber(name); }
|
||||
void lineDirective(const char* textp, int& enterExitRef);
|
||||
void linenoInc() { m_lineno++; }
|
||||
@@ -337,6 +351,8 @@ public:
|
||||
#endif
|
||||
|
||||
int lineno () const { return m_lineno; }
|
||||
V3LangCode language () const { return singleton().numberToLang(m_filenameno); }
|
||||
void updateLanguage ();
|
||||
string ascii() const;
|
||||
const string filename () const { return singleton().numberToName(m_filenameno); }
|
||||
const string filenameLetters() const { return singleton().filenameLetters(m_filenameno); }
|
||||
|
||||
+4
-4
@@ -275,10 +275,10 @@ void V3Graph::dumpDotFile(const string& filename, bool colorAsSubgraph) {
|
||||
|
||||
// Header
|
||||
*logp<<"digraph v3graph {\n";
|
||||
*logp<<"\trankdir="<<dotRankDir()<<"\n";
|
||||
*logp<<"\t//size="<<"\"7.5,10\""<<"\n";
|
||||
*logp<<"\tnTITLE\t[fontsize=20 label=\""<<filename<<"\", shape=box, style=bold, color=black];\n";
|
||||
*logp<<"\n";
|
||||
*logp<<"\tgraph\t[label=\""<<filename<<"\",\n";
|
||||
*logp<<"\t\t labelloc=t, labeljust=l,\n";
|
||||
*logp<<"\t\t //size="<<"\"7.5,10\","<<"\n";
|
||||
*logp<<"\t\t rankdir="<<dotRankDir()<<"];\n";
|
||||
|
||||
// List of all possible subgraphs
|
||||
typedef multimap<string,V3GraphVertex*> SubgraphMmap;
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Language code class
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
//
|
||||
// Verilator is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
#ifndef _V3LANGCODE_H_
|
||||
#define _V3LANGCODE_H_ 1
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
//######################################################################
|
||||
//! Class for the different languages supported.
|
||||
//! A separate file, since used both in V3Options (globally) and FileLine 9per
|
||||
//! file).
|
||||
class V3LangCode {
|
||||
public:
|
||||
enum en {
|
||||
L_ERROR, // Must be first.
|
||||
L1364_1995,
|
||||
L1364_2001,
|
||||
L1364_2005,
|
||||
L1800_2005,
|
||||
L1800_2009,
|
||||
// ***Add new elements below also***
|
||||
_ENUM_END
|
||||
};
|
||||
const char* ascii() const {
|
||||
const char* names[] = {
|
||||
// These must match the `begin_keywords values.
|
||||
" ERROR",
|
||||
"1364-1995",
|
||||
"1364-2001",
|
||||
"1364-2005",
|
||||
"1800-2005",
|
||||
"1800-2009"
|
||||
};
|
||||
return names[m_e];
|
||||
};
|
||||
static V3LangCode mostRecent() { return V3LangCode(L1800_2009); }
|
||||
bool legal() const { return m_e != L_ERROR; }
|
||||
//
|
||||
enum en m_e;
|
||||
inline V3LangCode () : m_e(L_ERROR) {}
|
||||
inline V3LangCode (en _e) : m_e(_e) {}
|
||||
V3LangCode (const char* textp);
|
||||
explicit inline V3LangCode (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
||||
#endif // guard
|
||||
+7
-4
@@ -96,6 +96,7 @@ private:
|
||||
|
||||
// STATE
|
||||
V3InFilter* m_filterp; // Parser filter
|
||||
V3ParseSym* m_parseSymp; // Parser symbol table
|
||||
|
||||
// Below state needs to be preserved between each module call.
|
||||
AstNodeModule* m_modp; // Current module
|
||||
@@ -202,7 +203,7 @@ private:
|
||||
// Read-subfile
|
||||
// If file not found, make AstNotFoundModule, rather than error out.
|
||||
// We'll throw the error when we know the module will really be needed.
|
||||
V3Parse parser (v3Global.rootp(), m_filterp);
|
||||
V3Parse parser (v3Global.rootp(), m_filterp, m_parseSymp);
|
||||
parser.parseFile(nodep->fileline(), nodep->modName(), false, "");
|
||||
V3Error::abortIfErrors();
|
||||
// We've read new modules, grab new pointers to their names
|
||||
@@ -284,6 +285,7 @@ private:
|
||||
if (nodep->modp()) {
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
UINFO(4," Link Cell done: "<<nodep<<endl);
|
||||
}
|
||||
|
||||
// Accelerate the recursion
|
||||
@@ -316,9 +318,10 @@ private:
|
||||
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
LinkCellsVisitor(AstNetlist* rootp, V3InFilter* filterp)
|
||||
LinkCellsVisitor(AstNetlist* rootp, V3InFilter* filterp, V3ParseSym* parseSymp)
|
||||
: m_mods(rootp) {
|
||||
m_filterp = filterp;
|
||||
m_parseSymp = parseSymp;
|
||||
m_modp = NULL;
|
||||
m_libVertexp = NULL;
|
||||
m_topVertexp = NULL;
|
||||
@@ -330,7 +333,7 @@ public:
|
||||
//######################################################################
|
||||
// Link class functions
|
||||
|
||||
void V3LinkCells::link(AstNetlist* rootp, V3InFilter* filterp) {
|
||||
void V3LinkCells::link(AstNetlist* rootp, V3InFilter* filterp, V3ParseSym* parseSymp) {
|
||||
UINFO(4,__FUNCTION__<<": "<<endl);
|
||||
LinkCellsVisitor visitor (rootp, filterp);
|
||||
LinkCellsVisitor visitor (rootp, filterp, parseSymp);
|
||||
}
|
||||
|
||||
+2
-1
@@ -26,12 +26,13 @@
|
||||
#include "V3Ast.h"
|
||||
|
||||
class V3InFilter;
|
||||
class V3ParseSym;
|
||||
|
||||
//============================================================================
|
||||
|
||||
class V3LinkCells {
|
||||
public:
|
||||
static void link(AstNetlist* nodep, V3InFilter* filterp);
|
||||
static void link(AstNetlist* nodep, V3InFilter* filterp, V3ParseSym* parseSymp);
|
||||
};
|
||||
|
||||
#endif // Guard
|
||||
|
||||
+31
-8
@@ -154,6 +154,7 @@ public:
|
||||
// See t_gen_forif.v for an example.
|
||||
} else {
|
||||
preErrorDump();
|
||||
UINFO(4,"name "<<name<<endl); // Not always same as nodep->name
|
||||
UINFO(4,"Var1 "<<nodep<<endl);
|
||||
UINFO(4,"Var2 "<<fnodep<<endl);
|
||||
if (nodep->type() == fnodep->type()) {
|
||||
@@ -450,6 +451,9 @@ private:
|
||||
string oldscope = m_scope;
|
||||
VSymEnt* oldModSymp = m_modSymp;
|
||||
VSymEnt* oldCurSymp = m_curSymp;
|
||||
int oldParamNum = m_paramNum;
|
||||
int oldBeginNum = m_beginNum;
|
||||
int oldModBeginNum = m_modBeginNum;
|
||||
if (doit) {
|
||||
UINFO(2," Link Module: "<<nodep<<endl);
|
||||
if (nodep->dead()) nodep->v3fatalSrc("Module in cell tree mislabeled as dead?");
|
||||
@@ -481,6 +485,9 @@ private:
|
||||
m_scope = oldscope;
|
||||
m_modSymp = oldModSymp;
|
||||
m_curSymp = oldCurSymp;
|
||||
m_paramNum = oldParamNum;
|
||||
m_beginNum = oldBeginNum;
|
||||
m_modBeginNum = oldModBeginNum;
|
||||
// Prep for next
|
||||
m_packagep = NULL;
|
||||
}
|
||||
@@ -497,6 +504,7 @@ private:
|
||||
AstBegin* oldbeginp = m_beginp;
|
||||
VSymEnt* oldModSymp = m_modSymp;
|
||||
VSymEnt* oldCurSymp = m_curSymp;
|
||||
int oldParamNum = m_paramNum;
|
||||
// Where do we add it?
|
||||
VSymEnt* aboveSymp = m_curSymp;
|
||||
string origname = AstNode::dedotName(nodep->name());
|
||||
@@ -522,6 +530,7 @@ private:
|
||||
m_beginp = oldbeginp;
|
||||
m_modSymp = oldModSymp;
|
||||
m_curSymp = oldCurSymp;
|
||||
m_paramNum = oldParamNum;
|
||||
}
|
||||
virtual void visit(AstCellInline* nodep, AstNUser*) {
|
||||
UINFO(5," CELLINLINE under "<<m_scope<<" is "<<nodep<<endl);
|
||||
@@ -544,6 +553,10 @@ private:
|
||||
m_statep->insertInline(aboveSymp, m_modSymp, nodep, nodep->name());
|
||||
}
|
||||
}
|
||||
virtual void visit(AstDefParam* nodep, AstNUser*) {
|
||||
nodep->user1p(m_curSymp);
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
virtual void visit(AstGenerate* nodep, AstNUser*) {
|
||||
// Begin: ... blocks often replicate under genif/genfor, so simply suppress duplicate checks
|
||||
// See t_gen_forif.v for an example.
|
||||
@@ -739,8 +752,7 @@ private:
|
||||
}
|
||||
}
|
||||
m_curSymp->import(srcp, nodep->name());
|
||||
// No longer needed
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
// No longer needed, but can't delete until any multi-instantiated modules are expanded
|
||||
}
|
||||
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
@@ -834,14 +846,15 @@ private:
|
||||
virtual void visit(AstDefParam* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
nodep->v3warn(DEFPARAM,"Suggest replace defparam with Verilog 2001 #(."<<nodep->name()<<"(...etc...))");
|
||||
VSymEnt* foundp = m_statep->getNodeSym(m_modp)->findIdFallback(nodep->path());
|
||||
VSymEnt* foundp = m_statep->getNodeSym(nodep)->findIdFallback(nodep->path());
|
||||
AstCell* cellp = foundp->nodep()->castCell();
|
||||
if (!cellp) {
|
||||
nodep->v3error("In defparam, cell "<<nodep->path()<<" never declared");
|
||||
} else {
|
||||
AstNode* exprp = nodep->rhsp()->unlinkFrBack();
|
||||
UINFO(9,"Defparam cell "<<nodep->path()<<"."<<nodep->name()
|
||||
<<" <= "<<exprp<<endl);
|
||||
<<" attach-to "<<cellp
|
||||
<<" <= "<<exprp<<endl);
|
||||
// Don't need to check the name of the defparam exists. V3Param does.
|
||||
AstPin* pinp = new AstPin (nodep->fileline(),
|
||||
-1, // Pin# not relevant
|
||||
@@ -1006,7 +1019,7 @@ private:
|
||||
AstCell* m_cellp; // Current cell
|
||||
AstNodeModule* m_modp; // Current module
|
||||
AstNodeFTask* m_ftaskp; // Current function/task
|
||||
AstDot* m_dotp; // Current dot
|
||||
AstDot* m_dotp; // Current dot
|
||||
DotPosition m_dotPos; // Scope part of dotted resolution
|
||||
bool m_dotErr; // Error found in dotted resolution, ignore upwards
|
||||
string m_dotText; // String of dotted names found in below parseref
|
||||
@@ -1239,6 +1252,7 @@ private:
|
||||
if (m_dotText!="") m_dotText += ".";
|
||||
m_dotText += nodep->name();
|
||||
m_dotSymp = foundp;
|
||||
m_dotPos = DP_SCOPE;
|
||||
// Upper AstDot visitor will handle it from here
|
||||
}
|
||||
}
|
||||
@@ -1292,6 +1306,7 @@ private:
|
||||
<<"'"<<" as a "<<foundp->nodep()->typeName()
|
||||
<<" but expected a "<<expectWhat);
|
||||
} else if (m_dotText=="") {
|
||||
UINFO(7," ErrParseRef curSymp=se"<<(void*)m_curSymp<<" dotSymp=se"<<(void*)m_dotSymp<<endl);
|
||||
nodep->v3error("Can't find definition of "<<expectWhat
|
||||
<<": "<<nodep->prettyName());
|
||||
} else {
|
||||
@@ -1351,6 +1366,7 @@ private:
|
||||
VSymEnt* okSymp;
|
||||
VSymEnt* dotSymp = m_curSymp; // Start search at current scope
|
||||
if (nodep->inlinedDots()!="") { // Correct for current scope
|
||||
dotSymp = m_modSymp; // Dotted lookup is always relative to module, as maybe variable name lower down with same scope name we want to ignore (t_math_divw)
|
||||
string inl = AstNode::dedotName(nodep->inlinedDots());
|
||||
dotSymp = m_statep->findDotted(dotSymp, inl, baddot, okSymp);
|
||||
if (!dotSymp) {
|
||||
@@ -1440,7 +1456,9 @@ private:
|
||||
nodep->packagep(foundp->packagep());
|
||||
UINFO(7," Resolved "<<nodep<<endl); // Also prints taskp
|
||||
} else {
|
||||
// Note ParseRef has similar error handling/message output
|
||||
m_statep->preErrorDump();
|
||||
UINFO(7," ErrFtask curSymp=se"<<(void*)m_curSymp<<" dotSymp=se"<<(void*)dotSymp<<endl);
|
||||
if (nodep->dotted() == "") {
|
||||
nodep->v3error("Can't find definition of task/function: "<<nodep->prettyName());
|
||||
} else {
|
||||
@@ -1454,8 +1472,8 @@ private:
|
||||
}
|
||||
virtual void visit(AstSelBit* nodep, AstNUser*) {
|
||||
if (nodep->user3SetOnce()) return;
|
||||
nodep->lhsp()->iterateAndNext(*this);
|
||||
if (m_dotPos == DP_SCOPE) { // Already under dot, so this is {modulepart} DOT {modulepart}
|
||||
nodep->lhsp()->iterateAndNext(*this);
|
||||
if (AstConst* constp = nodep->rhsp()->castConst()) {
|
||||
string index = AstNode::encodeNumber(constp->toSInt());
|
||||
m_dotText += "__BRA__"+index+"__KET__";
|
||||
@@ -1463,9 +1481,10 @@ private:
|
||||
nodep->v3error("Unsupported: Non-constant inside []'s in the cell part of a dotted reference");
|
||||
}
|
||||
// And pass up m_dotText
|
||||
} else {
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
nodep->fromp()->iterateAndNext(*this);
|
||||
nodep->bitp()->iterateAndNext(*this);
|
||||
nodep->attrp()->iterateAndNext(*this);
|
||||
}
|
||||
virtual void visit(AstBegin* nodep, AstNUser*) {
|
||||
UINFO(5," "<<nodep<<endl);
|
||||
@@ -1522,6 +1541,10 @@ private:
|
||||
}
|
||||
nodep->unlinkFrBack()->deleteTree();
|
||||
}
|
||||
virtual void visit(AstPackageImport* nodep, AstNUser*) {
|
||||
// No longer needed
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
}
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
// Default: Just iterate
|
||||
nodep->iterateChildren(*this);
|
||||
|
||||
+70
-58
@@ -34,6 +34,7 @@
|
||||
#include <memory>
|
||||
|
||||
#include "V3Global.h"
|
||||
#include "V3String.h"
|
||||
#include "V3Options.h"
|
||||
#include "V3Error.h"
|
||||
#include "V3File.h"
|
||||
@@ -54,6 +55,7 @@ struct V3OptionsImp {
|
||||
set<string> m_incDirUserSet; // Include directories (for removing duplicates)
|
||||
list<string> m_incDirFallbacks; // Include directories (ordered)
|
||||
set<string> m_incDirFallbackSet; // Include directories (for removing duplicates)
|
||||
map<string,V3LangCode> m_langExts; // Language extension map
|
||||
list<string> m_libExtVs; // Library extensions (ordered)
|
||||
set<string> m_libExtVSet; // Library extensions (for removing duplicates)
|
||||
DirMap m_dirMap; // Directory listing
|
||||
@@ -75,6 +77,12 @@ struct V3OptionsImp {
|
||||
}
|
||||
}
|
||||
}
|
||||
void addLangExt(const string &langext, const V3LangCode lc) {
|
||||
// New language extension replaces any pre-existing one.
|
||||
(void)m_langExts.erase(langext);
|
||||
m_langExts[langext] = lc;
|
||||
}
|
||||
|
||||
void addLibExtV(const string& libext) {
|
||||
if (m_libExtVSet.find(libext) == m_libExtVSet.end()) {
|
||||
m_libExtVSet.insert(libext);
|
||||
@@ -90,6 +98,9 @@ void V3Options::addIncDirUser(const string& incdir) {
|
||||
void V3Options::addIncDirFallback(const string& incdir) {
|
||||
m_impp->addIncDirFallback(incdir);
|
||||
}
|
||||
void V3Options::addLangExt(const string &langext, const V3LangCode lc) {
|
||||
m_impp->addLangExt(langext, lc);
|
||||
}
|
||||
void V3Options::addLibExtV(const string& libext) {
|
||||
m_impp->addLibExtV(libext);
|
||||
}
|
||||
@@ -157,7 +168,7 @@ string V3Options::allArgsString() {
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
// Language class
|
||||
// V3LangCode class functions
|
||||
|
||||
V3LangCode::V3LangCode (const char* textp) {
|
||||
// Return code for given string, or ERROR, which is a bad code
|
||||
@@ -364,10 +375,28 @@ void V3Options::filePathLookedMsg(FileLine* fl, const string& modname) {
|
||||
}
|
||||
}
|
||||
|
||||
//! Determine what language is associated with a filename
|
||||
|
||||
//! If we recognize the extension, use its language, otherwise, use the
|
||||
//! default language.
|
||||
V3LangCode V3Options::fileLanguage(const string &filename) {
|
||||
string ext = filenameNonDir(filename);
|
||||
string::size_type pos;
|
||||
if ((pos = ext.rfind(".")) != string::npos) {
|
||||
ext.erase(0, pos + 1);
|
||||
map<string,V3LangCode>::iterator it = m_impp->m_langExts.find(ext);
|
||||
if (it != m_impp->m_langExts.end()) {
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
return m_defaultLanguage;
|
||||
}
|
||||
|
||||
|
||||
void V3Options::unlinkRegexp(const string& dir, const string& regexp) {
|
||||
if (DIR* dirp = opendir(dir.c_str())) {
|
||||
while (struct dirent* direntp = readdir(dirp)) {
|
||||
if (wildmatch(direntp->d_name, regexp.c_str())) {
|
||||
if (VString::wildmatch(direntp->d_name, regexp.c_str())) {
|
||||
string fullname = dir + "/" + string(direntp->d_name);
|
||||
unlink (fullname.c_str());
|
||||
}
|
||||
@@ -433,9 +462,9 @@ string V3Options::getenvSYSTEMC_ARCH() {
|
||||
#else
|
||||
struct utsname uts;
|
||||
uname(&uts);
|
||||
string sysname = downcase(uts.sysname); // aka 'uname -s'
|
||||
if (wildmatch(sysname.c_str(), "*solaris*")) { var = "gccsparcOS5"; }
|
||||
else if (wildmatch(sysname.c_str(), "*cygwin*")) { var ="cygwin"; }
|
||||
string sysname = VString::downcase(uts.sysname); // aka 'uname -s'
|
||||
if (VString::wildmatch(sysname.c_str(), "*solaris*")) { var = "gccsparcOS5"; }
|
||||
else if (VString::wildmatch(sysname.c_str(), "*cygwin*")) { var ="cygwin"; }
|
||||
else { var = "linux"; }
|
||||
#endif
|
||||
setenvStr("SYSTEMC_ARCH", var,"From sysname '"+sysname+"'");
|
||||
@@ -542,54 +571,6 @@ string V3Options::getenvVERILATOR_ROOT() {
|
||||
return var;
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
// Wildcard
|
||||
|
||||
// Double procedures, inlined, unrolls loop much better
|
||||
inline bool V3Options::wildmatchi(const char* s, const char* p) {
|
||||
for ( ; *p; s++, p++) {
|
||||
if (*p!='*') {
|
||||
if (((*s)!=(*p)) && *p != '?')
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
// Trailing star matches everything.
|
||||
if (!*++p) return true;
|
||||
while (wildmatch(s, p) == false)
|
||||
if (*++s == '\0')
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return (*s == '\0');
|
||||
}
|
||||
|
||||
bool V3Options::wildmatch(const char* s, const char* p) {
|
||||
for ( ; *p; s++, p++) {
|
||||
if (*p!='*') {
|
||||
if (((*s)!=(*p)) && *p != '?')
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
// Trailing star matches everything.
|
||||
if (!*++p) return true;
|
||||
while (wildmatchi(s, p) == false)
|
||||
if (*++s == '\0')
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return (*s == '\0');
|
||||
}
|
||||
|
||||
string V3Options::downcase(const string& str) {
|
||||
string out = str;
|
||||
for (string::iterator pos = out.begin(); pos != out.end(); ++pos) {
|
||||
*pos = tolower(*pos);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
// V3 Options accessors
|
||||
|
||||
@@ -680,6 +661,17 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
||||
else if ( !strncmp (sw, "+incdir+", 8)) {
|
||||
addIncDirUser (parseFileArg(optdir, string (sw+strlen("+incdir+"))));
|
||||
}
|
||||
else if (parseLangExt(sw, "+systemverilogext+", V3LangCode::L1800_2009)
|
||||
|| parseLangExt(sw, "+verilog1995ext+", V3LangCode::L1364_1995)
|
||||
|| parseLangExt(sw, "+verilog2001ext+", V3LangCode::L1364_2001)
|
||||
|| parseLangExt(sw, "+1364-1995ext+", V3LangCode::L1364_1995)
|
||||
|| parseLangExt(sw, "+1364-2001ext+", V3LangCode::L1364_2001)
|
||||
|| parseLangExt(sw, "+1364-2005ext+", V3LangCode::L1364_2005)
|
||||
|| parseLangExt(sw, "+1800-2005ext+", V3LangCode::L1800_2005)
|
||||
|| parseLangExt(sw, "+1800-2009ext+", V3LangCode::L1800_2009)) {
|
||||
// Nothing to do here - all done in the test
|
||||
|
||||
}
|
||||
else if ( !strncmp (sw, "+libext+", 8)) {
|
||||
string exts = string(sw+strlen("+libext+"));
|
||||
string::size_type pos;
|
||||
@@ -737,15 +729,17 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
||||
else if ( onoff (sw, "-profile-cfuncs", flag/*ref*/) ) { m_profileCFuncs = flag; }
|
||||
else if ( onoff (sw, "-psl", flag/*ref*/) ) { m_psl = flag; }
|
||||
else if ( onoff (sw, "-public", flag/*ref*/) ) { m_public = flag; }
|
||||
else if ( onoff (sw, "-savable", flag/*ref*/) ) { m_savable = flag; }
|
||||
else if ( !strcmp (sw, "-sc") ) { m_outFormatOk = true; m_systemC = true; m_systemPerl = false; }
|
||||
else if ( onoff (sw, "-skip-identical", flag/*ref*/) ) { m_skipIdentical = flag; }
|
||||
else if ( !strcmp (sw, "-sp") ) { m_outFormatOk = true; m_systemC = true; m_systemPerl = true; }
|
||||
else if ( onoff (sw, "-stats", flag/*ref*/) ) { m_stats = flag; }
|
||||
else if ( !strcmp (sw, "-sv") ) { m_language = V3LangCode::L1800_2005; }
|
||||
else if ( !strcmp (sw, "-sv") ) { m_defaultLanguage = V3LangCode::L1800_2005; }
|
||||
else if ( onoff (sw, "-trace", flag/*ref*/) ) { m_trace = flag; }
|
||||
else if ( onoff (sw, "-trace-dups", flag/*ref*/) ) { m_traceDups = flag; }
|
||||
else if ( onoff (sw, "-trace-underscore", flag/*ref*/) ) { m_traceUnderscore = flag; }
|
||||
else if ( onoff (sw, "-underline-zero", flag/*ref*/) ) { m_underlineZero = flag; } // Undocumented, old Verilator-2
|
||||
else if ( onoff (sw, "-x-initial-edge", flag/*ref*/) ) { m_xInitialEdge = flag; }
|
||||
else if ( onoff (sw, "-xml-only", flag/*ref*/) ) { m_xmlOnly = flag; } // Undocumented, still experimental
|
||||
// Optimization
|
||||
else if ( !strncmp (sw, "-O", 2) ) {
|
||||
@@ -824,11 +818,12 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
||||
shift;
|
||||
addLdLibs(argv[i]);
|
||||
}
|
||||
else if ( !strcmp (sw, "-language") && (i+1)<argc ) {
|
||||
else if ( (!strcmp (sw, "-language") && (i+1)<argc)
|
||||
|| (!strcmp (sw, "-default-language") && (i+1)<argc)) {
|
||||
shift;
|
||||
V3LangCode optval = V3LangCode(argv[i]);
|
||||
if (optval.legal()) {
|
||||
m_language = optval;
|
||||
m_defaultLanguage = optval;
|
||||
} else {
|
||||
fl->v3fatal("Unknown language specified: "<<argv[i]);
|
||||
}
|
||||
@@ -1119,6 +1114,21 @@ string V3Options::parseFileArg(const string& optdir, const string& relfilename)
|
||||
|
||||
//======================================================================
|
||||
|
||||
//! Utility to see if we have a language extension argument and if so add it.
|
||||
bool V3Options::parseLangExt (const char* swp, //!< argument text
|
||||
const char* langswp, //!< option to match
|
||||
const V3LangCode lc) { //!< language code
|
||||
int len = strlen(langswp);
|
||||
if (!strncmp(swp, langswp, len)) {
|
||||
addLangExt(swp + len, lc);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
|
||||
void V3Options::showVersion(bool verbose) {
|
||||
cout <<version();
|
||||
cout <<endl;
|
||||
@@ -1181,6 +1191,7 @@ V3Options::V3Options() {
|
||||
m_preprocOnly = false;
|
||||
m_psl = false;
|
||||
m_public = false;
|
||||
m_savable = false;
|
||||
m_skipIdentical = true;
|
||||
m_stats = false;
|
||||
m_systemC = false;
|
||||
@@ -1189,6 +1200,7 @@ V3Options::V3Options() {
|
||||
m_traceDups = false;
|
||||
m_traceUnderscore = false;
|
||||
m_underlineZero = false;
|
||||
m_xInitialEdge = false;
|
||||
m_xmlOnly = false;
|
||||
|
||||
m_convergeLimit = 100;
|
||||
@@ -1214,7 +1226,7 @@ V3Options::V3Options() {
|
||||
m_unusedRegexp = "*unused*";
|
||||
m_xAssign = "fast";
|
||||
|
||||
m_language = V3LangCode::mostRecent();
|
||||
m_defaultLanguage = V3LangCode::mostRecent();
|
||||
|
||||
optimize(true);
|
||||
// Default +libext+
|
||||
@@ -1231,7 +1243,7 @@ V3Options::~V3Options() {
|
||||
|
||||
void V3Options::setDebugMode(int level) {
|
||||
V3Error::debugDefault(level);
|
||||
m_dumpTree = true;
|
||||
if (!m_dumpTree) m_dumpTree = true; // Don't override if already set.
|
||||
m_stats = true;
|
||||
m_debugCheck = true;
|
||||
cout << "Starting "<<version()<<endl;
|
||||
|
||||
+12
-45
@@ -29,43 +29,7 @@
|
||||
#include <set>
|
||||
|
||||
#include "V3Global.h"
|
||||
|
||||
//######################################################################
|
||||
|
||||
class V3LangCode {
|
||||
public:
|
||||
enum en {
|
||||
L_ERROR, // Must be first.
|
||||
L1364_1995,
|
||||
L1364_2001,
|
||||
L1364_2005,
|
||||
L1800_2005,
|
||||
L1800_2009,
|
||||
// ***Add new elements below also***
|
||||
_ENUM_END
|
||||
};
|
||||
const char* ascii() const {
|
||||
const char* names[] = {
|
||||
// These must match the `begin_keywords values.
|
||||
" ERROR",
|
||||
"1364-1995",
|
||||
"1364-2001",
|
||||
"1364-2005",
|
||||
"1800-2005",
|
||||
"1800-2009"
|
||||
};
|
||||
return names[m_e];
|
||||
};
|
||||
static V3LangCode mostRecent() { return V3LangCode(L1800_2009); }
|
||||
bool legal() const { return m_e != L_ERROR; }
|
||||
//
|
||||
enum en m_e;
|
||||
inline V3LangCode () : m_e(L_ERROR) {}
|
||||
inline V3LangCode (en _e) : m_e(_e) {}
|
||||
V3LangCode (const char* textp); // Return matching code or ERROR
|
||||
explicit inline V3LangCode (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
};
|
||||
#include "V3LangCode.h"
|
||||
|
||||
//######################################################################
|
||||
// V3Options - Command line options
|
||||
@@ -115,6 +79,7 @@ class V3Options {
|
||||
bool m_profileCFuncs;// main switch: --profile-cfuncs
|
||||
bool m_psl; // main switch: --psl
|
||||
bool m_public; // main switch: --public
|
||||
bool m_savable; // main switch: --savable
|
||||
bool m_systemC; // main switch: --sc: System C instead of simple C++
|
||||
bool m_skipIdentical;// main switch: --skip-identical
|
||||
bool m_systemPerl; // main switch: --sp: System Perl instead of SystemC (m_systemC also set)
|
||||
@@ -123,6 +88,7 @@ class V3Options {
|
||||
bool m_traceDups; // main switch: --trace-dups
|
||||
bool m_traceUnderscore;// main switch: --trace-underscore
|
||||
bool m_underlineZero;// main switch: --underline-zero; undocumented old Verilator 2
|
||||
bool m_xInitialEdge; // main switch: --x-initial-edge
|
||||
bool m_xmlOnly; // main switch: --xml-netlist
|
||||
|
||||
int m_convergeLimit;// main switch: --converge-limit
|
||||
@@ -154,8 +120,9 @@ class V3Options {
|
||||
string m_unusedRegexp; // main switch: --unused-regexp
|
||||
string m_xAssign; // main switch: --x-assign
|
||||
|
||||
// Consider moving m_language into FileLine, so can know language per-node
|
||||
V3LangCode m_language; // main switch: --language
|
||||
// Language is now held in FileLine, on a per-node basis. However we still
|
||||
// have a concept of the default language at a global level.
|
||||
V3LangCode m_defaultLanguage; // main switch: --language
|
||||
|
||||
// MEMBERS (optimizations)
|
||||
// // main switch: -Op: --public
|
||||
@@ -183,6 +150,7 @@ class V3Options {
|
||||
void addFuture(const string& flag);
|
||||
void addIncDirUser(const string& incdir); // User requested
|
||||
void addIncDirFallback(const string& incdir); // Low priority if not found otherwise
|
||||
void addLangExt(const string &langext, const V3LangCode lc);
|
||||
void addLibExtV(const string& libext);
|
||||
void optimize(int level);
|
||||
void showVersion(bool verbose);
|
||||
@@ -190,9 +158,9 @@ class V3Options {
|
||||
bool onoff(const char* sw, const char* arg, bool& flag);
|
||||
bool suffixed(const char* sw, const char* arg);
|
||||
string parseFileArg(const string& optdir, const string& relfilename);
|
||||
bool parseLangExt(const char* swp, const char* langswp, const V3LangCode lc);
|
||||
string filePathCheckOneDir(const string& modname, const string& dirname);
|
||||
|
||||
static bool wildmatchi(const char* s, const char* p);
|
||||
static string getenvStr(const string& envvar, const string& defaultValue);
|
||||
static void setenvStr(const string& envvar, const string& value, const string& why);
|
||||
static string getenvSYSTEMPERLGuts();
|
||||
@@ -223,6 +191,7 @@ class V3Options {
|
||||
bool systemPerl() const { return m_systemPerl; }
|
||||
bool usingSystemCLibs() const { return !lintOnly() && (systemPerl() || systemC()); }
|
||||
bool usingSystemPerlLibs() const { return !lintOnly() && (systemPerl() || coverage()); }
|
||||
bool savable() const { return m_savable; }
|
||||
bool skipIdentical() const { return m_skipIdentical; }
|
||||
bool stats() const { return m_stats; }
|
||||
bool assertOn() const { return m_assert; } // assertOn as __FILE__ may be defined
|
||||
@@ -251,6 +220,7 @@ class V3Options {
|
||||
bool lintOnly() const { return m_lintOnly; }
|
||||
bool ignc() const { return m_ignc; }
|
||||
bool inhibitSim() const { return m_inhibitSim; }
|
||||
bool xInitialEdge() const { return m_xInitialEdge; }
|
||||
bool xmlOnly() const { return m_xmlOnly; }
|
||||
|
||||
int convergeLimit() const { return m_convergeLimit; }
|
||||
@@ -285,7 +255,7 @@ class V3Options {
|
||||
const V3StringSet& ldLibs() const { return m_ldLibs; }
|
||||
const V3StringSet& libraryFiles() const { return m_libraryFiles; }
|
||||
const V3StringList& vFiles() const { return m_vFiles; }
|
||||
const V3LangCode& language() const { return m_language; }
|
||||
const V3LangCode& defaultLanguage() const { return m_defaultLanguage; }
|
||||
|
||||
bool isFuture(const string& flag) const;
|
||||
bool isLibraryFile(const string& filename) const;
|
||||
@@ -321,10 +291,6 @@ class V3Options {
|
||||
void parseOptsList (FileLine* fl, const string& optdir, int argc, char** argv);
|
||||
void parseOptsFile (FileLine* fl, const string& filename, bool rel);
|
||||
|
||||
// METHODS (generic string utilities)
|
||||
static bool wildmatch(const char* s, const char* p);
|
||||
static string downcase(const string& str);
|
||||
|
||||
// METHODS (generic file utilities)
|
||||
static string filenameFromDirBase (const string& dir, const string& basename);
|
||||
static string filenameNonDir (const string& filename); ///< Return non-directory part of filename
|
||||
@@ -352,6 +318,7 @@ class V3Options {
|
||||
string fileExists (const string& filename);
|
||||
string filePath (FileLine* fl, const string& modname, const string& errmsg);
|
||||
void filePathLookedMsg(FileLine* fl, const string& modname);
|
||||
V3LangCode fileLanguage(const string &filename);
|
||||
static bool fileStatDir (const string& filename);
|
||||
static bool fileStatNormal (const string& filename);
|
||||
|
||||
|
||||
+9
-7
@@ -76,8 +76,8 @@ private:
|
||||
LongMap m_longMap; // Hash of very long names to unique identity number
|
||||
int m_longId;
|
||||
|
||||
typedef deque<AstNodeModule*> ModDeque;
|
||||
ModDeque m_todoModps; // Modules left to process
|
||||
typedef multimap<int,AstNodeModule*> LevelModMap;
|
||||
LevelModMap m_todoModps; // Modules left to process
|
||||
|
||||
// METHODS
|
||||
static int debug() {
|
||||
@@ -125,10 +125,12 @@ private:
|
||||
}
|
||||
void visitModules() {
|
||||
// Loop on all modules left to process
|
||||
// Hitting a cell adds to the END of this list, so since cells originally exist top->bottom
|
||||
// we process in top->bottom order too.
|
||||
// Hitting a cell adds to the appropriate leval of this level-sorted list,
|
||||
// so since cells originally exist top->bottom we process in top->bottom order too.
|
||||
while (!m_todoModps.empty()) {
|
||||
AstNodeModule* nodep = m_todoModps.front(); m_todoModps.pop_front();
|
||||
LevelModMap::iterator it = m_todoModps.begin();
|
||||
AstNodeModule* nodep = it->second;
|
||||
m_todoModps.erase(it);
|
||||
if (!nodep->user5SetOnce()) { // Process once; note clone() must clear so we do it again
|
||||
UINFO(4," MOD "<<nodep<<endl);
|
||||
nodep->iterateChildren(*this);
|
||||
@@ -147,7 +149,7 @@ private:
|
||||
UINFO(4," MOD-dead. "<<nodep<<endl); // Marked by LinkDot
|
||||
} else if (nodep->level() <= 2) { // Haven't added top yet, so level 2 is the top
|
||||
// Add request to END of modules left to process
|
||||
m_todoModps.push_back(nodep);
|
||||
m_todoModps.insert(make_pair(nodep->level(),nodep));
|
||||
visitModules();
|
||||
} else if (nodep->user5()) {
|
||||
UINFO(4," MOD-done "<<nodep<<endl); // Already did it
|
||||
@@ -443,7 +445,7 @@ void ParamVisitor::visit(AstCell* nodep, AstNUser*) {
|
||||
}
|
||||
|
||||
// Now remember to process the child module at the end of the module
|
||||
m_todoModps.push_back(nodep->modp());
|
||||
m_todoModps.insert(make_pair(nodep->modp()->level(),nodep->modp()));
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
|
||||
+2
-1
@@ -28,6 +28,7 @@
|
||||
class AstNetlist;
|
||||
class V3InFilter;
|
||||
class V3ParseImp;
|
||||
class V3ParseSym;
|
||||
|
||||
//============================================================================
|
||||
|
||||
@@ -38,7 +39,7 @@ private:
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
// We must allow reading multiple files into one parser
|
||||
V3Parse(AstNetlist* rootp, V3InFilter* filterp);
|
||||
V3Parse(AstNetlist* rootp, V3InFilter* filterp, V3ParseSym* symp);
|
||||
~V3Parse();
|
||||
|
||||
// METHODS
|
||||
|
||||
+8
-4
@@ -100,8 +100,12 @@ void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool i
|
||||
// Set language standard up front
|
||||
if (!v3Global.opt.preprocOnly()) {
|
||||
// Leting lex parse this saves us from having to specially en/decode
|
||||
// from the V3LangCode to the various Lex BEGIN states.
|
||||
ppPushText((string)"`begin_keywords \""+v3Global.opt.language().ascii()+"\"\n");
|
||||
// from the V3LangCode to the various Lex BEGIN states. The language
|
||||
// of this source file is updated here, in case there have been any
|
||||
// intervening +<lang>ext+ options since it was first ecountered.
|
||||
FileLine *modfileline = new FileLine (modfilename, 0);
|
||||
modfileline->updateLanguage();
|
||||
ppPushText((string)"`begin_keywords \""+modfileline->language().ascii()+"\"\n");
|
||||
}
|
||||
|
||||
// Preprocess into m_ppBuffer
|
||||
@@ -159,8 +163,8 @@ void V3ParseImp::lexFile(const string& modname) {
|
||||
//======================================================================
|
||||
// V3Parse functions
|
||||
|
||||
V3Parse::V3Parse(AstNetlist* rootp, V3InFilter* filterp) {
|
||||
m_impp = new V3ParseImp (rootp, filterp);
|
||||
V3Parse::V3Parse(AstNetlist* rootp, V3InFilter* filterp, V3ParseSym* symp) {
|
||||
m_impp = new V3ParseImp (rootp, filterp, symp);
|
||||
}
|
||||
V3Parse::~V3Parse() {
|
||||
delete m_impp; m_impp = NULL;
|
||||
|
||||
+8
-121
@@ -25,7 +25,7 @@
|
||||
#include "V3Error.h"
|
||||
#include "V3Global.h"
|
||||
#include "V3Parse.h"
|
||||
#include "V3SymTable.h"
|
||||
#include "V3ParseSym.h"
|
||||
#include <deque>
|
||||
|
||||
class V3Lexer;
|
||||
@@ -75,6 +75,7 @@ struct V3ParseBisonYYSType {
|
||||
AstNodeVarRef* varnodep;
|
||||
AstPackage* packagep;
|
||||
AstParseRef* parserefp;
|
||||
AstPatMember* patmemberp;
|
||||
AstPin* pinp;
|
||||
AstRange* rangep;
|
||||
AstSenTree* sentreep;
|
||||
@@ -85,132 +86,18 @@ struct V3ParseBisonYYSType {
|
||||
|
||||
#define YYSTYPE V3ParseBisonYYSType
|
||||
|
||||
//######################################################################
|
||||
// Symbol table for parsing
|
||||
|
||||
class V3ParseSym {
|
||||
// TYPES
|
||||
typedef vector<VSymEnt*> SymStack;
|
||||
|
||||
private:
|
||||
// MEMBERS
|
||||
static int s_anonNum; // Number of next anonymous object (parser use only)
|
||||
VSymGraph m_syms; // Graph of symbol tree
|
||||
VSymEnt* m_symTableNextId; // Symbol table for next lexer lookup (parser use only)
|
||||
VSymEnt* m_symCurrentp; // Active symbol table for additions/lookups
|
||||
SymStack m_sympStack; // Stack of upper nodes with pending symbol tables
|
||||
|
||||
private:
|
||||
// METHODS
|
||||
static VSymEnt* getTable(AstNode* nodep) {
|
||||
if (!nodep->user4p()) nodep->v3fatalSrc("Current symtable not found");
|
||||
return nodep->user4p()->castSymEnt();
|
||||
}
|
||||
|
||||
public:
|
||||
VSymEnt* nextId() const { return m_symTableNextId; }
|
||||
VSymEnt* symCurrentp() const { return m_symCurrentp; }
|
||||
VSymEnt* symRootp() const { return m_syms.rootp(); }
|
||||
|
||||
VSymEnt* findNewTable(AstNode* nodep) {
|
||||
if (!nodep->user4p()) {
|
||||
VSymEnt* symsp = new VSymEnt(&m_syms, nodep);
|
||||
nodep->user4p(symsp);
|
||||
}
|
||||
return getTable(nodep);
|
||||
}
|
||||
void nextId(AstNode* entp) {
|
||||
if (entp) {
|
||||
UINFO(9,"symTableNextId under "<<entp<<"-"<<entp->type().ascii()<<endl);
|
||||
m_symTableNextId = getTable(entp);
|
||||
}
|
||||
else {
|
||||
UINFO(9,"symTableNextId under NULL"<<endl);
|
||||
m_symTableNextId = NULL;
|
||||
}
|
||||
}
|
||||
void reinsert(AstNode* nodep, VSymEnt* parentp=NULL) {
|
||||
reinsert(nodep, parentp, nodep->name());
|
||||
}
|
||||
void reinsert(AstNode* nodep, VSymEnt* parentp, string name) {
|
||||
if (!parentp) parentp = symCurrentp();
|
||||
if (name == "") { // New name with space in name so can't collide with users
|
||||
name = string(" anon") + nodep->type().ascii() + cvtToStr(++s_anonNum);
|
||||
}
|
||||
parentp->reinsert(name, findNewTable(nodep));
|
||||
}
|
||||
void pushNew(AstNode* nodep) { pushNewUnder(nodep, NULL); }
|
||||
void pushNewUnder(AstNode* nodep, VSymEnt* parentp) {
|
||||
if (!parentp) parentp = symCurrentp();
|
||||
VSymEnt* symp = findNewTable(nodep); // Will set user4p, which is how we connect table to node
|
||||
symp->fallbackp(parentp);
|
||||
reinsert(nodep, parentp);
|
||||
pushScope(symp);
|
||||
}
|
||||
void pushScope(VSymEnt* symp) {
|
||||
m_sympStack.push_back(symp);
|
||||
m_symCurrentp = symp;
|
||||
}
|
||||
void popScope(AstNode* nodep) {
|
||||
if (symCurrentp()->nodep() != nodep) {
|
||||
if (debug()) { showUpward(); dump(cout,"-mism: "); }
|
||||
nodep->v3fatalSrc("Symbols suggest ending "<<symCurrentp()->nodep()->prettyTypeName()
|
||||
<<" but parser thinks ending "<<nodep->prettyTypeName());
|
||||
return;
|
||||
}
|
||||
m_sympStack.pop_back();
|
||||
if (m_sympStack.empty()) { nodep->v3fatalSrc("symbol stack underflow"); return; }
|
||||
m_symCurrentp = m_sympStack.back();
|
||||
}
|
||||
void showUpward () {
|
||||
UINFO(1,"ParseSym Stack:\n");
|
||||
for (SymStack::reverse_iterator it=m_sympStack.rbegin(); it!=m_sympStack.rend(); ++it) {
|
||||
VSymEnt* symp = *it;
|
||||
UINFO(1,"\t"<<symp->nodep()<<endl);
|
||||
}
|
||||
UINFO(1,"ParseSym Current: "<<symCurrentp()->nodep()<<endl);
|
||||
}
|
||||
void dump(ostream& os, const string& indent="") {
|
||||
m_syms.dump(os,indent);
|
||||
}
|
||||
AstNode* findEntUpward (const string& name) {
|
||||
// Lookup the given string as an identifier, return type of the id, scanning upward
|
||||
return symCurrentp()->findIdFallback(name)->nodep();
|
||||
}
|
||||
void import(AstNode* packagep, const string& id_or_star) {
|
||||
// Import from package::id_or_star to this
|
||||
VSymEnt* symp = getTable(packagep);
|
||||
if (!symp) { // Internal problem, because we earlier found pkg to label it an ID__aPACKAGE
|
||||
packagep->v3fatalSrc("Import package not found");
|
||||
return;
|
||||
}
|
||||
// Walk old sym table and reinsert into current table
|
||||
// We let V3LinkDot report the error instead of us
|
||||
symCurrentp()->import(symp, id_or_star);
|
||||
}
|
||||
public:
|
||||
// CREATORS
|
||||
V3ParseSym(AstNetlist* rootp)
|
||||
: m_syms(rootp) {
|
||||
s_anonNum = 0; // Number of next anonymous object
|
||||
pushScope(findNewTable(rootp));
|
||||
m_symTableNextId = NULL;
|
||||
m_symCurrentp = symCurrentp();
|
||||
}
|
||||
~V3ParseSym() {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
||||
class V3ParseImp {
|
||||
// MEMBERS
|
||||
AstNetlist* m_rootp; // Root of the design
|
||||
V3InFilter* m_filterp; // Reading filter
|
||||
V3ParseSym* m_symp; // Symbol table
|
||||
|
||||
V3Lexer* m_lexerp; // Current FlexLexer
|
||||
static V3ParseImp* s_parsep; // Current THIS, bison() isn't class based
|
||||
FileLine* m_fileline; // Filename/linenumber currently active
|
||||
|
||||
V3ParseSym m_sym; // Symbol table
|
||||
bool m_inCellDefine; // Inside a `celldefine
|
||||
bool m_inLibrary; // Currently reading a library vs. regular file
|
||||
int m_inBeginKwd; // Inside a `begin_keywords
|
||||
@@ -307,14 +194,14 @@ public:
|
||||
size_t flexPpInputToLex(char* buf, size_t max_size) { return ppInputToLex(buf,max_size); }
|
||||
|
||||
//==== Symbol tables
|
||||
V3ParseSym* symp() { return &m_sym; }
|
||||
V3ParseSym* symp() { return m_symp; }
|
||||
|
||||
public:
|
||||
// CREATORS
|
||||
V3ParseImp(AstNetlist* rootp, V3InFilter* filterp)
|
||||
: m_filterp(filterp), m_sym(rootp) {
|
||||
V3ParseImp(AstNetlist* rootp, V3InFilter* filterp, V3ParseSym* parserSymp)
|
||||
: m_rootp(rootp), m_filterp(filterp), m_symp(parserSymp) {
|
||||
m_fileline = NULL;
|
||||
m_rootp = rootp; m_lexerp = NULL;
|
||||
m_lexerp = NULL;
|
||||
m_inCellDefine = false;
|
||||
m_inLibrary = false;
|
||||
m_inBeginKwd = 0;
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Common header between parser and lex
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2009-2012 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
//
|
||||
// Verilator is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
#ifndef _V3PARSESYM_H_
|
||||
#define _V3PARSESYM_H_ 1
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include "V3Error.h"
|
||||
#include "V3Global.h"
|
||||
#include "V3SymTable.h"
|
||||
#include <deque>
|
||||
|
||||
//######################################################################
|
||||
// Symbol table for parsing
|
||||
|
||||
class V3ParseSym {
|
||||
// TYPES
|
||||
typedef vector<VSymEnt*> SymStack;
|
||||
|
||||
private:
|
||||
// MEMBERS
|
||||
static int s_anonNum; // Number of next anonymous object (parser use only)
|
||||
VSymGraph m_syms; // Graph of symbol tree
|
||||
VSymEnt* m_symTableNextId; // Symbol table for next lexer lookup (parser use only)
|
||||
VSymEnt* m_symCurrentp; // Active symbol table for additions/lookups
|
||||
SymStack m_sympStack; // Stack of upper nodes with pending symbol tables
|
||||
|
||||
private:
|
||||
// METHODS
|
||||
static VSymEnt* getTable(AstNode* nodep) {
|
||||
if (!nodep->user4p()) nodep->v3fatalSrc("Current symtable not found");
|
||||
return nodep->user4p()->castSymEnt();
|
||||
}
|
||||
|
||||
public:
|
||||
VSymEnt* nextId() const { return m_symTableNextId; }
|
||||
VSymEnt* symCurrentp() const { return m_symCurrentp; }
|
||||
VSymEnt* symRootp() const { return m_syms.rootp(); }
|
||||
|
||||
VSymEnt* findNewTable(AstNode* nodep) {
|
||||
if (!nodep->user4p()) {
|
||||
VSymEnt* symsp = new VSymEnt(&m_syms, nodep);
|
||||
nodep->user4p(symsp);
|
||||
}
|
||||
return getTable(nodep);
|
||||
}
|
||||
void nextId(AstNode* entp) {
|
||||
if (entp) {
|
||||
UINFO(9,"symTableNextId under "<<entp<<"-"<<entp->type().ascii()<<endl);
|
||||
m_symTableNextId = getTable(entp);
|
||||
}
|
||||
else {
|
||||
UINFO(9,"symTableNextId under NULL"<<endl);
|
||||
m_symTableNextId = NULL;
|
||||
}
|
||||
}
|
||||
void reinsert(AstNode* nodep, VSymEnt* parentp=NULL) {
|
||||
reinsert(nodep, parentp, nodep->name());
|
||||
}
|
||||
void reinsert(AstNode* nodep, VSymEnt* parentp, string name) {
|
||||
if (!parentp) parentp = symCurrentp();
|
||||
if (name == "") { // New name with space in name so can't collide with users
|
||||
name = string(" anon") + nodep->type().ascii() + cvtToStr(++s_anonNum);
|
||||
}
|
||||
parentp->reinsert(name, findNewTable(nodep));
|
||||
}
|
||||
void pushNew(AstNode* nodep) { pushNewUnder(nodep, NULL); }
|
||||
void pushNewUnder(AstNode* nodep, VSymEnt* parentp) {
|
||||
if (!parentp) parentp = symCurrentp();
|
||||
VSymEnt* symp = findNewTable(nodep); // Will set user4p, which is how we connect table to node
|
||||
symp->fallbackp(parentp);
|
||||
reinsert(nodep, parentp);
|
||||
pushScope(symp);
|
||||
}
|
||||
void pushScope(VSymEnt* symp) {
|
||||
m_sympStack.push_back(symp);
|
||||
m_symCurrentp = symp;
|
||||
}
|
||||
void popScope(AstNode* nodep) {
|
||||
if (symCurrentp()->nodep() != nodep) {
|
||||
if (debug()) { showUpward(); dump(cout,"-mism: "); }
|
||||
nodep->v3fatalSrc("Symbols suggest ending "<<symCurrentp()->nodep()->prettyTypeName()
|
||||
<<" but parser thinks ending "<<nodep->prettyTypeName());
|
||||
return;
|
||||
}
|
||||
m_sympStack.pop_back();
|
||||
if (m_sympStack.empty()) { nodep->v3fatalSrc("symbol stack underflow"); return; }
|
||||
m_symCurrentp = m_sympStack.back();
|
||||
}
|
||||
void showUpward () {
|
||||
UINFO(1,"ParseSym Stack:\n");
|
||||
for (SymStack::reverse_iterator it=m_sympStack.rbegin(); it!=m_sympStack.rend(); ++it) {
|
||||
VSymEnt* symp = *it;
|
||||
UINFO(1,"\t"<<symp->nodep()<<endl);
|
||||
}
|
||||
UINFO(1,"ParseSym Current: "<<symCurrentp()->nodep()<<endl);
|
||||
}
|
||||
void dump(ostream& os, const string& indent="") {
|
||||
m_syms.dump(os,indent);
|
||||
}
|
||||
AstNode* findEntUpward (const string& name) {
|
||||
// Lookup the given string as an identifier, return type of the id, scanning upward
|
||||
return symCurrentp()->findIdFallback(name)->nodep();
|
||||
}
|
||||
void import(AstNode* packagep, const string& id_or_star) {
|
||||
// Import from package::id_or_star to this
|
||||
VSymEnt* symp = getTable(packagep);
|
||||
if (!symp) { // Internal problem, because we earlier found pkg to label it an ID__aPACKAGE
|
||||
packagep->v3fatalSrc("Import package not found");
|
||||
return;
|
||||
}
|
||||
// Walk old sym table and reinsert into current table
|
||||
// We let V3LinkDot report the error instead of us
|
||||
symCurrentp()->import(symp, id_or_star);
|
||||
}
|
||||
public:
|
||||
// CREATORS
|
||||
V3ParseSym(AstNetlist* rootp)
|
||||
: m_syms(rootp) {
|
||||
s_anonNum = 0; // Number of next anonymous object
|
||||
pushScope(findNewTable(rootp));
|
||||
m_symTableNextId = NULL;
|
||||
m_symCurrentp = symCurrentp();
|
||||
}
|
||||
~V3ParseSym() {}
|
||||
};
|
||||
|
||||
#endif // Guard
|
||||
+6
-22
@@ -54,14 +54,6 @@ class SliceCloneVisitor : public AstNVisitor {
|
||||
// AstNodeAssign::user2() -> int. The number of clones needed for this assign
|
||||
// AstArraySel::user3() -> bool. Error detected
|
||||
|
||||
// ENUMS
|
||||
enum RedOp { // The type of unary operation to be expanded
|
||||
REDOP_UNKNOWN, // Unknown/Unsupported
|
||||
REDOP_OR, // Or Reduction
|
||||
REDOP_AND, // And Reduction
|
||||
REDOP_XOR, // Xor Reduction
|
||||
REDOP_XNOR}; // Xnor Reduction
|
||||
|
||||
// STATE
|
||||
vector<vector<unsigned> > m_selBits; // Indexes of the ArraySel we are expanding
|
||||
int m_vecIdx; // Current vector index
|
||||
@@ -140,14 +132,6 @@ class SliceCloneVisitor : public AstNVisitor {
|
||||
m_selBits.clear();
|
||||
UINFO(4, "Cloning "<<nodep->user2()<<" times: "<<nodep<<endl);
|
||||
|
||||
// Figure out what type of operation this is so we don't have to cast on
|
||||
// every clone.
|
||||
RedOp redOpType = REDOP_UNKNOWN;
|
||||
if (nodep->castRedOr()) redOpType = REDOP_OR;
|
||||
else if (nodep->castRedAnd()) redOpType = REDOP_AND;
|
||||
else if (nodep->castRedXor()) redOpType = REDOP_XOR;
|
||||
else if (nodep->castRedXnor()) redOpType = REDOP_XNOR;
|
||||
|
||||
AstNode* lhsp = NULL;
|
||||
AstNode* rhsp = NULL;
|
||||
for (int i = 0; i < nodep->user2(); ++i) {
|
||||
@@ -158,20 +142,20 @@ class SliceCloneVisitor : public AstNVisitor {
|
||||
if (!lhsp) lhsp = clonep;
|
||||
else rhsp = clonep;
|
||||
if (lhsp && rhsp) {
|
||||
switch (redOpType) {
|
||||
case REDOP_OR:
|
||||
switch (nodep->type()) {
|
||||
case AstType::atREDOR:
|
||||
lhsp = new AstOr(nodep->fileline(), lhsp, rhsp);
|
||||
break;
|
||||
case REDOP_AND:
|
||||
case AstType::atREDAND:
|
||||
lhsp = new AstAnd(nodep->fileline(), lhsp, rhsp);
|
||||
break;
|
||||
case REDOP_XOR:
|
||||
case AstType::atREDXOR:
|
||||
lhsp = new AstXor(nodep->fileline(), lhsp, rhsp);
|
||||
break;
|
||||
case REDOP_XNOR:
|
||||
case AstType::atREDXNOR:
|
||||
lhsp = new AstXnor(nodep->fileline(), lhsp, rhsp);
|
||||
break;
|
||||
default: // REDOP_UNKNOWN
|
||||
default:
|
||||
nodep->v3fatalSrc("Unsupported: Unary operation on multiple packed dimensions");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Options parsing
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
//
|
||||
// Verilator is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
|
||||
#include "V3String.h"
|
||||
|
||||
//######################################################################
|
||||
// Wildcard
|
||||
|
||||
// Double procedures, inlined, unrolls loop much better
|
||||
inline bool VString::wildmatchi(const char* s, const char* p) {
|
||||
for ( ; *p; s++, p++) {
|
||||
if (*p!='*') {
|
||||
if (((*s)!=(*p)) && *p != '?')
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
// Trailing star matches everything.
|
||||
if (!*++p) return true;
|
||||
while (wildmatch(s, p) == false)
|
||||
if (*++s == '\0')
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return (*s == '\0');
|
||||
}
|
||||
|
||||
bool VString::wildmatch(const char* s, const char* p) {
|
||||
for ( ; *p; s++, p++) {
|
||||
if (*p!='*') {
|
||||
if (((*s)!=(*p)) && *p != '?')
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
// Trailing star matches everything.
|
||||
if (!*++p) return true;
|
||||
while (wildmatchi(s, p) == false)
|
||||
if (*++s == '\0')
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return (*s == '\0');
|
||||
}
|
||||
|
||||
string VString::downcase(const string& str) {
|
||||
string out = str;
|
||||
for (string::iterator pos = out.begin(); pos != out.end(); ++pos) {
|
||||
*pos = tolower(*pos);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: String manipulation
|
||||
//
|
||||
// Code available from: http://www.veripool.org/verilator
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
//
|
||||
// Verilator is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
#ifndef _V3STRING_H_
|
||||
#define _V3STRING_H_ 1
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
#include <string>
|
||||
|
||||
//######################################################################
|
||||
// VString - String manipulation
|
||||
|
||||
class VString {
|
||||
static bool wildmatchi(const char* s, const char* p);
|
||||
public:
|
||||
// METHODS (generic string utilities)
|
||||
static bool wildmatch(const char* s, const char* p);
|
||||
static string downcase(const string& str);
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
// Compute FNV1a (Fowler/Noll/Vo) hashes
|
||||
// See http://www.isthe.com/chongo/tech/comp/fnv/index.html
|
||||
// Algorithmic basis for these functions was in the public domain, by chongo <Landon Curt Noll>
|
||||
|
||||
class VHashFnv {
|
||||
enum { FNV1_64_INIT = 0xcbf29ce484222325ULL }; // Initial value
|
||||
vluint64_t m_hash;
|
||||
|
||||
inline void hashC(uint8_t c) {
|
||||
m_hash ^= c;
|
||||
// Below is faster than m_hash *= 0x100000001b3ULL;
|
||||
m_hash += ((m_hash << 1) + (m_hash << 4) + (m_hash << 5)
|
||||
+ (m_hash << 7) + (m_hash << 8) + (m_hash << 40));
|
||||
}
|
||||
public:
|
||||
VHashFnv() : m_hash(FNV1_64_INIT) {}
|
||||
~VHashFnv() {}
|
||||
|
||||
vluint64_t value() const { return m_hash; }
|
||||
|
||||
VHashFnv& hash(const void* bufp, size_t len) { // Memory
|
||||
const uint8_t* bp = (const uint8_t*)bufp;
|
||||
const uint8_t* be = bp + len;
|
||||
while (bp < be) hashC((vluint64_t)*bp++);
|
||||
return *this;
|
||||
}
|
||||
VHashFnv& hash(const char* strp) { // String
|
||||
const uint8_t* sp = (const uint8_t*)strp;
|
||||
while (*sp) hashC((vluint64_t)*sp++);
|
||||
return *this;
|
||||
}
|
||||
VHashFnv& hash(const string& str) { return hash(str.c_str()); }
|
||||
VHashFnv& hash(vluint64_t n) {
|
||||
hashC(n>>0); hashC(n>>8); hashC(n>>16); hashC(n>>24);
|
||||
hashC(n>>32); hashC(n>>40); hashC(n>>48); hashC(n>>56);
|
||||
return *this;
|
||||
}
|
||||
VHashFnv& hash(uint32_t n) {
|
||||
hashC(n>>0); hashC(n>>8); hashC(n>>16); hashC(n>>24);
|
||||
return *this;
|
||||
}
|
||||
VHashFnv& hash(uint16_t n) {
|
||||
hashC(n>>0); hashC(n>>8);
|
||||
return *this;
|
||||
}
|
||||
VHashFnv& hash(uint8_t n) { hashC(n); return *this; }
|
||||
VHashFnv& hash(int n) { hashC((vluint64_t)n); return *this; }
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
||||
#endif // guard
|
||||
+14
-3
@@ -53,14 +53,14 @@ private:
|
||||
VSymEnt* m_parentp; // Table that created this table, dot notation needed to resolve into it
|
||||
AstPackage* m_packagep; // Package node is in (for V3LinkDot, unused here)
|
||||
string m_symPrefix; // String to prefix symbols with (for V3LinkDot, unused here)
|
||||
#if 0 // debug
|
||||
#ifdef VL_DEBUG
|
||||
static int debug() {
|
||||
static int level = -1;
|
||||
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel("V3LinkDot.cpp");
|
||||
return level;
|
||||
}
|
||||
#else
|
||||
static int debug() { return 0; } // NOT runtime, too hot of a function
|
||||
static inline int debug() { return 0; } // NOT runtime, too hot of a function
|
||||
#endif
|
||||
public:
|
||||
void dumpIterate(ostream& os, VSymMap& doneSymsr, const string& indent, int numLevels, const string& searchName) {
|
||||
@@ -87,7 +87,18 @@ public:
|
||||
|
||||
// METHODS
|
||||
VSymEnt(VSymGraph* graphp, AstNode* nodep); // Below
|
||||
~VSymEnt() {}
|
||||
~VSymEnt() {
|
||||
// Change links so we coredump if used
|
||||
#ifdef VL_DEBUG
|
||||
m_nodep = (AstNode*)1;
|
||||
m_fallbackp = (VSymEnt*)1;
|
||||
m_parentp = (VSymEnt*)1;
|
||||
m_packagep = (AstPackage*)1;
|
||||
#endif
|
||||
}
|
||||
#if defined(VL_DEBUG) && !defined(VL_LEAK_CHECKS)
|
||||
void operator delete(void* objp, size_t size) {} // For testing, leak so above destructor 1 assignments work
|
||||
#endif
|
||||
void fallbackp(VSymEnt* entp) { m_fallbackp = entp; }
|
||||
void parentp(VSymEnt* entp) { m_parentp = entp; }
|
||||
VSymEnt* parentp() const { return m_parentp; }
|
||||
|
||||
+1
-1
@@ -666,7 +666,7 @@ private:
|
||||
// We could use 64-bits of a MD5/SHA hash rather than a string here,
|
||||
// but the compare is only done on first call then memoized, so it's not worth optimizing.
|
||||
string stmt;
|
||||
stmt += "static int __Vfuncnum = -1;\n";
|
||||
stmt += "static int __Vfuncnum = -1;\n"; // Static doesn't need save-restore as if below will re-fill proper value
|
||||
// First time init (faster than what the compiler does if we did a singleton
|
||||
stmt += "if (VL_UNLIKELY(__Vfuncnum==-1)) { __Vfuncnum = Verilated::exportFuncNum(\""+nodep->cname()+"\"); }\n";
|
||||
// If the find fails, it will throw an error
|
||||
|
||||
+2
-1
@@ -36,6 +36,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "V3Global.h"
|
||||
#include "V3String.h"
|
||||
#include "V3Undriven.h"
|
||||
#include "V3Ast.h"
|
||||
|
||||
@@ -135,7 +136,7 @@ public:
|
||||
bool unusedMatch(AstVar* nodep) {
|
||||
const char* regexpp = v3Global.opt.unusedRegexp().c_str();
|
||||
if (!regexpp || !*regexpp) return false;
|
||||
return V3Options::wildmatch(nodep->prettyName().c_str(), regexpp);
|
||||
return VString::wildmatch(nodep->prettyName().c_str(), regexpp);
|
||||
}
|
||||
void reportViolations() {
|
||||
// Combine bits into overall state
|
||||
|
||||
+166
-23
@@ -119,6 +119,7 @@ private:
|
||||
AstFunc* m_funcp; // Current function
|
||||
AstInitial* m_initialp; // Current initial block
|
||||
AstAttrOf* m_attrp; // Current attribute
|
||||
AstNodeDType* m_assDTypep; // Assign LHS data type for assignment pattern
|
||||
bool m_doGenerate; // Do errors later inside generate statement
|
||||
|
||||
// CLASSES
|
||||
@@ -995,6 +996,132 @@ private:
|
||||
pushDeletep(nodep); nodep=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstPattern* nodep, AstNUser* vup) {
|
||||
if (nodep->didWidthAndSet()) return;
|
||||
UINFO(9,"PATTERN "<<nodep<<endl);
|
||||
AstNodeDType* oldAssDTypep = m_assDTypep;
|
||||
{
|
||||
if (!m_assDTypep) nodep->v3error("Unsupported/Illegal: Assignment pattern not underneath an assignment");
|
||||
m_assDTypep = m_assDTypep->skipRefp();
|
||||
UINFO(9," adtypep "<<m_assDTypep<<endl);
|
||||
nodep->dtypep(m_assDTypep);
|
||||
for (AstPatMember* patp = nodep->itemsp()->castPatMember(); patp; patp = patp->nextp()->castPatMember()) {
|
||||
// Determine replication count, and replicate initial value as widths need to be individually determined
|
||||
int times = visitPatMemberRep(patp);
|
||||
for (int i=1; i<times; i++) {
|
||||
AstNode* newp = patp->cloneTree(false);
|
||||
patp->addNextHere(newp);
|
||||
// This loop will see the new elements as part of nextp()
|
||||
}
|
||||
}
|
||||
AstPatMember* defaultp = NULL;
|
||||
for (AstPatMember* patp = nodep->itemsp()->castPatMember(); patp; patp = patp->nextp()->castPatMember()) {
|
||||
if (patp->isDefault()) {
|
||||
if (defaultp) nodep->v3error("Multiple '{ default: } clauses");
|
||||
defaultp = patp;
|
||||
patp->unlinkFrBack();
|
||||
}
|
||||
}
|
||||
if (AstNodeClassDType* classp = m_assDTypep->castNodeClassDType()) {
|
||||
// Due to "default" and tagged patterns, we need to determine
|
||||
// which member each AstPatMember corresponds to before we can
|
||||
// determine the dtypep for that PatMember's value, and then
|
||||
// width the initial value appropriately.
|
||||
typedef map<AstMemberDType*,AstPatMember*> PatMap;
|
||||
PatMap patmap;
|
||||
{
|
||||
AstMemberDType* memp = classp->membersp();
|
||||
AstPatMember* patp = nodep->itemsp()->castPatMember();
|
||||
for (; memp || patp; ) {
|
||||
if (patp) {
|
||||
if (patp->keyp()) {
|
||||
if (AstText* textp = patp->keyp()->castText()) {
|
||||
memp = classp->findMember(textp->text());
|
||||
if (!memp) {
|
||||
patp->keyp()->v3error("Assignment pattern key '"<<textp->text()<<"' not found as member");
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
patp->keyp()->v3error("Assignment pattern key not supported/understood: "<<patp->keyp()->prettyTypeName());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (memp && !patp) {
|
||||
// Missing init elements, warn below
|
||||
memp=NULL; patp=NULL; break;
|
||||
} else if (!memp && patp) { patp->v3error("Assignment pattern contains too many elements");
|
||||
memp=NULL; patp=NULL; break;
|
||||
} else {
|
||||
patmap.insert(make_pair(memp, patp));
|
||||
}
|
||||
// Next
|
||||
if (memp) memp = memp->nextp()->castMemberDType();
|
||||
if (patp) patp = patp->nextp()->castPatMember();
|
||||
}
|
||||
}
|
||||
AstNode* newp = NULL;
|
||||
for (AstMemberDType* memp = classp->membersp(); memp; memp=memp->nextp()->castMemberDType()) {
|
||||
PatMap::iterator it = patmap.find(memp);
|
||||
AstPatMember* newpatp = NULL;
|
||||
AstPatMember* patp = NULL;
|
||||
if (it == patmap.end()) {
|
||||
if (defaultp) {
|
||||
newpatp = defaultp->cloneTree(false);
|
||||
patp = newpatp;
|
||||
}
|
||||
else {
|
||||
patp->v3error("Assignment pattern missed initializing elements: "<<memp->prettyTypeName());
|
||||
}
|
||||
} else {
|
||||
patp = it->second;
|
||||
}
|
||||
// Determine initial values
|
||||
m_assDTypep = memp;
|
||||
patp->dtypep(memp);
|
||||
patp->accept(*this,WidthVP(patp->width(),patp->width(),BOTH).p());
|
||||
// Convert to concat for now
|
||||
if (!newp) newp = patp->lhsp()->unlinkFrBack();
|
||||
else {
|
||||
AstConcat* concatp = new AstConcat(patp->fileline(), newp, patp->lhsp()->unlinkFrBack());
|
||||
newp = concatp;
|
||||
newp->dtypeSetLogicSized(concatp->lhsp()->width()+concatp->rhsp()->width(),
|
||||
concatp->lhsp()->width()+concatp->rhsp()->width(),
|
||||
nodep->dtypep()->numeric());
|
||||
}
|
||||
if (newpatp) pushDeletep(newpatp);
|
||||
}
|
||||
if (newp) nodep->replaceWith(newp);
|
||||
else nodep->v3error("Assignment pattern with no members");
|
||||
pushDeletep(nodep); nodep = NULL; // Deletes defaultp also, if present
|
||||
} else {
|
||||
nodep->v3error("Unsupported: Assignment pattern applies against non struct/union: "<<m_assDTypep->prettyTypeName());
|
||||
}
|
||||
}
|
||||
m_assDTypep = oldAssDTypep;
|
||||
}
|
||||
virtual void visit(AstPatMember* nodep, AstNUser* vup) {
|
||||
if (!nodep->dtypep()) nodep->v3fatalSrc("Pattern member type not assigned by AstPattern visitor");
|
||||
if (!m_assDTypep) nodep->v3error("Unsupported/Illegal: Assignment pattern member not underneath an assignment");
|
||||
nodep->lhsp()->dtypeFrom(nodep);
|
||||
nodep->iterateChildren(*this,WidthVP(nodep->dtypep()->width(),nodep->dtypep()->width(),BOTH).p());
|
||||
widthCheck(nodep,"LHS",nodep->lhsp(),nodep->width(),nodep->width());
|
||||
}
|
||||
int visitPatMemberRep(AstPatMember* nodep) {
|
||||
uint32_t times = 1;
|
||||
if (nodep->repp()) { // else repp()==NULL shorthand for rep count 1
|
||||
nodep->repp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||
checkCvtUS(nodep->repp());
|
||||
V3Const::constifyParamsEdit(nodep->repp()); // repp may change
|
||||
AstConst* constp = nodep->repp()->castConst();
|
||||
if (!constp) { nodep->v3error("Replication value isn't a constant."); times=0; }
|
||||
else times = constp->toUInt();
|
||||
if (times==0) { nodep->v3error("Pattern replication value of 0 is not legal."); times=1; }
|
||||
nodep->repp()->unlinkFrBackWithNext()->deleteTree(); // Done with replicate before cloning
|
||||
}
|
||||
return times;
|
||||
}
|
||||
|
||||
virtual void visit(AstPslClocked* nodep, AstNUser*) {
|
||||
nodep->propp()->iterateAndNext(*this,WidthVP(1,1,BOTH).p());
|
||||
nodep->sensesp()->iterateAndNext(*this);
|
||||
@@ -1077,27 +1204,32 @@ private:
|
||||
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
|
||||
// TOP LEVEL NODE
|
||||
//if (debug()) nodep->dumpTree(cout," AssignPre: ");
|
||||
nodep->lhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||
nodep->rhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,PRELIM).p());
|
||||
if (!nodep->lhsp()->dtypep()) nodep->v3fatalSrc("How can LHS be untyped?");
|
||||
if (!nodep->lhsp()->dtypep()->widthSized()) nodep->v3fatalSrc("How can LHS be unsized?");
|
||||
if (!nodep->lhsp()->isDouble() && nodep->rhsp()->isDouble()) {
|
||||
spliceCvtS(nodep->rhsp(), false); // Round RHS
|
||||
} else if (nodep->lhsp()->isDouble() && !nodep->rhsp()->isDouble()) {
|
||||
spliceCvtD(nodep->rhsp());
|
||||
AstNodeDType* oldAssDTypep = m_assDTypep;
|
||||
{
|
||||
nodep->lhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||
if (!nodep->lhsp()->dtypep()) nodep->v3fatalSrc("How can LHS be untyped?");
|
||||
if (!nodep->lhsp()->dtypep()->widthSized()) nodep->v3fatalSrc("How can LHS be unsized?");
|
||||
m_assDTypep = nodep->lhsp()->dtypep();
|
||||
nodep->rhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,PRELIM).p());
|
||||
if (!nodep->lhsp()->isDouble() && nodep->rhsp()->isDouble()) {
|
||||
spliceCvtS(nodep->rhsp(), false); // Round RHS
|
||||
} else if (nodep->lhsp()->isDouble() && !nodep->rhsp()->isDouble()) {
|
||||
spliceCvtD(nodep->rhsp());
|
||||
}
|
||||
int awidth = nodep->lhsp()->width();
|
||||
if (awidth==0) {
|
||||
awidth = nodep->rhsp()->width(); // Parameters can propagate by unsized assignment
|
||||
}
|
||||
nodep->rhsp()->iterateAndNext(*this,WidthVP(awidth,awidth,FINAL).p());
|
||||
nodep->dtypeFrom(nodep->lhsp());
|
||||
nodep->dtypeChgWidth(awidth,awidth); // We know the assign will truncate, so rather
|
||||
// than using "width" and have the optimizer truncate the result, we do
|
||||
// it using the normal width reduction checks.
|
||||
//UINFO(0,"aw "<<awidth<<" w"<<nodep->rhsp()->width()<<" m"<<nodep->rhsp()->widthMin()<<endl);
|
||||
widthCheck(nodep,"Assign RHS",nodep->rhsp(),awidth,awidth);
|
||||
//if (debug()) nodep->dumpTree(cout," AssignOut: ");
|
||||
}
|
||||
int awidth = nodep->lhsp()->width();
|
||||
if (awidth==0) {
|
||||
awidth = nodep->rhsp()->width(); // Parameters can propagate by unsized assignment
|
||||
}
|
||||
nodep->rhsp()->iterateAndNext(*this,WidthVP(awidth,awidth,FINAL).p());
|
||||
nodep->dtypeFrom(nodep->lhsp());
|
||||
nodep->dtypeChgWidth(awidth,awidth); // We know the assign will truncate, so rather
|
||||
// than using "width" and have the optimizer truncate the result, we do
|
||||
// it using the normal width reduction checks.
|
||||
//UINFO(0,"aw "<<awidth<<" w"<<nodep->rhsp()->width()<<" m"<<nodep->rhsp()->widthMin()<<endl);
|
||||
widthCheck(nodep,"Assign RHS",nodep->rhsp(),awidth,awidth);
|
||||
//if (debug()) nodep->dumpTree(cout," AssignOut: ");
|
||||
m_assDTypep = oldAssDTypep;
|
||||
}
|
||||
virtual void visit(AstSFormatF* nodep, AstNUser*) {
|
||||
// Excludes NodeDisplay, see below
|
||||
@@ -1689,9 +1821,19 @@ private:
|
||||
int width=nodep->width(); int ewidth=nodep->widthMin();
|
||||
nodep->lhsp()->iterateAndNext(*this,WidthVP(width,ewidth,FINAL).p());
|
||||
widthCheck(nodep,"LHS",nodep->lhsp(),width,ewidth);
|
||||
if (nodep->rhsp()->width()>32)
|
||||
nodep->rhsp()->v3error("Unsupported: Shifting of by over 32-bit number isn't supported."
|
||||
<<" (This isn't a shift of 32 bits, but a shift of 2^32, or 4 billion!)\n");
|
||||
if (nodep->rhsp()->width()>32) {
|
||||
AstConst* shiftp = nodep->rhsp()->castConst();
|
||||
if (shiftp && shiftp->num().mostSetBitP1() <= 32) {
|
||||
// If (number)<<96'h1, then make it into (number)<<32'h1
|
||||
V3Number num (shiftp->fileline(), 32, 0); num.opAssign(shiftp->num());
|
||||
AstNode* shiftp = nodep->rhsp();
|
||||
nodep->rhsp()->replaceWith(new AstConst(shiftp->fileline(), num));
|
||||
shiftp->deleteTree(); shiftp=NULL;
|
||||
} else {
|
||||
nodep->rhsp()->v3error("Unsupported: Shifting of by over 32-bit number isn't supported."
|
||||
<<" (This isn't a shift of 32 bits, but a shift of 2^32, or 4 billion!)\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
return nodep; // May edit
|
||||
}
|
||||
@@ -2200,6 +2342,7 @@ public:
|
||||
m_funcp = NULL;
|
||||
m_initialp = NULL;
|
||||
m_attrp = NULL;
|
||||
m_assDTypep = NULL;
|
||||
m_doGenerate = doGenerate;
|
||||
}
|
||||
AstNode* mainAcceptEdit(AstNode* nodep) {
|
||||
|
||||
+4
-2
@@ -70,6 +70,7 @@
|
||||
#include "V3Order.h"
|
||||
#include "V3Param.h"
|
||||
#include "V3Parse.h"
|
||||
#include "V3ParseSym.h"
|
||||
#include "V3PreShell.h"
|
||||
#include "V3Premit.h"
|
||||
#include "V3Scope.h"
|
||||
@@ -111,8 +112,9 @@ void V3Global::readFiles() {
|
||||
AstUser4InUse inuser4;
|
||||
|
||||
V3InFilter filter (v3Global.opt.pipeFilter());
|
||||
V3ParseSym parseSyms (v3Global.rootp()); // Symbol table must be common across all parsing
|
||||
|
||||
V3Parse parser (v3Global.rootp(), &filter);
|
||||
V3Parse parser (v3Global.rootp(), &filter, &parseSyms);
|
||||
// Read top module
|
||||
for (V3StringList::const_iterator it = v3Global.opt.vFiles().begin();
|
||||
it != v3Global.opt.vFiles().end(); ++it) {
|
||||
@@ -135,7 +137,7 @@ void V3Global::readFiles() {
|
||||
|
||||
if (!v3Global.opt.preprocOnly()) {
|
||||
// Resolve all modules cells refer to
|
||||
V3LinkCells::link(v3Global.rootp(), &filter);
|
||||
V3LinkCells::link(v3Global.rootp(), &filter, &parseSyms);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+150
-34
@@ -208,6 +208,9 @@ class AstSenTree;
|
||||
%token<strp> yaID__LEX "IDENTIFIER-in-lex"
|
||||
%token<strp> yaID__aPACKAGE "PACKAGE-IDENTIFIER"
|
||||
%token<strp> yaID__aTYPE "TYPE-IDENTIFIER"
|
||||
// Can't predecode aFUNCTION, can declare after use
|
||||
// Can't predecode aINTERFACE, can declare after use
|
||||
// Can't predecode aTASK, can declare after use
|
||||
|
||||
// IEEE: integral_number
|
||||
%token<nump> yaINTNUM "INTEGER NUMBER"
|
||||
@@ -631,6 +634,7 @@ descriptionList: // IEEE: part of source_text
|
||||
|
||||
description: // ==IEEE: description
|
||||
module_declaration { }
|
||||
// // udp_declaration moved into module_declaration
|
||||
//UNSUP interface_declaration { }
|
||||
| program_declaration { }
|
||||
| package_declaration { }
|
||||
@@ -644,6 +648,7 @@ description: // ==IEEE: description
|
||||
|
||||
timeunits_declaration<nodep>: // ==IEEE: timeunits_declaration
|
||||
yTIMEUNIT yaTIMENUM ';' { $$ = NULL; }
|
||||
| yTIMEUNIT yaTIMENUM '/' yaTIMENUM ';' { $$ = NULL; }
|
||||
| yTIMEPRECISION yaTIMENUM ';' { $$ = NULL; }
|
||||
;
|
||||
|
||||
@@ -681,6 +686,7 @@ package_itemList<nodep>: // IEEE: { package_item }
|
||||
package_item<nodep>: // ==IEEE: package_item
|
||||
package_or_generate_item_declaration { $$ = $1; }
|
||||
//UNSUP anonymous_program { $$ = $1; }
|
||||
//UNSUP package_export_declaration { $$ = $1; }
|
||||
| timeunits_declaration { $$ = $1; }
|
||||
;
|
||||
|
||||
@@ -689,15 +695,16 @@ package_or_generate_item_declaration<nodep>: // ==IEEE: package_or_generate_item
|
||||
| data_declaration { $$ = $1; }
|
||||
| task_declaration { $$ = $1; }
|
||||
| function_declaration { $$ = $1; }
|
||||
//UNSUP checker_declaration { $$ = $1; }
|
||||
| dpi_import_export { $$ = $1; }
|
||||
//UNSUP extern_constraint_declaration { $$ = $1; }
|
||||
//UNSUP class_declaration { $$ = $1; }
|
||||
// // class_constructor_declaration is part of function_declaration
|
||||
| local_parameter_declaration ';' { $$ = $1; }
|
||||
| parameter_declaration ';' { $$ = $1; }
|
||||
| local_parameter_declaration { $$ = $1; }
|
||||
//UNSUP covergroup_declaration { $$ = $1; }
|
||||
//UNSUP overload_declaration { $$ = $1; }
|
||||
//UNSUP concurrent_assertion_item_declaration { $$ = $1; }
|
||||
//UNSUP assertion_item_declaration { $$ = $1; }
|
||||
| ';' { $$ = NULL; }
|
||||
;
|
||||
|
||||
@@ -822,13 +829,17 @@ port<nodep>: // ==IEEE: port
|
||||
// // IEEE: interface_port_header port_identifier { unpacked_dimension }
|
||||
// // Expanded interface_port_header
|
||||
// // We use instantCb here because the non-port form looks just like a module instantiation
|
||||
//UNSUP portDirNetE id/*interface*/ idAny/*port*/ rangeListE sigAttrListE { VARDTYPE($2); VARDONEA($<fl>3, $3, $4); PARSEP->instantCb($<fl>2, $2, $3, $4); PINNUMINC(); }
|
||||
//UNSUP portDirNetE yINTERFACE idAny/*port*/ rangeListE sigAttrListE { VARDTYPE($2); VARDONEA($<fl>3, $3, $4); PINNUMINC(); }
|
||||
//UNSUP portDirNetE id/*interface*/ '.' idAny/*modport*/ idAny/*port*/ rangeListE sigAttrListE { VARDTYPE($2); VARDONEA($<fl>5, $5, $6); PARSEP->instantCb($<fl>2, $2, $5, $6); PINNUMINC(); }
|
||||
//UNSUP portDirNetE yINTERFACE '.' idAny/*modport*/ idAny/*port*/ rangeListE sigAttrListE { VARDTYPE($2); VARDONEA($<fl>5, $5, $6); PINNUMINC(); }
|
||||
//UNSUP portDirNetE id/*interface*/ idAny/*port*/ rangeListE sigAttrListE
|
||||
//UNSUP { VARDTYPE($2); VARDONEA($<fl>3, $3, $4); PARSEP->instantCb($<fl>2, $2, $3, $4); PINNUMINC(); }
|
||||
//UNSUP portDirNetE yINTERFACE idAny/*port*/ rangeListE sigAttrListE
|
||||
//UNSUP { VARDTYPE($2); VARDONEA($<fl>3, $3, $4); PINNUMINC(); }
|
||||
//UNSUP portDirNetE id/*interface*/ '.' idAny/*modport*/ idAny/*port*/ rangeListE sigAttrListE
|
||||
//UNSUP { VARDTYPE($2); VARDONEA($<fl>5, $5, $6); PARSEP->instantCb($<fl>2, $2, $5, $6); PINNUMINC(); }
|
||||
//UNSUP portDirNetE yINTERFACE '.' idAny/*modport*/ idAny/*port*/ rangeListE sigAttrListE
|
||||
//UNSUP { VARDTYPE($2); VARDONEA($<fl>5, $5, $6); PINNUMINC(); }
|
||||
//
|
||||
// // IEEE: ansi_port_declaration, with [port_direction] removed
|
||||
// // IEEE: [ net_port_header | interface_port_header ] port_identifier { unpacked_dimension }
|
||||
// // IEEE: [ net_port_header | interface_port_header ] port_identifier { unpacked_dimension } [ '=' constant_expression ]
|
||||
// // IEEE: [ net_port_header | variable_port_header ] '.' port_identifier '(' [ expression ] ')'
|
||||
// // IEEE: [ variable_port_header ] port_identifier { variable_dimension } [ '=' constant_expression ]
|
||||
// // Substitute net_port_header = [ port_direction ] net_port_type
|
||||
@@ -852,11 +863,16 @@ port<nodep>: // ==IEEE: port
|
||||
//
|
||||
// // Note implicit rules looks just line declaring additional followon port
|
||||
// // No VARDECL("port") for implicit, as we don't want to declare variables for them
|
||||
//UNSUP portDirNetE data_type '.' portSig '(' portAssignExprE ')' sigAttrListE { UNSUP }
|
||||
//UNSUP portDirNetE yVAR data_type '.' portSig '(' portAssignExprE ')' sigAttrListE { UNSUP }
|
||||
//UNSUP portDirNetE yVAR implicit_type '.' portSig '(' portAssignExprE ')' sigAttrListE { UNSUP }
|
||||
//UNSUP portDirNetE signingE rangeList '.' portSig '(' portAssignExprE ')' sigAttrListE { UNSUP }
|
||||
//UNSUP portDirNetE /*implicit*/ '.' portSig '(' portAssignExprE ')' sigAttrListE { UNSUP }
|
||||
//UNSUP portDirNetE data_type '.' portSig '(' portAssignExprE ')' sigAttrListE
|
||||
//UNSUP { UNSUP }
|
||||
//UNSUP portDirNetE yVAR data_type '.' portSig '(' portAssignExprE ')' sigAttrListE
|
||||
//UNSUP { UNSUP }
|
||||
//UNSUP portDirNetE yVAR implicit_type '.' portSig '(' portAssignExprE ')' sigAttrListE
|
||||
//UNSUP { UNSUP }
|
||||
//UNSUP portDirNetE signingE rangeList '.' portSig '(' portAssignExprE ')' sigAttrListE
|
||||
//UNSUP { UNSUP }
|
||||
//UNSUP portDirNetE /*implicit*/ '.' portSig '(' portAssignExprE ')' sigAttrListE
|
||||
//UNSUP { UNSUP }
|
||||
//
|
||||
portDirNetE data_type portSig variable_dimensionListE sigAttrListE
|
||||
{ $$=$3; VARDTYPE($2); $$->addNextNull(VARDONEP($$,$4,$5)); }
|
||||
@@ -955,6 +971,7 @@ program_generate_item<nodep>: // ==IEEE: program_generate_item
|
||||
loop_generate_construct { $$ = $1; }
|
||||
| conditional_generate_construct { $$ = $1; }
|
||||
| generate_region { $$ = $1; }
|
||||
//UNSUP elaboration_system_task { $$ = $1; }
|
||||
;
|
||||
|
||||
//************************************************
|
||||
@@ -977,7 +994,7 @@ genvar_identifierDecl<varp>: // IEEE: genvar_identifier (for declaration)
|
||||
|
||||
local_parameter_declaration<nodep>: // IEEE: local_parameter_declaration
|
||||
// // See notes in parameter_declaration
|
||||
local_parameter_declarationFront list_of_param_assignments ';' { $$ = $2; }
|
||||
local_parameter_declarationFront list_of_param_assignments { $$ = $2; }
|
||||
;
|
||||
|
||||
parameter_declaration<nodep>: // IEEE: parameter_declaration
|
||||
@@ -1471,7 +1488,7 @@ non_port_module_item<nodep>: // ==IEEE: non_port_module_item
|
||||
| yaSCDTOR { $$ = new AstScDtor($<fl>1,*$1); }
|
||||
| yVL_INLINE_MODULE { $$ = new AstPragma($1,AstPragmaType::INLINE_MODULE); }
|
||||
| yVL_NO_INLINE_MODULE { $$ = new AstPragma($1,AstPragmaType::NO_INLINE_MODULE); }
|
||||
| yVL_PUBLIC_MODULE { $$ = new AstPragma($1,AstPragmaType::PUBLIC_MODULE); }
|
||||
| yVL_PUBLIC_MODULE { $$ = new AstPragma($1,AstPragmaType::PUBLIC_MODULE); v3Global.dpi(true); }
|
||||
;
|
||||
|
||||
module_or_generate_item<nodep>: // ==IEEE: module_or_generate_item
|
||||
@@ -1480,7 +1497,8 @@ module_or_generate_item<nodep>: // ==IEEE: module_or_generate_item
|
||||
// // IEEE: gate_instantiation + udp_instantiation + module_instantiation
|
||||
// // not here, see etcInst in module_common_item
|
||||
// // We joined udp & module definitions, so this goes here
|
||||
| table { $$ = $1; }
|
||||
| combinational_body { $$ = $1; }
|
||||
// // This module_common_item shared with interface_or_generate_item:module_common_item
|
||||
| module_common_item { $$ = $1; }
|
||||
;
|
||||
|
||||
@@ -1530,6 +1548,11 @@ module_or_generate_item_declaration<nodep>: // ==IEEE: module_or_generate_item_d
|
||||
|
||||
//************************************************
|
||||
// Generates
|
||||
//
|
||||
// Way down in generate_item is speced a difference between module,
|
||||
// interface and checker generates. modules and interfaces are almost
|
||||
// identical (minus DEFPARAMs) so we overlap them. Checkers are too
|
||||
// different, so we copy all rules for checkers.
|
||||
|
||||
generate_region<nodep>: // ==IEEE: generate_region
|
||||
yGENERATE genItemList yENDGENERATE { $$ = new AstGenerate($1, $2); }
|
||||
@@ -1554,13 +1577,13 @@ genItemBegin<nodep>: // IEEE: part of generate_block
|
||||
;
|
||||
|
||||
genItemOrBegin<nodep>: // Not in IEEE, but our begin isn't under generate_item
|
||||
generate_item { $$ = $1; }
|
||||
| genItemBegin { $$ = $1; }
|
||||
~c~generate_item { $$ = $1; }
|
||||
| ~c~genItemBegin { $$ = $1; }
|
||||
;
|
||||
|
||||
genItemList<nodep>:
|
||||
genItemOrBegin { $$ = $1; }
|
||||
| genItemList genItemOrBegin { $$ = $1->addNextNull($2); }
|
||||
~c~genItemOrBegin { $$ = $1; }
|
||||
| ~c~genItemList ~c~genItemOrBegin { $$ = $1->addNextNull($2); }
|
||||
;
|
||||
|
||||
generate_item<nodep>: // IEEE: module_or_interface_or_generate_item
|
||||
@@ -1568,16 +1591,19 @@ generate_item<nodep>: // IEEE: module_or_interface_or_generate_item
|
||||
module_or_generate_item { $$ = $1; }
|
||||
// // Only legal when in a generate under an interface
|
||||
//UNSUP interface_or_generate_item { $$ = $1; }
|
||||
// // IEEE: checker_or_generate_item
|
||||
// // Only legal when in a generate under a checker
|
||||
// // so below in c_generate_item
|
||||
;
|
||||
|
||||
conditional_generate_construct<nodep>: // ==IEEE: conditional_generate_construct
|
||||
yCASE '(' expr ')' case_generate_itemListE yENDCASE { $$ = new AstGenCase($1,$3,$5); }
|
||||
yCASE '(' expr ')' ~c~case_generate_itemListE yENDCASE { $$ = new AstGenCase($1,$3,$5); }
|
||||
| yIF '(' expr ')' generate_block_or_null %prec prLOWER_THAN_ELSE { $$ = new AstGenIf($1,$3,$5,NULL); }
|
||||
| yIF '(' expr ')' generate_block_or_null yELSE generate_block_or_null { $$ = new AstGenIf($1,$3,$5,$7); }
|
||||
;
|
||||
|
||||
loop_generate_construct<nodep>: // ==IEEE: loop_generate_construct
|
||||
yFOR '(' genvar_initialization ';' expr ';' genvar_iteration ')' generate_block_or_null
|
||||
yFOR '(' genvar_initialization ';' expr ';' genvar_iteration ')' ~c~generate_block_or_null
|
||||
{ // Convert BEGIN(...) to BEGIN(GENFOR(...)), as we need the BEGIN to hide the local genvar
|
||||
AstBegin* lowerBegp = $9->castBegin();
|
||||
if ($9 && !lowerBegp) $9->v3fatalSrc("Child of GENFOR should have been begin");
|
||||
@@ -1633,8 +1659,8 @@ case_generate_itemListE<nodep>: // IEEE: [{ case_generate_itemList }]
|
||||
;
|
||||
|
||||
case_generate_itemList<nodep>: // IEEE: { case_generate_itemList }
|
||||
case_generate_item { $$=$1; }
|
||||
| case_generate_itemList case_generate_item { $$=$1; $1->addNext($2); }
|
||||
~c~case_generate_item { $$=$1; }
|
||||
| ~c~case_generate_itemList ~c~case_generate_item { $$=$1; $1->addNext($2); }
|
||||
;
|
||||
|
||||
case_generate_item<nodep>: // ==IEEE: case_generate_item
|
||||
@@ -1719,11 +1745,11 @@ sigAttrList<nodep>:
|
||||
sigAttr<nodep>:
|
||||
yVL_CLOCK { $$ = new AstAttrOf($1,AstAttrType::VAR_CLOCK); }
|
||||
| yVL_CLOCK_ENABLE { $$ = new AstAttrOf($1,AstAttrType::VAR_CLOCK_ENABLE); }
|
||||
| yVL_PUBLIC { $$ = new AstAttrOf($1,AstAttrType::VAR_PUBLIC); }
|
||||
| yVL_PUBLIC_FLAT { $$ = new AstAttrOf($1,AstAttrType::VAR_PUBLIC_FLAT); }
|
||||
| yVL_PUBLIC_FLAT_RD { $$ = new AstAttrOf($1,AstAttrType::VAR_PUBLIC_FLAT_RD); }
|
||||
| yVL_PUBLIC_FLAT_RW { $$ = new AstAttrOf($1,AstAttrType::VAR_PUBLIC_FLAT_RW); }
|
||||
| yVL_PUBLIC_FLAT_RW attr_event_control { $$ = new AstAttrOf($1,AstAttrType::VAR_PUBLIC_FLAT_RW);
|
||||
| yVL_PUBLIC { $$ = new AstAttrOf($1,AstAttrType::VAR_PUBLIC); v3Global.dpi(true); }
|
||||
| yVL_PUBLIC_FLAT { $$ = new AstAttrOf($1,AstAttrType::VAR_PUBLIC_FLAT); v3Global.dpi(true); }
|
||||
| yVL_PUBLIC_FLAT_RD { $$ = new AstAttrOf($1,AstAttrType::VAR_PUBLIC_FLAT_RD); v3Global.dpi(true); }
|
||||
| yVL_PUBLIC_FLAT_RW { $$ = new AstAttrOf($1,AstAttrType::VAR_PUBLIC_FLAT_RW); v3Global.dpi(true); }
|
||||
| yVL_PUBLIC_FLAT_RW attr_event_control { $$ = new AstAttrOf($1,AstAttrType::VAR_PUBLIC_FLAT_RW); v3Global.dpi(true);
|
||||
$$ = $$->addNext(new AstAlwaysPublic($1,$2,NULL)); }
|
||||
| yVL_ISOLATE_ASSIGNMENTS { $$ = new AstAttrOf($1,AstAttrType::VAR_ISOLATE_ASSIGNMENTS); }
|
||||
| yVL_SC_BV { $$ = new AstAttrOf($1,AstAttrType::VAR_SC_BV); }
|
||||
@@ -1806,6 +1832,7 @@ defparam_assignment<nodep>: // ==IEEE: defparam_assignment
|
||||
// gate (strong0) [#(delay)] [name] (pins) [, (pins)...] ; // gate_instantiation
|
||||
// program_id [#(params}] name ; // program_instantiation
|
||||
// interface_id [#(params}] name ; // interface_instantiation
|
||||
// checker_id name (pins) ; // checker_instantiation
|
||||
|
||||
etcInst<nodep>: // IEEE: module_instantiation + gate_instantiation + udp_instantiation
|
||||
instDecl { $$ = $1; }
|
||||
@@ -1940,7 +1967,7 @@ stmtBlock<nodep>: // IEEE: statement + seq_block + par_block
|
||||
|
||||
seq_block<nodep>: // ==IEEE: seq_block
|
||||
// // IEEE doesn't allow declarations in unnamed blocks, but several simulators do.
|
||||
// // So need begin's even if unnamed to scope variables down
|
||||
// // So need AstBegin's even if unnamed to scope variables down
|
||||
seq_blockFront blockDeclStmtList yEND endLabelE { $$=$1; $1->addStmtsp($2); SYMP->popScope($1); GRAMMARP->endLabel($<fl>4,$1,$4); }
|
||||
| seq_blockFront /**/ yEND endLabelE { $$=$1; SYMP->popScope($1); GRAMMARP->endLabel($<fl>3,$1,$3); }
|
||||
;
|
||||
@@ -1964,9 +1991,10 @@ block_item_declarationList<nodep>: // IEEE: [ block_item_declaration ]
|
||||
|
||||
block_item_declaration<nodep>: // ==IEEE: block_item_declaration
|
||||
data_declaration { $$ = $1; }
|
||||
| local_parameter_declaration { $$ = $1; }
|
||||
| local_parameter_declaration ';' { $$ = $1; }
|
||||
| parameter_declaration ';' { $$ = $1; }
|
||||
//UNSUP overload_declaration { $$ = $1; }
|
||||
//UNSUP let_declaration { $$ = $1; }
|
||||
;
|
||||
|
||||
stmtList<nodep>:
|
||||
@@ -1988,6 +2016,8 @@ statement_item<nodep>: // IEEE: statement_item
|
||||
foperator_assignment ';' { $$ = $1; }
|
||||
//
|
||||
// // IEEE: blocking_assignment
|
||||
// // 1800-2009 restricts LHS of assignment to new to not have a range
|
||||
// // This is ignored to avoid conflicts
|
||||
//UNSUP fexprLvalue '=' class_new ';' { UNSUP }
|
||||
//UNSUP fexprLvalue '=' dynamic_array_new ';' { UNSUP }
|
||||
//
|
||||
@@ -2058,6 +2088,7 @@ statement_item<nodep>: // IEEE: statement_item
|
||||
| yFOR '(' for_initialization expr ';' for_stepE ')' stmtBlock
|
||||
{ $$ = new AstBegin($1,"",$3); $3->addNext(new AstWhile($1, $4,$8,$6)); }
|
||||
| yDO stmtBlock yWHILE '(' expr ')' ';' { $$ = $2->cloneTree(true); $$->addNext(new AstWhile($1,$5,$2));}
|
||||
// // IEEE says array_identifier here, but dotted accepted in VMM and 1800-2009
|
||||
//UNSUP yFOREACH '(' idClassForeach/*array_id[loop_variables]*/ ')' stmt { UNSUP }
|
||||
//
|
||||
// // IEEE: jump_statement
|
||||
@@ -2188,6 +2219,71 @@ caseCondList<nodep>: // IEEE: part of case_item
|
||||
| caseCondList ',' expr { $$ = $1;$1->addNext($3); }
|
||||
;
|
||||
|
||||
patternNoExpr<nodep>: // IEEE: pattern **Excluding Expr*
|
||||
'.' id/*variable*/ { $1->v3error("Unsupported: '{} tagged patterns"); $$=NULL; }
|
||||
| yP_DOTSTAR { $1->v3error("Unsupported: '{} tagged patterns"); $$=NULL; }
|
||||
// // IEEE: "expr" excluded; expand in callers
|
||||
// // "yTAGGED id [expr]" Already part of expr
|
||||
//UNSUP yTAGGED id/*member_identifier*/ patternNoExpr { $1->v3error("Unsupported: '{} tagged patterns"); $$=NULL; }
|
||||
// // "yP_TICKBRA patternList '}'" part of expr under assignment_pattern
|
||||
;
|
||||
|
||||
patternList<nodep>: // IEEE: part of pattern
|
||||
patternOne { $$ = $1; }
|
||||
| patternList ',' patternOne { $$ = $1->addNextNull($3); }
|
||||
;
|
||||
|
||||
patternOne<nodep>: // IEEE: part of pattern
|
||||
expr { $$ = new AstPatMember($1->fileline(),$1,NULL,NULL); }
|
||||
| expr '{' argsExprList '}' { $$ = new AstPatMember($2,$3,NULL,$1); }
|
||||
| patternNoExpr { $$ = $1; }
|
||||
;
|
||||
|
||||
patternMemberList<nodep>: // IEEE: part of pattern and assignment_pattern
|
||||
patternMemberOne { $$ = $1; }
|
||||
| patternMemberList ',' patternMemberOne { $$ = $1->addNextNull($3); }
|
||||
;
|
||||
|
||||
patternMemberOne<patmemberp>: // IEEE: part of pattern and assignment_pattern
|
||||
patternKey ':' expr { $$ = new AstPatMember($2,$3,$1,NULL); }
|
||||
| patternKey ':' patternNoExpr { $2->v3error("Unsupported: '{} .* patterns"); $$=NULL; }
|
||||
// // From assignment_pattern_key
|
||||
| yDEFAULT ':' expr { $$ = new AstPatMember($2,$3,NULL,NULL); $$->isDefault(true); }
|
||||
| yDEFAULT ':' patternNoExpr { $2->v3error("Unsupported: '{} .* patterns"); $$=NULL; }
|
||||
;
|
||||
|
||||
patternKey<nodep>: // IEEE: merge structure_pattern_key, array_pattern_key, assignment_pattern_key
|
||||
// // IEEE: structure_pattern_key
|
||||
// // id/*member*/ is part of constExpr below
|
||||
//UNSUP constExpr { $$ = $1; }
|
||||
// // IEEE: assignment_pattern_key
|
||||
//UNSUP simple_type { $1->v3error("Unsupported: '{} with data type as key"); $$=$1; }
|
||||
// // simple_type reference looks like constExpr
|
||||
// // Verilator:
|
||||
// // The above expressions cause problems because "foo" may be a constant identifier
|
||||
// // (if array) or a reference to the "foo"member (if structure)
|
||||
// // So for now we only allow a true constant number, or a identifier which we treat as a structure member name
|
||||
yaINTNUM { $$ = new AstConst($<fl>1,*$1); }
|
||||
| yaFLOATNUM { $$ = new AstConst($<fl>1,AstConst::RealDouble(),$1); }
|
||||
| yaID__ETC { $$ = new AstText($<fl>1,*$1); }
|
||||
;
|
||||
|
||||
assignment_pattern<nodep>: // ==IEEE: assignment_pattern
|
||||
// This doesn't match the text of the spec. I think a : is missing, or example code needed
|
||||
// yP_TICKBRA constExpr exprList '}' { $$="'{"+$2+" "+$3"}"; }
|
||||
// // "'{ const_expression }" is same as patternList with one entry
|
||||
// // From patternNoExpr
|
||||
// // also IEEE: "''{' expression { ',' expression } '}'"
|
||||
// // matches since patternList includes expr
|
||||
yP_TICKBRA patternList '}' { $$ = new AstPattern($1,$2); }
|
||||
// // From patternNoExpr
|
||||
// // also IEEE "''{' structure_pattern_key ':' ...
|
||||
// // also IEEE "''{' array_pattern_key ':' ...
|
||||
| yP_TICKBRA patternMemberList '}' { $$ = new AstPattern($1,$2); }
|
||||
// // IEEE: Not in grammar, but in VMM
|
||||
| yP_TICKBRA '}' { $1->v3error("Unsupported: Empty '{}"); $$=NULL; }
|
||||
;
|
||||
|
||||
// "datatype id = x {, id = x }" | "yaId = x {, id=x}" is legal
|
||||
for_initialization<nodep>: // ==IEEE: for_initialization + for_variable_declaration + extra terminating ";"
|
||||
// // IEEE: for_variable_declaration
|
||||
@@ -2221,6 +2317,14 @@ taskRef<parserefp>: // IEEE: part of tf_call
|
||||
;
|
||||
|
||||
funcRef<parserefp>: // IEEE: part of tf_call
|
||||
// // package_scope/hierarchical_... is part of expr, so just need ID
|
||||
// // making-a id-is-a
|
||||
// // ----------------- ------------------
|
||||
// // tf_call tf_identifier expr (list_of_arguments)
|
||||
// // method_call(post .) function_identifier expr (list_of_arguments)
|
||||
// // property_instance property_identifier property_actual_arg
|
||||
// // sequence_instance sequence_identifier sequence_actual_arg
|
||||
// // let_expression let_identifier let_actual_arg
|
||||
idDotted '(' list_of_argumentsE ')' { $$ = new AstParseRef($1->fileline(), AstParseRefExp::PX_FTASK, "", $1, new AstFuncRef($2, "", $3)); $$->start(true); }
|
||||
| package_scopeIdFollows idDotted '(' list_of_argumentsE ')' { AstFuncRef* f=new AstFuncRef($3,"",$4); f->packagep($1); $$ = new AstParseRef($2->fileline(), AstParseRefExp::PX_FTASK, "", $2, f); $$->start(true); }
|
||||
//UNSUP: idDotted is really just id to allow dotted method calls
|
||||
@@ -2436,7 +2540,7 @@ tf_item_declaration<nodep>: // ==IEEE: tf_item_declaration
|
||||
;
|
||||
|
||||
tf_item_declarationVerilator<nodep>: // Verilator extensions
|
||||
yVL_PUBLIC { $$ = new AstPragma($1,AstPragmaType::PUBLIC_TASK); }
|
||||
yVL_PUBLIC { $$ = new AstPragma($1,AstPragmaType::PUBLIC_TASK); v3Global.dpi(true); }
|
||||
| yVL_NO_INLINE_TASK { $$ = new AstPragma($1,AstPragmaType::NO_INLINE_TASK); }
|
||||
;
|
||||
|
||||
@@ -2644,6 +2748,9 @@ expr<nodep>: // IEEE: part of expression/constant_expression/primary
|
||||
// // method_call:array_method requires a '.'
|
||||
//UNSUP ~l~expr '.' array_methodNoRoot { UNSUP }
|
||||
//
|
||||
// // IEEE: let_expression
|
||||
// // see funcRef
|
||||
//
|
||||
// // IEEE: '(' mintypmax_expression ')'
|
||||
| ~noPar__IGNORE~'(' expr ')' { $$ = $2; }
|
||||
//UNSUP ~noPar__IGNORE~'(' expr ':' expr ':' expr ')' { $$ = $4; }
|
||||
@@ -2701,11 +2808,11 @@ exprOkLvalue<nodep>: // expression that's also OK to use as a variable_lvalue
|
||||
// // IEEE: concatenation/constant_concatenation
|
||||
| '{' cateList '}' { $$ = $2; }
|
||||
// // IEEE: assignment_pattern_expression
|
||||
// // IEEE: [ assignment_pattern_expression_type ] == [ ps_type_id /ps_paremeter_id]
|
||||
// // IEEE: [ assignment_pattern_expression_type ] == [ ps_type_id /ps_paremeter_id/data_type]
|
||||
// // We allow more here than the spec requires
|
||||
//UNSUP ~l~exprScope assignment_pattern { UNSUP }
|
||||
//UNSUP data_type assignment_pattern { UNSUP }
|
||||
//UNSUP assignment_pattern { UNSUP }
|
||||
| assignment_pattern { $$ = $1; }
|
||||
//
|
||||
//UNSUP streaming_concatenation { UNSUP }
|
||||
;
|
||||
@@ -2713,6 +2820,7 @@ exprOkLvalue<nodep>: // expression that's also OK to use as a variable_lvalue
|
||||
exprScope<nodep>: // scope and variable for use to inside an expression
|
||||
// // Here we've split method_call_root | implicit_class_handle | class_scope | package_scope
|
||||
// // from the object being called and let expr's "." deal with resolving it.
|
||||
// // (note method_call_root was simplified to require a primary in 1800-2009)
|
||||
//
|
||||
// // IEEE: [ implicit_class_handle . | class_scope | package_scope ] hierarchical_identifier select
|
||||
// // Or method_call_body without parenthesis
|
||||
@@ -2968,7 +3076,7 @@ strengthSpecE: // IEEE: drive_strength + pullup_strength + pulldown_strength +
|
||||
//************************************************
|
||||
// Tables
|
||||
|
||||
table<nodep>: // IEEE: combinational_body + sequential_body
|
||||
combinational_body<nodep>: // IEEE: combinational_body + sequential_body
|
||||
yTABLE tableEntryList yENDTABLE { $$ = new AstUdpTable($1,$2); }
|
||||
;
|
||||
|
||||
@@ -3066,6 +3174,7 @@ idClassSel<parserefp>: // Misc Ref to dotted, and/or arrayed, and/or bit-range
|
||||
//UNSUP ySUPER '.' idDotted { UNSUP }
|
||||
//UNSUP yTHIS '.' ySUPER '.' idDotted { UNSUP }
|
||||
// // Expanded: package_scope idDotted
|
||||
//UNSUP class_scopeIdFollows idDotted { UNSUP }
|
||||
//UNSUP package_scopeIdFollows idDotted { UNSUP }
|
||||
;
|
||||
|
||||
@@ -3141,6 +3250,8 @@ labeledStmt<nodep>:
|
||||
concurrent_assertion_item<nodep>: // IEEE: concurrent_assertion_item
|
||||
concurrent_assertion_statement { $$ = $1; }
|
||||
| id/*block_identifier*/ ':' concurrent_assertion_statement { $$ = new AstBegin($2,*$1,$3); }
|
||||
// // IEEE: checker_instantiation
|
||||
// // identical to module_instantiation; see etcInst
|
||||
;
|
||||
|
||||
concurrent_assertion_statement<nodep>: // ==IEEE: concurrent_assertion_statement
|
||||
@@ -3187,12 +3298,15 @@ ps_type<dtypep>: // IEEE: ps_parameter_identifier | ps_type_identifier
|
||||
// Even though we looked up the type and have a AstNode* to it,
|
||||
// we can't fully resolve it because it may have been just a forward definition.
|
||||
package_scopeIdFollowsE yaID__aTYPE { $$ = new AstRefDType($<fl>2, *$2); $$->castRefDType()->packagep($1); }
|
||||
// // Simplify typing - from ps_covergroup_identifier
|
||||
//UNSUP package_scopeIdFollowsE yaID__aCOVERGROUP { $<fl>$=$<fl>1; $$=$1+$2; }
|
||||
;
|
||||
|
||||
//=== Below rules assume special scoping per above
|
||||
|
||||
package_scopeIdFollowsE<packagep>: // IEEE: [package_scope]
|
||||
// // IMPORTANT: The lexer will parse the following ID to be in the found package
|
||||
// // class_qualifier := [ yLOCAL '::' ] [ implicit_class_handle '.' class_scope ]
|
||||
/* empty */ { $$ = NULL; }
|
||||
| package_scopeIdFollows { $$ = $1; }
|
||||
;
|
||||
@@ -3204,6 +3318,8 @@ package_scopeIdFollows<packagep>: // IEEE: package_scope
|
||||
/*cont*/ yP_COLONCOLON { $$ = GRAMMARP->unitPackage($<fl>1); }
|
||||
| yaID__aPACKAGE { SYMP->nextId($<scp>1); }
|
||||
/*cont*/ yP_COLONCOLON { $$ = $<scp>1->castPackage(); }
|
||||
//UNSUP yLOCAL__COLONCOLON { PARSEP->symTableNextId($<scp>1); }
|
||||
//UNSUP /*cont*/ yP_COLONCOLON { UNSUP }
|
||||
;
|
||||
|
||||
//************************************************
|
||||
|
||||
+54
-5
@@ -20,8 +20,9 @@ use vars qw ($Debug %Vars $Driver $Fork);
|
||||
use POSIX qw(strftime);
|
||||
|
||||
$::Driver = 1;
|
||||
$::Have_Forker = 0;
|
||||
|
||||
eval "use Parallel::Forker; \$Fork=Parallel::Forker->new(use_sig_child=>1);";
|
||||
eval "use Parallel::Forker; \$Fork=Parallel::Forker->new(use_sig_child=>1); \$::Have_Forker=1;";
|
||||
$Fork = Forker->new(use_sig_child=>1) if !$Fork;
|
||||
$SIG{CHLD} = sub { $Fork->sig_child() if $Fork; };
|
||||
$SIG{TERM} = sub { $Fork->kill_tree_all('TERM') if $Fork; die "Quitting...\n"; };
|
||||
@@ -185,7 +186,8 @@ sub one_test {
|
||||
if ($opt_stop) { die "%Error: --stop and errors found\n"; }
|
||||
}
|
||||
$LeftCnt--;
|
||||
print STDERR "==SUMMARY: Left $LeftCnt Passed $OkCnt Unsup $UnsupCnt Skipped $SkipCnt Failed $FailCnt\n";
|
||||
my $LeftMsg = $::Have_Forker ? $LeftCnt : "NO-FORKER";
|
||||
print STDERR "==SUMMARY: Left $LeftMsg Passed $OkCnt Unsup $UnsupCnt Skipped $SkipCnt Failed $FailCnt\n";
|
||||
},
|
||||
)->ready();
|
||||
}
|
||||
@@ -476,6 +478,7 @@ sub compile_vlt_flags {
|
||||
$self->{sc} = 1 if ($checkflags =~ /-sc\b/);
|
||||
$self->{sp} = 1 if ($checkflags =~ /-sp\b/);
|
||||
$self->{trace} = 1 if ($opt_trace || $checkflags =~ /-trace\b/);
|
||||
$self->{savable} = 1 if ($checkflags =~ /-savable\b/);
|
||||
$self->{coverage} = 1 if ($checkflags =~ /-coverage\b/);
|
||||
|
||||
my @verilator_flags = @{$param{verilator_flags}};
|
||||
@@ -963,15 +966,39 @@ sub _make_main {
|
||||
print $fh "#include \"systemc.h\"\n" if $self->sc;
|
||||
print $fh "#include \"systemperl.h\"\n" if $self->sp;
|
||||
print $fh "#include \"verilated_vcd_c.h\"\n" if $self->{trace} && !$self->sp;
|
||||
print $fh "#include \"verilated_save.h\"\n" if $self->{savable};
|
||||
print $fh "#include \"SpTraceVcd.h\"\n" if $self->{trace} && $self->sp;
|
||||
|
||||
print $fh "$VM_PREFIX * topp;\n";
|
||||
if (!$self->sc_or_sp) {
|
||||
print $fh "unsigned int main_time = false;\n";
|
||||
print $fh "vluint64_t main_time = false;\n";
|
||||
print $fh "double sc_time_stamp () {\n";
|
||||
print $fh " return main_time;\n";
|
||||
print $fh "}\n";
|
||||
}
|
||||
|
||||
if ($self->{savable}) {
|
||||
$fh->print("\n");
|
||||
$fh->print("void save_model(const char* filenamep) {\n");
|
||||
$fh->print(" VL_PRINTF(\"Saving model to '%s'\\n\", filenamep);\n");
|
||||
$fh->print(" VerilatedSave os;\n");
|
||||
$fh->print(" os.open(filenamep);\n");
|
||||
$fh->print(" os << main_time;\n");
|
||||
$fh->print(" os << *topp;\n");
|
||||
$fh->print(" os.close();\n");
|
||||
$fh->print("}\n");
|
||||
$fh->print("\n");
|
||||
$fh->print("void restore_model(const char* filenamep) {\n");
|
||||
$fh->print(" VL_PRINTF(\"Restoring model from '%s'\\n\", filenamep);\n");
|
||||
$fh->print(" VerilatedRestore os;\n");
|
||||
$fh->print(" os.open(filenamep);\n");
|
||||
$fh->print(" os >> main_time;\n");
|
||||
$fh->print(" os >> *topp;\n");
|
||||
$fh->print(" os.close();\n");
|
||||
$fh->print("}\n");
|
||||
}
|
||||
|
||||
#### Main
|
||||
if ($self->sc_or_sp) {
|
||||
print $fh "extern int sc_main(int argc, char **argv);\n";
|
||||
print $fh "int sc_main(int argc, char **argv) {\n";
|
||||
@@ -1017,9 +1044,24 @@ sub _make_main {
|
||||
$fh->print("#endif\n");
|
||||
}
|
||||
|
||||
print $fh " ${set}fastclk = false;\n" if $self->{inputs}{fastclk};
|
||||
print $fh " ${set}clk = false;\n" if $self->{inputs}{clk};
|
||||
if ($self->{savable}) {
|
||||
$fh->print(" const char* save_time_strp = Verilated::commandArgsPlusMatch(\"save_time=\");\n");
|
||||
$fh->print(" const char* save_restore_strp = Verilated::commandArgsPlusMatch(\"save_restore=\");\n");
|
||||
$fh->print(" unsigned int save_time = !save_time_strp[0] ? 0 : atoi(save_time_strp+strlen(\"+save_time=\"));\n");
|
||||
$fh->print(" unsigned int save_restore = !save_restore_strp[0] ? 0 : 1;\n");
|
||||
}
|
||||
|
||||
if ($self->{savable}) {
|
||||
$fh->print(" if (save_restore) {\n");
|
||||
$fh->print(" restore_model(\"$self->{obj_dir}/saved.vltsv\");\n");
|
||||
$fh->print(" } else {\n");
|
||||
} else {
|
||||
$fh->print(" {\n");
|
||||
}
|
||||
print $fh " ${set}fastclk = false;\n" if $self->{inputs}{fastclk};
|
||||
print $fh " ${set}clk = false;\n" if $self->{inputs}{clk};
|
||||
_print_advance_time($self, $fh, 10);
|
||||
print $fh " }\n";
|
||||
|
||||
print $fh " while (sc_time_stamp() < sim_time && !Verilated::gotFinish()) {\n";
|
||||
for (my $i=0; $i<5; $i++) {
|
||||
@@ -1032,6 +1074,13 @@ sub _make_main {
|
||||
print $fh " ${set}clk=!${set}clk;\n";
|
||||
$action = 1;
|
||||
}
|
||||
if ($self->{savable}) {
|
||||
$fh->print(" if (sc_time_stamp() == save_time && save_time) {\n");
|
||||
$fh->print(" save_model(\"$self->{obj_dir}/saved.vltsv\");\n");
|
||||
$fh->print(" printf(\"Exiting after save_model\\n\");\n");
|
||||
$fh->print(" exit(0);\n");
|
||||
$fh->print(" }\n");
|
||||
}
|
||||
_print_advance_time($self, $fh, 1, $action);
|
||||
}
|
||||
print $fh " }\n";
|
||||
|
||||
@@ -39,86 +39,70 @@ module t (/*AUTOARG*/
|
||||
// big endian
|
||||
always @ (posedge clk)
|
||||
if (cnt[1:0]==2'd0) begin
|
||||
// initialize to defaults (all bits 1'bx)
|
||||
if (cnt[30:2]== 0) array_bg <= {WA{ {WB{1'bx}} }};
|
||||
else if (cnt[30:2]== 1) array_bg <= {WA{ {WB{1'bx}} }};
|
||||
else if (cnt[30:2]== 2) array_bg <= {WA{ {WB{1'bx}} }};
|
||||
else if (cnt[30:2]== 3) array_bg <= {WA{ {WB{1'bx}} }};
|
||||
else if (cnt[30:2]== 4) array_bg <= {WA{ {WB{1'bx}} }};
|
||||
else if (cnt[30:2]== 5) array_bg <= {WA{ {WB{1'bx}} }};
|
||||
else if (cnt[30:2]== 6) array_bg <= {WA{ {WB{1'bx}} }};
|
||||
else if (cnt[30:2]== 7) array_bg <= {WA{ {WB{1'bx}} }};
|
||||
else if (cnt[30:2]== 8) array_bg <= {WA{ {WB{1'bx}} }};
|
||||
else if (cnt[30:2]== 9) array_bg <= {WA{ {WB{1'bx}} }};
|
||||
else if (cnt[30:2]==10) array_bg <= {WA{ {WB{1'bx}} }};
|
||||
// initialize to defaults (all bits 1'b0)
|
||||
if (cnt[30:2]== 0) array_bg <= '0;
|
||||
else if (cnt[30:2]== 1) array_bg <= '0;
|
||||
else if (cnt[30:2]== 2) array_bg <= '0;
|
||||
else if (cnt[30:2]== 3) array_bg <= '0;
|
||||
else if (cnt[30:2]== 4) array_bg <= '0;
|
||||
else if (cnt[30:2]== 5) array_bg <= '0;
|
||||
else if (cnt[30:2]== 6) array_bg <= '0;
|
||||
else if (cnt[30:2]== 7) array_bg <= '0;
|
||||
else if (cnt[30:2]== 8) array_bg <= '0;
|
||||
else if (cnt[30:2]== 9) array_bg <= '0;
|
||||
else if (cnt[30:2]==10) array_bg <= '0;
|
||||
end else if (cnt[1:0]==2'd1) begin
|
||||
// write data into whole or part of the array using literals
|
||||
if (cnt[30:2]== 0) begin end
|
||||
else if (cnt[30:2]== 1) array_bg <= '{ 3 ,2 ,1, 0 };
|
||||
else if (cnt[30:2]== 2) array_bg <= '{0:4, 1:5, 2:6, 3:7};
|
||||
else if (cnt[30:2]== 3) array_bg <= '{default:13};
|
||||
else if (cnt[30:2]== 2) array_bg <= '{default:13};
|
||||
else if (cnt[30:2]== 3) array_bg <= '{0:4, 1:5, 2:6, 3:7};
|
||||
else if (cnt[30:2]== 4) array_bg <= '{2:15, default:13};
|
||||
else if (cnt[30:2]== 5) array_bg <= '{WA { {WB/2 {2'b10}} }};
|
||||
else if (cnt[30:2]== 6) array_bg <= '{WA { {3'b101, {WB/2-1{2'b10}}} }};
|
||||
else if (cnt[30:2]== 7) array_bg <= '{WA { {WB/2-1{2'b10}} }};
|
||||
else if (cnt[30:2]== 8) array_bg [WA/2-1:0 ] <= '{WA/2{ {WB/2 {2'b10}} }};
|
||||
else if (cnt[30:2]== 9) array_bg [WA -1:WA/2] <= '{WA/2{ {WB/2 {2'b01}} }};
|
||||
else if (cnt[30:2]==10) array_bg <= '{cnt+0, cnt+1, cnt+2, cnt+3};
|
||||
else if (cnt[30:2]== 5) array_bg <= '{WA { {WB {2'b10}} }};
|
||||
else if (cnt[30:2]== 6) array_bg <= '{cnt+0, cnt+1, cnt+2, cnt+3};
|
||||
end else if (cnt[1:0]==2'd2) begin
|
||||
// chack array agains expected value
|
||||
if (cnt[30:2]== 0) begin if (array_bg !== 16'bxxxxxxxxxxxxxxxx) begin $display("%b", array_bg); $stop(); end end
|
||||
if (cnt[30:2]== 0) begin if (array_bg !== 16'b0000000000000000) begin $display("%b", array_bg); $stop(); end end
|
||||
else if (cnt[30:2]== 1) begin if (array_bg !== 16'b0011001000010000) begin $display("%b", array_bg); $stop(); end end
|
||||
else if (cnt[30:2]== 2) begin if (array_bg !== 16'b0111011001010100) begin $display("%b", array_bg); $stop(); end end
|
||||
else if (cnt[30:2]== 3) begin if (array_bg !== 16'b1101110111011101) begin $display("%b", array_bg); $stop(); end end
|
||||
else if (cnt[30:2]== 2) begin if (array_bg !== 16'b1101110111011101) begin $display("%b", array_bg); $stop(); end end
|
||||
else if (cnt[30:2]== 3) begin if (array_bg !== 16'b0111011001010100) begin $display("%b", array_bg); $stop(); end end
|
||||
else if (cnt[30:2]== 4) begin if (array_bg !== 16'b1101111111011101) begin $display("%b", array_bg); $stop(); end end
|
||||
else if (cnt[30:2]== 5) begin if (array_bg !== 16'b1010101010101010) begin $display("%b", array_bg); $stop(); end end
|
||||
else if (cnt[30:2]== 6) begin if (array_bg !== 16'b0110011001100110) begin $display("%b", array_bg); $stop(); end end
|
||||
else if (cnt[30:2]== 7) begin if (array_bg !== 16'b0010001000100010) begin $display("%b", array_bg); $stop(); end end
|
||||
else if (cnt[30:2]== 8) begin if (array_bg !== 16'b10101010xxxxxxxx) begin $display("%b", array_bg); $stop(); end end
|
||||
else if (cnt[30:2]== 9) begin if (array_bg !== 16'bxxxxxxxx10101010) begin $display("%b", array_bg); $stop(); end end
|
||||
else if (cnt[30:2]==10) begin if (array_bg !== 16'b1001101010111100) begin $display("%b", array_bg); $stop(); end end
|
||||
else if (cnt[30:2]== 6) begin if (array_bg !== 16'b1001101010111100) begin $display("%b", array_bg); $stop(); end end
|
||||
end
|
||||
|
||||
// little endian
|
||||
always @ (posedge clk)
|
||||
if (cnt[1:0]==2'd0) begin
|
||||
// initialize to defaults (all bits 1'bx)
|
||||
if (cnt[30:2]== 0) array_lt <= {WA{ {WB{1'bx}} }};
|
||||
else if (cnt[30:2]== 1) array_lt <= {WA{ {WB{1'bx}} }};
|
||||
else if (cnt[30:2]== 2) array_lt <= {WA{ {WB{1'bx}} }};
|
||||
else if (cnt[30:2]== 3) array_lt <= {WA{ {WB{1'bx}} }};
|
||||
else if (cnt[30:2]== 4) array_lt <= {WA{ {WB{1'bx}} }};
|
||||
else if (cnt[30:2]== 5) array_lt <= {WA{ {WB{1'bx}} }};
|
||||
else if (cnt[30:2]== 6) array_lt <= {WA{ {WB{1'bx}} }};
|
||||
else if (cnt[30:2]== 7) array_lt <= {WA{ {WB{1'bx}} }};
|
||||
else if (cnt[30:2]== 8) array_lt <= {WA{ {WB{1'bx}} }};
|
||||
else if (cnt[30:2]== 9) array_lt <= {WA{ {WB{1'bx}} }};
|
||||
else if (cnt[30:2]==10) array_lt <= {WA{ {WB{1'bx}} }};
|
||||
// initialize to defaults (all bits 1'b0)
|
||||
if (cnt[30:2]== 0) array_lt <= '0;
|
||||
else if (cnt[30:2]== 1) array_lt <= '0;
|
||||
else if (cnt[30:2]== 2) array_lt <= '0;
|
||||
else if (cnt[30:2]== 3) array_lt <= '0;
|
||||
else if (cnt[30:2]== 4) array_lt <= '0;
|
||||
else if (cnt[30:2]== 5) array_lt <= '0;
|
||||
else if (cnt[30:2]== 6) array_lt <= '0;
|
||||
else if (cnt[30:2]== 7) array_lt <= '0;
|
||||
else if (cnt[30:2]== 8) array_lt <= '0;
|
||||
else if (cnt[30:2]== 9) array_lt <= '0;
|
||||
else if (cnt[30:2]==10) array_lt <= '0;
|
||||
end else if (cnt[1:0]==2'd1) begin
|
||||
// write data into whole or part of the array using literals
|
||||
if (cnt[30:2]== 0) begin end
|
||||
else if (cnt[30:2]== 1) array_lt <= '{ 3 ,2 ,1, 0 };
|
||||
else if (cnt[30:2]== 2) array_lt <= '{3:4, 2:5, 1:6, 0:7};
|
||||
else if (cnt[30:2]== 3) array_lt <= '{default:13};
|
||||
else if (cnt[30:2]== 2) array_lt <= '{default:13};
|
||||
else if (cnt[30:2]== 3) array_lt <= '{3:4, 2:5, 1:6, 0:7};
|
||||
else if (cnt[30:2]== 4) array_lt <= '{1:15, default:13};
|
||||
else if (cnt[30:2]== 5) array_lt <= '{WA { {WB/2 {2'b10}} }};
|
||||
else if (cnt[30:2]== 6) array_lt <= '{WA { {3'b101, {WB/2-1{2'b10}}} }};
|
||||
else if (cnt[30:2]== 7) array_lt <= '{WA { {WB/2-1{2'b10}} }};
|
||||
else if (cnt[30:2]== 8) array_lt [0 :WA/2-1] <= '{WA/2{ {WB/2 {2'b10}} }};
|
||||
else if (cnt[30:2]== 9) array_lt [WA/2:WA -1] <= '{WA/2{ {WB/2 {2'b01}} }};
|
||||
else if (cnt[30:2]==10) array_lt <= '{cnt+0, cnt+1, cnt+2, cnt+3};
|
||||
end else if (cnt[1:0]==2'd2) begin
|
||||
// chack array agains expected value
|
||||
if (cnt[30:2]== 0) begin if (array_lt !== 16'bxxxxxxxxxxxxxxxx) begin $display("%b", array_lt); $stop(); end end
|
||||
if (cnt[30:2]== 0) begin if (array_lt !== 16'b0000000000000000) begin $display("%b", array_lt); $stop(); end end
|
||||
else if (cnt[30:2]== 1) begin if (array_lt !== 16'b0011001000010000) begin $display("%b", array_lt); $stop(); end end
|
||||
else if (cnt[30:2]== 2) begin if (array_lt !== 16'b0111011001010100) begin $display("%b", array_lt); $stop(); end end
|
||||
else if (cnt[30:2]== 3) begin if (array_lt !== 16'b1101110111011101) begin $display("%b", array_lt); $stop(); end end
|
||||
else if (cnt[30:2]== 2) begin if (array_lt !== 16'b1101110111011101) begin $display("%b", array_lt); $stop(); end end
|
||||
else if (cnt[30:2]== 3) begin if (array_lt !== 16'b0111011001010100) begin $display("%b", array_lt); $stop(); end end
|
||||
else if (cnt[30:2]== 4) begin if (array_lt !== 16'b1101111111011101) begin $display("%b", array_lt); $stop(); end end
|
||||
else if (cnt[30:2]== 5) begin if (array_lt !== 16'b1010101010101010) begin $display("%b", array_lt); $stop(); end end
|
||||
else if (cnt[30:2]== 6) begin if (array_lt !== 16'b0110011001100110) begin $display("%b", array_lt); $stop(); end end
|
||||
else if (cnt[30:2]== 7) begin if (array_lt !== 16'b0010001000100010) begin $display("%b", array_lt); $stop(); end end
|
||||
else if (cnt[30:2]== 8) begin if (array_lt !== 16'b10101010xxxxxxxx) begin $display("%b", array_lt); $stop(); end end
|
||||
else if (cnt[30:2]== 9) begin if (array_lt !== 16'bxxxxxxxx10101010) begin $display("%b", array_lt); $stop(); end end
|
||||
else if (cnt[30:2]==10) begin if (array_lt !== 16'b1001101010111100) begin $display("%b", array_lt); $stop(); end end
|
||||
end
|
||||
|
||||
|
||||
@@ -24,6 +24,10 @@ module t (/*AUTOARG*/
|
||||
|
||||
integer cnt = 0;
|
||||
|
||||
// msg926
|
||||
logic [3:0][31:0] packedArray;
|
||||
initial packedArray <= '0;
|
||||
|
||||
// event counter
|
||||
always @ (posedge clk) begin
|
||||
cnt <= cnt + 1;
|
||||
@@ -39,17 +43,17 @@ module t (/*AUTOARG*/
|
||||
// big endian
|
||||
always @ (posedge clk)
|
||||
if (cnt[1:0]==2'd0) begin
|
||||
// initialize to defaaults (all bits to x)
|
||||
if (cnt[30:2]==0) array_bg <= {WA *WB{1'bx} };
|
||||
else if (cnt[30:2]==1) array_bg <= {WA{ {WB{1'bx}} }};
|
||||
else if (cnt[30:2]==2) array_bg <= {WA{ {WB{1'bx}} }};
|
||||
else if (cnt[30:2]==3) array_bg <= {WA{ {WB{1'bx}} }};
|
||||
else if (cnt[30:2]==4) array_bg <= {WA{ {WB{1'bx}} }};
|
||||
else if (cnt[30:2]==5) array_bg <= {WA{ {WB{1'bx}} }};
|
||||
else if (cnt[30:2]==6) array_bg <= {WA{ {WB{1'bx}} }};
|
||||
else if (cnt[30:2]==7) array_bg <= {WA{ {WB{1'bx}} }};
|
||||
else if (cnt[30:2]==8) array_bg <= {WA{ {WB{1'bx}} }};
|
||||
else if (cnt[30:2]==9) array_bg <= {WA{ {WB{1'bx}} }};
|
||||
// initialize to defaaults (all bits to 0)
|
||||
if (cnt[30:2]==0) array_bg <= '0;
|
||||
else if (cnt[30:2]==1) array_bg <= '0;
|
||||
else if (cnt[30:2]==2) array_bg <= '0;
|
||||
else if (cnt[30:2]==3) array_bg <= '0;
|
||||
else if (cnt[30:2]==4) array_bg <= '0;
|
||||
else if (cnt[30:2]==5) array_bg <= '0;
|
||||
else if (cnt[30:2]==6) array_bg <= '0;
|
||||
else if (cnt[30:2]==7) array_bg <= '0;
|
||||
else if (cnt[30:2]==8) array_bg <= '0;
|
||||
else if (cnt[30:2]==9) array_bg <= '0;
|
||||
end else if (cnt[1:0]==2'd1) begin
|
||||
// write value to array
|
||||
if (cnt[30:2]==0) begin end
|
||||
@@ -64,19 +68,19 @@ module t (/*AUTOARG*/
|
||||
else if (cnt[30:2]==9) array_bg [WA -1 ][WB -1 ] <= {1 *1 +0{1'b1}};
|
||||
end else if (cnt[1:0]==2'd2) begin
|
||||
// check array value
|
||||
if (cnt[30:2]==0) begin if (array_bg !== 64'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx) begin $display("%b", array_bg); $stop(); end end
|
||||
if (cnt[30:2]==0) begin if (array_bg !== 64'b0000000000000000000000000000000000000000000000000000000000000000) begin $display("%b", array_bg); $stop(); end end
|
||||
else if (cnt[30:2]==1) begin if (array_bg !== 64'b1111111111111111111111111111111111111111111111111111111111111111) begin $display("%b", array_bg); $stop(); end end
|
||||
else if (cnt[30:2]==2) begin if (array_bg !== 64'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx11111111111111111111111111111111) begin $display("%b", array_bg); $stop(); end end
|
||||
else if (cnt[30:2]==3) begin if (array_bg !== 64'b11111111111111111111111111111111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx) begin $display("%b", array_bg); $stop(); end end
|
||||
else if (cnt[30:2]==4) begin if (array_bg !== 64'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx11111111) begin $display("%b", array_bg); $stop(); end end
|
||||
else if (cnt[30:2]==5) begin if (array_bg !== 64'b11111111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx) begin $display("%b", array_bg); $stop(); end end
|
||||
else if (cnt[30:2]==6) begin if (array_bg !== 64'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1111) begin $display("%b", array_bg); $stop(); end end
|
||||
else if (cnt[30:2]==7) begin if (array_bg !== 64'b1111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx) begin $display("%b", array_bg); $stop(); end end
|
||||
else if (cnt[30:2]==8) begin if (array_bg !== 64'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1) begin $display("%b", array_bg); $stop(); end end
|
||||
else if (cnt[30:2]==9) begin if (array_bg !== 64'b1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx) begin $display("%b", array_bg); $stop(); end end
|
||||
else if (cnt[30:2]==2) begin if (array_bg !== 64'b0000000000000000000000000000000011111111111111111111111111111111) begin $display("%b", array_bg); $stop(); end end
|
||||
else if (cnt[30:2]==3) begin if (array_bg !== 64'b1111111111111111111111111111111100000000000000000000000000000000) begin $display("%b", array_bg); $stop(); end end
|
||||
else if (cnt[30:2]==4) begin if (array_bg !== 64'b0000000000000000000000000000000000000000000000000000000011111111) begin $display("%b", array_bg); $stop(); end end
|
||||
else if (cnt[30:2]==5) begin if (array_bg !== 64'b1111111100000000000000000000000000000000000000000000000000000000) begin $display("%b", array_bg); $stop(); end end
|
||||
else if (cnt[30:2]==6) begin if (array_bg !== 64'b0000000000000000000000000000000000000000000000000000000000001111) begin $display("%b", array_bg); $stop(); end end
|
||||
else if (cnt[30:2]==7) begin if (array_bg !== 64'b1111000000000000000000000000000000000000000000000000000000000000) begin $display("%b", array_bg); $stop(); end end
|
||||
else if (cnt[30:2]==8) begin if (array_bg !== 64'b0000000000000000000000000000000000000000000000000000000000000001) begin $display("%b", array_bg); $stop(); end end
|
||||
else if (cnt[30:2]==9) begin if (array_bg !== 64'b1000000000000000000000000000000000000000000000000000000000000000) begin $display("%b", array_bg); $stop(); end end
|
||||
end else if (cnt[1:0]==2'd3) begin
|
||||
// read value from array (not a very good test for now)
|
||||
if (cnt[30:2]==0) begin if (array_bg !== {WA *WB {1'bx}}) $stop(); end
|
||||
if (cnt[30:2]==0) begin if (array_bg !== {WA *WB {1'b0}}) $stop(); end
|
||||
else if (cnt[30:2]==1) begin if (array_bg !== {WA *WB +0{1'b1}}) $stop(); end
|
||||
else if (cnt[30:2]==2) begin if (array_bg [WA/2-1:0 ] !== {WA/2*WB +0{1'b1}}) $stop(); end
|
||||
else if (cnt[30:2]==3) begin if (array_bg [WA -1:WA/2] !== {WA/2*WB +0{1'b1}}) $stop(); end
|
||||
@@ -91,17 +95,17 @@ module t (/*AUTOARG*/
|
||||
// little endian
|
||||
always @ (posedge clk)
|
||||
if (cnt[1:0]==2'd0) begin
|
||||
// initialize to defaaults (all bits to x)
|
||||
if (cnt[30:2]==0) array_lt <= {WA *WB{1'bx} };
|
||||
else if (cnt[30:2]==1) array_lt <= {WA{ {WB{1'bx}} }};
|
||||
else if (cnt[30:2]==2) array_lt <= {WA{ {WB{1'bx}} }};
|
||||
else if (cnt[30:2]==3) array_lt <= {WA{ {WB{1'bx}} }};
|
||||
else if (cnt[30:2]==4) array_lt <= {WA{ {WB{1'bx}} }};
|
||||
else if (cnt[30:2]==5) array_lt <= {WA{ {WB{1'bx}} }};
|
||||
else if (cnt[30:2]==6) array_lt <= {WA{ {WB{1'bx}} }};
|
||||
else if (cnt[30:2]==7) array_lt <= {WA{ {WB{1'bx}} }};
|
||||
else if (cnt[30:2]==8) array_lt <= {WA{ {WB{1'bx}} }};
|
||||
else if (cnt[30:2]==9) array_lt <= {WA{ {WB{1'bx}} }};
|
||||
// initialize to defaaults (all bits to 0)
|
||||
if (cnt[30:2]==0) array_lt <= '0;
|
||||
else if (cnt[30:2]==1) array_lt <= '0;
|
||||
else if (cnt[30:2]==2) array_lt <= '0;
|
||||
else if (cnt[30:2]==3) array_lt <= '0;
|
||||
else if (cnt[30:2]==4) array_lt <= '0;
|
||||
else if (cnt[30:2]==5) array_lt <= '0;
|
||||
else if (cnt[30:2]==6) array_lt <= '0;
|
||||
else if (cnt[30:2]==7) array_lt <= '0;
|
||||
else if (cnt[30:2]==8) array_lt <= '0;
|
||||
else if (cnt[30:2]==9) array_lt <= '0;
|
||||
end else if (cnt[1:0]==2'd1) begin
|
||||
// write value to array
|
||||
if (cnt[30:2]==0) begin end
|
||||
@@ -116,19 +120,19 @@ module t (/*AUTOARG*/
|
||||
else if (cnt[30:2]==9) array_lt [ WA -1][ WB -1] <= {1 *1 +0{1'b1}};
|
||||
end else if (cnt[1:0]==2'd2) begin
|
||||
// check array value
|
||||
if (cnt[30:2]==0) begin if (array_lt !== 64'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx) begin $display("%b", array_lt); $stop(); end end
|
||||
if (cnt[30:2]==0) begin if (array_lt !== 64'b0000000000000000000000000000000000000000000000000000000000000000) begin $display("%b", array_lt); $stop(); end end
|
||||
else if (cnt[30:2]==1) begin if (array_lt !== 64'b1111111111111111111111111111111111111111111111111111111111111111) begin $display("%b", array_lt); $stop(); end end
|
||||
else if (cnt[30:2]==2) begin if (array_lt !== 64'b11111111111111111111111111111111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx) begin $display("%b", array_lt); $stop(); end end
|
||||
else if (cnt[30:2]==3) begin if (array_lt !== 64'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx11111111111111111111111111111111) begin $display("%b", array_lt); $stop(); end end
|
||||
else if (cnt[30:2]==4) begin if (array_lt !== 64'b11111111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx) begin $display("%b", array_lt); $stop(); end end
|
||||
else if (cnt[30:2]==5) begin if (array_lt !== 64'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx11111111) begin $display("%b", array_lt); $stop(); end end
|
||||
else if (cnt[30:2]==6) begin if (array_lt !== 64'b1111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx) begin $display("%b", array_lt); $stop(); end end
|
||||
else if (cnt[30:2]==7) begin if (array_lt !== 64'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1111) begin $display("%b", array_lt); $stop(); end end
|
||||
else if (cnt[30:2]==8) begin if (array_lt !== 64'b1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx) begin $display("%b", array_lt); $stop(); end end
|
||||
else if (cnt[30:2]==9) begin if (array_lt !== 64'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1) begin $display("%b", array_lt); $stop(); end end
|
||||
else if (cnt[30:2]==2) begin if (array_lt !== 64'b1111111111111111111111111111111100000000000000000000000000000000) begin $display("%b", array_lt); $stop(); end end
|
||||
else if (cnt[30:2]==3) begin if (array_lt !== 64'b0000000000000000000000000000000011111111111111111111111111111111) begin $display("%b", array_lt); $stop(); end end
|
||||
else if (cnt[30:2]==4) begin if (array_lt !== 64'b1111111100000000000000000000000000000000000000000000000000000000) begin $display("%b", array_lt); $stop(); end end
|
||||
else if (cnt[30:2]==5) begin if (array_lt !== 64'b0000000000000000000000000000000000000000000000000000000011111111) begin $display("%b", array_lt); $stop(); end end
|
||||
else if (cnt[30:2]==6) begin if (array_lt !== 64'b1111000000000000000000000000000000000000000000000000000000000000) begin $display("%b", array_lt); $stop(); end end
|
||||
else if (cnt[30:2]==7) begin if (array_lt !== 64'b0000000000000000000000000000000000000000000000000000000000001111) begin $display("%b", array_lt); $stop(); end end
|
||||
else if (cnt[30:2]==8) begin if (array_lt !== 64'b1000000000000000000000000000000000000000000000000000000000000000) begin $display("%b", array_lt); $stop(); end end
|
||||
else if (cnt[30:2]==9) begin if (array_lt !== 64'b0000000000000000000000000000000000000000000000000000000000000001) begin $display("%b", array_lt); $stop(); end end
|
||||
end else if (cnt[1:0]==2'd3) begin
|
||||
// read value from array (not a very good test for now)
|
||||
if (cnt[30:2]==0) begin if (array_lt !== {WA *WB {1'bx}}) $stop(); end
|
||||
if (cnt[30:2]==0) begin if (array_lt !== {WA *WB {1'b0}}) $stop(); end
|
||||
else if (cnt[30:2]==1) begin if (array_lt !== {WA *WB +0{1'b1}}) $stop(); end
|
||||
else if (cnt[30:2]==2) begin if (array_lt [0 :WA/2-1] !== {WA/2*WB +0{1'b1}}) $stop(); end
|
||||
else if (cnt[30:2]==3) begin if (array_lt [WA/2:WA -1] !== {WA/2*WB +0{1'b1}}) $stop(); end
|
||||
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,279 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2012 by Wilson Snyder.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
|
||||
integer cyc=0;
|
||||
reg [63:0] crc;
|
||||
reg [63:0] sum;
|
||||
|
||||
// Take CRC data and apply to testblock inputs
|
||||
wire [7:0] operand_a = crc[7:0];
|
||||
wire [7:0] operand_b = crc[15:8];
|
||||
|
||||
/*AUTOWIRE*/
|
||||
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
||||
wire [6:0] out; // From test of Test.v
|
||||
// End of automatics
|
||||
|
||||
Test test (/*AUTOINST*/
|
||||
// Outputs
|
||||
.out (out[6:0]),
|
||||
// Inputs
|
||||
.clk (clk),
|
||||
.operand_a (operand_a[7:0]),
|
||||
.operand_b (operand_b[7:0]));
|
||||
|
||||
// Aggregate outputs into a single result vector
|
||||
wire [63:0] result = {57'h0, out};
|
||||
|
||||
// Test loop
|
||||
always @ (posedge clk) begin
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("[%0t] cyc==%0d crc=%x result=%x\n",$time, cyc, crc, result);
|
||||
`endif
|
||||
cyc <= cyc + 1;
|
||||
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
|
||||
sum <= result ^ {sum[62:0],sum[63]^sum[2]^sum[0]};
|
||||
if (cyc==0) begin
|
||||
// Setup
|
||||
crc <= 64'h5aef0c8d_d70a4497;
|
||||
sum <= 64'h0;
|
||||
end
|
||||
else if (cyc<10) begin
|
||||
sum <= 64'h0;
|
||||
end
|
||||
else if (cyc<90) begin
|
||||
end
|
||||
else if (cyc==99) begin
|
||||
$write("[%0t] cyc==%0d crc=%x sum=%x\n",$time, cyc, crc, sum);
|
||||
if (crc !== 64'hc77bb9b3784ea091) $stop;
|
||||
// What checksum will we end up with (above print should match)
|
||||
`define EXPECTED_SUM 64'h8a78c2ec4946ac38
|
||||
if (sum !== `EXPECTED_SUM) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module Test
|
||||
(
|
||||
// Inputs
|
||||
input wire clk,
|
||||
input wire [7:0] operand_a, // operand a
|
||||
input wire [7:0] operand_b, // operand b
|
||||
// Outputs
|
||||
output wire [6:0] out
|
||||
);
|
||||
|
||||
wire [6:0] clz_a;
|
||||
wire [6:0] clz_b;
|
||||
|
||||
clz u_clz_a
|
||||
(
|
||||
// Inputs
|
||||
.data_i (operand_a),
|
||||
.out (clz_a));
|
||||
|
||||
clz u_clz_b
|
||||
(
|
||||
// Inputs
|
||||
.data_i (operand_b),
|
||||
.out (clz_b));
|
||||
|
||||
assign out = clz_a - clz_b;
|
||||
`ifdef TEST_VERBOSE
|
||||
always @(posedge clk)
|
||||
$display("Out(%x) = clz_a(%x) - clz_b(%x)", out, clz_a, clz_b);
|
||||
`endif
|
||||
|
||||
endmodule
|
||||
|
||||
`define def_0000_001x 8'b0000_0010, 8'b0000_0011
|
||||
|
||||
`define def_0000_01xx 8'b0000_0100, 8'b0000_0101, 8'b0000_0110, 8'b0000_0111
|
||||
|
||||
`define def_0000_10xx 8'b0000_1000, 8'b0000_1001, 8'b0000_1010, 8'b0000_1011
|
||||
`define def_0000_11xx 8'b0000_1100, 8'b0000_1101, 8'b0000_1110, 8'b0000_1111
|
||||
`define def_0000_1xxx `def_0000_10xx, `def_0000_11xx
|
||||
|
||||
`define def_0001_00xx 8'b0001_0000, 8'b0001_0001, 8'b0001_0010, 8'b0001_0011
|
||||
`define def_0001_01xx 8'b0001_0100, 8'b0001_0101, 8'b0001_0110, 8'b0001_0111
|
||||
`define def_0001_10xx 8'b0001_1000, 8'b0001_1001, 8'b0001_1010, 8'b0001_1011
|
||||
`define def_0001_11xx 8'b0001_1100, 8'b0001_1101, 8'b0001_1110, 8'b0001_1111
|
||||
|
||||
`define def_0010_00xx 8'b0010_0000, 8'b0010_0001, 8'b0010_0010, 8'b0010_0011
|
||||
`define def_0010_01xx 8'b0010_0100, 8'b0010_0101, 8'b0010_0110, 8'b0010_0111
|
||||
`define def_0010_10xx 8'b0010_1000, 8'b0010_1001, 8'b0010_1010, 8'b0010_1011
|
||||
`define def_0010_11xx 8'b0010_1100, 8'b0010_1101, 8'b0010_1110, 8'b0010_1111
|
||||
|
||||
`define def_0011_00xx 8'b0011_0000, 8'b0011_0001, 8'b0011_0010, 8'b0011_0011
|
||||
`define def_0011_01xx 8'b0011_0100, 8'b0011_0101, 8'b0011_0110, 8'b0011_0111
|
||||
`define def_0011_10xx 8'b0011_1000, 8'b0011_1001, 8'b0011_1010, 8'b0011_1011
|
||||
`define def_0011_11xx 8'b0011_1100, 8'b0011_1101, 8'b0011_1110, 8'b0011_1111
|
||||
|
||||
`define def_0100_00xx 8'b0100_0000, 8'b0100_0001, 8'b0100_0010, 8'b0100_0011
|
||||
`define def_0100_01xx 8'b0100_0100, 8'b0100_0101, 8'b0100_0110, 8'b0100_0111
|
||||
`define def_0100_10xx 8'b0100_1000, 8'b0100_1001, 8'b0100_1010, 8'b0100_1011
|
||||
`define def_0100_11xx 8'b0100_1100, 8'b0100_1101, 8'b0100_1110, 8'b0100_1111
|
||||
|
||||
`define def_0101_00xx 8'b0101_0000, 8'b0101_0001, 8'b0101_0010, 8'b0101_0011
|
||||
`define def_0101_01xx 8'b0101_0100, 8'b0101_0101, 8'b0101_0110, 8'b0101_0111
|
||||
`define def_0101_10xx 8'b0101_1000, 8'b0101_1001, 8'b0101_1010, 8'b0101_1011
|
||||
`define def_0101_11xx 8'b0101_1100, 8'b0101_1101, 8'b0101_1110, 8'b0101_1111
|
||||
|
||||
`define def_0110_00xx 8'b0110_0000, 8'b0110_0001, 8'b0110_0010, 8'b0110_0011
|
||||
`define def_0110_01xx 8'b0110_0100, 8'b0110_0101, 8'b0110_0110, 8'b0110_0111
|
||||
`define def_0110_10xx 8'b0110_1000, 8'b0110_1001, 8'b0110_1010, 8'b0110_1011
|
||||
`define def_0110_11xx 8'b0110_1100, 8'b0110_1101, 8'b0110_1110, 8'b0110_1111
|
||||
|
||||
`define def_0111_00xx 8'b0111_0000, 8'b0111_0001, 8'b0111_0010, 8'b0111_0011
|
||||
`define def_0111_01xx 8'b0111_0100, 8'b0111_0101, 8'b0111_0110, 8'b0111_0111
|
||||
`define def_0111_10xx 8'b0111_1000, 8'b0111_1001, 8'b0111_1010, 8'b0111_1011
|
||||
`define def_0111_11xx 8'b0111_1100, 8'b0111_1101, 8'b0111_1110, 8'b0111_1111
|
||||
|
||||
`define def_1000_00xx 8'b1000_0000, 8'b1000_0001, 8'b1000_0010, 8'b1000_0011
|
||||
`define def_1000_01xx 8'b1000_0100, 8'b1000_0101, 8'b1000_0110, 8'b1000_0111
|
||||
`define def_1000_10xx 8'b1000_1000, 8'b1000_1001, 8'b1000_1010, 8'b1000_1011
|
||||
`define def_1000_11xx 8'b1000_1100, 8'b1000_1101, 8'b1000_1110, 8'b1000_1111
|
||||
|
||||
`define def_1001_00xx 8'b1001_0000, 8'b1001_0001, 8'b1001_0010, 8'b1001_0011
|
||||
`define def_1001_01xx 8'b1001_0100, 8'b1001_0101, 8'b1001_0110, 8'b1001_0111
|
||||
`define def_1001_10xx 8'b1001_1000, 8'b1001_1001, 8'b1001_1010, 8'b1001_1011
|
||||
`define def_1001_11xx 8'b1001_1100, 8'b1001_1101, 8'b1001_1110, 8'b1001_1111
|
||||
|
||||
`define def_1010_00xx 8'b1010_0000, 8'b1010_0001, 8'b1010_0010, 8'b1010_0011
|
||||
`define def_1010_01xx 8'b1010_0100, 8'b1010_0101, 8'b1010_0110, 8'b1010_0111
|
||||
`define def_1010_10xx 8'b1010_1000, 8'b1010_1001, 8'b1010_1010, 8'b1010_1011
|
||||
`define def_1010_11xx 8'b1010_1100, 8'b1010_1101, 8'b1010_1110, 8'b1010_1111
|
||||
|
||||
`define def_1011_00xx 8'b1011_0000, 8'b1011_0001, 8'b1011_0010, 8'b1011_0011
|
||||
`define def_1011_01xx 8'b1011_0100, 8'b1011_0101, 8'b1011_0110, 8'b1011_0111
|
||||
`define def_1011_10xx 8'b1011_1000, 8'b1011_1001, 8'b1011_1010, 8'b1011_1011
|
||||
`define def_1011_11xx 8'b1011_1100, 8'b1011_1101, 8'b1011_1110, 8'b1011_1111
|
||||
|
||||
`define def_1100_00xx 8'b1100_0000, 8'b1100_0001, 8'b1100_0010, 8'b1100_0011
|
||||
`define def_1100_01xx 8'b1100_0100, 8'b1100_0101, 8'b1100_0110, 8'b1100_0111
|
||||
`define def_1100_10xx 8'b1100_1000, 8'b1100_1001, 8'b1100_1010, 8'b1100_1011
|
||||
`define def_1100_11xx 8'b1100_1100, 8'b1100_1101, 8'b1100_1110, 8'b1100_1111
|
||||
|
||||
`define def_1101_00xx 8'b1101_0000, 8'b1101_0001, 8'b1101_0010, 8'b1101_0011
|
||||
`define def_1101_01xx 8'b1101_0100, 8'b1101_0101, 8'b1101_0110, 8'b1101_0111
|
||||
`define def_1101_10xx 8'b1101_1000, 8'b1101_1001, 8'b1101_1010, 8'b1101_1011
|
||||
`define def_1101_11xx 8'b1101_1100, 8'b1101_1101, 8'b1101_1110, 8'b1101_1111
|
||||
|
||||
`define def_1110_00xx 8'b1110_0000, 8'b1110_0001, 8'b1110_0010, 8'b1110_0011
|
||||
`define def_1110_01xx 8'b1110_0100, 8'b1110_0101, 8'b1110_0110, 8'b1110_0111
|
||||
`define def_1110_10xx 8'b1110_1000, 8'b1110_1001, 8'b1110_1010, 8'b1110_1011
|
||||
`define def_1110_11xx 8'b1110_1100, 8'b1110_1101, 8'b1110_1110, 8'b1110_1111
|
||||
|
||||
`define def_1111_00xx 8'b1111_0000, 8'b1111_0001, 8'b1111_0010, 8'b1111_0011
|
||||
`define def_1111_01xx 8'b1111_0100, 8'b1111_0101, 8'b1111_0110, 8'b1111_0111
|
||||
`define def_1111_10xx 8'b1111_1000, 8'b1111_1001, 8'b1111_1010, 8'b1111_1011
|
||||
`define def_1111_11xx 8'b1111_1100, 8'b1111_1101, 8'b1111_1110, 8'b1111_1111
|
||||
|
||||
`define def_0001_xxxx `def_0001_00xx, `def_0001_01xx, `def_0001_10xx, `def_0001_11xx
|
||||
`define def_0010_xxxx `def_0010_00xx, `def_0010_01xx, `def_0010_10xx, `def_0010_11xx
|
||||
`define def_0011_xxxx `def_0011_00xx, `def_0011_01xx, `def_0011_10xx, `def_0011_11xx
|
||||
`define def_0100_xxxx `def_0100_00xx, `def_0100_01xx, `def_0100_10xx, `def_0100_11xx
|
||||
`define def_0101_xxxx `def_0101_00xx, `def_0101_01xx, `def_0101_10xx, `def_0101_11xx
|
||||
`define def_0110_xxxx `def_0110_00xx, `def_0110_01xx, `def_0110_10xx, `def_0110_11xx
|
||||
`define def_0111_xxxx `def_0111_00xx, `def_0111_01xx, `def_0111_10xx, `def_0111_11xx
|
||||
|
||||
`define def_1000_xxxx `def_1000_00xx, `def_1000_01xx, `def_1000_10xx, `def_1000_11xx
|
||||
`define def_1001_xxxx `def_1001_00xx, `def_1001_01xx, `def_1001_10xx, `def_1001_11xx
|
||||
`define def_1010_xxxx `def_1010_00xx, `def_1010_01xx, `def_1010_10xx, `def_1010_11xx
|
||||
`define def_1011_xxxx `def_1011_00xx, `def_1011_01xx, `def_1011_10xx, `def_1011_11xx
|
||||
`define def_1100_xxxx `def_1100_00xx, `def_1100_01xx, `def_1100_10xx, `def_1100_11xx
|
||||
`define def_1101_xxxx `def_1101_00xx, `def_1101_01xx, `def_1101_10xx, `def_1101_11xx
|
||||
`define def_1110_xxxx `def_1110_00xx, `def_1110_01xx, `def_1110_10xx, `def_1110_11xx
|
||||
`define def_1111_xxxx `def_1111_00xx, `def_1111_01xx, `def_1111_10xx, `def_1111_11xx
|
||||
|
||||
`define def_1xxx_xxxx `def_1000_xxxx, `def_1001_xxxx, `def_1010_xxxx, `def_1011_xxxx, \
|
||||
`def_1100_xxxx, `def_1101_xxxx, `def_1110_xxxx, `def_1111_xxxx
|
||||
`define def_01xx_xxxx `def_0100_xxxx, `def_0101_xxxx, `def_0110_xxxx, `def_0111_xxxx
|
||||
`define def_001x_xxxx `def_0010_xxxx, `def_0011_xxxx
|
||||
|
||||
|
||||
|
||||
module clz(
|
||||
input wire [7:0] data_i,
|
||||
output wire [6:0] out
|
||||
);
|
||||
|
||||
// -----------------------------
|
||||
// Reg declarations
|
||||
// -----------------------------
|
||||
|
||||
reg [2:0] clz_byte0;
|
||||
reg [2:0] clz_byte1;
|
||||
reg [2:0] clz_byte2;
|
||||
reg [2:0] clz_byte3;
|
||||
|
||||
always @*
|
||||
case (data_i)
|
||||
`def_1xxx_xxxx : clz_byte0 = 3'b000;
|
||||
`def_01xx_xxxx : clz_byte0 = 3'b001;
|
||||
`def_001x_xxxx : clz_byte0 = 3'b010;
|
||||
`def_0001_xxxx : clz_byte0 = 3'b011;
|
||||
`def_0000_1xxx : clz_byte0 = 3'b100;
|
||||
`def_0000_01xx : clz_byte0 = 3'b101;
|
||||
`def_0000_001x : clz_byte0 = 3'b110;
|
||||
8'b0000_0001 : clz_byte0 = 3'b111;
|
||||
8'b0000_0000 : clz_byte0 = 3'b111;
|
||||
default : clz_byte0 = 3'bxxx;
|
||||
endcase
|
||||
|
||||
always @*
|
||||
case (data_i)
|
||||
`def_1xxx_xxxx : clz_byte1 = 3'b000;
|
||||
`def_01xx_xxxx : clz_byte1 = 3'b001;
|
||||
`def_001x_xxxx : clz_byte1 = 3'b010;
|
||||
`def_0001_xxxx : clz_byte1 = 3'b011;
|
||||
`def_0000_1xxx : clz_byte1 = 3'b100;
|
||||
`def_0000_01xx : clz_byte1 = 3'b101;
|
||||
`def_0000_001x : clz_byte1 = 3'b110;
|
||||
8'b0000_0001 : clz_byte1 = 3'b111;
|
||||
8'b0000_0000 : clz_byte1 = 3'b111;
|
||||
default : clz_byte1 = 3'bxxx;
|
||||
endcase
|
||||
|
||||
always @*
|
||||
case (data_i)
|
||||
`def_1xxx_xxxx : clz_byte2 = 3'b000;
|
||||
`def_01xx_xxxx : clz_byte2 = 3'b001;
|
||||
`def_001x_xxxx : clz_byte2 = 3'b010;
|
||||
`def_0001_xxxx : clz_byte2 = 3'b011;
|
||||
`def_0000_1xxx : clz_byte2 = 3'b100;
|
||||
`def_0000_01xx : clz_byte2 = 3'b101;
|
||||
`def_0000_001x : clz_byte2 = 3'b110;
|
||||
8'b0000_0001 : clz_byte2 = 3'b111;
|
||||
8'b0000_0000 : clz_byte2 = 3'b111;
|
||||
default : clz_byte2 = 3'bxxx;
|
||||
endcase
|
||||
always @*
|
||||
case (data_i)
|
||||
`def_1xxx_xxxx : clz_byte3 = 3'b000;
|
||||
`def_01xx_xxxx : clz_byte3 = 3'b001;
|
||||
`def_001x_xxxx : clz_byte3 = 3'b010;
|
||||
`def_0001_xxxx : clz_byte3 = 3'b011;
|
||||
`def_0000_1xxx : clz_byte3 = 3'b100;
|
||||
`def_0000_01xx : clz_byte3 = 3'b101;
|
||||
`def_0000_001x : clz_byte3 = 3'b110;
|
||||
8'b0000_0001 : clz_byte3 = 3'b111;
|
||||
8'b0000_0000 : clz_byte3 = 3'b111;
|
||||
default : clz_byte3 = 3'bxxx;
|
||||
endcase
|
||||
|
||||
assign out = {4'b0000, clz_byte1};
|
||||
|
||||
endmodule // clz
|
||||
|
||||
@@ -97,7 +97,8 @@ void t_embed_child_io_eval (unsigned char clk,
|
||||
VL_DEBUG_IF(VL_PRINTF(" t_embed1_child_io_eval\n"); );
|
||||
Vt_embed1_child* __modelp = __get_modelp();
|
||||
VL_DEBUG_IF(VL_PRINTF("[%0ld] in clk=%x b=%x V=%x R=%x\n",
|
||||
VL_TIME_Q(), clk, bit_in, vec_in[0], is_ref););
|
||||
(long int) (VL_TIME_Q()), clk, bit_in, vec_in[0],
|
||||
is_ref););
|
||||
__modelp->clk = clk;
|
||||
__modelp->bit_in = bit_in;
|
||||
__modelp->vec_in = vec_in[0];
|
||||
@@ -119,5 +120,6 @@ void t_embed_child_io_eval (unsigned char clk,
|
||||
wide_out[3] = __modelp->wide_out[3];
|
||||
*did_init_out = __modelp->did_init_out;
|
||||
VL_DEBUG_IF(VL_PRINTF("[%0ld] out b=%x V=%x DI=%x\n",
|
||||
VL_TIME_Q(), *bit_out, *vec_out, *did_init_out););
|
||||
(long int)(VL_TIME_Q()), *bit_out, *vec_out,
|
||||
*did_init_out););
|
||||
}
|
||||
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
v_flags2 => ["--lint-only --inline-mult 1"],
|
||||
verilator_make_gcc => 0,
|
||||
make_top_shell => 0,
|
||||
make_main => 0,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,28 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2012 by Wilson Snyder.
|
||||
|
||||
module init;
|
||||
|
||||
task t1;
|
||||
reg ba,bb,bc,bd,be,bf,bg,bh,bi,bj,bk,bl,bm,bn,bo,bp,bq,br,bs,bt,bu,bv,bw,bx,by,bz;
|
||||
reg ca,cb,cc,cd,ce,cf,cg,ch,ci,cj,ck,cl,cm,cn,co,cp,cq,cr,cs,ct,cu,cv,cw,cx,cy,cz;
|
||||
reg da,db,dc,dd,de,df,dg,dh,di,dj,dk,dl,dm,dn, dp,dq,dr,ds,dt,du,dv,dw,dx,dy,dz;
|
||||
begin : READER
|
||||
$display ("Time: %0t Instance: %m", $time);
|
||||
end
|
||||
endtask
|
||||
|
||||
task t2;
|
||||
reg ba,bb,bc,bd,be,bf,bg,bh,bi,bj,bk,bl,bm,bn,bo,bp,bq,br,bs,bt,bu,bv,bw,bx,by,bz;
|
||||
begin : READER
|
||||
$display ("Time: %0t Instance: %m", $time);
|
||||
end
|
||||
endtask
|
||||
endmodule
|
||||
|
||||
module test();
|
||||
init u_ram1();
|
||||
init u_ram2();
|
||||
endmodule
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,34 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2012 by Chandan Egbert.
|
||||
|
||||
// See bug569
|
||||
|
||||
module t();
|
||||
`ifdef T_FUNC_V_NOINL
|
||||
// verilator no_inline_module
|
||||
`endif
|
||||
level1 ul1();
|
||||
initial ul1.doit(4'b0);
|
||||
endmodule
|
||||
|
||||
module level1();
|
||||
`ifdef T_FUNC_V_NOINL
|
||||
// verilator no_inline_module
|
||||
`endif
|
||||
level2 ul2();
|
||||
|
||||
task doit(input logic [3:0] v);
|
||||
ul2.mem = v;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
endtask
|
||||
endmodule
|
||||
|
||||
module level2();
|
||||
`ifdef T_FUNC_V_NOINL
|
||||
// verilator no_inline_module
|
||||
`endif
|
||||
logic [3:0] mem;
|
||||
endmodule
|
||||
Executable
+21
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
top_filename("t/t_func_v.v");
|
||||
|
||||
compile (
|
||||
v_flags2 => ['+define+T_FUNC_V_NOINL',],
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,43 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2012 by Wilson Snyder.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
parameter PAR = 3;
|
||||
|
||||
wire [31:0] o1a,o1b;
|
||||
|
||||
m1 #(0) m1a(.o(o1a));
|
||||
m1 #(1) m1b(.o(o1b));
|
||||
|
||||
always @ (posedge clk) begin
|
||||
if (o1a != 8) $stop;
|
||||
if (o1b != 4) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
|
||||
module m1 (output wire [31:0] o);
|
||||
parameter W = 0;
|
||||
generate
|
||||
if (W == 0) begin
|
||||
m2 m2 (.o(o));
|
||||
defparam m2.PAR2 = 8;
|
||||
end
|
||||
else begin
|
||||
m2 m2 (.o(o));
|
||||
defparam m2.PAR2 = 4;
|
||||
end
|
||||
endgenerate
|
||||
endmodule
|
||||
|
||||
module m2 (output wire [31:0] o);
|
||||
parameter PAR2 = 10;
|
||||
assign o = PAR2;
|
||||
endmodule
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
$Self->{vlt} and $Self->unsupported("Verilator unsupported, bug517");
|
||||
|
||||
# Compile time only test
|
||||
compile (
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,72 @@
|
||||
// DESCRIPTION: Verilator: Test generate index usage.
|
||||
//
|
||||
// The code illustrates a problem in Verilator's handling of constant
|
||||
// expressions inside generate indexes.
|
||||
//
|
||||
// This is a regression test against issue 517.
|
||||
//
|
||||
// **If you do not wish for your code to be released to the public
|
||||
// please note it here, otherwise:**
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2012 by Jeremy Bennett.
|
||||
|
||||
|
||||
`define START 8
|
||||
`define SIZE 4
|
||||
`define END (`START + `SIZE)
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
|
||||
reg [`END-1:0] y;
|
||||
wire [`END-1:0] x;
|
||||
|
||||
foo foo_i (.y (y),
|
||||
.x (x),
|
||||
.clk (clk));
|
||||
|
||||
always @(posedge clk) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule // t
|
||||
|
||||
|
||||
module foo(output wire [`END-1:0] y,
|
||||
input wire [`END-1:0] x,
|
||||
input wire clk);
|
||||
|
||||
function peek_bar;
|
||||
peek_bar = bar_inst[`START].i_bar.r; // this is ok
|
||||
peek_bar = bar_inst[`START + 1].i_bar.r; // this fails, should not.
|
||||
endfunction
|
||||
|
||||
genvar g;
|
||||
generate
|
||||
for (g = `START; g < `END; g = g + 1) begin: bar_inst
|
||||
bar i_bar(.x (x[g]),
|
||||
.y (y[g]),
|
||||
.clk (clk));
|
||||
end
|
||||
endgenerate
|
||||
|
||||
endmodule : foo
|
||||
|
||||
|
||||
module bar(output wire y,
|
||||
input wire x,
|
||||
input wire clk);
|
||||
|
||||
reg r = 0;
|
||||
assign y = r;
|
||||
|
||||
always @(posedge clk) begin
|
||||
r = x ? ~x : y;
|
||||
end
|
||||
|
||||
endmodule : bar
|
||||
Executable
+31
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
expect=>quotemeta(
|
||||
q{created tag with scope = top.v.tag
|
||||
created tag with scope = top.v.b.gen[0].tag
|
||||
created tag with scope = top.v.b.gen[1].tag
|
||||
mod a has scope = top.v
|
||||
mod a has tag = top.v.tag
|
||||
mod b has scope = top.v.b
|
||||
mod b has tag = top.v.tag
|
||||
mod c has scope = top.v.b.gen[0].c
|
||||
mod c has tag = top.v.b.gen[0].tag
|
||||
mod c has scope = top.v.b.gen[1].c
|
||||
mod c has tag = top.v.b.gen[1].tag
|
||||
*-* All Finished *-*}),
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,84 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2012 by Wilson Snyder.
|
||||
|
||||
/* Acceptable answer 1
|
||||
created tag with scope = top.t.tag
|
||||
created tag with scope = top.t.b.gen[0].tag
|
||||
created tag with scope = top.t.b.gen[1].tag
|
||||
mod a has scope = top.t
|
||||
mod a has tag = top.t.tag
|
||||
mod b has scope = top.t.b
|
||||
mod b has tag = top.t.tag
|
||||
mod c has scope = top.t.b.gen[0].c
|
||||
mod c has tag = top.t.b.gen[0].tag
|
||||
mod c has scope = top.t.b.gen[1].c
|
||||
mod c has tag = top.t.b.gen[1].tag
|
||||
*/
|
||||
/* Acceptable answer 2
|
||||
created tag with scope = top.t.tag
|
||||
created tag with scope = top.t.b.gen[0].tag
|
||||
created tag with scope = top.t.b.gen[1].tag
|
||||
mod a has scope = top.t
|
||||
mod a has tag = top.t.tag
|
||||
mod b has scope = top.t.b
|
||||
mod b has tag = top.t.tag
|
||||
mod c has scope = top.t.b.gen[0].c
|
||||
mod c has tag = top.t.tag
|
||||
mod c has scope = top.t.b.gen[1].c
|
||||
mod c has tag = top.t.tag
|
||||
*/
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
integer cyc=0;
|
||||
|
||||
tag tag ();
|
||||
b b ();
|
||||
|
||||
always @ (t.cyc) begin
|
||||
if (t.cyc == 2) $display("mod a has scope = %m");
|
||||
if (t.cyc == 2) $display("mod a has tag = %0s", tag.scope);
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
cyc <= cyc + 1;
|
||||
if (cyc==99) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
|
||||
module b ();
|
||||
genvar g;
|
||||
generate
|
||||
for (g=0; g<2; g++) begin : gen
|
||||
tag tag ();
|
||||
c c ();
|
||||
end
|
||||
endgenerate
|
||||
always @ (t.cyc) begin
|
||||
if (t.cyc == 3) $display("mod b has scope = %m");
|
||||
if (t.cyc == 3) $display("mod b has tag = %0s", tag.scope);
|
||||
end
|
||||
endmodule
|
||||
|
||||
module c ();
|
||||
always @ (t.cyc) begin
|
||||
if (t.cyc == 4) $display("mod c has scope = %m");
|
||||
if (t.cyc == 4) $display("mod c has tag = %0s", tag.scope);
|
||||
end
|
||||
endmodule
|
||||
|
||||
module tag ();
|
||||
bit [100*8-1:0] scope;
|
||||
initial begin
|
||||
$sformat(scope,"%m");
|
||||
$display("created tag with scope = %0s",scope);
|
||||
end
|
||||
endmodule
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
v_flags2 => ["--lint-only"],
|
||||
make_top_shell => 0,
|
||||
make_main => 0,
|
||||
verilator_make_gcc => 0,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,24 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2012 by Chandan Egbert.
|
||||
|
||||
module sub();
|
||||
endmodule
|
||||
|
||||
module t(input logic a, input logic b,
|
||||
output logic x, output logic y);
|
||||
|
||||
always_comb begin
|
||||
integer i;
|
||||
x = a;
|
||||
end
|
||||
|
||||
sub u0();
|
||||
|
||||
always_comb begin
|
||||
integer j;
|
||||
y = b;
|
||||
end
|
||||
|
||||
endmodule
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
verilator_flags2 => ["--x-initial-edge"]
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,101 @@
|
||||
// DESCRIPTION: Verilator: initial edge issue
|
||||
//
|
||||
// The module initial_edge drives the output "res" high when the reset signal,
|
||||
// rst, goes high.
|
||||
//
|
||||
// The module initial_edge_n drives the output "res_n" high when the reset
|
||||
// signal, rst_n, goes low.
|
||||
//
|
||||
// For 4-state simulators, that edge occurs when the initial value of rst_n,
|
||||
// X, goes to zero. However, by default for Verilator, being 2-state, the
|
||||
// initial value is zero, so no edge is seen.
|
||||
//
|
||||
// This is not a bug in verilator (it is bad design to rely on an edge
|
||||
// transition from an unitialized signal), but the problem is that there are
|
||||
// quite a few instances of code out there that seems to be dependent on this
|
||||
// behaviour to get out of reset.
|
||||
//
|
||||
// The Verilator --x-initial-edge flag causes these initial edges to trigger,
|
||||
// thus matching the behaviour of a 4-state simulator. This is reportedly also
|
||||
// the behaviour of commercial cycle accurate modelling tools as well.
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use, without
|
||||
// warranty, 2012 by Wilson Snyder.
|
||||
|
||||
`timescale 1ns/1ns
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
|
||||
wire res;
|
||||
wire res_n;
|
||||
reg rst;
|
||||
reg rst_n;
|
||||
|
||||
integer count = 0;
|
||||
|
||||
initial_edge i_edge (.res (res),
|
||||
.rst (rst));
|
||||
|
||||
initial_edge_n i_edge_n (.res_n (res_n),
|
||||
.rst_n (rst_n));
|
||||
|
||||
// run for 3 cycles, with one cycle of reset.
|
||||
always @(posedge clk) begin
|
||||
|
||||
rst <= (count == 0) ? 1 : 0;
|
||||
rst_n <= (count == 0) ? 0 : 1;
|
||||
|
||||
if (count == 3) begin
|
||||
if ((res == 1) && (res_n == 1)) begin
|
||||
$write ("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
else begin
|
||||
`ifdef TEST_VERBOSE
|
||||
$write ("FAILED: res = %b, res_n = %b\n", res, res_n);
|
||||
`endif
|
||||
$stop;
|
||||
end
|
||||
end
|
||||
|
||||
count = count + 1;
|
||||
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
module initial_edge_n (res_n,
|
||||
rst_n);
|
||||
output res_n;
|
||||
input rst_n;
|
||||
|
||||
reg res_n = 1'b0;
|
||||
|
||||
always @(negedge rst_n) begin
|
||||
if (rst_n == 1'b0) begin
|
||||
res_n <= 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule // initial_edge_n
|
||||
|
||||
|
||||
module initial_edge (res,
|
||||
rst);
|
||||
output res;
|
||||
input rst;
|
||||
|
||||
reg res = 1'b0;
|
||||
|
||||
always @(posedge rst) begin
|
||||
if (rst == 1'b1) begin
|
||||
res <= 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule // initial_edge
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
top_filename("t/t_initial_edge.v");
|
||||
|
||||
# This works with other simulators, we we don't run it for them. It should
|
||||
# fail with Verilator if --x-initial-edge is not specified.
|
||||
$Self->{vlt} or $Self->skip("Verilator only test");
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
execute (
|
||||
fails => 1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
Executable
+14
@@ -0,0 +1,14 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,32 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2012 by Wilson Snyder.
|
||||
|
||||
module t;
|
||||
sub #(10,11,12,13) sub ();
|
||||
|
||||
endmodule
|
||||
|
||||
module sub ();
|
||||
parameter A = 0;
|
||||
parameter B = 1;
|
||||
|
||||
ip ip();
|
||||
|
||||
parameter C = 2;
|
||||
parameter D = 3;
|
||||
|
||||
initial begin
|
||||
if (A!=10) $stop;
|
||||
if (B!=11) $stop;
|
||||
if (C!=12) $stop;
|
||||
if (D!=13) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module ip;
|
||||
endmodule
|
||||
Executable
+16
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
# This is a compile only test.
|
||||
compile (
|
||||
v_flags2 => ["+verilog2001ext+v"],
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,51 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// A test of the +verilog1995ext+ and +verilog2001ext+ flags.
|
||||
//
|
||||
// This source code contains constructs that are valid in Verilog 2001 and
|
||||
// SystemVerilog 2005/2009, but not in Verilog 1995. So it should fail if we
|
||||
// set the language to be 1995, but not 2001.
|
||||
//
|
||||
// Compile only test, so no need for "All Finished" output.
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2012 by Jeremy Bennett.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
|
||||
reg [1:0] res;
|
||||
|
||||
// Instantiate the test
|
||||
test test_i (/*AUTOINST*/
|
||||
// Outputs
|
||||
.res (res),
|
||||
// Inputs
|
||||
.clk (clk),
|
||||
.in (1'b1));
|
||||
|
||||
endmodule
|
||||
|
||||
module test (// Outputs
|
||||
res,
|
||||
// Inputs
|
||||
clk,
|
||||
in
|
||||
);
|
||||
output [1:0] res;
|
||||
input clk;
|
||||
input in;
|
||||
|
||||
// This is a Verilog 2001 test
|
||||
generate
|
||||
genvar i;
|
||||
for (i=0; i<2; i=i+1) begin
|
||||
always @(posedge clk) begin
|
||||
res[i:i] <= in;
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
endmodule
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
top_filename("t/t_langext_1.v");
|
||||
|
||||
# This is a compile only test.
|
||||
compile (
|
||||
v_flags2 => ["+verilog1995ext+v"],
|
||||
fails => 1
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
Executable
+16
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
# This is a compile only test.
|
||||
compile (
|
||||
v_flags2 => ["+systemverilogext+v"],
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,55 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// A test of the +1364-1995ext+ and +systemverilogext+ flags.
|
||||
//
|
||||
// This source code contains constructs that are valid in SystemVerilog 2009
|
||||
// but not in Verilog 1995. So it should fail if we set the language to be
|
||||
// Verilog 1995, but not SystemVerilog 2009.
|
||||
//
|
||||
// Compile only test, so no need for "All Finished" output.
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2012 by Jeremy Bennett.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
|
||||
reg [1:0] res;
|
||||
|
||||
|
||||
// Instantiate the test
|
||||
test test_i (/*AUTOINST*/
|
||||
// Outputs
|
||||
.res (res),
|
||||
// Inputs
|
||||
.clk (clk),
|
||||
.in (1'b1));
|
||||
|
||||
endmodule
|
||||
|
||||
module test (// Outputs
|
||||
res,
|
||||
// Inputs
|
||||
clk,
|
||||
in
|
||||
);
|
||||
output [1:0] res;
|
||||
input clk;
|
||||
input in;
|
||||
|
||||
// This is a SystemVerilog 2009 only test
|
||||
generate
|
||||
genvar i;
|
||||
for (i=0; i<2; i=i+1) begin
|
||||
always @(posedge clk) begin
|
||||
unique0 case (i)
|
||||
0: res[0:0] <= in;
|
||||
1: res[1:1] <= in;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
endmodule
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
top_filename("t/t_langext_2.v");
|
||||
|
||||
# This is a compile only test.
|
||||
compile (
|
||||
v_flags2 => ["+1364-1995ext+v"],
|
||||
fails => 1
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
Executable
+16
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
# This is a compile only test.
|
||||
compile (
|
||||
v_flags2 => ["+1364-2005ext+v"],
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,21 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// A test of the +verilog2001ext+ and +verilog2005ext+ flags.
|
||||
//
|
||||
// This source code uses the uwire declaration, which is only valid in Verilog
|
||||
// 2005.
|
||||
//
|
||||
// Compile only test, so no need for "All Finished" output.
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2012 by Jeremy Bennett.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
|
||||
uwire w; // Only in Verilog 2005
|
||||
|
||||
endmodule
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
top_filename("t/t_langext_3.v");
|
||||
|
||||
# This is a compile only test.
|
||||
compile (
|
||||
v_flags2 => ["+1364-2001ext+v"],
|
||||
fails => 1
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
top_filename("t/t_langext_2.v");
|
||||
|
||||
# This is a compile only test.
|
||||
compile (
|
||||
v_flags2 => ["+1800-2009ext+v"],
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
top_filename("t/t_langext_2.v");
|
||||
|
||||
# This is a compile only test.
|
||||
compile (
|
||||
v_flags2 => ["+1800-2005ext+v"],
|
||||
fails => 1
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -40,6 +40,8 @@ module t (/*AUTOARG*/
|
||||
if (5'sb10110>>>2 != 5'sb11101) $stop;
|
||||
if (5'sb10110<<2 != 5'sb11000) $stop;
|
||||
if (5'sb10110<<<2 != 5'sb11000) $stop;
|
||||
// Allow >64 bit shifts if the shift amount is a constant
|
||||
if ((64'sh458c2de282e30f8b >> 68'sh4) !== 64'sh0458c2de282e30f8) $stop;
|
||||
end
|
||||
if (cyc==2) begin
|
||||
amt <= 32'd28;
|
||||
|
||||
@@ -53,6 +53,11 @@ module t (/*AUTOARG*/
|
||||
// verilator lint_on WIDTH
|
||||
end
|
||||
|
||||
reg signed [32:0] bug349;
|
||||
|
||||
initial
|
||||
begin
|
||||
end
|
||||
integer i;
|
||||
initial begin
|
||||
if ((-1 >>> 3) != -1) $stop; // Decimals are signed
|
||||
@@ -81,6 +86,10 @@ module t (/*AUTOARG*/
|
||||
i = -'sd12 /3; if (i !== 32'hfffffffc) $stop;
|
||||
i = -4'sd12 /3; if (i !== 32'h00000001) $stop;
|
||||
// verilator lint_on WIDTH
|
||||
|
||||
// verilator lint_off WIDTH
|
||||
bug349 = 4'sb1111 - 1'b1;
|
||||
if (bug349 != 32'he) $stop;
|
||||
end
|
||||
|
||||
function signed [15:0] copy_signed;
|
||||
|
||||
@@ -8,7 +8,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
v_flags => ["--lint-only"],
|
||||
v_flags2 => ["--lint-only"],
|
||||
fails=>1,
|
||||
expect=>
|
||||
'%Error: t/t_mem_packed_assign_bad.v:\d+: Unsupported: Assignment between packed arrays of different dimensions
|
||||
|
||||
@@ -9,6 +9,9 @@ package functions;
|
||||
function real abs (real num);
|
||||
abs = (num <0) ? -num : num;
|
||||
endfunction
|
||||
function real neg (real num);
|
||||
return -abs(num); // Check package funcs can call package funcs
|
||||
endfunction
|
||||
endpackage
|
||||
|
||||
module t ();
|
||||
@@ -19,6 +22,8 @@ module t ();
|
||||
initial begin
|
||||
if (abs(-2.1) != 2.1) $stop;
|
||||
if (abs(2.2) != 2.2) $stop;
|
||||
if (neg(-2.1) != -2.1) $stop;
|
||||
if (neg(2.2) != -2.2) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
@@ -19,7 +19,9 @@ module t ();
|
||||
// synthesis translate on
|
||||
localparam LP_PACK_AND_MOD = 20;
|
||||
initial begin
|
||||
// verilator lint_off STMTDLY
|
||||
#10;
|
||||
// verilator lint_on STMTDLY
|
||||
if (LP_PACK_AND_MOD != 20) $stop;
|
||||
check_param();
|
||||
$write("*-* All Finished *-*\n");
|
||||
|
||||
Executable
+16
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
# Compile only
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,68 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2009 by Wilson Snyder.
|
||||
|
||||
package defs;
|
||||
function automatic integer max;
|
||||
input integer a;
|
||||
input integer b;
|
||||
max = (a > b) ? a : b;
|
||||
endfunction
|
||||
|
||||
function automatic integer log2;
|
||||
input integer value;
|
||||
value = value >> 1;
|
||||
for (log2 = 0; value > 0; log2 = log2 + 1)
|
||||
value = value >> 1;
|
||||
endfunction
|
||||
|
||||
function automatic integer ceil_log2;
|
||||
input integer value;
|
||||
value = value - 1;
|
||||
for (ceil_log2 = 0; value > 0; ceil_log2 = ceil_log2 + 1)
|
||||
value = value >> 1;
|
||||
endfunction
|
||||
endpackage
|
||||
|
||||
module sub();
|
||||
|
||||
import defs::*;
|
||||
|
||||
parameter RAND_NUM_MAX = "";
|
||||
|
||||
localparam DATA_RANGE = RAND_NUM_MAX + 1;
|
||||
localparam DATA_WIDTH = ceil_log2(DATA_RANGE);
|
||||
localparam WIDTH = max(4, ceil_log2(DATA_RANGE + 1));
|
||||
|
||||
endmodule
|
||||
|
||||
module t(/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
|
||||
import defs::*;
|
||||
|
||||
parameter WHICH = 0;
|
||||
parameter MAX_COUNT = 10;
|
||||
|
||||
localparam MAX_EXPONENT = log2(MAX_COUNT);
|
||||
localparam EXPONENT_WIDTH = ceil_log2(MAX_EXPONENT + 1);
|
||||
|
||||
input clk;
|
||||
|
||||
generate
|
||||
if (WHICH == 1)
|
||||
begin : which_true
|
||||
sub sub_true();
|
||||
defparam sub_true.RAND_NUM_MAX = MAX_EXPONENT;
|
||||
end
|
||||
else
|
||||
begin : which_false
|
||||
sub sub_false();
|
||||
defparam sub_false.RAND_NUM_MAX = MAX_COUNT;
|
||||
end
|
||||
endgenerate
|
||||
|
||||
endmodule
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
verilator_flags2 => ["--lint-only"],
|
||||
verilator_make_gcc => 0,
|
||||
make_top_shell => 0,
|
||||
make_main => 0,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,29 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use.
|
||||
|
||||
// bug541
|
||||
module t(clk,odata);
|
||||
input clk;
|
||||
output [7:0] odata;
|
||||
paramtest_DFFRE #(1) dffre0(clk,odata[7]);
|
||||
paramtest_WRAP #(7) dffe0(clk,odata[6:0]);
|
||||
endmodule
|
||||
|
||||
module paramtest_WRAP(clk,q);
|
||||
parameter W=1;
|
||||
input clk;
|
||||
output [W-1:0] q;
|
||||
paramtest_DFFRE #(W) dffre0(clk,q);
|
||||
endmodule
|
||||
|
||||
module paramtest_DFFRE(clk,q);
|
||||
parameter W=1;
|
||||
parameter [W-1:0] INIT={W{1'b0}};
|
||||
input clk;
|
||||
output [W-1:0] q;
|
||||
reg [W-1:0] q;
|
||||
always @(posedge clk) begin
|
||||
q <= INIT;
|
||||
end
|
||||
endmodule
|
||||
Executable
+15
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
# Compile only test.
|
||||
compile (
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,39 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// A test case for parameterized module.
|
||||
//
|
||||
// When a module is instantiatied with parameter, there will be two modules in
|
||||
// the tree and eventually one will be removed after param and deadifyModules.
|
||||
//
|
||||
// This test is to check that the removal of dead module will not cause
|
||||
// compilation error. Possible error was/is seen as:
|
||||
//
|
||||
// pure virtual method called
|
||||
// terminate called without an active exception
|
||||
// %Error: Verilator aborted. Consider trying --debug --gdbbt
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2012 by Jie Xu.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
wire [71:0] ctrl;
|
||||
|
||||
memory #(.words(72)) i_memory (.clk (clk));
|
||||
|
||||
assign ctrl = i_memory.mem[0];
|
||||
endmodule
|
||||
|
||||
|
||||
// memory module, which is used with parameter
|
||||
module memory (clk);
|
||||
input clk;
|
||||
|
||||
parameter words = 16384, bits = 72;
|
||||
|
||||
reg [bits-1 :0] mem[words-1 : 0];
|
||||
|
||||
endmodule
|
||||
Executable
+28
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
v_flags2 => ["--savable"],
|
||||
save_time => 500,
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>0,
|
||||
all_run_flags => ['+save_time=500'],
|
||||
);
|
||||
|
||||
-r "$Self->{obj_dir}/saved.vltsv" or $Self->error("Saved.vltsv not created\n");
|
||||
|
||||
execute (
|
||||
all_run_flags => ['+save_restore=1'],
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,77 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2012 by Wilson Snyder.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
/*verilator no_inline_module*/ // So we'll get hiearachy we can test
|
||||
input clk;
|
||||
|
||||
sub sub (/*AUTOINST*/
|
||||
// Inputs
|
||||
.clk (clk));
|
||||
endmodule
|
||||
|
||||
module sub (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
|
||||
input clk;
|
||||
/*verilator no_inline_module*/ // So we'll get hiearachy we can test
|
||||
|
||||
integer cyc=0;
|
||||
|
||||
reg [127:0] save128;
|
||||
reg [47:0] save48;
|
||||
reg [1:0] save2;
|
||||
reg [255:0] cycdone; // Make sure each cycle executes exactly once
|
||||
reg [31:0] vec[2:1][2:1];
|
||||
real r;
|
||||
string s,s2;
|
||||
|
||||
// Test loop
|
||||
always @ (posedge clk) begin
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("[%0t] cyc==%0d\n",$time, cyc);
|
||||
`endif
|
||||
cyc <= cyc + 1;
|
||||
if (cycdone[cyc[7:0]]) $stop;
|
||||
cycdone[cyc[7:0]] <= '1;
|
||||
if (cyc==0) begin
|
||||
// Setup
|
||||
save128 <= 128'hc77bb9b3784ea0914afe43fb79d7b71e;
|
||||
save48 <= 48'h4afe43fb79d7;
|
||||
save2 <= 2'b10;
|
||||
vec[1][1] <= 32'h0101;
|
||||
vec[1][2] <= 32'h0102;
|
||||
vec[2][1] <= 32'h0201;
|
||||
vec[2][2] <= 32'h0202;
|
||||
r <= 1.234;
|
||||
s <= "hello";
|
||||
end
|
||||
if (cyc==1) begin
|
||||
if ($test$plusargs("save_restore")!=0) begin
|
||||
// Don't allow the restored model to run from time 0, it must run from a restore
|
||||
$write("%%Error: didn't really restore\n");
|
||||
$stop;
|
||||
end
|
||||
end
|
||||
else if (cyc==99) begin
|
||||
if (save128 !== 128'hc77bb9b3784ea0914afe43fb79d7b71e) $stop;
|
||||
if (save48 !== 48'h4afe43fb79d7) $stop;
|
||||
if (save2 !== 2'b10) $stop;
|
||||
if (cycdone !== {{(256-99){1'b0}}, {99{1'b1}}}) $stop;
|
||||
if (vec[1][1] !== 32'h0101) $stop;
|
||||
if (vec[1][2] !== 32'h0102) $stop;
|
||||
if (vec[2][1] !== 32'h0201) $stop;
|
||||
if (vec[2][2] !== 32'h0202) $stop;
|
||||
if (r != 1.234) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,37 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2012 by Wilson Snyder.
|
||||
|
||||
package TEST_TYPES;
|
||||
typedef struct packed {
|
||||
logic stuff;
|
||||
} a_struct_t;
|
||||
endpackage // TEST_TYPES
|
||||
|
||||
module t(clk);
|
||||
input clk;
|
||||
TEST_TYPES::a_struct_t [3:0] a_out;
|
||||
sub sub (.a_out);
|
||||
always @ (posedge clk) begin
|
||||
if (a_out[0] != 1'b0) $stop;
|
||||
if (a_out[1] != 1'b1) $stop;
|
||||
if (a_out[2] != 1'b0) $stop;
|
||||
if (a_out[3] != 1'b1) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
|
||||
module sub(a_out);
|
||||
parameter n = 4;
|
||||
output TEST_TYPES::a_struct_t [n-1:0] a_out;
|
||||
always_comb begin
|
||||
for (int i=0;i<n;i++)
|
||||
a_out[i].stuff = i[0];
|
||||
end
|
||||
endmodule
|
||||
|
||||
// Local Variables:
|
||||
// verilog-typedef-regexp: "_t$"
|
||||
// End:
|
||||
@@ -15,6 +15,11 @@ module t;
|
||||
bit b0;
|
||||
} b4_t;
|
||||
|
||||
typedef struct packed { // [3:0]
|
||||
b4_t x1;
|
||||
b4_t x0;
|
||||
} b4x2_t;
|
||||
|
||||
typedef union packed { // [3:0]
|
||||
bit [3:0] quad0;
|
||||
b4_t quad1;
|
||||
@@ -60,7 +65,6 @@ module t;
|
||||
if (arr[1].four !== 4'b1010) $stop;
|
||||
//
|
||||
// Initialization
|
||||
`ifndef VERILATOR // UNSUPPORTED
|
||||
begin
|
||||
b4_t q = '{1'b1, 1'b1, 1'b0, 1'b0};
|
||||
if (q != 4'b1100) $stop;
|
||||
@@ -74,18 +78,21 @@ module t;
|
||||
if (q != 4'b1111) $stop;
|
||||
end
|
||||
begin
|
||||
b4_t q = '{b0:1'b1, b2:1'b1, b3:1'b1, b1:1'b0};
|
||||
if (q != 4'b1101) $stop;
|
||||
b4x2_t m = '{4'b1001, '{1'b1, 1'b0, 1'b1, 1'b1}};
|
||||
if (m != 8'b10011011) $stop;
|
||||
end
|
||||
begin
|
||||
b4_t q = '{default:1'b1};
|
||||
if (q != 4'b1111) $stop;
|
||||
q.b1 = 0;
|
||||
if (q != 4'b1101) $stop;
|
||||
{q.b3,q.b2} = 2'b10;
|
||||
if (q != 4'b1001) $stop;
|
||||
end
|
||||
`endif
|
||||
begin
|
||||
b4_t q = '{b0:1'b1, b2:1'b1, b3:1'b1, b1:1'b0};
|
||||
if (q != 4'b1101) $stop;
|
||||
end
|
||||
begin
|
||||
b4_t q = '{b2:1'b0, default:1'b1};
|
||||
if (q != 4'b1011) $stop;
|
||||
end
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
|
||||
@@ -7,8 +7,6 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
$Self->{vlt} and $Self->unsupported("Verilator unsupported, bug355");
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user