mirror of
https://github.com/verilator/verilator.git
synced 2026-10-02 16:13:34 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ad53833040 | ||
|
|
bc8c85668a | ||
|
|
d12a3dde45 | ||
|
|
301c878c0f | ||
|
|
bd55bfa071 | ||
|
|
6d2f09b579 | ||
|
|
4bfea7f54d | ||
|
|
55906486d8 | ||
|
|
d5478e6e08 | ||
|
|
d88d85c172 | ||
|
|
59c3c536c7 | ||
|
|
a007458cb8 | ||
|
|
d051912f21 | ||
|
|
a547158a50 | ||
|
|
95f2351aa0 | ||
|
|
698aaffb0b | ||
|
|
73eccecbf8 | ||
|
|
ae4a261463 | ||
|
|
c9f0d0cec2 | ||
|
|
4fa1e45d45 | ||
|
|
1b3d252bfe | ||
|
|
a9ba4a9fcd | ||
|
|
7f49619875 | ||
|
|
696660639a | ||
|
|
da4323062d | ||
|
|
a901e171b2 | ||
|
|
6e41d532fe | ||
|
|
4fc78ffb58 | ||
|
|
8137f41fc3 | ||
|
|
2e9471797d | ||
|
|
344248cea0 | ||
|
|
2789e3dba5 | ||
|
|
cca759a41e | ||
|
|
4f7b3d8882 | ||
|
|
2b330b78b7 | ||
|
|
d47ca1912b | ||
|
|
3fd2108b10 | ||
|
|
96e2a407f4 | ||
|
|
cdf18c96f4 | ||
|
|
53acaa05b8 | ||
|
|
fb85679068 | ||
|
|
9558e14479 | ||
|
|
4af0af93bf | ||
|
|
df4bc950fe | ||
|
|
250394f72b | ||
|
|
ca83fd6dc1 | ||
|
|
d5e9e7cd2b | ||
|
|
9a96f621ef | ||
|
|
5d7ce096c6 | ||
|
|
c9f8109c06 | ||
|
|
a20b4f2864 | ||
|
|
44a19d2a0a | ||
|
|
02f3beb8db | ||
|
|
3269cc3d90 | ||
|
|
fb70a1f4ab | ||
|
|
df0aa483ce | ||
|
|
c83f12a55c | ||
|
|
9704f59566 | ||
|
|
2923893d34 | ||
|
|
890dab0742 | ||
|
|
607e26b041 | ||
|
|
ea75290f65 | ||
|
|
a176054118 | ||
|
|
9a697dc5f5 | ||
|
|
cfdb852843 | ||
|
|
2e67a91982 | ||
|
|
074ca9330d | ||
|
|
f0d7cdcb20 | ||
|
|
40d961e059 | ||
|
|
e5de759236 | ||
|
|
e26a75c59d | ||
|
|
8701145b40 | ||
|
|
a2558886c8 | ||
|
|
f818ee86ae | ||
|
|
ad0dbdaa9c | ||
|
|
a9f14b294f | ||
|
|
a435ae98f9 | ||
|
|
481b261458 | ||
|
|
48df52d743 | ||
|
|
0af0d3b171 | ||
|
|
8287cf35e7 | ||
|
|
fab7924cc2 | ||
|
|
0ab739e8b1 | ||
|
|
2dcd4d171b | ||
|
|
e7f4d18c3d | ||
|
|
1611362c22 | ||
|
|
2327698160 | ||
|
|
71c1f00ec2 | ||
|
|
6574a126ef | ||
|
|
1e68086355 | ||
|
|
326cc8fd67 | ||
|
|
4afcb421bd | ||
|
|
8d21917035 | ||
|
|
4ca7f8834c | ||
|
|
b43299c8da | ||
|
|
b763809f5e | ||
|
|
2cb97f7475 | ||
|
|
6283df7491 | ||
|
|
acc4490370 | ||
|
|
f85c1a995a | ||
|
|
809e5fda8a | ||
|
|
dce245da5a | ||
|
|
d261c4cd27 | ||
|
|
c33299d542 | ||
|
|
ebdf8a5f3c | ||
|
|
c8852d183f | ||
|
|
9f161b20ef | ||
|
|
40f9d64973 | ||
|
|
4a2e68a0fd | ||
|
|
bcd90d3401 | ||
|
|
114af7d33f | ||
|
|
7b83d2de49 | ||
|
|
850de5913d | ||
|
|
bb9ee46f40 | ||
|
|
e94fc1305b | ||
|
|
3e4e8feb29 | ||
|
|
fedf347b1a | ||
|
|
285277a50b | ||
|
|
323c96f42f | ||
|
|
7dee344ea9 | ||
|
|
65bce588e4 | ||
|
|
233ff1b744 | ||
|
|
0837e39787 | ||
|
|
86db565a21 | ||
|
|
d6ac5e5001 | ||
|
|
e6443f1981 | ||
|
|
d13e6c73db | ||
|
|
79ca7f3cb5 | ||
|
|
cfd07ccd34 | ||
|
|
48047d523a | ||
|
|
eeb8fc2626 | ||
|
|
3d1baf3f2f | ||
|
|
4e382d6765 | ||
|
|
582963375d | ||
|
|
56c7c1bcc8 | ||
|
|
f88e57ddb8 | ||
|
|
9d98e012e4 | ||
|
|
d305a774f0 | ||
|
|
16b0c8d353 | ||
|
|
55da4fdbf6 | ||
|
|
ed2fbd8f25 | ||
|
|
42199bc8e5 | ||
|
|
7c5318768c | ||
|
|
aba25aab19 | ||
|
|
f99bd33f91 | ||
|
|
a6a6ce83f0 | ||
|
|
f4908a9758 | ||
|
|
5e4ca4b76a | ||
|
|
1e938d0e90 | ||
|
|
f3704f4c05 | ||
|
|
8800efe953 | ||
|
|
a320c4584e | ||
|
|
3841850168 | ||
|
|
beb3885840 | ||
|
|
06967c0c46 | ||
|
|
9a382c572c |
@@ -3,6 +3,144 @@ Revision history for Verilator
|
||||
The contributors that suggested a given feature are shown in []. [by ...]
|
||||
indicates the contributor was also the author of the fix; Thanks!
|
||||
|
||||
* Verilator 3.820 2011/07/28
|
||||
|
||||
** Support 'real' numbers and related functions.
|
||||
|
||||
*** Support 'const' variables in limited cases; similar to enums. [Alex Solomatnikov]
|
||||
|
||||
*** Support disable for loop escapes.
|
||||
|
||||
*** Support $fopen and I/O with integer instead of `verilator_file_descriptor.
|
||||
|
||||
*** Support coverage in -cc and -sc output modes. [John Li]
|
||||
Note this requires SystemPerl 1.338 or newer.
|
||||
|
||||
**** Fix vpi_register_cb using bad s_cb_data, bug370. [by Thomas Watts]
|
||||
|
||||
**** Fix $display missing leading zeros in %0d, bug367. [Alex Solomatnikov]
|
||||
|
||||
**** Use 'vluint64_t' for SystemC instead of (same sized) 'uint64' for MSVC++.
|
||||
|
||||
* Verilator 3.813 2011/06/28
|
||||
|
||||
*** Support bit vectors > 64 bits wide in DPI import and exports.
|
||||
|
||||
*** Fix out of memory on slice syntax error, bug354. [Alex Solomatnikov]
|
||||
|
||||
**** Fix error on enum references to other packages, bug339. [Alex Solomatnikov]
|
||||
|
||||
**** Fix DPI undeclared svBitVecVal compile error, bug346. [Chandan Egbert]
|
||||
|
||||
**** Fix DPI bit vector compile errors, bug347, bug359. [Chandan Egbert]
|
||||
|
||||
**** Fix CDCRSTLOGIC report showing endpoint flops without resets.
|
||||
|
||||
**** Fix compiler warnings on SPARC, bug288. [Ahmed El-Mahmoudy]
|
||||
|
||||
* Verilator 3.812 2011/04/06
|
||||
|
||||
*** Add --trace-max-width and --trace-max-array, bug319. [Alex Solomatnikov]
|
||||
|
||||
*** Add --Wno-fatal to turn off abort on warnings. [by Stefan Wallentowitz]
|
||||
|
||||
**** Support ${...} and $(...) env vars in .vc files. [by Stefan Wallentowitz]
|
||||
|
||||
**** Support $bits(data_type), bug327. [Alex Solomatnikov]
|
||||
|
||||
**** Support loop unrolling on width mismatches, bug333. [Joe Eiler]
|
||||
|
||||
**** Support simple cast operators, bug335. [Alex Solomatnikov]
|
||||
|
||||
**** Accelerate bit-selected inversions.
|
||||
|
||||
**** Add error on circular parameter definitions, bug329. [Alex Solomatnikov]
|
||||
|
||||
**** Fix concatenates and vectored bufif1, bug326. [Iztok Jeras]
|
||||
|
||||
* Verilator 3.811 2011/02/14
|
||||
|
||||
**** Report errors on duplicated or empty pins, bug321. [Christian Leber]
|
||||
|
||||
**** Report error on function call output tied to constant. [Bernard Deadman]
|
||||
|
||||
**** Throw UNUSED/UNDRIVEN only once per net in a parametrized module.
|
||||
|
||||
**** Fix internal error on functions called as SV tasks. [Bernard Deadman]
|
||||
|
||||
**** Fix internal error on non-inlined inout pins. [Jeff Winston]
|
||||
|
||||
**** Fix false BLKSEQ on non-unrolled for loop indexes. [Jeff Winston]
|
||||
|
||||
**** Fix block comment not separating identifiers, bug311. [Gene Sullivan]
|
||||
|
||||
**** Fix warnings to point to lowest net usage, not upper level ports.
|
||||
|
||||
**** Fix error on constants connected to outputs, bug323. [Christian Leber]
|
||||
|
||||
* Verilator 3.810 2011/01/03
|
||||
|
||||
** Add limited support for VPI access to public signals, see docs.
|
||||
|
||||
*** Add -F option to read relative option files, bug297. [Neil Hamilton]
|
||||
|
||||
*** Support ++,--,+= etc as standalone statements. [Alex Solomatnikov]
|
||||
|
||||
**** When running with VERILATOR_ROOT, optionally find binaries under bin.
|
||||
|
||||
**** Suppress WIDTH warnings when adding/subtracting 1'b1.
|
||||
|
||||
** Add -Wall, -Wwarn-style, -Wno-style to enable code style warnings
|
||||
that have been added to this release, and disabled by default:
|
||||
|
||||
*** With --Wall, add BLKSEQ warning on blocking assignments in seq blocks.
|
||||
|
||||
*** With --Wall, add DECLFILENAME warning on modules not matching filename.
|
||||
|
||||
*** With --Wall, add DEFPARAM warning on deprecated defparam statements.
|
||||
|
||||
*** With --Wall, add IFDEPTH warning on deep if statements.
|
||||
|
||||
*** With --Wall, add INCABSPATH warning on `include with absolute paths.
|
||||
|
||||
*** With --Wall, add SYNCASYNCNET warning on mixed sync/async reset nets.
|
||||
|
||||
*** With --Wall, add UNDRIVEN warning on undriven nets.
|
||||
|
||||
*** With --Wall, add UNUSED warning on unused nets.
|
||||
|
||||
*** The VARHIDDEN warning is now disabled by default, use -Wall to enable.
|
||||
|
||||
* Verilator 3.805 2010/11/02
|
||||
|
||||
**** Add warning when directory contains spaces, msg378. [Salman Sheikh]
|
||||
|
||||
**** Fix wrong filename on include file errors, bug289. [Brad Parker]
|
||||
|
||||
**** Fix segfault on SystemVerilog "output wire foo=0", bug291. [Joshua Wise]
|
||||
|
||||
**** Fix DPI export name not found, msg369. [Terry Chen]
|
||||
|
||||
* Verilator 3.804 2010/09/20
|
||||
|
||||
*** Support tracing/coverage of underscore signals, bug280. [by Jason McMullan]
|
||||
|
||||
**** Fix preprocessor `` of existing base define, bug283. [Usha Priyadharshini]
|
||||
|
||||
**** Increase define recursions before error. [Paul Liu]
|
||||
|
||||
**** On core dump, print debug suggestions.
|
||||
|
||||
* Verilator 3.803 2010/07/10
|
||||
|
||||
*** Fix preprocessor preservation of newlines across macro substitutions.
|
||||
|
||||
**** Fix preprocessor stringification of nested macros.
|
||||
|
||||
**** Fix some constant parameter functions causing crash, bug253. [Nick Bowler]
|
||||
|
||||
**** Fix do {...} while() not requiring final semicolon.
|
||||
|
||||
* Verilator 3.802 2010/05/01
|
||||
|
||||
*** Support runtime access to public signal names.
|
||||
@@ -1629,7 +1767,7 @@ of input ports exists for tracing.
|
||||
|
||||
This uses outline mode in Emacs. See C-h m [M-x describe-mode].
|
||||
|
||||
Copyright 2001-2010 by Wilson Snyder. This program is free software; you
|
||||
Copyright 2001-2011 by Wilson Snyder. This program is free software; you
|
||||
can redistribute it and/or modify it under the terms of either the GNU
|
||||
Lesser General Public License Version 3 or the Perl Artistic License
|
||||
Version 2.0.
|
||||
|
||||
+3
-2
@@ -9,7 +9,7 @@
|
||||
#
|
||||
#*****************************************************************************
|
||||
#
|
||||
# Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
# Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
@@ -118,8 +118,9 @@ DISTFILES_INC = $(INFOS) .gitignore Artistic COPYING COPYING.LESSER \
|
||||
src/.*ignore src/*.in src/*.cpp src/*.[chly] src/astgen src/bisonpre src/*fix \
|
||||
src/*.pl src/*.pod \
|
||||
test_*/.*ignore test_*/Makefile* test_*/*.cpp \
|
||||
test_*/*.pl test_*/*.v test_*/*.vc test_*/vlint \
|
||||
test_*/*.pl test_*/*.v test_*/*.vc test_*/*.vh \
|
||||
test_verilated/vgen*.pl \
|
||||
test_regress/t/tsub/*.v* \
|
||||
test_regress/t/*.cpp \
|
||||
test_regress/t/*.h \
|
||||
test_regress/t/*.dat \
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// DESCRIPTION: Verilator: List of To Do issues.
|
||||
//
|
||||
// Copyright 2004-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2004-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -62,11 +62,15 @@ Usability:
|
||||
* Print version/etc message at runtime. (4.000?)
|
||||
Include number of lines of code, percent comments, code complexity measurement
|
||||
<-80chars------------------------------------------------------------------->
|
||||
Verilator 3.600 - fast, free, open-sourced. Copyright 2001-2010.
|
||||
Verilator 3.600 - fast, free, open-sourced. Copyright 2001-2011.
|
||||
Verilated #### modules, #### instances, ##### sigs,
|
||||
#### non-comment lines, ##### ops, ### KB model size
|
||||
* Default the --l2name to remove extra "v" level of hierarchy (flag to make "top")
|
||||
|
||||
Lint:
|
||||
* CDCRSTLOGIC should allow filtering with paths
|
||||
"waive CDCRSTLOGIC --from a.b.sig --to a.c.sig --via OR"
|
||||
|
||||
Internal Code:
|
||||
* Eliminate the AstNUser* passed to all visitors; its only needed in V3Width,
|
||||
and removing it will speed up and simplify all the other code.
|
||||
|
||||
+431
-93
@@ -3,7 +3,7 @@ eval 'exec perl -wS $0 ${1+"$@"}'
|
||||
if 0;
|
||||
######################################################################
|
||||
#
|
||||
# Copyright 2003-2010 by Wilson Snyder. This program is free software; you
|
||||
# Copyright 2003-2011 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
@@ -78,15 +78,17 @@ if (! GetOptions (
|
||||
}
|
||||
|
||||
# Determine runtime flags and run
|
||||
if ($opt_gdbbt && !gdb_works()) {
|
||||
warn "-Info: --gdbbt ignored: gdb doesn't seem to be working\n" if $Debug;
|
||||
$opt_gdbbt = 0;
|
||||
}
|
||||
if ($opt_gdbbt && !$opt_gdb && $Debug) {
|
||||
# Run under GDB to get gdbbt
|
||||
run ("gdb ".verilator_bin()
|
||||
." --batch --quiet"
|
||||
." --batch --quiet --return-child-result"
|
||||
." -ex 'run ".join(' ',@Opt_Verilator_Sw)."'"
|
||||
." -ex 'set width 0'"
|
||||
." -ex 'bt'"
|
||||
." -ex 'c'");
|
||||
die "%Error: --gdbbt looses the exit status; so must assume run went badly...";
|
||||
." -ex 'bt'");
|
||||
} else {
|
||||
# Normal, non gdb
|
||||
run (($opt_gdb?"$opt_gdb ":"")
|
||||
@@ -113,9 +115,18 @@ sub debug {
|
||||
sub verilator_bin {
|
||||
my $bin = "";
|
||||
# Use VERILATOR_ROOT if defined, else assume verilator_bin is in the search path
|
||||
$bin .= $ENV{VERILATOR_ROOT}."/" if defined($ENV{VERILATOR_ROOT});
|
||||
$bin .= ($ENV{VERILATOR_BIN}
|
||||
|| ($Debug ? "verilator_bin_dbg" : "verilator_bin"));
|
||||
my $basename = ($ENV{VERILATOR_BIN}
|
||||
|| ($Debug ? "verilator_bin_dbg" : "verilator_bin"));
|
||||
if (defined($ENV{VERILATOR_ROOT})) {
|
||||
my $dir = $ENV{VERILATOR_ROOT};
|
||||
if (-x "$dir/bin/$basename") { # From a "make install" into VERILATOR_ROOT
|
||||
$bin = "$dir/bin/$basename";
|
||||
} else {
|
||||
$bin = "$dir/$basename"; # From pointing to kit directory
|
||||
}
|
||||
} else {
|
||||
$bin = $basename;
|
||||
}
|
||||
return $bin;
|
||||
}
|
||||
|
||||
@@ -123,9 +134,21 @@ sub verilator_bin {
|
||||
#######################################################################
|
||||
# Utilities
|
||||
|
||||
sub gdb_works {
|
||||
$! = undef; # Cleanup -x
|
||||
system("gdb /bin/echo"
|
||||
." --batch-silent --quiet --return-child-result"
|
||||
." -ex 'run -n'" # `echo -n`
|
||||
." -ex 'set width 0'"
|
||||
." -ex 'bt'");
|
||||
my $status = $?;
|
||||
return $status==0;
|
||||
}
|
||||
|
||||
sub run {
|
||||
# Run command, check errors
|
||||
my $command = shift;
|
||||
$! = undef; # Cleanup -x
|
||||
print "\t$command\n" if $Debug>=3;
|
||||
system($command);
|
||||
my $status = $?;
|
||||
@@ -137,6 +160,15 @@ sub run {
|
||||
warn "%Error: export VERILATOR_ROOT=".($ENV{VERILATOR_ROOT}||"")."\n";
|
||||
warn "%Error: $command\n";
|
||||
}
|
||||
if ($status & 255) {
|
||||
if (($status & 255) == 8 || ($status & 255) == 11) { # SIGFPA or SIGSEGV
|
||||
warn "%Error: Verilator internal fault, sorry. Consider trying --debug --gdbbt\n" if !$Debug;
|
||||
} elsif (($status & 255) == 6) { # SIGABRT
|
||||
warn "%Error: Verilator aborted. Consider trying --debug --gdbbt\n" if !$Debug;
|
||||
} else {
|
||||
warn "%Error: Verilator threw signal $status. Consider trying --debug --gdbbt\n" if !$Debug;
|
||||
}
|
||||
}
|
||||
die "%Error: Command Failed $command\n";
|
||||
}
|
||||
}
|
||||
@@ -199,7 +231,7 @@ descriptions in the next sections for more information.
|
||||
--bbox-sys Blackbox unknown $system calls
|
||||
--bbox-unsup Blackbox unsupported language features
|
||||
--bin <filename> Override Verilator binary
|
||||
-CFLAGS <flags> C++ Compiler flags for makefile
|
||||
-CFLAGS <flags> C++ Compiler flags for makefile
|
||||
--cc Create C++ output
|
||||
--cdc Clock domain crossing analysis
|
||||
--compiler <compiler-name> Tune for specified C++ compiler
|
||||
@@ -207,6 +239,7 @@ descriptions in the next sections for more information.
|
||||
--coverage-line Enable line coverage
|
||||
--coverage-toggle Enable toggle coverage
|
||||
--coverage-user Enable PSL/SVL user coverage
|
||||
--coverage-underscore Enable covarge of _signals
|
||||
-D<var>[=<value>] Set preprocessor define
|
||||
--debug Enable debugging
|
||||
--debug-check Enable debugging assertions
|
||||
@@ -214,17 +247,20 @@ descriptions in the next sections for more information.
|
||||
--debugi-<srcfile> <level> Enable debugging a source file at a level
|
||||
+define+<var>+<value> Set preprocessor define
|
||||
--dump-tree Enable dumping .tree files
|
||||
-E Preprocess, but do not compile
|
||||
-E Preprocess, but do not compile
|
||||
--error-limit <value> Abort after this number of errors
|
||||
--exe Link to create executable
|
||||
-F <file> Parse options from a file, relatively
|
||||
-f <file> Parse options from a file
|
||||
--help Display this help.
|
||||
--gdbbt Run Verilator under GDB for backtrace
|
||||
--help Display this help
|
||||
-I<dir> Directory to search for includes
|
||||
--if-depth <value> Tune IFDEPTH warning
|
||||
+incdir+<dir> Directory to search for includes
|
||||
--inhibit-sim Create function to turn off sim
|
||||
--inline-mult <value> Tune module inlining
|
||||
-LDFLAGS <flags> Linker pre-object flags for makefile
|
||||
-LDLIBS <flags> Linker library flags for makefile
|
||||
-LDFLAGS <flags> Linker pre-object flags for makefile
|
||||
-LDLIBS <flags> Linker library flags for makefile
|
||||
--language <lang> Language standard to parse
|
||||
+libext+<ext>+[ext]... Extensions for finding modules
|
||||
--lint-only Lint, but do not make output
|
||||
@@ -232,18 +268,18 @@ descriptions in the next sections for more information.
|
||||
--MP Create phony dependency targets
|
||||
--Mdir <directory> Name of output object directory
|
||||
--mod-prefix <topname> Name to prepend to lower classes
|
||||
--no-pins64 Don't use uint64_t's for 33-64 bit sigs
|
||||
--no-pins64 Don't use vluint64_t's for 33-64 bit sigs
|
||||
--no-skip-identical Disable skipping identical output
|
||||
+notimingchecks Ignored
|
||||
-O0 Disable optimizations
|
||||
-O3 High performance optimizations
|
||||
-O<optimization-letter> Selectable optimizations
|
||||
-o <executable> Name of final executable
|
||||
-o <executable> Name of final executable
|
||||
--output-split <bytes> Split .cpp files into pieces
|
||||
--output-split-cfuncs <statements> Split .ccp functions
|
||||
--pins-bv <bits> Specify types for top level ports
|
||||
--pins-uint8 Specify types for top level ports
|
||||
--pipe-filter <command> Filter all input through a script
|
||||
--pipe-filter <command> Filter all input through a script
|
||||
--prefix <topname> Name of top level class
|
||||
--profile-cfuncs Name functions for profiling
|
||||
--private Debugging; see docs
|
||||
@@ -256,15 +292,21 @@ descriptions in the next sections for more information.
|
||||
--top-module <topname> Name of top level input module
|
||||
--trace Enable waveform creation
|
||||
--trace-depth <levels> Depth of tracing
|
||||
--trace-max-array <bits> Maximum bit width for tracing
|
||||
--trace-max-width <depth> Maximum array depth for tracing
|
||||
--trace-underscore Enable tracing of _signals
|
||||
-U<var> Undefine preprocessor define
|
||||
--unroll-count <loops> Tune maximum loop iterations
|
||||
--unroll-stmts <stmts> Tune maximum loop body size
|
||||
--unused-regexp <regexp> Tune UNUSED lint signals
|
||||
-V Verbose version and config
|
||||
-v <filename> Verilog library
|
||||
-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
|
||||
-y <dir> Directory to search for modules
|
||||
|
||||
@@ -426,6 +468,11 @@ counting such behavior.
|
||||
A /*verilator coverage_off/on */ comment pair can be used around signals
|
||||
that do not need toggle analysis, such as RAMs and register files.
|
||||
|
||||
=item --coverage-underscore
|
||||
|
||||
Enable coverage of signals that start with an underscore. Normally, these
|
||||
signals are not covered. See also --trace-underscore.
|
||||
|
||||
=item --coverage-user
|
||||
|
||||
Enables user inserted functional coverage. Currently, all functional
|
||||
@@ -486,10 +533,28 @@ After this number of errors or warnings are encountered, exit. Defaults to
|
||||
Generate a executable. You will also need to pass additional .cpp files on
|
||||
the command line that implement the main loop for your simulation.
|
||||
|
||||
=item -F I<file>
|
||||
|
||||
Read the specified file, and act as if all text inside it was specified as
|
||||
command line parameters. Any relative paths are relative to the directory
|
||||
containing the specified file. See also -f. Note -F is fairly standard
|
||||
across Verilog tools.
|
||||
|
||||
=item -f I<file>
|
||||
|
||||
Read the specified file, and act as if all text inside it was specified as
|
||||
command line parameters. Note -f is fairly standard across Verilog tools.
|
||||
command line parameters. Any relative paths are relative to the current
|
||||
directory. See also -F. Note -f is fairly standard across Verilog tools.
|
||||
|
||||
The file may contain // comments which are ignored to the end of the line.
|
||||
Any $VAR, $(VAR), or ${VAR} will be replaced with the specified environment
|
||||
variable.
|
||||
|
||||
=item --gdbbt
|
||||
|
||||
If --debug is specified, run Verilator underneath a GDB process and print
|
||||
a backtrace on exit. Without --debug or if GDB doesn't seem to work, this
|
||||
flag is ignored.
|
||||
|
||||
=item --help
|
||||
|
||||
@@ -502,6 +567,11 @@ include directories or libraries. Same as +incdir and -y; +incdir and -y
|
||||
are fairly standard across Verilog tools while -I is an alias for GCC
|
||||
compatibility.
|
||||
|
||||
=item --if-depth I<value>
|
||||
|
||||
Rarely needed. Set the depth at which the IFDEPTH warning will fire,
|
||||
defaults to 0 which disables this warning.
|
||||
|
||||
=item +incdir+I<dir>
|
||||
|
||||
Add the directory to the list of directories that should be searched for
|
||||
@@ -547,12 +617,15 @@ appropriate `begin_keywords.
|
||||
|
||||
Specify the extensions that should be used for finding modules. If for
|
||||
example module I<x> is referenced, look in I<x>.I<ext>. Note +libext+ is
|
||||
fairly standard across Verilog tools.
|
||||
fairly standard across Verilog tools. Defaults to .v and .sv.
|
||||
|
||||
=item --lint-only
|
||||
|
||||
Check the files for lint violations only, do not create any other output.
|
||||
|
||||
You may also want the -Wall option to enable messages that are considered
|
||||
stylistic and not enabled by default.
|
||||
|
||||
If the design is not to be completely Verilated see also the --bbox-sys and
|
||||
--bbox-unsup options.
|
||||
|
||||
@@ -640,7 +713,7 @@ Backward compatible alias for "--pins-bv 65". Note that's a 65, not a 64.
|
||||
=item --pins-bv I<width>
|
||||
|
||||
Specifies SystemC inputs/outputs of greater than or equal to I<width> bits
|
||||
wide should use sc_bv's instead of uint32/uint64_t's. The default is
|
||||
wide should use sc_bv's instead of uint32/vluint64_t's. The default is
|
||||
"--pins-bv 65". Versions before Verilator 3.671 defaulted to "--pins-bv
|
||||
33". The more sc_bv is used, the worse for performance.
|
||||
|
||||
@@ -750,6 +823,23 @@ Specify the number of levels deep to enable tracing, for example
|
||||
entire model. Using a small number will decrease visibility, but greatly
|
||||
improve runtime and trace file size.
|
||||
|
||||
=item --trace-max-array I<bits>
|
||||
|
||||
Rarely needed. Specify the maximum array depth of a signal that may be
|
||||
traced. Defaults to 32, as tracing large arrays may greatly slow traced
|
||||
simulations.
|
||||
|
||||
=item --trace-max-width I<depth>
|
||||
|
||||
Rarely needed. Specify the maximum bit width of a signal that may be
|
||||
traced. Defaults to 256, as tracing large vectors may greatly slow traced
|
||||
simulations.
|
||||
|
||||
=item --trace-underscore
|
||||
|
||||
Enable tracing of signals that start with an underscore. Normally, these
|
||||
signals are not output during tracing. See also --coverage-underscore.
|
||||
|
||||
=item -UI<var>
|
||||
|
||||
Undefines the given preprocessor symbol.
|
||||
@@ -764,6 +854,12 @@ unrolled. See also BLKLOOPINIT warning.
|
||||
Rarely needed. Specifies the maximum number of statements in a loop for
|
||||
that loop to be unrolled. See also BLKLOOPINIT warning.
|
||||
|
||||
=item --unused-regexp I<regexp>
|
||||
|
||||
Rarely needed. Specifies a simple regexp with * and ? that if a signal
|
||||
name matches will suppress the UNUSED warning. Defaults to "*unused*".
|
||||
Setting it to "" disables matching.
|
||||
|
||||
=item -V
|
||||
|
||||
Shows the verbose version, including configuration information compiled
|
||||
@@ -775,6 +871,11 @@ 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 -Wall
|
||||
|
||||
Enable all warnings, including code style warnings that are normally
|
||||
disabled by default.
|
||||
|
||||
=item -Werror-I<message>
|
||||
|
||||
Convert the specified warning message into a error message. This is
|
||||
@@ -783,11 +884,11 @@ example C<-Werror-NOUNOPTFLAT>.
|
||||
|
||||
=item -Wfuture-I<message>
|
||||
|
||||
Suppress unknown Verilator comments or warning messages with the given
|
||||
message code. This is used to allow code written with pragmas for a later
|
||||
version of Verilator to run under a older version; add -Wfuture- arguments
|
||||
for each message code or comment that the new version supports which the
|
||||
older version does not support.
|
||||
Rarely needed. Suppress unknown Verilator comments or warning messages
|
||||
with the given message code. This is used to allow code written with
|
||||
pragmas for a later version of Verilator to run under a older version; add
|
||||
-Wfuture- arguments for each message code or comment that the new version
|
||||
supports which the older version does not support.
|
||||
|
||||
=item -Wno-I<message>
|
||||
|
||||
@@ -795,19 +896,49 @@ Disable the specified warning message.
|
||||
|
||||
=item -Wno-lint
|
||||
|
||||
Disable all lint related warning messages. This is equivalent to
|
||||
"-Wno-CASEINCOMPLETE -Wno-CASEOVERLAP -Wno-CASEX -Wno-CASEWITHX
|
||||
-Wno-CMPCONST -Wno-IMPLICIT -Wno-LITENDIAN -Wno-UNDRIVEN -Wno-UNSIGNED
|
||||
-Wno-UNUSED -Wno-VARHIDDEN -Wno-WIDTH".
|
||||
Disable all lint related warning messages, and all style warnings. This is
|
||||
equivalent to "-Wno-CASEINCOMPLETE -Wno-CASEOVERLAP -Wno-CASEX
|
||||
-Wno-CASEWITHX -Wno-CMPCONST -Wno-IMPLICIT -Wno-LITENDIAN -Wno-SYNCASYNCNET
|
||||
-Wno-UNDRIVEN -Wno-UNSIGNED -Wno-UNUSED -Wno-WIDTH" plus the list shown for
|
||||
Wno-style.
|
||||
|
||||
It is strongly recommended you cleanup your code rather than using this
|
||||
option, it is only intended to be use when running test-cases of code
|
||||
received from third parties.
|
||||
|
||||
=item -Wno-style
|
||||
|
||||
Disable all code style related warning messages (note by default they are
|
||||
already disabled). This is equivalent to "-Wno-DECLFILENAME -Wno-DEFPARAM
|
||||
-Wno-INCABSPATH -Wno-SYNCASYNCNET -Wno-UNDRIVEN -Wno-UNUSED
|
||||
-Wno-VARHIDDEN".
|
||||
|
||||
=item -Wno-fatal
|
||||
|
||||
When warnings are detected, print them, but do not exit the simulator.
|
||||
|
||||
Having warning messages in builds is sloppy. It is strongly recommended
|
||||
you cleanup your code, use inline lint_off, or use -Wno-... flags rather
|
||||
than using this option.
|
||||
|
||||
=item -Wwarn-I<message>
|
||||
|
||||
Enables the specified warning message.
|
||||
|
||||
=item -Wwarn-lint
|
||||
|
||||
Enable all lint related warning messages (note by default they are already
|
||||
enabled), but do not affect style messages. This is equivalent to
|
||||
"-Wwarn-CASEINCOMPLETE -Wwarn-CASEOVERLAP -Wwarn-CASEX -Wwarn-CASEWITHX
|
||||
-Wwarn-CMPCONST -Wwarn-IMPLICIT -Wwarn-LITENDIAN -Wwarn-REALCVT
|
||||
-Wwarn-UNSIGNED -Wwarn-WIDTH".
|
||||
|
||||
=item -Wwarn-style
|
||||
|
||||
Enable all code style related warning messages. This is equivalent to
|
||||
"-Wwarn-DECLFILENAME -Wwarn-DEFPARAM -Wwarn-INCABSPATH -Wwarn-SYNCASYNCNET
|
||||
-Wwarn-UNDRIVEN -Wwarn-UNUSED -Wwarn-VARHIDDEN".
|
||||
|
||||
=item -x-assign 0
|
||||
|
||||
=item -x-assign 1
|
||||
@@ -850,7 +981,7 @@ We'll compile this example into C++.
|
||||
|
||||
cat <<EOF >our.v
|
||||
module our;
|
||||
initial begin \$display("Hello World"); \$finish; end
|
||||
initial begin $display("Hello World"); $finish; end
|
||||
endmodule
|
||||
EOF
|
||||
|
||||
@@ -865,10 +996,15 @@ We'll compile this example into C++.
|
||||
}
|
||||
EOF
|
||||
|
||||
Now we run Verilator on our little example.
|
||||
If you installed Verilator from sources, or a tarball, but not as part of
|
||||
your operating system (as an RPM), first you need to point to the kit:
|
||||
|
||||
export VERILATOR_ROOT=/path/to/where/verilator/was/installed
|
||||
$VERILATOR_ROOT/bin/verilator --cc our.v --exe sim_main.cpp
|
||||
export PATH=$VERILATOR_ROOT/bin:$PATH
|
||||
|
||||
Now we run Verilator on our little example.
|
||||
|
||||
verilator -Wall --cc our.v --exe sim_main.cpp
|
||||
|
||||
We can see the source code under the "obj_dir" directory. See the FILES
|
||||
section below for descriptions of some of the files that were created.
|
||||
@@ -910,7 +1046,7 @@ This is an example similar to the above, but using SystemPerl.
|
||||
module our (clk);
|
||||
input clk; // Clock is required to get initial activation
|
||||
always @ (posedge clk)
|
||||
begin \$display("Hello World"); \$finish; end
|
||||
begin $display("Hello World"); $finish; end
|
||||
endmodule
|
||||
EOF
|
||||
|
||||
@@ -927,10 +1063,15 @@ This is an example similar to the above, but using SystemPerl.
|
||||
}
|
||||
EOF
|
||||
|
||||
Now we run Verilator on our little example.
|
||||
If you installed Verilator from sources, or a tarball, but not as part of
|
||||
your operating system (as an RPM), first you need to point to the kit:
|
||||
|
||||
export VERILATOR_ROOT=/path/to/where/verilator/was/installed
|
||||
$VERILATOR_ROOT/bin/verilator --sp our.v
|
||||
export PATH=$VERILATOR_ROOT/bin:$PATH
|
||||
|
||||
Now we run Verilator on our little example.
|
||||
|
||||
verilator -Wall --sp our.v
|
||||
|
||||
Then we convert the SystemPerl output to SystemC.
|
||||
|
||||
@@ -1141,7 +1282,8 @@ for debugging and selecting between multiple operating system builds.
|
||||
Specifies the directory containing the distribution kit. This is used to
|
||||
find the executable, Perl library, and include files. If not specified, it
|
||||
will come from a default optionally specified at configure time (before
|
||||
Verilator was compiled).
|
||||
Verilator was compiled). It should not be specified if using a pre-compiled
|
||||
Verilator RPM as the hardcoded value should be correct.
|
||||
|
||||
=back
|
||||
|
||||
@@ -1210,7 +1352,7 @@ will plug directly into a SystemC netlist.
|
||||
The SC_MODULE gets the same pinout as the Verilog module, with the
|
||||
following type conversions: Pins of a single bit become bool. Pins 2-32
|
||||
bits wide become uint32_t's. Pins 33-64 bits wide become sc_bv's or
|
||||
uint64_t's depending on the --no-pins64 switch. Wider pins become sc_bv's.
|
||||
vluint64_t's depending on the --no-pins64 switch. Wider pins become sc_bv's.
|
||||
(Uints simulate the fastest so are used where possible.)
|
||||
|
||||
Lower modules are not pure SystemC code. This is a feature, as using the
|
||||
@@ -1295,6 +1437,38 @@ The /*verilator sformat*/ indicates that this function accepts a $display
|
||||
like format specifier followed by any number of arguments to satisfy the
|
||||
format.
|
||||
|
||||
=head2 DPI Context Functions
|
||||
|
||||
Verilator supports IEEE DPI Context Functions. Context imports pass the
|
||||
simulator context, including calling scope name, and filename and line
|
||||
number to the C code. For example, in Verilog:
|
||||
|
||||
import "DPI-C" context function int dpic_line();
|
||||
initial $display("This is line %d, again, line %d\n", `line, dpic_line());
|
||||
|
||||
This will call C++ code which may then use the svGet* functions to read
|
||||
information, in this case the line number of the Verilog statement that
|
||||
invoked the dpic_line function:
|
||||
|
||||
int dpic_line() {
|
||||
// Get a scope: svScope scope = svGetScope();
|
||||
|
||||
const char* scopenamep = svGetNameFromScope(scope);
|
||||
assert(scopenamep);
|
||||
|
||||
const char* filenamep = "";
|
||||
int lineno = 0;
|
||||
if (svGetCallerInfo(&filenamep, &lineno)) {
|
||||
printf("dpic_line called from scope %s on line %d\n",
|
||||
scopenamep, lineno);
|
||||
return lineno;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
See the IEEE Standard for more information.
|
||||
|
||||
=head2 DPI Header Isolation
|
||||
|
||||
Verilator places the IEEE standard header files such as svdpi.h into a
|
||||
@@ -1306,12 +1480,64 @@ svdpi.h and similar standard files with different contents, the vltstd
|
||||
directory should not be included to prevent picking up incompatible
|
||||
definitions.
|
||||
|
||||
=head2 Public Functions
|
||||
=head2 Public Functions
|
||||
|
||||
Instead of DPI exporting, there's also Verilator public functions, which
|
||||
are slightly faster, but less compatible.
|
||||
|
||||
|
||||
=head1 VERIFICATION PROCEDURAL INTERFACE (VPI)
|
||||
|
||||
Verilator supports a very limited subset of the VPI. This subset allows
|
||||
inspection, examination, value change callbacks, and depositing of values
|
||||
to public signals only.
|
||||
|
||||
To access signals via the VPI, Verilator must be told exactly which signals
|
||||
are to be accessed. This is done using the Verilator public pragmas
|
||||
documented below.
|
||||
|
||||
Verilator has an important difference from an event based simulator; signal
|
||||
values that are changed by the VPI will not immediately propagate their
|
||||
values, instead the top level header file's eval() method must be called.
|
||||
Normally this would be part of the normal evaluation (IE the next clock
|
||||
edge), not as part of the value change. This makes the performance of VPI
|
||||
routines extremely fast compared to event based simulators, but can confuse
|
||||
some test-benches that expect immediate propagation.
|
||||
|
||||
Note the VPI by it's specified implementation will always be much slower
|
||||
than accessing the Verilator values by direct reference
|
||||
(structure->module->signame), as the VPI accessors perform lookup in
|
||||
functions at runtime requiring at best hundreds of instructions, while the
|
||||
direct references are evaluated by the compiler and result in only a couple
|
||||
of instructions.
|
||||
|
||||
=head2 VPI Example
|
||||
|
||||
In the below example, we have readme marked read-only, and writeme which if
|
||||
written from outside the model will have the same semantics as if it
|
||||
changed on the specified clock edge.
|
||||
|
||||
module t;
|
||||
reg readme /*verilator public_flat_rd*/;
|
||||
reg writeme /*verilator public_flat_rw @(posedge clk) */;
|
||||
endmodule
|
||||
|
||||
There are many online tutorials and books on the VPI, but an example that
|
||||
accesses the above would be:
|
||||
|
||||
void read_and_check() {
|
||||
vpiHandle vh1 = vpi_handle_by_name((PLI_BYTE8*)"t.readme", NULL);
|
||||
if (!vh1) { error... }
|
||||
const char* name = vpi_get_str(vpiName, vh1);
|
||||
printf("Module name: %s\n"); // Prints "readme"
|
||||
|
||||
s_vpi_value v;
|
||||
v.format = vpiIntVal;
|
||||
vpi_get_value(vh1, &v);
|
||||
printf("Value of v: %d\n", v.value.integer); // Prints "readme"
|
||||
}
|
||||
|
||||
|
||||
=head1 CROSS COMPILATION
|
||||
|
||||
Verilator supports cross-compiling Verilated code. This is generally used
|
||||
@@ -1389,20 +1615,25 @@ Verilator configuration commands.
|
||||
|
||||
=item coverage_off [-file "<filename>" [-lines <line> [ - <line> ]]]
|
||||
|
||||
Disable coverage for the specified filename (or all files if omitted) and
|
||||
range of line numbers (or all lines if omitted). Often used to ignore an
|
||||
entire module for coverage analysis purposes.
|
||||
Disable coverage for the specified filename (or wildcard with '*' or '?',
|
||||
or all files if omitted) and range of line numbers (or all lines if
|
||||
omitted). Often used to ignore an entire module for coverage analysis
|
||||
purposes.
|
||||
|
||||
=item lint_off -msg <message> [-file "<filename>" [-lines <line> [ - <line>]]]
|
||||
=item lint_off [-msg <message>] [-file "<filename>" [-lines <line> [ - <line>]]]
|
||||
|
||||
Disables the specified lint warning in the specified filename (or all files
|
||||
if omitted) and range of line numbers (or all lines if omitted).
|
||||
Disables the specified lint warning, in the specified filename (or wildcard
|
||||
with '*' or '?', or all files if omitted) and range of line numbers (or all
|
||||
lines if omitted).
|
||||
|
||||
If the -msg is omitted, all lint warnings are disabled. This will override
|
||||
all later lint warning enables for the specified region.
|
||||
|
||||
=item tracing_off [-file "<filename>" [-lines <line> [ - <line> ]]]
|
||||
|
||||
Disable waveform tracing for all future signals declared in the specified
|
||||
filename (or all files if omitted) and range of line numbers (or all lines
|
||||
if omitted).
|
||||
filename (or wildcard with '*' or '?', or all files if omitted) and range
|
||||
of line numbers (or all lines if omitted).
|
||||
|
||||
=back
|
||||
|
||||
@@ -1430,7 +1661,7 @@ please file a bug if a feature you need is missing.
|
||||
Verilator supports ==? and !=? operators, ++ and -- in some contexts,
|
||||
$bits, $countones, $error, $fatal, $info, $isunknown, $onehot, $onehot0,
|
||||
$unit, $warning, always_comb, always_ff, always_latch, bit, byte, chandle,
|
||||
do-while, enum, export, final, import, int, logic, longint, package,
|
||||
const, do-while, enum, export, final, import, int, logic, longint, package,
|
||||
program, shortint, time, typedef, var, void, priority case/if, and unique
|
||||
case/if.
|
||||
|
||||
@@ -1480,8 +1711,8 @@ assertion clocks.
|
||||
=head2 Synthesis Directive Assertion Support
|
||||
|
||||
With the --assert switch, Verilator reads any "//synopsys full_case" or "//
|
||||
synopsys parallel_case" directives. The same applies to any "//cadence" or
|
||||
"// ambit synthesis" directives of the same form.
|
||||
synopsys parallel_case" directives. The same applies to any "// ambit
|
||||
synthesis", "//cadence" or "//pragma" directives of the same form.
|
||||
|
||||
When these synthesis directives are discovered, Verilator will either
|
||||
formally prove the directive to be true, or failing that, will insert the
|
||||
@@ -1865,7 +2096,7 @@ that Verilator will print a list of known scopes to help your debugging.
|
||||
|
||||
=head2 Floating Point
|
||||
|
||||
Floating Point numbers are not synthesizable, and so not supported.
|
||||
Floating Point (real) numbers are supported.
|
||||
|
||||
=head2 Latches
|
||||
|
||||
@@ -1908,7 +2139,7 @@ of the form:
|
||||
|
||||
inout driver;
|
||||
wire driver = (enable) ? output_value : 1'bz;
|
||||
|
||||
|
||||
Will be converted to
|
||||
|
||||
input driver__in; // Value being driven in from "external" drivers
|
||||
@@ -2011,11 +2242,29 @@ supply1, task, time, tri, typedef, var, vectored, while, wire, xnor, xor
|
||||
|
||||
Generally supported.
|
||||
|
||||
=item ++, -- operators
|
||||
|
||||
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 cast operator
|
||||
|
||||
Casting is supported only between simple scalar types, signed and unsigned,
|
||||
not arrays nor structs.
|
||||
|
||||
=item chandle
|
||||
|
||||
Treated as a "longint"; does not yet warn about operations that are
|
||||
specified as illegal on chandles.
|
||||
|
||||
=item disable
|
||||
|
||||
Disable statements may be used only if the block being disabled is a block
|
||||
the disable statement itself is inside. This was commonly used to provide
|
||||
loop break and continue functionality before SystemVerilog added the break
|
||||
and continue keywords.
|
||||
|
||||
=item priority if, unique if
|
||||
|
||||
Priority and unique if's are treated as normal ifs and not asserted to be
|
||||
@@ -2064,11 +2313,6 @@ The rarely used optional parameter to $finish and $stop is ignored.
|
||||
|
||||
File descriptors passed to the file PLI calls must be file descriptors, not
|
||||
MCDs, which includes the mode parameter to $fopen being mandatory.
|
||||
Verilator will convert the integer used to hold the file descriptor into a
|
||||
internal FILE*. To prevent core dumps due to mis-use, and because integers
|
||||
are 32 bits while FILE*s may be 64 bits, the descriptor must be stored in a
|
||||
reg [63:0] rather than an integer. The define `verilator_file_descriptor in
|
||||
verilated.v can be used to hide this difference.
|
||||
|
||||
=item $fscanf, $sscanf
|
||||
|
||||
@@ -2092,10 +2336,6 @@ Read memory commands should work properly. Note Verilator and the Verilog
|
||||
specification does not include support for readmem to multi-dimensional
|
||||
arrays.
|
||||
|
||||
=item $realtime
|
||||
|
||||
Treated as $time.
|
||||
|
||||
=item $test$plusargs, $value$plusargs
|
||||
|
||||
Supported, but the instantiating C++/SystemC testbench must call
|
||||
@@ -2158,6 +2398,20 @@ inside a public task.
|
||||
Ignoring this warning may make Verilator simulations differ from other
|
||||
simulators.
|
||||
|
||||
=item BLKSEQ
|
||||
|
||||
This indicates that a blocking assignment (=) is used in a sequential
|
||||
block. Generally non-blocking/delayed assignments (<=) are used in
|
||||
sequential blocks, to avoid the possibility of simulator races. It can be
|
||||
reasonable to do this if the generated signal is used ONLY later in the
|
||||
same block, however this style is generally discouraged as it is error
|
||||
prone.
|
||||
|
||||
always @ (posedge clk) foo = ...
|
||||
|
||||
Disabled by default as this is a code style warning; it will simulate
|
||||
correctly.
|
||||
|
||||
=item BLKLOOPINIT
|
||||
|
||||
This indicates that the initialization of an array needs to use non-delayed
|
||||
@@ -2242,6 +2496,26 @@ L<http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA_rev1_2.pdf>
|
||||
Ignoring this warning may make Verilator simulations differ from other
|
||||
simulators.
|
||||
|
||||
=item DECLFILENAME
|
||||
|
||||
Warns that a module or other declaration's name doesn't match the filename
|
||||
with path and extension stripped that it is declared in. The filename a
|
||||
modules/interfaces/programs is declared in should match the name of the
|
||||
module etc. so that -y directory searching will work. This warning is
|
||||
printed for only the first mismatching module in any given file, and -v
|
||||
library files are ignored.
|
||||
|
||||
Disabled by default as this is a code style warning; it will simulate
|
||||
correctly.
|
||||
|
||||
=item DEFPARAM
|
||||
|
||||
Warns that the "defparam" statement was deprecated in Verilog 2001 and all
|
||||
designs should now be using the #(...) format to specify parameters.
|
||||
|
||||
Disabled by default as this is a code style warning; it will simulate
|
||||
correctly.
|
||||
|
||||
=item GENCLK
|
||||
|
||||
Warns that the specified signal is generated, but is also being used as a
|
||||
@@ -2255,6 +2529,16 @@ additional ones.)
|
||||
Ignoring this warning may make Verilator simulations differ from other
|
||||
simulators.
|
||||
|
||||
=item IFDEPTH
|
||||
|
||||
Warns that if/if else statements have exceeded the depth specified with
|
||||
--if-depth, as they are likely to result in slow priority encoders. Unique
|
||||
and priority if statements are ignored. Solutions include changing the
|
||||
code to a case statement, or a SystemVerilog 'unique if' or 'priority if'.
|
||||
|
||||
Disabled by default as this is a code style warning; it will simulate
|
||||
correctly.
|
||||
|
||||
=item IMPERFECTSCH
|
||||
|
||||
Warns that the scheduling of the model is not absolutely perfect, and some
|
||||
@@ -2283,6 +2567,17 @@ Verilator cannot schedule these variables correctly.
|
||||
Ignoring this warning may make Verilator simulations differ from other
|
||||
simulators.
|
||||
|
||||
=item INCABSPATH
|
||||
|
||||
Warns that an `include filename specifies an absolute path. This means the
|
||||
code will not work on any other system with a different file system layout.
|
||||
Instead of using absolute paths, relative paths (preferably without any
|
||||
directory specified whatever) should be used, and +include used on the
|
||||
command line to specify the top include source directory.
|
||||
|
||||
Disabled by default as this is a code style warning; it will simulate
|
||||
correctly.
|
||||
|
||||
=item LITENDIAN
|
||||
|
||||
Warns that a vector is declared with little endian bit numbering
|
||||
@@ -2320,6 +2615,11 @@ not really needed. The best solution is to insure that each module is in a
|
||||
unique file by the same name. Otherwise, make sure all library files are
|
||||
read in as libraries with -v, instead of automatically with -y.
|
||||
|
||||
=item REALCVT
|
||||
|
||||
Warns that a real number is being implicitly rounded to an integer, with
|
||||
possible loss of precision.
|
||||
|
||||
=item REDEFMACRO
|
||||
|
||||
Warns that you have redefined the same macro with a different value, for
|
||||
@@ -2354,6 +2654,18 @@ name would result in odd C compiler errors. You may disable this error
|
||||
message as you would disable warnings, but the symbol will be renamed by
|
||||
Verilator to avoid the conflict.
|
||||
|
||||
=item SYNCASYNCNET
|
||||
|
||||
Warns that the specified net is used in at least two different always
|
||||
statements with posedge/negedges (i.e. a flop). One usage has the signal
|
||||
in the sensitivity list and body, probably as a async reset, and the other
|
||||
usage has the signal only in the body, probably as a sync reset. Mixing
|
||||
sync and async resets is usually a mistake. The warning may be disabled
|
||||
with a lint_off pragma around the net, or either flopped block.
|
||||
|
||||
Disabled by default as this is a code style warning; it will simulate
|
||||
correctly.
|
||||
|
||||
=item TASKNSVAR
|
||||
|
||||
Error when a call to a task or function has a output from that task tied to
|
||||
@@ -2379,9 +2691,11 @@ cases would result in simulator mismatches.
|
||||
|
||||
=item UNDRIVEN
|
||||
|
||||
Warns that the specified signal is never sourced.
|
||||
Warns that the specified signal is never sourced. Verilator is fairly
|
||||
liberal in the usage calculations; making a signal public, or loading only
|
||||
a single array element marks the entire signal as driven.
|
||||
|
||||
Ignoring this warning will only suppress the lint check, it will simulate
|
||||
Disabled by default as this is a code style warning; it will simulate
|
||||
correctly.
|
||||
|
||||
=item UNOPT
|
||||
@@ -2464,12 +2778,31 @@ correctly.
|
||||
|
||||
=item UNUSED
|
||||
|
||||
Warns that the specified signal is never sinked. This is a future message,
|
||||
currently Verilator will not produce this warning.
|
||||
Warns that the specified signal is never sinked. Verilator is fairly
|
||||
liberal in the usage calculations; making a signal public, a signal
|
||||
matching --unused-regexp ("*unused*") or accessing only a single array
|
||||
element marks the entire signal as used.
|
||||
|
||||
Ignoring this warning will only suppress the lint check, it will simulate
|
||||
Disabled by default as this is a code style warning; it will simulate
|
||||
correctly.
|
||||
|
||||
A recommended style for unused nets is to put at the bottom of a file code
|
||||
similar to the following:
|
||||
|
||||
wire _unused_ok = &{1'b0,
|
||||
sig_not_used_a,
|
||||
sig_not_used_yet_b, // To be fixed
|
||||
1'b0};
|
||||
|
||||
The reduction AND and constant zeros mean the net will always be zero, so
|
||||
won't use simulation time. The redundant leading and trailing zeros avoid
|
||||
syntax errors if there are no signals between them. The magic name
|
||||
"unused" (-unused-regexp) is recognized by Verilator and suppresses
|
||||
warnings; if using other lint tools, either teach to tool to ignore signals
|
||||
with "unused" in the name, or put the appropriate lint_off around the wire.
|
||||
Having unused signals in one place makes it easy to find what is unused,
|
||||
and reduces the number of lint_off pragmas, reducing bugs.
|
||||
|
||||
=item VARHIDDEN
|
||||
|
||||
Warns that a task, function, or begin/end block is declaring a variable by
|
||||
@@ -2477,7 +2810,7 @@ the same name as a variable in the upper level module or begin/end block
|
||||
(thus hiding the upper variable from being able to be used.) Rename the
|
||||
variable to avoid confusion when reading the code.
|
||||
|
||||
Ignoring this warning will only suppress the lint check, it will simulate
|
||||
Disabled by default as this is a code style warning; it will simulate
|
||||
correctly.
|
||||
|
||||
=item WIDTH
|
||||
@@ -2636,7 +2969,7 @@ finally call "trace_object->close()". For an example, see below and the
|
||||
test_c/sim_main.cpp file of the distribution.
|
||||
|
||||
You also need to compile verilated_vcd_c.cpp and add it to your link,
|
||||
preferably by adding the dependancies in $(VK_GLOBAL_OBJS) to your
|
||||
preferably by adding the dependencies in $(VK_GLOBAL_OBJS) to your
|
||||
Makefile's link rule. This is done for you if using the Verilator --exe
|
||||
flag.
|
||||
|
||||
@@ -2676,7 +3009,7 @@ question, however the timescale and timeprecision will not inherited from
|
||||
your SystemC settings.
|
||||
|
||||
You also need to compile verilated_vcd_sc.cpp and verilated_vcd_c.cpp and
|
||||
add them to your link, preferably by adding the dependancies in
|
||||
add them to your link, preferably by adding the dependencies in
|
||||
$(VK_GLOBAL_OBJS) to your Makefile's link rule. This is done for you if
|
||||
using the Verilator --exe flag.
|
||||
|
||||
@@ -2721,8 +3054,8 @@ network disk. Network disks are generally far slower.
|
||||
=item How do I do coverage analysis?
|
||||
|
||||
Verilator supports both block (line) coverage and user inserted functional
|
||||
coverage. Both currently require SystemPerl output mode and the SystemPerl
|
||||
package.
|
||||
coverage. Both require the SystemPerl package to be installed but do not
|
||||
require use of the SystemPerl output mode.
|
||||
|
||||
First, run verilator with the --coverage option. If you're using your own
|
||||
makefile, compile the model with the GCC flag -DSP_COVERAGE_ENABLE (if
|
||||
@@ -2790,11 +3123,11 @@ Makefile's link rule.
|
||||
|
||||
=item Is the PLI supported?
|
||||
|
||||
No, but the DPI is.
|
||||
Only somewhat. More specifically, the common PLI-ish calls $display,
|
||||
$finish, $stop, $time, $write are converted to C++ equivalents. You can
|
||||
also use the "import DPI" SystemVerilog feature to call C code (see the
|
||||
chapter above). There is also limited VPI access to public signals.
|
||||
|
||||
More specifically, the common PLI-ish calls $display, $finish, $stop,
|
||||
$time, $write are converted to C++ equivalents. You can also use the
|
||||
"import DPI" SystemVerilog feature to call C code (see the chapter above).
|
||||
If you want something more complex, since Verilator emits standard C++
|
||||
code, you can simply write your own C++ routines that can access and modify
|
||||
signal values without needing any PLI interface code, and call it with
|
||||
@@ -2845,7 +3178,7 @@ as you would any other member variable.
|
||||
|
||||
Signals are the smallest of 8 bit chars, 16 bit shorts, 32 bit longs, or 64
|
||||
bit long longs that fits the width of the signal. Generally, you can use
|
||||
just uint32_t's for 1 to 32 bits, or uint64_t for 1 to 64 bits, and the
|
||||
just uint32_t's for 1 to 32 bits, or vluint64_t for 1 to 64 bits, and the
|
||||
compiler will properly up-convert smaller entities.
|
||||
|
||||
Signals wider than 64 bits are stored as an array of 32-bit uint32_t's.
|
||||
@@ -2966,25 +3299,30 @@ Brooks, Duane Galbi, Paul Wasson, and Wilson Snyder. Major testers include
|
||||
Jeff Dutton, Ralf Karge, David Hewson, Wim Michiels, and Gene Weber.
|
||||
|
||||
Some of the people who have provided ideas and feedback for Verilator
|
||||
include David Addison, Hans Van Antwerpen, Vasu Arasanipalai, Jens Arm, J
|
||||
include: David Addison, Hans Van Antwerpen, Vasu Arasanipalai, Jens Arm, J
|
||||
Baxter, Jeremy Bennett, David Black, Gregg Bouchard, Christopher Boumenot,
|
||||
Byron Bradley, Bryan Brady, Lane Brooks, John Brownlee, Lawrence Butcher,
|
||||
Chris Candler, Lauren Carlson, Donal Casey, Robert A. Clark, Allan
|
||||
Cochrane, Gunter Dannoritzer, Bernard Deadman, John Deroo, John Dickol,
|
||||
Danny Ding, Alex Duller, Jeff Dutton, Robert Farrell, Eugen Fekete, Andrea
|
||||
Foletto, Bob Fredieu, Shankar Giri, Sam Gladstone, Chitlesh Goorah, Thomas
|
||||
Hawkins, David Hewson, Jae Hossell, Ben Jackson, Mike Kagen, Guy-Armand
|
||||
Kamendje, Vasu Kandadi, Patricio Kaplan, Ralf Karge, Dan Katz, Sol Katzman,
|
||||
Jonathan Kimmitt, Gernot Koch, Soon Koh, Steve Kolecki, Steve Lang,
|
||||
Stephane Laurent, Charlie Lind, Dan Lussier, Fred Ma, Duraid Madina, Mark
|
||||
Marshall, Wim Michiels, Dennis Muhlestein, John Murphy, Richard Myers,
|
||||
Dimitris Nalbantis, Paul Nitza, Pete Nixon, Lisa Noack, Mark Nodine,
|
||||
Andreas Olofsson, Niranjan Prabhu, Oleg Rodionov, John Sanguinetti, Mike
|
||||
Shinkarovsky, Rafael Shirakawa, Rodney Sinclair, Brian Small, Art Stamness,
|
||||
John Stroebel, Emerson Suguimoto, Renga Sundararajan, Stefan Thiede, Gary
|
||||
Thomas, Steve Tong, Holger Waechtler, Shawn Wang, Greg Waters, Eugene
|
||||
Weber, Leon Wildman, Gerald Williams, Jeff Winston, Johan Wouters, and Ding
|
||||
Xiaoliang.
|
||||
Nick Bowler, Byron Bradley, Bryan Brady, Lane Brooks, John Brownlee,
|
||||
Lawrence Butcher, Chris Candler, Lauren Carlson, Donal Casey, Terry Chen,
|
||||
Robert A. Clark, Allan Cochrane, Gunter Dannoritzer, Ashutosh Das, Bernard
|
||||
Deadman, John Deroo, John Dickol, Danny Ding, Ivan Djordjevic, Alex Duller,
|
||||
Jeff Dutton, Chandan Egbert, Joe Eiler, Ahmed El-Mahmoudy, Robert Farrell,
|
||||
Eugen Fekete, Andrea Foletto, Bob Fredieu, Shankar Giri, Sam Gladstone,
|
||||
Amir Gonnen, Chitlesh Goorah, Neil Hamilton, Thomas Hawkins, David Hewson,
|
||||
Jae Hossell, Ben Jackson, Iztok Jeras, Mike Kagen, Guy-Armand Kamendje,
|
||||
Vasu Kandadi, Patricio Kaplan, Ralf Karge, Dan Katz, Sol Katzman, Jonathan
|
||||
Kimmitt, Gernot Koch, Soon Koh, Steve Kolecki, Steve Lang, Stephane
|
||||
Laurent, Christian Leber, Charlie Lind, Paul Liu, Dan Lussier, Fred Ma,
|
||||
Duraid Madina, Mark Marshall, Jason McMullan, Wim Michiels, Dennis
|
||||
Muhlestein, John Murphy, Richard Myers, Dimitris Nalbantis, Paul Nitza,
|
||||
Pete Nixon, Lisa Noack, Mark Nodine, Andreas Olofsson, Brad Parker, Dominic
|
||||
Plunkett, Niranjan Prabhu, Usha Priyadharshini, Oleg Rodionov, John
|
||||
Sanguinetti, Salman Sheikh, Mike Shinkarovsky, Rafael Shirakawa, Jeffrey
|
||||
Short, Rodney Sinclair, Brian Small, Alex Solomatnikov, Art Stamness, John
|
||||
Stroebel, Emerson Suguimoto, Gene Sullivan, Renga Sundararajan, Stefan
|
||||
Thiede, Gary Thomas, Steve Tong, Holger Waechtler, Stefan Wallentowitz,
|
||||
Shawn Wang, Greg Waters, Eugene Weber, David Welch, Leon Wildman, Gerald
|
||||
Williams, Trevor Williams, Jeff Winston, Joshua Wise, Johan Wouters, and
|
||||
Ding Xiaoliang.
|
||||
|
||||
Thanks all.
|
||||
|
||||
@@ -2993,7 +3331,7 @@ Thanks all.
|
||||
|
||||
The latest version is available from L<http://www.veripool.org/>.
|
||||
|
||||
Copyright 2003-2010 by Wilson Snyder. Verilator is free software; you can
|
||||
Copyright 2003-2011 by Wilson Snyder. Verilator is free software; you can
|
||||
redistribute it and/or modify the Verilator internals under the terms of
|
||||
either the GNU Lesser General Public License Version 3 or the Perl Artistic
|
||||
License Version 2.0.
|
||||
|
||||
@@ -177,7 +177,7 @@ Do not show differences in line numbering.
|
||||
|
||||
The latest version is available from L<http://www.veripool.org/verilator>.
|
||||
|
||||
Copyright 2005-2010 by Wilson Snyder. This package is free software; you can
|
||||
Copyright 2005-2011 by Wilson Snyder. This package 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.
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ eval 'exec perl -wS $0 ${1+"$@"}'
|
||||
if 0;
|
||||
# DESCRIPTION: Print include statements for each ARGV
|
||||
#
|
||||
# Copyright 2003-2010 by Wilson Snyder. This package is free software; you can
|
||||
# Copyright 2003-2011 by Wilson Snyder. This package 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.
|
||||
######################################################################
|
||||
|
||||
@@ -208,7 +208,7 @@ Displays this message and program version and exits.
|
||||
|
||||
The latest version is available from L<http://www.veripool.org/>.
|
||||
|
||||
Copyright 2007-2010 by Wilson Snyder. Verilator is free software; you can
|
||||
Copyright 2007-2011 by Wilson Snyder. Verilator 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.
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
dnl DESCRIPTION: Process this file with autoconf to produce a configure script.
|
||||
dnl
|
||||
dnl Copyright 2003-2010 by Wilson Snyder. Verilator is free software; you can
|
||||
dnl Copyright 2003-2011 by Wilson Snyder. Verilator is free software; you can
|
||||
dnl redistribute it and/or modify it under the terms of either the GNU Lesser
|
||||
dnl General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||
|
||||
|
||||
+54
-13
@@ -1,7 +1,7 @@
|
||||
// -*- C++ -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||
// Version 2.0.
|
||||
@@ -26,7 +26,6 @@
|
||||
#define _VERILATED_CPP_
|
||||
#include "verilated_imp.h"
|
||||
#include <cctype>
|
||||
#include <vector>
|
||||
|
||||
#define VL_VALUE_STRING_MAX_WIDTH 1024 ///< Max static char array for VL_VALUE_STRING
|
||||
|
||||
@@ -285,12 +284,15 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
||||
// Note also assumes variables < 64 are not wide, this assumption is
|
||||
// sometimes not true in low-level routines written here in verilated.cpp
|
||||
static VL_THREAD char tmp[VL_VALUE_STRING_MAX_WIDTH];
|
||||
static VL_THREAD char tmpf[VL_VALUE_STRING_MAX_WIDTH];
|
||||
const char* pctp = NULL; // Most recent %##.##g format
|
||||
bool inPct = false;
|
||||
bool widthSet = false;
|
||||
int width = 0;
|
||||
const char* pos = formatp;
|
||||
for (; *pos; ++pos) {
|
||||
if (!inPct && pos[0]=='%') {
|
||||
pctp = pos;
|
||||
inPct = true;
|
||||
widthSet = false;
|
||||
width = 0;
|
||||
@@ -312,6 +314,9 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
||||
widthSet = true;
|
||||
width = width*10 + (fmt - '0');
|
||||
break;
|
||||
case '.':
|
||||
inPct = true; // Get more digits
|
||||
break;
|
||||
case '%':
|
||||
output += '%';
|
||||
break;
|
||||
@@ -325,6 +330,16 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
||||
output += cstrp;
|
||||
break;
|
||||
}
|
||||
case 'e':
|
||||
case 'f':
|
||||
case 'g': {
|
||||
double d = va_arg(ap, double);
|
||||
strncpy(tmpf, pctp, pos-pctp+1);
|
||||
tmpf[pos-pctp+1] = '\0';
|
||||
sprintf(tmp, tmpf, d);
|
||||
output += tmp;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// Deal with all read-and-print somethings
|
||||
const int lbits = va_arg(ap, int);
|
||||
@@ -358,14 +373,26 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
||||
case 'd': { // Signed decimal
|
||||
int digits=sprintf(tmp,"%" VL_PRI64 "d",(vlsint64_t)(VL_EXTENDS_QQ(lbits,lbits,ld)));
|
||||
int needmore = width-digits;
|
||||
if (needmore>0) output.append(needmore,' '); // Pre-pad spaces
|
||||
if (needmore>0) {
|
||||
if (pctp && pctp[0] && pctp[1]=='0') { //%0
|
||||
output.append(needmore,'0'); // Pre-pad zero
|
||||
} else {
|
||||
output.append(needmore,' '); // Pre-pad spaces
|
||||
}
|
||||
}
|
||||
output += tmp;
|
||||
break;
|
||||
}
|
||||
case 'u': { // Unsigned decimal
|
||||
int digits=sprintf(tmp,"%" VL_PRI64 "u",ld);
|
||||
int needmore = width-digits;
|
||||
if (needmore>0) output.append(needmore,' '); // Pre-pad spaces
|
||||
if (needmore>0) {
|
||||
if (pctp && pctp[0] && pctp[1]=='0') { //%0
|
||||
output.append(needmore,'0'); // Pre-pad zero
|
||||
} else {
|
||||
output.append(needmore,' '); // Pre-pad spaces
|
||||
}
|
||||
}
|
||||
output += tmp;
|
||||
break;
|
||||
}
|
||||
@@ -628,6 +655,10 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
||||
//===========================================================================
|
||||
// File I/O
|
||||
|
||||
FILE* VL_CVT_I_FP(IData lhs) {
|
||||
return VerilatedImp::fdToFp(lhs);
|
||||
}
|
||||
|
||||
void _VL_VINT_TO_STRING(int obits, char* destoutp, WDataInP sourcep) {
|
||||
// See also VL_DATA_TO_STRING_NW
|
||||
int lsb=obits-1;
|
||||
@@ -655,8 +686,8 @@ void _VL_STRING_TO_VINT(int obits, void* destp, int srclen, const char* srcp) {
|
||||
for (; i<bytes; i++) { *op++ = 0; }
|
||||
}
|
||||
|
||||
IData VL_FGETS_IXQ(int obits, void* destp, QData fpq) {
|
||||
FILE* fp = VL_CVT_Q_FP(fpq);
|
||||
IData VL_FGETS_IXI(int obits, void* destp, IData fpi) {
|
||||
FILE* fp = VL_CVT_I_FP(fpi);
|
||||
if (VL_UNLIKELY(!fp)) return 0;
|
||||
|
||||
// The string needs to be padded with 0's in unused spaces in front of
|
||||
@@ -683,16 +714,26 @@ IData VL_FGETS_IXQ(int obits, void* destp, QData fpq) {
|
||||
return got;
|
||||
}
|
||||
|
||||
QData VL_FOPEN_QI(QData filename, IData mode) {
|
||||
IData VL_FOPEN_QI(QData filename, IData mode) {
|
||||
IData fnw[2]; VL_SET_WQ(fnw, filename);
|
||||
return VL_FOPEN_WI(2, fnw, mode);
|
||||
}
|
||||
QData VL_FOPEN_WI(int fnwords, WDataInP filenamep, IData mode) {
|
||||
IData VL_FOPEN_WI(int fnwords, WDataInP filenamep, IData mode) {
|
||||
char filenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1];
|
||||
_VL_VINT_TO_STRING(fnwords*VL_WORDSIZE, filenamez, filenamep);
|
||||
char modez[5];
|
||||
_VL_VINT_TO_STRING(VL_WORDSIZE, modez, &mode);
|
||||
return VL_CVT_FP_Q(fopen(filenamez,modez));
|
||||
return VL_FOPEN_S(filenamez,modez);
|
||||
}
|
||||
IData VL_FOPEN_S(const char* filenamep, const char* modep) {
|
||||
return VerilatedImp::fdNew(fopen(filenamep,modep));
|
||||
}
|
||||
|
||||
void VL_FCLOSE_I(IData fdi) {
|
||||
FILE* fp = VL_CVT_I_FP(fdi);
|
||||
if (VL_UNLIKELY(!fp)) return;
|
||||
fclose(fp);
|
||||
VerilatedImp::fdDelete(fdi);
|
||||
}
|
||||
|
||||
void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...) {
|
||||
@@ -726,8 +767,8 @@ void VL_WRITEF(const char* formatp, ...) {
|
||||
VL_PRINTF("%s", output.c_str());
|
||||
}
|
||||
|
||||
void VL_FWRITEF(QData fpq, const char* formatp, ...) {
|
||||
FILE* fp = VL_CVT_Q_FP(fpq);
|
||||
void VL_FWRITEF(IData fpi, const char* formatp, ...) {
|
||||
FILE* fp = VL_CVT_I_FP(fpi);
|
||||
if (VL_UNLIKELY(!fp)) return;
|
||||
|
||||
va_list ap;
|
||||
@@ -739,8 +780,8 @@ void VL_FWRITEF(QData fpq, const char* formatp, ...) {
|
||||
fputs(output.c_str(), fp);
|
||||
}
|
||||
|
||||
IData VL_FSCANF_IX(QData fpq, const char* formatp, ...) {
|
||||
FILE* fp = VL_CVT_Q_FP(fpq);
|
||||
IData VL_FSCANF_IX(IData fpi, const char* formatp, ...) {
|
||||
FILE* fp = VL_CVT_I_FP(fpi);
|
||||
if (VL_UNLIKELY(!fp)) return 0;
|
||||
|
||||
va_list ap;
|
||||
|
||||
+45
-30
@@ -1,7 +1,7 @@
|
||||
// -*- C++ -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||
// Version 2.0.
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
// <iostream> avoided to reduce compile time
|
||||
// <string> avoided and instead in verilated_heavy.h to reduce compile time
|
||||
using namespace std;
|
||||
@@ -321,11 +322,14 @@ extern WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp); ///< Zero reset a
|
||||
extern WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, bool is_modulus);
|
||||
|
||||
/// File I/O
|
||||
extern IData VL_FGETS_IXQ(int obits, void* destp, QData fpq);
|
||||
extern IData VL_FGETS_IXI(int obits, void* destp, IData fpi);
|
||||
|
||||
extern QData VL_FOPEN_WI(int fnwords, WDataInP ofilename, IData mode);
|
||||
extern QData VL_FOPEN_QI(QData ofilename, IData mode);
|
||||
inline QData VL_FOPEN_II(IData ofilename, IData mode) { return VL_FOPEN_QI(ofilename,mode); }
|
||||
extern IData VL_FOPEN_S(const char* filenamep, const char* mode);
|
||||
extern IData VL_FOPEN_WI(int fnwords, WDataInP ofilename, IData mode);
|
||||
extern IData VL_FOPEN_QI(QData ofilename, IData mode);
|
||||
inline IData VL_FOPEN_II(IData ofilename, IData mode) { return VL_FOPEN_QI(ofilename,mode); }
|
||||
|
||||
extern void VL_FCLOSE_I(IData fdi);
|
||||
|
||||
extern void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||
WDataInP ofilename, void* memp, IData start, IData end);
|
||||
@@ -336,9 +340,9 @@ inline void VL_READMEM_I(bool hex, int width, int depth, int array_lsb, int fnwo
|
||||
VL_READMEM_Q(hex, width,depth,array_lsb,fnwords, ofilename,memp,start,end); }
|
||||
|
||||
extern void VL_WRITEF(const char* formatp, ...);
|
||||
extern void VL_FWRITEF(QData fpq, const char* formatp, ...);
|
||||
extern void VL_FWRITEF(IData fpi, const char* formatp, ...);
|
||||
|
||||
extern IData VL_FSCANF_IX(QData fpq, const char* formatp, ...);
|
||||
extern IData VL_FSCANF_IX(IData fpi, const char* formatp, ...);
|
||||
extern IData VL_SSCANF_IIX(int lbits, IData ld, const char* formatp, ...);
|
||||
extern IData VL_SSCANF_IQX(int lbits, QData ld, const char* formatp, ...);
|
||||
extern IData VL_SSCANF_IWX(int lbits, WDataInP lwp, const char* formatp, ...);
|
||||
@@ -364,15 +368,24 @@ extern const char* vl_mc_scan_plusargs(const char* prefixp); // PLIish
|
||||
#define VL_SET_QW(lwp) ( ((QData)(lwp[0])) | ((QData)(lwp[1])<<((QData)(VL_WORDSIZE)) ))
|
||||
#define _VL_SET_QII(ld,rd) ( ((QData)(ld)<<VL_ULL(32)) | (QData)(rd) )
|
||||
|
||||
/// Return FILE* from IData
|
||||
extern FILE* VL_CVT_I_FP(IData lhs);
|
||||
|
||||
// Use a union to avoid cast-to-different-size warnings
|
||||
/// Return FILE* from QData
|
||||
static inline FILE* VL_CVT_Q_FP(QData lhs) { union { FILE* fp; QData q; } u; u.q=lhs; return u.fp; }
|
||||
/// Return void* from QData
|
||||
static inline void* VL_CVT_Q_VP(QData lhs) { union { void* fp; QData q; } u; u.q=lhs; return u.fp; }
|
||||
/// Return QData from FILE*
|
||||
static inline QData VL_CVT_FP_Q(FILE* fp) { union { FILE* fp; QData q; } u; u.q=0; u.fp=fp; return u.q; }
|
||||
/// Return QData from void*
|
||||
static inline QData VL_CVT_VP_Q(void* fp) { union { void* fp; QData q; } u; u.q=0; u.fp=fp; return u.q; }
|
||||
/// Return double from QData (bits, not numerically)
|
||||
static inline double VL_CVT_D_Q(QData lhs) { union { double d; QData q; } u; u.q=lhs; return u.d; }
|
||||
/// Return QData from double (bits, not numerically)
|
||||
static inline QData VL_CVT_Q_D(double lhs) { union { double d; QData q; } u; u.d=lhs; return u.q; }
|
||||
/// Return double from QData (numeric)
|
||||
static inline double VL_ITOR_D_I(IData lhs) { return ((double)((vlsint32_t)(lhs))); }
|
||||
/// Return QData from double (numeric)
|
||||
static inline IData VL_RTOI_I_D(double lhs) { return ((vlsint32_t)(trunc(lhs))); }
|
||||
/// Return QData from double (numeric)
|
||||
static inline IData VL_RTOIROUND_I_D(double lhs) { return ((vlsint32_t)(round(lhs))); }
|
||||
|
||||
// Sign extend such that if MSB set, we get ffff_ffff, else 0s
|
||||
// (Requires clean input)
|
||||
@@ -391,6 +404,9 @@ void _VL_DEBUG_PRINT_W(int lbits, WDataInP iwp);
|
||||
//=========================================================================
|
||||
// Pli macros
|
||||
|
||||
#ifndef VL_TIME_PRECISION
|
||||
# define VL_TIME_PRECISION -12 ///< Timescale units only for for VPI return - picoseconds
|
||||
#endif
|
||||
#ifndef VL_TIME_MULTIPLIER
|
||||
# define VL_TIME_MULTIPLIER 1
|
||||
#endif
|
||||
@@ -399,9 +415,11 @@ void _VL_DEBUG_PRINT_W(int lbits, WDataInP iwp);
|
||||
#if defined(SYSTEMC_VERSION) && (SYSTEMC_VERSION>20011000)
|
||||
# define VL_TIME_I() ((IData)(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
|
||||
# define VL_TIME_Q() ((QData)(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
|
||||
# define VL_TIME_D() ((double)(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
|
||||
#else
|
||||
# define VL_TIME_I() ((IData)(sc_time_stamp()*VL_TIME_MULTIPLIER))
|
||||
# define VL_TIME_Q() ((QData)(sc_time_stamp()*VL_TIME_MULTIPLIER))
|
||||
# define VL_TIME_D() ((double)(sc_time_stamp()*VL_TIME_MULTIPLIER))
|
||||
extern double sc_time_stamp();
|
||||
#endif
|
||||
|
||||
@@ -942,16 +960,13 @@ static inline WDataOutP VL_SUB_W(int words, WDataOutP owp,WDataInP lwp,WDataInP
|
||||
return(owp);
|
||||
}
|
||||
|
||||
// Optimization bug in GCC 2.96 and presumably all-pre GCC 3 versions need this workaround
|
||||
#if 1 //defined(__GNUC__) && __GNUC__ < 3
|
||||
static inline IData VL_UNARYMIN_I(IData data) { return -data; }
|
||||
static inline QData VL_UNARYMIN_Q(QData data) { return -data; }
|
||||
#else
|
||||
# define VL_UNARYMIN_I(IData data) (-(data))
|
||||
# define VL_UNARYMIN_Q(QData data) (-(data))
|
||||
#endif
|
||||
// Optimization bug in GCC 2.96 and presumably all-pre GCC 3 versions need this workaround,
|
||||
// we can't just
|
||||
//# define VL_NEGATE_I(data) (-(data))
|
||||
static inline IData VL_NEGATE_I(IData data) { return -data; }
|
||||
static inline QData VL_NEGATE_Q(QData data) { return -data; }
|
||||
|
||||
static inline WDataOutP VL_UNARYMIN_W(int words, WDataOutP owp,WDataInP lwp){
|
||||
static inline WDataOutP VL_NEGATE_W(int words, WDataOutP owp,WDataInP lwp){
|
||||
QData carry = 0;
|
||||
for (int i=0; i<words; i++) {
|
||||
carry = carry + (QData)(IData)(~lwp[i]);
|
||||
@@ -998,18 +1013,18 @@ static inline WDataOutP VL_MULS_WWW(int,int lbits,int, WDataOutP owp,WDataInP lw
|
||||
IData lneg = VL_SIGN_I(lbits,lwp[words-1]);
|
||||
if (lneg) { // Negate lhs
|
||||
lwusp = lwstore;
|
||||
VL_UNARYMIN_W(words, lwstore, lwp);
|
||||
VL_NEGATE_W(words, lwstore, lwp);
|
||||
lwstore[words-1] &= VL_MASK_I(lbits); // Clean it
|
||||
}
|
||||
IData rneg = VL_SIGN_I(lbits,rwp[words-1]);
|
||||
if (rneg) { // Negate rhs
|
||||
rwusp = rwstore;
|
||||
VL_UNARYMIN_W(words, rwstore, rwp);
|
||||
VL_NEGATE_W(words, rwstore, rwp);
|
||||
rwstore[words-1] &= VL_MASK_I(lbits); // Clean it
|
||||
}
|
||||
VL_MUL_W(words,owp,lwusp,rwusp);
|
||||
owp[words-1] &= VL_MASK_I(lbits); // Clean. Note it's ok for the multiply to overflow into the sign bit
|
||||
if ((lneg ^ rneg) & 1) { // Negate output (not using UNARYMIN, as owp==lwp)
|
||||
if ((lneg ^ rneg) & 1) { // Negate output (not using NEGATE, as owp==lwp)
|
||||
QData carry = 0;
|
||||
for (int i=0; i<words; i++) {
|
||||
carry = carry + (QData)(IData)(~owp[i]);
|
||||
@@ -1056,12 +1071,12 @@ static inline WDataOutP VL_DIVS_WWW(int lbits, WDataOutP owp,WDataInP lwp,WDataI
|
||||
IData rwstore[VL_MULS_MAX_WORDS];
|
||||
WDataInP ltup = lwp;
|
||||
WDataInP rtup = rwp;
|
||||
if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), lwstore, lwp)); }
|
||||
if (rsign) { rtup = _VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), rwstore, rwp)); }
|
||||
if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), lwstore, lwp)); }
|
||||
if (rsign) { rtup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), rwstore, rwp)); }
|
||||
if ((lsign && !rsign) || (!lsign && rsign)) {
|
||||
IData qNoSign[VL_MULS_MAX_WORDS];
|
||||
VL_DIV_WWW(lbits,qNoSign,ltup,rtup);
|
||||
_VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), owp, qNoSign));
|
||||
_VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), owp, qNoSign));
|
||||
return owp;
|
||||
} else {
|
||||
return VL_DIV_WWW(lbits,owp,ltup,rtup);
|
||||
@@ -1075,12 +1090,12 @@ static inline WDataOutP VL_MODDIVS_WWW(int lbits, WDataOutP owp,WDataInP lwp,WDa
|
||||
IData rwstore[VL_MULS_MAX_WORDS];
|
||||
WDataInP ltup = lwp;
|
||||
WDataInP rtup = rwp;
|
||||
if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), lwstore, lwp)); }
|
||||
if (rsign) { rtup = _VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), rwstore, rwp)); }
|
||||
if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), lwstore, lwp)); }
|
||||
if (rsign) { rtup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), rwstore, rwp)); }
|
||||
if (lsign) { // Only dividend sign matters for modulus
|
||||
IData qNoSign[VL_MULS_MAX_WORDS];
|
||||
VL_MODDIV_WWW(lbits,qNoSign,ltup,rtup);
|
||||
_VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), owp, qNoSign));
|
||||
_VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), owp, qNoSign));
|
||||
return owp;
|
||||
} else {
|
||||
return VL_MODDIV_WWW(lbits,owp,ltup,rtup);
|
||||
@@ -1633,6 +1648,6 @@ static inline WDataOutP VL_CONST_W_9X(int obits, WDataOutP o,
|
||||
|
||||
#undef _END
|
||||
|
||||
// Debugging
|
||||
//======================================================================
|
||||
|
||||
#endif /*_VERILATED_H_*/
|
||||
|
||||
+12
-1
@@ -2,7 +2,7 @@
|
||||
######################################################################
|
||||
# DESCRIPTION: Makefile commands for all verilated target files
|
||||
#
|
||||
# Copyright 2003-2010 by Wilson Snyder. Verilator is free software; you can
|
||||
# Copyright 2003-2011 by Wilson Snyder. Verilator 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.
|
||||
######################################################################
|
||||
@@ -19,6 +19,13 @@ RANLIB = ranlib
|
||||
SP_PREPROC = sp_preproc
|
||||
SP_INCLUDER = $(PERL) $(VERILATOR_ROOT)/bin/verilator_includer
|
||||
|
||||
######################################################################
|
||||
# Make checks
|
||||
|
||||
ifneq ($(words $(CURDIR)),1)
|
||||
$(error Unsupported: GNU Make cannot build in directories containing spaces, build elsewhere: '$(CURDIR)')
|
||||
endif
|
||||
|
||||
######################################################################
|
||||
# C Preprocessor flags
|
||||
|
||||
@@ -109,6 +116,10 @@ ifeq ($(VM_SP),1)
|
||||
$(SP_PREPROC) -M sp_preproc.d --tree $(VM_PREFIX).sp_tree \
|
||||
--preproc $(VK_CLASSES_SP)
|
||||
else
|
||||
ifeq ($(VM_COVERAGE),1)
|
||||
CPPFLAGS += -I$(SYSTEMPERL_INCLUDE)
|
||||
VPATH += $(SYSTEMPERL_INCLUDE)
|
||||
endif
|
||||
preproc:
|
||||
endif
|
||||
|
||||
|
||||
+3
-7
@@ -5,7 +5,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||
// Version 2.0.
|
||||
@@ -27,11 +27,7 @@
|
||||
`define coverage_block_off
|
||||
`endif
|
||||
|
||||
// Hide file descriptor difference
|
||||
`ifdef verilator
|
||||
`define verilator_file_descriptor reg [63:0]
|
||||
`else
|
||||
`define verilator_file_descriptor integer
|
||||
`endif
|
||||
// Hide file descriptor difference - deprecated - for older versions
|
||||
`define verilator_file_descriptor integer
|
||||
|
||||
`endif // guard
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// -*- C++ -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2009-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2009-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||
// Version 2.0.
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#define _VERILATED_DPI_CPP_
|
||||
#include "verilatedos.h"
|
||||
#include "verilated_dpi.h"
|
||||
#include "verilated_imp.h"
|
||||
|
||||
// On MSVC++ we need svdpi.h to declare exports, not imports
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
// -*- C++ -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||
// Version 2.0.
|
||||
//
|
||||
// Verilator is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
//*************************************************************************
|
||||
///
|
||||
/// \file
|
||||
/// \brief Verilator: Common include for all Verilated C files that use DPI
|
||||
///
|
||||
/// This file is included automatically by Verilator at the top of
|
||||
/// all C++ files it generates where DPI is used. It contains
|
||||
/// DPI interface functions required by the Verilated code.
|
||||
///
|
||||
/// Code available from: http://www.veripool.org/verilator
|
||||
///
|
||||
//*************************************************************************
|
||||
|
||||
|
||||
#ifndef _VERILATED_DPI_H_
|
||||
#define _VERILATED_DPI_H_ 1 ///< Header Guard
|
||||
|
||||
#include "verilated.h" // Presumed done by caller
|
||||
#include "svdpi.h"
|
||||
|
||||
//===================================================================
|
||||
// SETTING OPERATORS
|
||||
|
||||
/// Return svBitVecVal from WData
|
||||
static inline void VL_SET_W_SVBV(int obits, WDataOutP owp, svBitVecVal* lwp) {
|
||||
int words = VL_WORDS_I(obits);
|
||||
for (int i=0; i<words-1; i++) owp[i]=lwp[i];
|
||||
owp[words-1] = lwp[words-1] & VL_MASK_I(obits);
|
||||
}
|
||||
static inline void VL_SET_SVBV_W(int obits, svBitVecVal* owp, WDataInP lwp) {
|
||||
int words = VL_WORDS_I(obits);
|
||||
for (int i=0; i<words-1; i++) owp[i]=lwp[i];
|
||||
owp[words-1] = lwp[words-1] & VL_MASK_I(obits);
|
||||
}
|
||||
static inline void VL_SET_W_SVLV(int obits, WDataOutP owp, svLogicVecVal* lwp) {
|
||||
// Note we ignore X/Z in svLogicVecVal
|
||||
int words = VL_WORDS_I(obits);
|
||||
for (int i=0; i<words-1; i++) owp[i]=lwp[i].aval;
|
||||
owp[words-1] = lwp[words-1].aval & VL_MASK_I(obits);
|
||||
}
|
||||
static inline void VL_SET_SVLV_W(int obits, svLogicVecVal* owp, WDataInP lwp) {
|
||||
// Note we don't create X/Z in svLogicVecVal
|
||||
int words = VL_WORDS_I(obits);
|
||||
for (int i=0; i<words; i++) owp[i].bval=0;
|
||||
for (int i=0; i<words-1; i++) owp[i].aval=lwp[i];
|
||||
owp[words-1].aval = lwp[words-1] & VL_MASK_I(obits);
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
|
||||
#endif // _VERILATED_DPI_H_
|
||||
@@ -1,7 +1,7 @@
|
||||
// -*- C++ -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2010-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2010-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||
// Version 2.0.
|
||||
|
||||
+41
-3
@@ -1,7 +1,7 @@
|
||||
// -*- C++ -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2009-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2009-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||
// Version 2.0.
|
||||
@@ -35,6 +35,7 @@
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <string>
|
||||
|
||||
class VerilatedScope;
|
||||
@@ -49,7 +50,7 @@ class VerilatedImp {
|
||||
typedef vector<string> ArgVec;
|
||||
typedef map<pair<const void*,void*>,void*> UserMap;
|
||||
typedef map<const char*, const VerilatedScope*, VerilatedCStrCmp> ScopeNameMap;
|
||||
typedef map<const char*, int> ExportNameMap;
|
||||
typedef map<const char*, int, VerilatedCStrCmp> ExportNameMap;
|
||||
|
||||
// MEMBERS
|
||||
static VerilatedImp s_s; ///< Static Singleton; One and only static this
|
||||
@@ -62,9 +63,18 @@ class VerilatedImp {
|
||||
ExportNameMap m_exportMap; ///< Map of <export_func_proto, func number>
|
||||
int m_exportNext; ///< Next export funcnum
|
||||
|
||||
// File I/O
|
||||
vector<FILE*> m_fdps; ///< File descriptors
|
||||
deque<IData> m_fdFree; ///< List of free descriptors (SLOW - FOPEN/CLOSE only)
|
||||
|
||||
public: // But only for verilated*.cpp
|
||||
// CONSTRUCTORS
|
||||
VerilatedImp() : m_argVecLoaded(false), m_exportNext(0) {}
|
||||
VerilatedImp() : m_argVecLoaded(false), m_exportNext(0) {
|
||||
m_fdps.resize(3);
|
||||
m_fdps[0] = stdin;
|
||||
m_fdps[1] = stdout;
|
||||
m_fdps[2] = stderr;
|
||||
}
|
||||
~VerilatedImp() {}
|
||||
|
||||
// METHODS - arguments
|
||||
@@ -184,6 +194,34 @@ public: // But only for verilated*.cpp
|
||||
}
|
||||
// We don't free up m_exportMap until the end, because we can't be sure
|
||||
// what other models are using the assigned funcnum's.
|
||||
|
||||
public: // But only for verilated*.cpp
|
||||
// METHODS - file IO
|
||||
static IData fdNew(FILE* fp) {
|
||||
if (VL_UNLIKELY(!fp)) return 0;
|
||||
// Bit 31 indicates it's a descriptor not a MCD
|
||||
if (s_s.m_fdFree.empty()) {
|
||||
// Need to create more space in m_fdps and m_fdFree
|
||||
size_t start = s_s.m_fdps.size();
|
||||
s_s.m_fdps.resize(start*2);
|
||||
for (size_t i=start; i<start*2; i++) s_s.m_fdFree.push_back((IData)i);
|
||||
}
|
||||
IData idx = s_s.m_fdFree.back(); s_s.m_fdFree.pop_back();
|
||||
s_s.m_fdps[idx] = fp;
|
||||
return (idx | (1UL<<31)); // bit 31 indicates not MCD
|
||||
}
|
||||
static void fdDelete(IData fdi) {
|
||||
IData idx = VL_MASK_I(31) & fdi;
|
||||
if (VL_UNLIKELY(!(fdi & (1ULL<<31)) || idx >= s_s.m_fdps.size())) return;
|
||||
if (VL_UNLIKELY(!s_s.m_fdps[idx])) return; // Already free
|
||||
s_s.m_fdps[idx] = NULL;
|
||||
s_s.m_fdFree.push_back(idx);
|
||||
}
|
||||
static inline FILE* fdToFp(IData fdi) {
|
||||
IData idx = VL_MASK_I(31) & fdi;
|
||||
if (VL_UNLIKELY(!(fdi & (1ULL<<31)) || idx >= s_s.m_fdps.size())) return NULL;
|
||||
return s_s.m_fdps[idx];
|
||||
}
|
||||
};
|
||||
|
||||
#endif // Guard
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// -*- C++ -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2009-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2009-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||
// Version 2.0.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// -*- C++ -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||
// Version 2.0.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2001-2010 by Wilson Snyder. This program is free software;
|
||||
// Copyright 2001-2011 by Wilson Snyder. This program is free software;
|
||||
// you can redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||
//
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2001-2010 by Wilson Snyder. This program is free software;
|
||||
// Copyright 2001-2011 by Wilson Snyder. This program is free software;
|
||||
// you can redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||
//
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2001-2010 by Wilson Snyder. This program is free software;
|
||||
// Copyright 2001-2011 by Wilson Snyder. This program is free software;
|
||||
// you can redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||
//
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2001-2010 by Wilson Snyder. This program is free software;
|
||||
// Copyright 2001-2011 by Wilson Snyder. This program is free software;
|
||||
// you can redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||
//
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
// -*- C++ -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2009-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||
// Version 2.0.
|
||||
//
|
||||
// Verilator is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
//=========================================================================
|
||||
///
|
||||
/// \file
|
||||
/// \brief Verilator: VPI implementation code
|
||||
///
|
||||
/// This file must be compiled and linked against all objects
|
||||
/// created from Verilator or called by Verilator that use the VPI.
|
||||
///
|
||||
/// Code available from: http://www.veripool.org/verilator
|
||||
///
|
||||
//=========================================================================
|
||||
|
||||
#include "verilated_vpi.h"
|
||||
|
||||
//======================================================================
|
||||
|
||||
VerilatedVpi VerilatedVpi::s_s; // Singleton
|
||||
vluint8_t* VerilatedVpio::s_freeHead = NULL;
|
||||
|
||||
//======================================================================
|
||||
@@ -0,0 +1,855 @@
|
||||
// -*- C++ -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2009-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||
// Version 2.0.
|
||||
//
|
||||
// Verilator is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
//=========================================================================
|
||||
///
|
||||
/// \file
|
||||
/// \brief Verilator: VPI implementation code
|
||||
///
|
||||
/// This file must be compiled and linked against all objects
|
||||
/// created from Verilator or called by Verilator that use the VPI.
|
||||
///
|
||||
/// "//-" indicates features that are as yet unimplemented.
|
||||
///
|
||||
/// Code available from: http://www.veripool.org/verilator
|
||||
///
|
||||
//=========================================================================
|
||||
|
||||
#ifndef CHPI_VERILATED_VPI_H
|
||||
#define CHPI_VERILATED_VPI_H 1
|
||||
|
||||
#include "verilated.h"
|
||||
#include "verilated_syms.h"
|
||||
|
||||
//======================================================================
|
||||
// From IEEE 1800-2009 annex K
|
||||
|
||||
#include "vltstd/vpi_user.h"
|
||||
|
||||
//======================================================================
|
||||
// Internal macros
|
||||
|
||||
// Not supported yet
|
||||
#define _VL_VPI_UNIMP() \
|
||||
vl_fatal(__FILE__,__LINE__,"",Verilated::catName("Unsupported VPI function: ",VL_FUNC))
|
||||
|
||||
//======================================================================
|
||||
// Implementation
|
||||
|
||||
#include <set>
|
||||
|
||||
#define VL_DEBUG_IF_PLI VL_DEBUG_IF
|
||||
|
||||
// Base VPI handled object
|
||||
class VerilatedVpio {
|
||||
// MEM MANGLEMENT
|
||||
static vluint8_t* s_freeHead;
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
VerilatedVpio() {}
|
||||
virtual ~VerilatedVpio() {}
|
||||
inline static void* operator new(size_t size) {
|
||||
// We new and delete tons of vpi structures, so keep them around
|
||||
// To simplify our free list, we use a size large enough for all derived types
|
||||
// We reserve word zero for the next pointer, as that's safer in case a
|
||||
// dangling reference to the original remains around.
|
||||
static size_t chunk = 96;
|
||||
if (VL_UNLIKELY(size>chunk)) vl_fatal(__FILE__,__LINE__,"", "increase chunk");
|
||||
if (VL_LIKELY(s_freeHead)) {
|
||||
vluint8_t* newp = s_freeHead;
|
||||
s_freeHead = *((vluint8_t**)newp);
|
||||
return newp+8;
|
||||
} else {
|
||||
// +8: 8 bytes for next
|
||||
vluint8_t* newp = (vluint8_t*)(::operator new(chunk+8));
|
||||
return newp+8;
|
||||
}
|
||||
}
|
||||
inline static void operator delete(void* obj, size_t size) {
|
||||
vluint8_t* oldp = ((vluint8_t*)obj)-8;
|
||||
*((void**)oldp) = s_freeHead;
|
||||
s_freeHead = oldp;
|
||||
}
|
||||
// MEMBERS
|
||||
static inline VerilatedVpio* castp(vpiHandle h) { return dynamic_cast<VerilatedVpio*>((VerilatedVpio*)h); }
|
||||
inline vpiHandle castVpiHandle() { return (vpiHandle)(this); }
|
||||
// ACCESSORS
|
||||
virtual const char* name() { return "<null>"; }
|
||||
virtual const char* fullname() { return "<null>"; }
|
||||
virtual const char* defname() { return "<null>"; }
|
||||
virtual vpiHandle dovpi_scan() { return 0; }
|
||||
};
|
||||
|
||||
typedef PLI_INT32 (*VerilatedPliCb)(struct t_cb_data *);
|
||||
|
||||
class VerilatedVpioCb : public VerilatedVpio {
|
||||
t_cb_data m_cbData;
|
||||
s_vpi_value m_value;
|
||||
QData m_time;
|
||||
public:
|
||||
VerilatedVpioCb(const t_cb_data* cbDatap, QData time) : m_cbData(*cbDatap), m_time(time) {
|
||||
m_cbData.value = &m_value;
|
||||
}
|
||||
virtual ~VerilatedVpioCb() {}
|
||||
static inline VerilatedVpioCb* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioCb*>((VerilatedVpio*)h); }
|
||||
vluint32_t reason() const { return m_cbData.reason; }
|
||||
VerilatedPliCb cb_rtnp() const { return m_cbData.cb_rtn; }
|
||||
t_cb_data* cb_datap() { return &(m_cbData); }
|
||||
QData time() const { return m_time; }
|
||||
};
|
||||
|
||||
class VerilatedVpioConst : public VerilatedVpio {
|
||||
vlsint32_t m_num;
|
||||
public:
|
||||
VerilatedVpioConst(vlsint32_t num) : m_num(num) {}
|
||||
virtual ~VerilatedVpioConst() {}
|
||||
static inline VerilatedVpioConst* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioConst*>((VerilatedVpio*)h); }
|
||||
vlsint32_t num() const { return m_num; }
|
||||
};
|
||||
|
||||
class VerilatedVpioRange : public VerilatedVpio {
|
||||
vlsint32_t m_lhs; // Ranges can be signed
|
||||
vlsint32_t m_rhs;
|
||||
bool m_iteration;
|
||||
public:
|
||||
VerilatedVpioRange(vlsint32_t lhs, vlsint32_t rhs) : m_lhs(lhs), m_rhs(rhs), m_iteration(0) {}
|
||||
virtual ~VerilatedVpioRange() {}
|
||||
static inline VerilatedVpioRange* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioRange*>((VerilatedVpio*)h); }
|
||||
vlsint32_t lhs() const { return m_lhs; }
|
||||
vlsint32_t rhs() const { return m_rhs; }
|
||||
int iteration() const { return m_iteration; }
|
||||
void iterationInc() { ++m_iteration; }
|
||||
virtual vpiHandle dovpi_scan() {
|
||||
if (!iteration()) {
|
||||
VerilatedVpioRange* nextp = new VerilatedVpioRange(*this);
|
||||
nextp->iterationInc();
|
||||
return ((nextp)->castVpiHandle());
|
||||
} else {
|
||||
return 0; // End of list - only one deep
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class VerilatedVpioScope : public VerilatedVpio {
|
||||
const VerilatedScope* m_scopep;
|
||||
public:
|
||||
VerilatedVpioScope(const VerilatedScope* scopep)
|
||||
: m_scopep(scopep) {}
|
||||
virtual ~VerilatedVpioScope() {}
|
||||
static inline VerilatedVpioScope* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioScope*>((VerilatedVpio*)h); }
|
||||
const VerilatedScope* scopep() const { return m_scopep; }
|
||||
virtual const char* name() { return m_scopep->name(); }
|
||||
virtual const char* fullname() { return m_scopep->name(); }
|
||||
};
|
||||
|
||||
class VerilatedVpioVar : public VerilatedVpio {
|
||||
const VerilatedVar* m_varp;
|
||||
const VerilatedScope* m_scopep;
|
||||
vluint8_t* m_prevDatap; // Previous value of data, for cbValueChange
|
||||
vluint32_t m_mask; // memoized variable mask
|
||||
vluint32_t m_entSize; // memoized variable size
|
||||
protected:
|
||||
void* m_varDatap; // varp()->datap() adjusted for array entries
|
||||
vlsint32_t m_index;
|
||||
public:
|
||||
VerilatedVpioVar(const VerilatedVar* varp, const VerilatedScope* scopep)
|
||||
: m_varp(varp), m_scopep(scopep), m_index(0) {
|
||||
m_prevDatap = NULL;
|
||||
m_mask = VL_MASK_I(varp->range().bits());
|
||||
m_entSize = varp->entSize();
|
||||
m_varDatap = varp->datap();
|
||||
}
|
||||
virtual ~VerilatedVpioVar() {
|
||||
if (m_prevDatap) { delete [] m_prevDatap; m_prevDatap = NULL; }
|
||||
}
|
||||
static inline VerilatedVpioVar* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioVar*>((VerilatedVpio*)h); }
|
||||
const VerilatedVar* varp() const { return m_varp; }
|
||||
const VerilatedScope* scopep() const { return m_scopep; }
|
||||
vluint32_t mask() const { return m_mask; }
|
||||
vluint32_t entSize() const { return m_entSize; }
|
||||
virtual const char* name() { return m_varp->name(); }
|
||||
virtual const char* fullname() {
|
||||
static VL_THREAD string out;
|
||||
out = string(m_scopep->name())+"."+name();
|
||||
return out.c_str();
|
||||
}
|
||||
void* prevDatap() const { return m_prevDatap; }
|
||||
void* varDatap() const { return m_varDatap; }
|
||||
void createPrevDatap() {
|
||||
if (VL_UNLIKELY(!m_prevDatap)) {
|
||||
m_prevDatap = new vluint8_t [entSize()];
|
||||
memcpy(prevDatap(), varp()->datap(), entSize());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class VerilatedVpioVarIndex : public VerilatedVpioVar {
|
||||
public:
|
||||
VerilatedVpioVarIndex(const VerilatedVar* varp, const VerilatedScope* scopep,
|
||||
vlsint32_t index, int offset)
|
||||
: VerilatedVpioVar(varp, scopep) {
|
||||
m_index = index;
|
||||
m_varDatap = ((vluint8_t*)varp->datap()) + entSize()*offset;
|
||||
}
|
||||
virtual ~VerilatedVpioVarIndex() {}
|
||||
static inline VerilatedVpioVarIndex* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioVarIndex*>((VerilatedVpio*)h); }
|
||||
virtual const char* fullname() {
|
||||
static VL_THREAD string out;
|
||||
char num[20]; sprintf(num,"%d",m_index);
|
||||
out = string(scopep()->name())+"."+name()+"["+num+"]";
|
||||
return out.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
class VerilatedVpioVarIter : public VerilatedVpio {
|
||||
const VerilatedScope* m_scopep;
|
||||
VerilatedVarNameMap::iterator m_it;
|
||||
bool m_started;
|
||||
public:
|
||||
VerilatedVpioVarIter(const VerilatedScope* scopep)
|
||||
: m_scopep(scopep), m_started(false) { }
|
||||
virtual ~VerilatedVpioVarIter() {}
|
||||
static inline VerilatedVpioVarIter* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioVarIter*>((VerilatedVpio*)h); }
|
||||
virtual vpiHandle dovpi_scan() {
|
||||
if (VL_LIKELY(m_scopep->varsp())) {
|
||||
if (VL_UNLIKELY(!m_started)) { m_it = m_scopep->varsp()->begin(); m_started=true; }
|
||||
else if (VL_UNLIKELY(m_it == m_scopep->varsp()->end())) return 0;
|
||||
else ++m_it;
|
||||
if (m_it == m_scopep->varsp()->end()) return 0;
|
||||
return ((new VerilatedVpioVar(&(m_it->second), m_scopep))
|
||||
->castVpiHandle());
|
||||
} else {
|
||||
return 0; // End of list - only one deep
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//======================================================================
|
||||
|
||||
struct VerilatedVpiTimedCbsCmp {
|
||||
/// Ordering sets keyed by time, then callback descriptor
|
||||
bool operator() (const pair<QData,VerilatedVpioCb*>& a,
|
||||
const pair<QData,VerilatedVpioCb*>& b) const {
|
||||
if (a.first < b.first) return 1;
|
||||
if (a.first > b.first) return 0;
|
||||
return a.second < b.second;
|
||||
}
|
||||
};
|
||||
|
||||
class VerilatedVpi {
|
||||
enum { CB_ENUM_MAX_VALUE = cbAtEndOfSimTime+1 }; // Maxium callback reason
|
||||
typedef set<VerilatedVpioCb*> VpioCbSet;
|
||||
typedef set<pair<QData,VerilatedVpioCb*>,VerilatedVpiTimedCbsCmp > VpioTimedCbs;
|
||||
|
||||
VpioCbSet m_cbObjSets[CB_ENUM_MAX_VALUE]; // Callbacks for each supported reason
|
||||
VpioTimedCbs m_timedCbs; // Time based callbacks
|
||||
|
||||
static VerilatedVpi s_s; // Singleton
|
||||
|
||||
public:
|
||||
VerilatedVpi() {}
|
||||
~VerilatedVpi() {}
|
||||
static void cbReasonAdd(VerilatedVpioCb* vop) {
|
||||
if (vop->reason() == cbValueChange) {
|
||||
if (VerilatedVpioVar* varop = VerilatedVpioVar::castp(vop->cb_datap()->obj)) {
|
||||
varop->createPrevDatap();
|
||||
}
|
||||
}
|
||||
if (VL_UNLIKELY(vop->reason() >= CB_ENUM_MAX_VALUE)) vl_fatal(__FILE__,__LINE__,"", "vpi bb reason too large");
|
||||
s_s.m_cbObjSets[vop->reason()].insert(vop);
|
||||
}
|
||||
static void cbTimedAdd(VerilatedVpioCb* vop) {
|
||||
s_s.m_timedCbs.insert(make_pair(vop->time(), vop));
|
||||
}
|
||||
static void cbReasonRemove(VerilatedVpioCb* cbp) {
|
||||
VpioCbSet& cbObjSet = s_s.m_cbObjSets[cbp->reason()];
|
||||
VpioCbSet::iterator it=cbObjSet.find(cbp);
|
||||
if (VL_LIKELY(it != cbObjSet.end())) {
|
||||
cbObjSet.erase(it);
|
||||
}
|
||||
}
|
||||
static void cbTimedRemove(VerilatedVpioCb* cbp) {
|
||||
VpioTimedCbs::iterator it=s_s.m_timedCbs.find(make_pair(cbp->time(),cbp));
|
||||
if (VL_LIKELY(it != s_s.m_timedCbs.end())) {
|
||||
s_s.m_timedCbs.erase(it);
|
||||
}
|
||||
}
|
||||
static void callTimedCbs() {
|
||||
QData time = VL_TIME_Q();
|
||||
for (VpioTimedCbs::iterator it=s_s.m_timedCbs.begin(); it!=s_s.m_timedCbs.end(); ) {
|
||||
if (VL_UNLIKELY(it->first <= time)) {
|
||||
VerilatedVpioCb* vop = it->second;
|
||||
++it; // iterator may be deleted by callback
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: timed_callback %p\n",vop););
|
||||
(vop->cb_rtnp()) (vop->cb_datap());
|
||||
}
|
||||
else { ++it; }
|
||||
}
|
||||
}
|
||||
static QData cbNextDeadline() {
|
||||
VpioTimedCbs::iterator it=s_s.m_timedCbs.begin();
|
||||
if (VL_LIKELY(it!=s_s.m_timedCbs.end())) {
|
||||
return it->first;
|
||||
} else {
|
||||
return ~VL_ULL(0); // maxquad
|
||||
}
|
||||
}
|
||||
static void callCbs(vluint32_t reason) {
|
||||
VpioCbSet& cbObjSet = s_s.m_cbObjSets[reason];
|
||||
for (VpioCbSet::iterator it=cbObjSet.begin(); it!=cbObjSet.end();) {
|
||||
VerilatedVpioCb* vop = *it;
|
||||
++it; // iterator may be deleted by callback
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: reason_callback %d %p\n",reason,vop););
|
||||
(vop->cb_rtnp()) (vop->cb_datap());
|
||||
}
|
||||
}
|
||||
static void callValueCbs() {
|
||||
VpioCbSet& cbObjSet = s_s.m_cbObjSets[cbValueChange];
|
||||
for (VpioCbSet::iterator it=cbObjSet.begin(); it!=cbObjSet.end();) {
|
||||
VerilatedVpioCb* vop = *it;
|
||||
++it; // iterator may be deleted by callback
|
||||
if (VerilatedVpioVar* varop = VerilatedVpioVar::castp(vop->cb_datap()->obj)) {
|
||||
void* newDatap = varop->varDatap();
|
||||
void* prevDatap = varop->prevDatap(); // Was malloced when we added the callback
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: value_test %s v[0]=%d/%d %p %p\n",
|
||||
varop->fullname(), *((CData*)newDatap), *((CData*)prevDatap),
|
||||
newDatap, prevDatap););
|
||||
if (memcmp(prevDatap, newDatap, varop->entSize())) {
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: value_callback %p %s v[0]=%d\n",
|
||||
vop,varop->fullname(), *((CData*)newDatap)););
|
||||
memcpy(prevDatap, newDatap, varop->entSize());
|
||||
vpi_get_value(vop->cb_datap()->obj, vop->cb_datap()->value);
|
||||
(vop->cb_rtnp()) (vop->cb_datap());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// callback related
|
||||
|
||||
vpiHandle vpi_register_cb(p_cb_data cb_data_p) {
|
||||
if (VL_UNLIKELY(!cb_data_p)) return NULL;
|
||||
switch (cb_data_p->reason) {
|
||||
case cbAfterDelay: {
|
||||
QData time = 0;
|
||||
if (cb_data_p->time) time = _VL_SET_QII(cb_data_p->time->high, cb_data_p->time->low);
|
||||
VerilatedVpioCb* vop = new VerilatedVpioCb(cb_data_p, VL_TIME_Q()+time);
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_register_cb %d %p delay=%" VL_PRI64 "d\n",cb_data_p->reason,vop,time););
|
||||
VerilatedVpi::cbTimedAdd(vop);
|
||||
return vop->castVpiHandle();
|
||||
}
|
||||
case cbReadWriteSynch: // FALLTHRU // Supported via vlt_main.cpp
|
||||
case cbReadOnlySynch: // FALLTHRU // Supported via vlt_main.cpp
|
||||
case cbNextSimTime: // FALLTHRU // Supported via vlt_main.cpp
|
||||
case cbStartOfSimulation: // FALLTHRU // Supported via vlt_main.cpp
|
||||
case cbEndOfSimulation: // FALLTHRU // Supported via vlt_main.cpp
|
||||
case cbValueChange: // FALLTHRU // Supported via vlt_main.cpp
|
||||
case cbEnterInteractive: // FALLTHRU // NOP, but need to return handle, so make object
|
||||
case cbExitInteractive: // FALLTHRU // NOP, but need to return handle, so make object
|
||||
case cbInteractiveScopeChange: { // FALLTHRU // NOP, but need to return handle, so make object
|
||||
VerilatedVpioCb* vop = new VerilatedVpioCb(cb_data_p, 0);
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_register_cb %d %p\n",cb_data_p->reason,vop););
|
||||
VerilatedVpi::cbReasonAdd(vop);
|
||||
return vop->castVpiHandle();
|
||||
}
|
||||
default:
|
||||
_VL_VPI_UNIMP(); return NULL;
|
||||
};
|
||||
}
|
||||
|
||||
PLI_INT32 vpi_remove_cb(vpiHandle object) {
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_remove_cb %p\n",object););
|
||||
VerilatedVpioCb* vop = VerilatedVpioCb::castp(object);
|
||||
if (VL_UNLIKELY(!vop)) return 0;
|
||||
if (vop->cb_datap()->reason == cbAfterDelay) {
|
||||
VerilatedVpi::cbTimedRemove(vop);
|
||||
} else {
|
||||
VerilatedVpi::cbReasonRemove(vop);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-void vpi_get_cb_info(vpiHandle object, p_cb_data cb_data_p) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
//-vpiHandle vpi_register_systf(p_vpi_systf_data systf_data_p) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
//-void vpi_get_systf_info(vpiHandle object, p_vpi_systf_data systf_data_p) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
|
||||
// for obtaining handles
|
||||
|
||||
vpiHandle vpi_handle_by_name(PLI_BYTE8* namep, vpiHandle scope) {
|
||||
if (VL_UNLIKELY(!namep)) return NULL;
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_handle_by_name %s %p\n",namep,scope););
|
||||
VerilatedVpioScope* voScopep = VerilatedVpioScope::castp(scope);
|
||||
const VerilatedVar* varp;
|
||||
const VerilatedScope* scopep;
|
||||
string scopeAndName = namep;
|
||||
if (voScopep) {
|
||||
scopeAndName = string(voScopep->fullname()) + "." + namep;
|
||||
namep = (PLI_BYTE8*)scopeAndName.c_str();
|
||||
}
|
||||
{
|
||||
// This doesn't yet follow the hierarchy in the proper way
|
||||
scopep = Verilated::scopeFind(namep);
|
||||
if (scopep) { // Whole thing found as a scope
|
||||
return (new VerilatedVpioScope(scopep))->castVpiHandle();
|
||||
}
|
||||
const char* baseNamep = scopeAndName.c_str();
|
||||
string scopename;
|
||||
const char* dotp = strrchr(namep, '.');
|
||||
if (VL_LIKELY(dotp)) {
|
||||
baseNamep = dotp+1;
|
||||
scopename = string(namep,dotp-namep);
|
||||
}
|
||||
scopep = Verilated::scopeFind(scopename.c_str());
|
||||
if (!scopep) return NULL;
|
||||
varp = scopep->varFind(baseNamep);
|
||||
}
|
||||
if (!varp) return NULL;
|
||||
return (new VerilatedVpioVar(varp, scopep))->castVpiHandle();
|
||||
}
|
||||
|
||||
vpiHandle vpi_handle_by_index(vpiHandle object, PLI_INT32 indx) {
|
||||
// Used to get array entries
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_handle_by_index %p %d\n",object, indx););
|
||||
VerilatedVpioVar* varop = VerilatedVpioVar::castp(object);
|
||||
if (VL_LIKELY(varop)) {
|
||||
if (varop->varp()->dims()<2) return 0;
|
||||
if (VL_LIKELY(varop->varp()->array().lhs() >= varop->varp()->array().rhs())) {
|
||||
if (VL_UNLIKELY(indx > varop->varp()->array().lhs() || indx < varop->varp()->array().rhs())) return 0;
|
||||
return (new VerilatedVpioVarIndex(varop->varp(), varop->scopep(), indx,
|
||||
indx - varop->varp()->array().rhs()))
|
||||
->castVpiHandle();
|
||||
} else {
|
||||
if (VL_UNLIKELY(indx < varop->varp()->array().lhs() || indx > varop->varp()->array().rhs())) return 0;
|
||||
return (new VerilatedVpioVarIndex(varop->varp(), varop->scopep(), indx,
|
||||
indx - varop->varp()->array().lhs()))
|
||||
->castVpiHandle();
|
||||
}
|
||||
} else {
|
||||
_VL_VPI_UNIMP(); return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// for traversing relationships
|
||||
|
||||
vpiHandle vpi_handle(PLI_INT32 type, vpiHandle object) {
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_handle %d %p\n",type,object););
|
||||
switch (type) {
|
||||
case vpiLeftRange: // FALLTHRU
|
||||
case vpiRightRange: {
|
||||
if (VerilatedVpioVar* vop = VerilatedVpioVar::castp(object)) {
|
||||
vluint32_t num = ((type==vpiLeftRange)
|
||||
? vop->varp()->range().lhs()
|
||||
: vop->varp()->range().rhs());
|
||||
return (new VerilatedVpioConst(num))->castVpiHandle();
|
||||
} else if (VerilatedVpioRange* vop = VerilatedVpioRange::castp(object)) {
|
||||
vluint32_t num = ((type==vpiLeftRange)
|
||||
? vop->lhs()
|
||||
: vop->rhs());
|
||||
return (new VerilatedVpioConst(num))->castVpiHandle();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
default:
|
||||
_VL_VPI_UNIMP();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//-vpiHandle vpi_handle_multi(PLI_INT32 type, vpiHandle refHandle1, vpiHandle refHandle2, ... ) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
|
||||
vpiHandle vpi_iterate(PLI_INT32 type, vpiHandle object) {
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_iterate %d %p\n",type,object););
|
||||
switch (type) {
|
||||
case vpiMemoryWord: {
|
||||
VerilatedVpioVar* vop = VerilatedVpioVar::castp(object);
|
||||
if (VL_UNLIKELY(!vop)) return 0;
|
||||
if (vop->varp()->dims() < 2) return 0;
|
||||
// Unsupported is multidim list
|
||||
return ((new VerilatedVpioRange(vop->varp()->array().lhs(),
|
||||
vop->varp()->array().rhs()))
|
||||
->castVpiHandle());
|
||||
}
|
||||
case vpiReg: {
|
||||
VerilatedVpioScope* vop = VerilatedVpioScope::castp(object);
|
||||
if (VL_UNLIKELY(!vop)) return 0;
|
||||
return ((new VerilatedVpioVarIter(vop->scopep()))
|
||||
->castVpiHandle());
|
||||
}
|
||||
case vpiIODecl: // Skipping - we'll put under reg
|
||||
case vpiNet: // Skipping - we'll put under reg
|
||||
return 0;
|
||||
default:
|
||||
_VL_VPI_UNIMP(); return 0;
|
||||
}
|
||||
}
|
||||
vpiHandle vpi_scan(vpiHandle object) {
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_scan %p\n",object););
|
||||
VerilatedVpio* vop = VerilatedVpio::castp(object);
|
||||
if (VL_UNLIKELY(!vop)) return NULL;
|
||||
return vop->dovpi_scan();
|
||||
}
|
||||
|
||||
// for processing properties
|
||||
|
||||
PLI_INT32 vpi_get(PLI_INT32 property, vpiHandle object) {
|
||||
// Leave this in the header file - in many cases the compiler can constant propagate "object"
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_get %d %p\n",property,object););
|
||||
switch (property) {
|
||||
case vpiTimePrecision: {
|
||||
return VL_TIME_PRECISION;
|
||||
}
|
||||
case vpiType: {
|
||||
VerilatedVpioVar* vop = VerilatedVpioVar::castp(object);
|
||||
if (VL_UNLIKELY(!vop)) return 0;
|
||||
return ((vop->varp()->dims()>1) ? vpiMemory : vpiReg);
|
||||
}
|
||||
case vpiDirection: {
|
||||
// By forthought, the directions already are vpi enumerated
|
||||
VerilatedVpioVar* vop = VerilatedVpioVar::castp(object);
|
||||
if (VL_UNLIKELY(!vop)) return 0;
|
||||
return vop->varp()->vldir();
|
||||
}
|
||||
case vpiVector: {
|
||||
VerilatedVpioVar* vop = VerilatedVpioVar::castp(object);
|
||||
if (VL_UNLIKELY(!vop)) return 0;
|
||||
if (vop->varp()->dims()==0) return 0;
|
||||
else return 1;
|
||||
}
|
||||
default:
|
||||
_VL_VPI_UNIMP();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//-PLI_INT64 vpi_get64(PLI_INT32 property, vpiHandle object) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
|
||||
PLI_BYTE8 *vpi_get_str(PLI_INT32 property, vpiHandle object) {
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_get_str %d %p\n",property,object););
|
||||
VerilatedVpio* vop = VerilatedVpio::castp(object);
|
||||
if (VL_UNLIKELY(!vop)) return NULL;
|
||||
switch (property) {
|
||||
case vpiName: {
|
||||
return (PLI_BYTE8*)vop->name();
|
||||
}
|
||||
case vpiFullName: {
|
||||
return (PLI_BYTE8*)vop->fullname();
|
||||
}
|
||||
case vpiDefName: {
|
||||
return (PLI_BYTE8*)vop->defname();
|
||||
}
|
||||
default:
|
||||
_VL_VPI_UNIMP();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// delay processing
|
||||
|
||||
//-void vpi_get_delays(vpiHandle object, p_vpi_delay delay_p) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
//-void vpi_put_delays(vpiHandle object, p_vpi_delay delay_p) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
|
||||
// value processing
|
||||
|
||||
void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_get_value %p\n",object););
|
||||
if (VL_UNLIKELY(!value_p)) return;
|
||||
if (VerilatedVpioVar* vop = VerilatedVpioVar::castp(object)) {
|
||||
// We presume vpiValue.format = vpiIntVal or if single bit vpiScalarVal
|
||||
if (value_p->format == vpiVectorVal) {
|
||||
// Vector pointer must come from our memory pool
|
||||
// It only needs to persist until the next vpi_get_value
|
||||
static VL_THREAD t_vpi_vecval out[VL_MULS_MAX_WORDS*2];
|
||||
value_p->value.vector = out;
|
||||
switch (vop->varp()->vltype()) {
|
||||
case VLVT_UINT8:
|
||||
out[0].aval = *((CData*)(vop->varDatap()));
|
||||
out[0].bval = 0;
|
||||
return;
|
||||
case VLVT_UINT16:
|
||||
out[0].aval = *((SData*)(vop->varDatap()));
|
||||
out[0].bval = 0;
|
||||
return;
|
||||
case VLVT_UINT32:
|
||||
out[0].aval = *((IData*)(vop->varDatap()));
|
||||
out[0].bval = 0;
|
||||
return;
|
||||
case VLVT_WDATA: {
|
||||
int words = VL_WORDS_I(vop->varp()->range().bits());
|
||||
if (VL_UNLIKELY(words >= VL_MULS_MAX_WORDS)) {
|
||||
vl_fatal(__FILE__,__LINE__,"", "vpi_get_value with more than VL_MULS_MAX_WORDS; increase and recompile");
|
||||
}
|
||||
WDataInP datap = ((IData*)(vop->varDatap()));
|
||||
for (int i=0; i<words; i++) {
|
||||
out[i].aval = datap[i];
|
||||
out[i].bval = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
case VLVT_UINT64: {
|
||||
QData data = *((QData*)(vop->varDatap()));
|
||||
out[1].aval = (IData)(data>>VL_ULL(32));
|
||||
out[1].bval = 0;
|
||||
out[0].aval = (IData)(data);
|
||||
out[0].bval = 0;
|
||||
return;
|
||||
}
|
||||
default: {
|
||||
_VL_VPI_UNIMP();
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch (vop->varp()->vltype()) {
|
||||
case VLVT_UINT8:
|
||||
value_p->value.integer = *((CData*)(vop->varDatap()));
|
||||
return;
|
||||
case VLVT_UINT16:
|
||||
value_p->value.integer = *((SData*)(vop->varDatap()));
|
||||
return;
|
||||
case VLVT_UINT32:
|
||||
value_p->value.integer = *((IData*)(vop->varDatap()));
|
||||
return;
|
||||
case VLVT_WDATA:
|
||||
case VLVT_UINT64:
|
||||
// Not legal
|
||||
value_p->value.integer = 0;
|
||||
default:
|
||||
_VL_VPI_UNIMP();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (VerilatedVpioConst* vop = VerilatedVpioConst::castp(object)) {
|
||||
value_p->value.integer = vop->num();
|
||||
return;
|
||||
}
|
||||
_VL_VPI_UNIMP();
|
||||
}
|
||||
|
||||
vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
|
||||
p_vpi_time time_p, PLI_INT32 flags) {
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_put_value %p %p\n",object, value_p););
|
||||
if (VL_UNLIKELY(!value_p)) return 0;
|
||||
if (VerilatedVpioVar* vop = VerilatedVpioVar::castp(object)) {
|
||||
// We presume vpiValue.format = vpiIntVal or if single bit vpiScalarVal
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_put_value name=%s fmt=%d vali=%d\n",
|
||||
vop->fullname(), value_p->format, value_p->value.integer);
|
||||
VL_PRINTF("-vltVpi: varp=%p putatp=%p\n",
|
||||
vop->varp()->datap(), vop->varDatap()););
|
||||
if (VL_UNLIKELY(!vop->varp()->isPublicRW())) {
|
||||
VL_PRINTF("%%Warning: Ignoring vpi_put_value to signal marked read-only, use public_flat_rw instead: %s\n",
|
||||
vop->fullname());
|
||||
return 0;
|
||||
}
|
||||
if (value_p->format == vpiVectorVal) {
|
||||
if (VL_UNLIKELY(!value_p->value.vector)) return NULL;
|
||||
switch (vop->varp()->vltype()) {
|
||||
case VLVT_UINT8:
|
||||
*((CData*)(vop->varDatap())) = value_p->value.vector[0].aval;
|
||||
return object;
|
||||
case VLVT_UINT16:
|
||||
*((SData*)(vop->varDatap())) = value_p->value.vector[0].aval;
|
||||
return object;
|
||||
case VLVT_UINT32:
|
||||
*((IData*)(vop->varDatap())) = value_p->value.vector[0].aval;
|
||||
return object;
|
||||
case VLVT_WDATA: {
|
||||
int words = VL_WORDS_I(vop->varp()->range().bits());
|
||||
WDataOutP datap = ((IData*)(vop->varDatap()));
|
||||
for (int i=0; i<words; i++) {
|
||||
datap[i] = value_p->value.vector[i].aval;
|
||||
}
|
||||
return object;
|
||||
}
|
||||
case VLVT_UINT64: {
|
||||
*((QData*)(vop->varDatap())) = _VL_SET_QII(
|
||||
value_p->value.vector[1].aval,
|
||||
value_p->value.vector[0].aval);
|
||||
return object;
|
||||
}
|
||||
default: {
|
||||
_VL_VPI_UNIMP();
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch (vop->varp()->vltype()) {
|
||||
case VLVT_UINT8:
|
||||
*((CData*)(vop->varDatap())) = vop->mask() & value_p->value.integer;
|
||||
return object;
|
||||
case VLVT_UINT16:
|
||||
*((SData*)(vop->varDatap())) = vop->mask() & value_p->value.integer;
|
||||
return object;
|
||||
case VLVT_UINT32:
|
||||
*((IData*)(vop->varDatap())) = vop->mask() & value_p->value.integer;
|
||||
return object;
|
||||
case VLVT_WDATA: // FALLTHRU
|
||||
case VLVT_UINT64: // FALLTHRU
|
||||
default:
|
||||
_VL_VPI_UNIMP();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
_VL_VPI_UNIMP(); return NULL;
|
||||
}
|
||||
|
||||
//-void vpi_get_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p,
|
||||
//- PLI_INT32 *index_p, PLI_UINT32 num) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
//-void vpi_put_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p,
|
||||
//- PLI_INT32 *index_p, PLI_UINT32 num) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
|
||||
|
||||
// time processing
|
||||
|
||||
//-void vpi_get_time(vpiHandle object, p_vpi_time time_p) {
|
||||
//- _VL_VPI_UNIMP();
|
||||
//-}
|
||||
|
||||
// I/O routines
|
||||
|
||||
PLI_UINT32 vpi_mcd_open(PLI_BYTE8 *filenamep) {
|
||||
return VL_FOPEN_S(filenamep,"wb");
|
||||
}
|
||||
|
||||
PLI_UINT32 vpi_mcd_close(PLI_UINT32 mcd) {
|
||||
VL_FCLOSE_I(mcd); return 0;
|
||||
}
|
||||
|
||||
//-PLI_BYTE8 *vpi_mcd_name(PLI_UINT32 mcd) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
|
||||
PLI_INT32 vpi_mcd_printf(PLI_UINT32 mcd, PLI_BYTE8 *formatp, ...) {
|
||||
va_list ap;
|
||||
va_start(ap,formatp);
|
||||
int chars = vpi_mcd_vprintf(mcd, formatp, ap);
|
||||
va_end(ap);
|
||||
return chars;
|
||||
}
|
||||
|
||||
PLI_INT32 vpi_printf(PLI_BYTE8 *formatp, ...) {
|
||||
va_list ap;
|
||||
va_start(ap,formatp);
|
||||
int chars = vpi_vprintf(formatp, ap);
|
||||
va_end(ap);
|
||||
return chars;
|
||||
}
|
||||
|
||||
PLI_INT32 vpi_vprintf(PLI_BYTE8* formatp, va_list ap) {
|
||||
return VL_VPRINTF(formatp, ap);
|
||||
}
|
||||
|
||||
PLI_INT32 vpi_mcd_vprintf(PLI_UINT32 mcd, PLI_BYTE8 *format, va_list ap) {
|
||||
FILE* fp = VL_CVT_I_FP(mcd);
|
||||
if (VL_UNLIKELY(!fp)) return 0;
|
||||
int chars = vfprintf(fp, format, ap);
|
||||
return chars;
|
||||
}
|
||||
|
||||
PLI_INT32 vpi_flush(void) {
|
||||
Verilated::flushCall();
|
||||
return 0;
|
||||
}
|
||||
|
||||
PLI_INT32 vpi_mcd_flush(PLI_UINT32 mcd) {
|
||||
FILE* fp = VL_CVT_I_FP(mcd);
|
||||
if (VL_UNLIKELY(!fp)) return 1;
|
||||
fflush(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// utility routines
|
||||
|
||||
//-PLI_INT32 vpi_compare_objects(vpiHandle object1, vpiHandle object2) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
//-PLI_INT32 vpi_chk_error(p_vpi_error_info error_info_p) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
|
||||
PLI_INT32 vpi_free_object(vpiHandle object) {
|
||||
return vpi_release_handle(object); // Deprecated
|
||||
}
|
||||
|
||||
PLI_INT32 vpi_release_handle (vpiHandle object) {
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_release_handle %p\n",object););
|
||||
VerilatedVpio* vop = VerilatedVpio::castp(object);
|
||||
if (VL_UNLIKELY(!vop)) return 0;
|
||||
vpi_remove_cb(object); // May not be a callback, but that's ok
|
||||
delete vop;
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-PLI_INT32 vpi_get_vlog_info(p_vpi_vlog_info vlog_info_p) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
|
||||
// routines added with 1364-2001
|
||||
|
||||
//-PLI_INT32 vpi_get_data(PLI_INT32 id, PLI_BYTE8 *dataLoc, PLI_INT32 numOfBytes) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
//-PLI_INT32 vpi_put_data(PLI_INT32 id, PLI_BYTE8 *dataLoc, PLI_INT32 numOfBytes) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
//-void *vpi_get_userdata(vpiHandle obj) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
//-PLI_INT32 vpi_put_userdata(vpiHandle obj, void *userdata) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
|
||||
PLI_INT32 vpi_control(PLI_INT32 operation, ...) {
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_control %d\n",operation););
|
||||
switch (operation) {
|
||||
case vpiFinish: {
|
||||
vl_finish(__FILE__,__LINE__,"*VPI*");
|
||||
return 1;
|
||||
}
|
||||
case vpiStop: {
|
||||
vl_stop(__FILE__,__LINE__,"*VPI*");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
_VL_VPI_UNIMP(); return 0;
|
||||
}
|
||||
|
||||
//-vpiHandle vpi_handle_by_multi_index(vpiHandle obj, PLI_INT32 num_index, PLI_INT32 *index_array) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
|
||||
//======================================================================
|
||||
|
||||
#endif // Guard
|
||||
@@ -1,7 +1,7 @@
|
||||
// -*- C++ -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -250,7 +250,7 @@ what made a <e####> line in the tree dumps):
|
||||
|
||||
The latest version is available from L<http://www.veripool.org/>.
|
||||
|
||||
Copyright 2008-2010 by Wilson Snyder. Verilator is free software; you can
|
||||
Copyright 2008-2011 by Wilson Snyder. Verilator 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.
|
||||
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/perl -w
|
||||
######################################################################
|
||||
#
|
||||
# Copyright 2007-2010 by Wilson Snyder. This package is free software; you
|
||||
# Copyright 2007-2011 by Wilson Snyder. This package 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.
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/perl -w
|
||||
######################################################################
|
||||
#
|
||||
# Copyright 2007-2010 by Wilson Snyder. This package is free software; you
|
||||
# Copyright 2007-2011 by Wilson Snyder. This package 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.
|
||||
|
||||
+1
-1
@@ -143,7 +143,7 @@ Displays this message and program version and exits.
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2005-2010 by Wilson Snyder. Verilator is free software; you can
|
||||
Copyright 2005-2011 by Wilson Snyder. Verilator 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.
|
||||
|
||||
|
||||
+1
-1
@@ -184,7 +184,7 @@ Displays this message and program version and exits.
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2005-2010 by Wilson Snyder. Verilator is free software; you can
|
||||
Copyright 2005-2011 by Wilson Snyder. Verilator 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.
|
||||
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/perl -w
|
||||
######################################################################
|
||||
#
|
||||
# Copyright 2007-2010 by Wilson Snyder. This package is free software; you
|
||||
# Copyright 2007-2011 by Wilson Snyder. This package 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.
|
||||
|
||||
+1
-1
@@ -117,7 +117,7 @@ Displays this message and program version and exits.
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2009-2010 by Wilson Snyder. This package is free software; you
|
||||
Copyright 2009-2011 by Wilson Snyder. This package 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.
|
||||
|
||||
+2
-14
@@ -8,21 +8,9 @@ use strict;
|
||||
#======================================================================
|
||||
# main
|
||||
|
||||
delete $ENV{MODULE_VERSION};
|
||||
_setup_modules();
|
||||
module('add','axiom-athdl');
|
||||
eval `modulecmd perl add axiom-athdl`;
|
||||
exec('atsim',@ARGV);
|
||||
|
||||
#######################################################################
|
||||
# Modules package
|
||||
|
||||
sub _setup_modules {
|
||||
# Load the 'module' command into the environment
|
||||
my $init = "$ENV{MODULESHOME}/init/perl";
|
||||
(-f $init) or die "%Error: Script not found: $init,";
|
||||
require $init;
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
__END__
|
||||
|
||||
@@ -40,7 +28,7 @@ invoke_atsim - Invoke tool under "modules" command
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2005-2010 by Wilson Snyder. This package is free software; you
|
||||
Copyright 2005-2011 by Wilson Snyder. This package 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.
|
||||
|
||||
+2
-14
@@ -8,21 +8,9 @@ use strict;
|
||||
#======================================================================
|
||||
# main
|
||||
|
||||
delete $ENV{MODULE_VERSION};
|
||||
_setup_modules();
|
||||
module('add','cadence-ius');
|
||||
eval `modulecmd perl add cds-ius`;
|
||||
exec('iccr',@ARGV);
|
||||
|
||||
#######################################################################
|
||||
# Modules package
|
||||
|
||||
sub _setup_modules {
|
||||
# Load the 'module' command into the environment
|
||||
my $init = "$ENV{MODULESHOME}/init/perl";
|
||||
(-f $init) or die "%Error: Script not found: $init,";
|
||||
require $init;
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
__END__
|
||||
|
||||
@@ -40,7 +28,7 @@ invoke_iccr - Invoke tool under "modules" command
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2007-2010 by Wilson Snyder. This package is free software; you
|
||||
Copyright 2007-2011 by Wilson Snyder. This package 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.
|
||||
|
||||
+2
-14
@@ -8,21 +8,9 @@ use strict;
|
||||
#======================================================================
|
||||
# main
|
||||
|
||||
delete $ENV{MODULE_VERSION};
|
||||
_setup_modules();
|
||||
module('add','cadence-ius');
|
||||
eval `modulecmd perl add cds-ius`;
|
||||
exec('ncverilog',@ARGV);
|
||||
|
||||
#######################################################################
|
||||
# Modules package
|
||||
|
||||
sub _setup_modules {
|
||||
# Load the 'module' command into the environment
|
||||
my $init = "$ENV{MODULESHOME}/init/perl";
|
||||
(-f $init) or die "%Error: Script not found: $init,";
|
||||
require $init;
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
__END__
|
||||
|
||||
@@ -40,7 +28,7 @@ invoke_ncverilog - Invoke tool under "modules" command
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2005-2010 by Wilson Snyder. This package is free software; you
|
||||
Copyright 2005-2011 by Wilson Snyder. This package 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.
|
||||
|
||||
+2
-14
@@ -8,21 +8,9 @@ use strict;
|
||||
#======================================================================
|
||||
# main
|
||||
|
||||
delete $ENV{MODULE_VERSION};
|
||||
_setup_modules();
|
||||
module('add','synopsys-vcs');
|
||||
eval `modulecmd perl add synopsys-vcs`;
|
||||
exec('vcs',@ARGV);
|
||||
|
||||
#######################################################################
|
||||
# Modules package
|
||||
|
||||
sub _setup_modules {
|
||||
# Load the 'module' command into the environment
|
||||
my $init = "$ENV{MODULESHOME}/init/perl";
|
||||
(-f $init) or die "%Error: Script not found: $init,";
|
||||
require $init;
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
__END__
|
||||
|
||||
@@ -40,7 +28,7 @@ invoke_vcs - Invoke tool under "modules" command
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2005-2010 by Wilson Snyder. This package is free software; you
|
||||
Copyright 2005-2011 by Wilson Snyder. This package 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.
|
||||
|
||||
+2
-1
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/perl -w
|
||||
######################################################################
|
||||
#
|
||||
# Copyright 2010-2010 by Wilson Snyder. This package is free software; you
|
||||
# Copyright 2010-2011 by Wilson Snyder. This package 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.
|
||||
@@ -81,6 +81,7 @@ sub prep {
|
||||
$line =~ s/SP_NOTICE.*// if $sp;
|
||||
$line =~ s/vl_fatal.*// if !$sp;
|
||||
$line =~ s/VL_PRINT.*// if !$sp;
|
||||
$line =~ s/Copyright \d+-\d+/Copyright #-#/g;
|
||||
|
||||
push @wf, $line;
|
||||
|
||||
|
||||
@@ -256,7 +256,7 @@ sub gentree {
|
||||
'TRACE' => sub { p "TRACE what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
||||
'UCFUNC' => sub { p '$c(';p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p ")"; },
|
||||
'UCSTMT' => sub { p '$c(';p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p ");";nl; },
|
||||
'UNARYMIN' => sub { p " -";p1; },
|
||||
'NEGATE' => sub { p " -";p1; },
|
||||
'VAR' => sub { p_var(); },
|
||||
'VARPIN' => sub { p "VARPIN what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
||||
'VARREF' => sub { a1; },
|
||||
@@ -331,7 +331,7 @@ Displays this message and program version and exits.
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2005-2010 by Wilson Snyder. Verilator is free software; you can
|
||||
Copyright 2005-2011 by Wilson Snyder. Verilator 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.
|
||||
|
||||
|
||||
+44
-21
@@ -9,7 +9,7 @@ This is the Verilator Package README file.
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
This package is Copyright 2003-2010 by Wilson Snyder. (Report bugs to
|
||||
This package is Copyright 2003-2011 by Wilson Snyder. (Report bugs to
|
||||
L<http://www.veripool.org/>.)
|
||||
|
||||
Verilator is free software; you can redistribute it and/or modify it under
|
||||
@@ -72,15 +72,14 @@ Download the latest package from that site, and decompress.
|
||||
|
||||
If you will be using SystemC (vs straight C++ output), download SystemC
|
||||
2.0.1 from L<http://www.systemc.org>. Follow their installation
|
||||
instructions. As described in the System-Perl README, you will need to set
|
||||
SYSTEMC and/or SYSTEMC_KIT to point to this download. Also, set
|
||||
SYSTEMC_ARCH to the architecture name you used with SystemC, generally
|
||||
'linux' or 'cygwin'.
|
||||
instructions. You will need to set the SYSTEMC environment variable to
|
||||
point to this download. Also, setenv SYSTEMC_ARCH to the architecture name
|
||||
you used with SystemC, generally 'linux' or 'cygwin'.
|
||||
|
||||
=item
|
||||
|
||||
If you will be using SystemPerl or coverage, download and install
|
||||
Verilog-Perl, L<http://www.veripool.org/verilog-perl>.
|
||||
Verilator assumes you did a make in the SystemC kit directory and SYSTEMC
|
||||
points to that directory. There must be appropriate files in
|
||||
C<$SYSTEMC/include> and C<$SYSTEMC/lib-linux> for SystemC compilation to
|
||||
work.
|
||||
|
||||
=item
|
||||
|
||||
@@ -98,20 +97,49 @@ C<cd> to the Verilator directory containing this README.
|
||||
|
||||
You now have to decide how you're going to eventually install the kit.
|
||||
|
||||
Note Verilator builds the current value of VERILATOR_ROOT, SYSTEMC,
|
||||
SYSTEMC_ARCH, SYSTEMPERL, and SYSTEMPERL_INCLUDE as defaults into the
|
||||
executable, so try to have them correct before configuring.
|
||||
|
||||
=over 4
|
||||
|
||||
=item 1.
|
||||
|
||||
Our personal favorite is to always run Verilator from the kit directory.
|
||||
This allows the easiest experimentation and upgrading. It's also how most
|
||||
EDA tools operate; you just point to the tarball.
|
||||
EDA tools operate; to run any of them you point to the tarball.
|
||||
|
||||
export VERILATOR_ROOT=`pwd` # if your shell is bash
|
||||
setenv VERILATOR_ROOT `pwd` # if your shell is csh
|
||||
./configure
|
||||
|
||||
=item 2.
|
||||
|
||||
To install globally onto a "cad" disk with multiple versions of every tool,
|
||||
and add it to path using Modules/modulecmd:
|
||||
|
||||
unset VERILATOR_ROOT # if your shell is bash
|
||||
unsetenv VERILATOR_ROOT # if your shell is csh
|
||||
# For the tarball, use the version number instead of git describe
|
||||
./configure --prefix /CAD_DISK/verilator/`git describe | sed "s/verilator_//"`
|
||||
|
||||
After installing you'll want a module file like the following:
|
||||
|
||||
set install_root /CAD_DISK/verilator/{version-number-used-above}
|
||||
setenv VERILATOR_ROOT $install_root
|
||||
prepend-path PATH $install_root/bin
|
||||
prepend-path MANPATH $install_root/man
|
||||
|
||||
=item 3.
|
||||
|
||||
The next option is to install it globally, using the normal system paths:
|
||||
|
||||
unset VERILATOR_ROOT # if your shell is bash
|
||||
unsetenv VERILATOR_ROOT # if your shell is csh
|
||||
./configure
|
||||
|
||||
=item 4.
|
||||
|
||||
Alternatively you can configure a prefix that install will populate, as
|
||||
most GNU tools support:
|
||||
|
||||
@@ -119,11 +147,7 @@ most GNU tools support:
|
||||
unsetenv VERILATOR_ROOT # if your shell is csh
|
||||
./configure --prefix /opt/verilator-VERSION
|
||||
|
||||
Finally, if you are configuring Verilator to be part of a RPM or other
|
||||
distribution package system, you may want to tune the various install
|
||||
directories and use the --enable-defenv configure flag. This will take the
|
||||
current value of VERILATOR_ROOT, SYSTEMC, SYSTEMC_ARCH, SYSTEMPERL, and
|
||||
SYSTEMPERL_INCLUDE and build them as defaults into the executable.
|
||||
=back
|
||||
|
||||
=item
|
||||
|
||||
@@ -141,16 +165,15 @@ unsigned long uint32_t;}.
|
||||
|
||||
=item
|
||||
|
||||
If you used the VERILATOR_ROOT sheme you're done. Programs should set the
|
||||
If you used the VERILATOR_ROOT scheme you're done. Programs should set the
|
||||
environment variable VERILATOR_ROOT to point to this distribution, then
|
||||
execute $VERILATOR_ROOT/bin/verilator, which will find the path to all
|
||||
needed files.
|
||||
|
||||
If you used the prefix scheme, now do a C<make install>.
|
||||
|
||||
Verilator assumes you did a make in the SystemC kit directory. If not, you
|
||||
will need to populate C<$SYSTEMC/include> and C<$SYSTEMC/lib-linux>
|
||||
appropriately.
|
||||
If you used the prefix scheme, now do a C<make install>. To run verilator,
|
||||
have the verilator binary directory in your PATH (this should already be
|
||||
true if using the default configure), and make sure VERILATOR_ROOT is not
|
||||
set.
|
||||
|
||||
=back
|
||||
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ This is the Verilator Package.
|
||||
@node Copyright, Description, Top, Top
|
||||
@section Copyright
|
||||
|
||||
This package is Copyright 2003-2010 by Wilson Snyder @email{wsnyder@@wsnyder.org}.
|
||||
This package is Copyright 2003-2011 by Wilson Snyder @email{wsnyder@@wsnyder.org}.
|
||||
|
||||
Verilator is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License
|
||||
|
||||
+5
-1
@@ -7,7 +7,7 @@
|
||||
#
|
||||
#*****************************************************************************
|
||||
#
|
||||
# Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
# Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
@@ -46,6 +46,10 @@ export OBJCACHE_JOBS := -j $(shell objcache --jobs "$(OBJCACHE_HOSTS)")
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(words $(CURDIR)),1)
|
||||
$(error Unsupported: GNU Make cannot build in directories containing spaces, build elsewhere: '$(CURDIR)')
|
||||
endif
|
||||
|
||||
UNDER_GIT = $(wildcard ../.git/logs/HEAD)
|
||||
|
||||
#*********************************************************************
|
||||
|
||||
+2
-2
@@ -7,7 +7,7 @@
|
||||
#
|
||||
#*****************************************************************************
|
||||
#
|
||||
# Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
# Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
@@ -209,7 +209,6 @@ RAW_OBJS = \
|
||||
V3PreShell.o \
|
||||
V3Premit.o \
|
||||
V3Scope.o \
|
||||
V3Signed.o \
|
||||
V3Slice.o \
|
||||
V3Split.o \
|
||||
V3SplitAs.o \
|
||||
@@ -221,6 +220,7 @@ RAW_OBJS = \
|
||||
V3Trace.o \
|
||||
V3TraceDecl.o \
|
||||
V3Tristate.o \
|
||||
V3Undriven.o \
|
||||
V3Unknown.o \
|
||||
V3Unroll.o \
|
||||
V3Width.o \
|
||||
|
||||
+48
-13
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -160,26 +160,58 @@ public:
|
||||
|
||||
class ActiveDlyVisitor : public ActiveBaseVisitor {
|
||||
private:
|
||||
bool m_combo; // Combo logic
|
||||
AstNode* m_alwaysp; // Always we're under
|
||||
AstNode* m_assignp; // In assign
|
||||
// VISITORS
|
||||
virtual void visit(AstAssignDly* nodep, AstNUser*) {
|
||||
// Convert to a non-delayed assignment
|
||||
UINFO(5," ASSIGNDLY "<<nodep<<endl);
|
||||
nodep->v3warn(COMBDLY,"Delayed assignments (<=) in non-clocked (non flop or latch) blocks should be non-delayed assignments (=).");
|
||||
AstNode* newp = new AstAssign (nodep->fileline(),
|
||||
nodep->lhsp()->unlinkFrBack(),
|
||||
nodep->rhsp()->unlinkFrBack());
|
||||
nodep->replaceWith(newp);
|
||||
nodep->deleteTree(); nodep = NULL;
|
||||
if (m_combo) {
|
||||
// Convert to a non-delayed assignment
|
||||
UINFO(5," ASSIGNDLY "<<nodep<<endl);
|
||||
nodep->v3warn(COMBDLY,"Delayed assignments (<=) in non-clocked (non flop or latch) block; suggest blocking assignments (=).");
|
||||
AstNode* newp = new AstAssign (nodep->fileline(),
|
||||
nodep->lhsp()->unlinkFrBack(),
|
||||
nodep->rhsp()->unlinkFrBack());
|
||||
nodep->replaceWith(newp);
|
||||
nodep->deleteTree(); nodep = NULL;
|
||||
}
|
||||
}
|
||||
virtual void visit(AstAssign* nodep, AstNUser*) {
|
||||
if (!m_combo) {
|
||||
AstNode* las = m_assignp;
|
||||
m_assignp = nodep;
|
||||
nodep->lhsp()->iterateAndNext(*this);
|
||||
m_assignp = las;
|
||||
}
|
||||
}
|
||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||
AstVar* varp=nodep->varp();
|
||||
if (!m_combo
|
||||
&& m_assignp
|
||||
&& !varp->isUsedLoopIdx() // Ignore loop indicies
|
||||
&& !varp->isTemp()
|
||||
) {
|
||||
// Allow turning off warnings on the always, or the variable also
|
||||
if (!m_alwaysp->fileline()->warnIsOff(V3ErrorCode::BLKSEQ)
|
||||
&& !m_assignp->fileline()->warnIsOff(V3ErrorCode::BLKSEQ)
|
||||
&& !varp->fileline()->warnIsOff(V3ErrorCode::BLKSEQ)
|
||||
) {
|
||||
m_alwaysp->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true); // Complain just once for the entire always
|
||||
varp->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true);
|
||||
nodep->v3warn(BLKSEQ,"Blocking assignments (=) in sequential (flop or latch) block; suggest delayed assignments (<=).");
|
||||
}
|
||||
}
|
||||
}
|
||||
// Empty visitors, speed things up
|
||||
virtual void visit(AstNodeMath* nodep, AstNUser*) {}
|
||||
//--------------------
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
ActiveDlyVisitor(AstNode* nodep) {
|
||||
ActiveDlyVisitor(AstNode* nodep, bool combo) {
|
||||
m_alwaysp = nodep;
|
||||
m_combo = combo;
|
||||
m_assignp = NULL;
|
||||
nodep->accept(*this);
|
||||
}
|
||||
virtual ~ActiveDlyVisitor() {}
|
||||
@@ -317,7 +349,10 @@ private:
|
||||
|
||||
// Warn and/or convert any delayed assignments
|
||||
if (combo && !sequent) {
|
||||
ActiveDlyVisitor dlyvisitor (nodep);
|
||||
ActiveDlyVisitor dlyvisitor (nodep, true);
|
||||
}
|
||||
else if (!combo && sequent) {
|
||||
ActiveDlyVisitor dlyvisitor (nodep, false);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstAlways* nodep, AstNUser*) {
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+5
-4
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2005-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2005-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -182,7 +182,7 @@ private:
|
||||
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
|
||||
if (itemp->isDefault()) has_default=true;
|
||||
}
|
||||
if (nodep->fullPragma()) {
|
||||
if (nodep->fullPragma() || nodep->priorityPragma()) {
|
||||
// Simply need to add a default if there isn't one already
|
||||
m_statAsFull++;
|
||||
if (!has_default) {
|
||||
@@ -190,7 +190,7 @@ private:
|
||||
newFireAssert(nodep, "synthesis full_case, but non-match found")));
|
||||
}
|
||||
}
|
||||
if (nodep->parallelPragma()) {
|
||||
if (nodep->parallelPragma() || nodep->uniquePragma() || nodep->unique0Pragma()) {
|
||||
// Need to check that one, and only one of the case items match at any moment
|
||||
// If there's a default, we allow none to match, else exactly one must match
|
||||
m_statAsFull++;
|
||||
@@ -207,7 +207,8 @@ private:
|
||||
else propp = onep;
|
||||
}
|
||||
}
|
||||
AstNode* ohot = (has_default
|
||||
bool allow_none = has_default || nodep->unique0Pragma();
|
||||
AstNode* ohot = (allow_none
|
||||
? (new AstOneHot0(nodep->fileline(), propp))->castNode()
|
||||
: (new AstOneHot (nodep->fileline(), propp))->castNode());
|
||||
AstIf* ifp = new AstIf (nodep->fileline(),
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2005-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2005-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2005-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2005-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2005-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2005-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+7
-4
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -74,7 +74,9 @@ void AstNode::init() {
|
||||
m_clonep = NULL;
|
||||
m_cloneCnt = 0;
|
||||
// Attributes
|
||||
m_signed = false;
|
||||
m_numeric = (int)AstNumeric::UNSIGNED;
|
||||
m_didWidth = false;
|
||||
m_doingWidth = false;
|
||||
m_width = 0;
|
||||
m_widthMin = 0;
|
||||
m_user1p = NULL;
|
||||
@@ -192,6 +194,7 @@ string AstNode::prettyName(const string& namein) {
|
||||
}
|
||||
}
|
||||
if (pretty.substr(0,4) == "TOP.") pretty.replace(0,4,"");
|
||||
if (pretty.substr(0,5) == "TOP->") pretty.replace(0,5,"");
|
||||
return pretty;
|
||||
}
|
||||
|
||||
@@ -813,7 +816,7 @@ void AstNode::iterateAndNextIgnoreEdit(AstNVisitor& v, AstNUser* vup) {
|
||||
AstNode* AstNode::acceptSubtreeReturnEdits(AstNVisitor& v, AstNUser* vup) {
|
||||
// Some visitors perform tree edits (such as V3Const), and may even
|
||||
// replace/delete the exact nodep that the visitor is called with. If
|
||||
// this happens, the parent will loose the handle to the node that was
|
||||
// this happens, the parent will lose the handle to the node that was
|
||||
// processed.
|
||||
// To solve this, this function returns the pointer to the replacement node,
|
||||
// which in many cases is just the same node that was passed in.
|
||||
@@ -872,7 +875,7 @@ bool AstNode::sameTreeIter(AstNode* node2p, bool ignNext) {
|
||||
if (this==NULL || node2p==NULL) return false;
|
||||
if (this->type() != node2p->type()
|
||||
|| this->width() != node2p->width()
|
||||
|| this->isSigned() != node2p->isSigned()
|
||||
|| this->numeric() != node2p->numeric()
|
||||
|| !this->same(node2p)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
+64
-16
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -56,6 +56,36 @@ public:
|
||||
|
||||
//######################################################################
|
||||
|
||||
class AstNumeric {
|
||||
public:
|
||||
enum en {
|
||||
UNSIGNED,
|
||||
SIGNED,
|
||||
DOUBLE
|
||||
// Limited to 2 bits, unless change V3Ast's packing function
|
||||
};
|
||||
enum en m_e;
|
||||
const char* ascii() const {
|
||||
static const char* names[] = {
|
||||
"UNSIGNED","SIGNED","DOUBLE"
|
||||
};
|
||||
return names[m_e];
|
||||
};
|
||||
inline AstNumeric () {}
|
||||
inline AstNumeric (en _e) : m_e(_e) {}
|
||||
explicit inline AstNumeric (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
inline bool isDouble() const { return m_e==DOUBLE; }
|
||||
inline bool isSigned() const { return m_e==SIGNED; }
|
||||
inline bool isUnsigned() const { return m_e==UNSIGNED; }
|
||||
};
|
||||
inline bool operator== (AstNumeric lhs, AstNumeric rhs) { return (lhs.m_e == rhs.m_e); }
|
||||
inline bool operator== (AstNumeric lhs, AstNumeric::en rhs) { return (lhs.m_e == rhs); }
|
||||
inline bool operator== (AstNumeric::en lhs, AstNumeric rhs) { return (lhs == rhs.m_e); }
|
||||
inline ostream& operator<<(ostream& os, AstNumeric rhs) { return os<<rhs.ascii(); }
|
||||
|
||||
//######################################################################
|
||||
|
||||
class AstPragmaType {
|
||||
public:
|
||||
enum en {
|
||||
@@ -209,7 +239,7 @@ class AstBasicDTypeKwd {
|
||||
public:
|
||||
enum en {
|
||||
BIT, BYTE, CHANDLE, INT, INTEGER, LOGIC, LONGINT,
|
||||
REAL, REALTIME, SHORTINT, SHORTREAL, TIME,
|
||||
DOUBLE, SHORTINT, FLOAT, TIME,
|
||||
// Closer to a class type, but limited usage
|
||||
STRING,
|
||||
// Internal types for mid-steps
|
||||
@@ -221,7 +251,7 @@ public:
|
||||
const char* ascii() const {
|
||||
static const char* names[] = {
|
||||
"bit", "byte", "chandle", "int", "integer", "logic", "longint",
|
||||
"real", "realtime", "shortint", "shortreal", "time",
|
||||
"real", "shortint", "shortreal", "time",
|
||||
"string",
|
||||
"VerilatedScope*", "char*",
|
||||
"LOGIC_IMPLICIT"
|
||||
@@ -231,7 +261,7 @@ public:
|
||||
const char* dpiType() const {
|
||||
static const char* names[] = {
|
||||
"unsigned char", "char", "void*", "int", "int", "svLogic", "long long",
|
||||
"double", "double", "short int", "float", "long long",
|
||||
"double", "short int", "float", "long long",
|
||||
"const char*",
|
||||
"dpiScope", "const char*",
|
||||
""
|
||||
@@ -251,6 +281,8 @@ public:
|
||||
case INTEGER: return 32;
|
||||
case LOGIC: return 1;
|
||||
case LONGINT: return 64;
|
||||
case DOUBLE: return 64;
|
||||
case FLOAT: return 32;
|
||||
case SHORTINT: return 16;
|
||||
case TIME: return 64;
|
||||
case STRING: return 64; // Just the pointer, for today
|
||||
@@ -265,7 +297,7 @@ public:
|
||||
}
|
||||
bool isZeroInit() const { // Otherwise initializes to X
|
||||
return (m_e==BIT || m_e==BYTE || m_e==CHANDLE || m_e==INT || m_e==LONGINT || m_e==SHORTINT
|
||||
|| m_e==STRING);
|
||||
|| m_e==STRING || m_e==DOUBLE || m_e==FLOAT);
|
||||
}
|
||||
bool isSloppy() const { // Don't be as anal about width warnings
|
||||
return !(m_e==LOGIC || m_e==BIT);
|
||||
@@ -274,10 +306,13 @@ public:
|
||||
return (m_e==LOGIC || m_e==BIT);
|
||||
}
|
||||
bool isDpiUnsupported() const {
|
||||
return (m_e==LOGIC || m_e==TIME || m_e==REALTIME);
|
||||
return (m_e==LOGIC || m_e==TIME);
|
||||
}
|
||||
bool isOpaque() const { // IE not a simple number we can bit optimize
|
||||
return (m_e==STRING || m_e==SCOPEPTR || m_e==CHARPTR);
|
||||
return (m_e==STRING || m_e==SCOPEPTR || m_e==CHARPTR || m_e==DOUBLE || m_e==FLOAT);
|
||||
}
|
||||
bool isDouble() const {
|
||||
return (m_e==DOUBLE);
|
||||
}
|
||||
};
|
||||
inline bool operator== (AstBasicDTypeKwd lhs, AstBasicDTypeKwd rhs) { return (lhs.m_e == rhs.m_e); }
|
||||
@@ -684,7 +719,9 @@ class AstNode {
|
||||
static int s_cloneCntGbl; // Count of which userp is set
|
||||
|
||||
// Attributes
|
||||
bool m_signed:1; // Node is signed
|
||||
uint32_t m_numeric:2; // Node is real/signed - important that bitfields remain unsigned
|
||||
bool m_didWidth:1; // Did V3Width computation
|
||||
bool m_doingWidth:1; // Inside V3Width
|
||||
// // Space for more bools here
|
||||
|
||||
int m_width; // Bit width of operation
|
||||
@@ -780,6 +817,8 @@ public:
|
||||
static int instrCountLd() { return 2; } ///< Instruction cycles to load memory
|
||||
static int instrCountMul() { return 3; } ///< Instruction cycles to multiply integers
|
||||
static int instrCountPli() { return 20; } ///< Instruction cycles to call pli routines
|
||||
static int instrCountDouble() { return 8; } ///< Instruction cycles to convert or do floats
|
||||
static int instrCountDoubleDiv() { return 40; } ///< Instruction cycles to divide floats
|
||||
static int instrCountCall() { return instrCountBranch()+10; } ///< Instruction cycles to call subroutine
|
||||
static int instrCountTime() { return instrCountCall()+5; } ///< Instruction cycles to determine simulation time
|
||||
|
||||
@@ -807,10 +846,18 @@ public:
|
||||
bool widthSized() const { return !m_widthMin || m_widthMin==m_width; }
|
||||
void width(int width, int sized) { m_width=width; m_widthMin=sized; }
|
||||
void widthFrom(AstNode* fromp) { if (fromp) { m_width=fromp->m_width; m_widthMin=fromp->m_widthMin; }}
|
||||
void widthSignedFrom(AstNode* fromp) { widthFrom(fromp); signedFrom(fromp); }
|
||||
void signedFrom(AstNode* fromp) { if (fromp) { m_signed=fromp->m_signed; }}
|
||||
void isSigned(bool flag) { m_signed=flag; }
|
||||
bool isSigned() const { return m_signed; }
|
||||
void widthSignedFrom(AstNode* fromp) { widthFrom(fromp); numericFrom(fromp); }
|
||||
void numericFrom(AstNode* fromp) { numeric(fromp->numeric()); }
|
||||
void numeric(AstNumeric flag) { m_numeric = (int)flag; if (flag.isDouble()) width(64,64); }
|
||||
AstNumeric numeric() const { return AstNumeric(m_numeric); }
|
||||
bool isDouble() const { return numeric().isDouble(); }
|
||||
bool isSigned() const { return numeric().isSigned(); }
|
||||
void isSigned(bool flag) { numeric(flag ? AstNumeric::SIGNED : AstNumeric::UNSIGNED); }
|
||||
bool isUnsigned() const { return numeric().isUnsigned(); }
|
||||
void didWidth(bool flag) { m_didWidth=flag; }
|
||||
bool didWidth() const { return m_didWidth; }
|
||||
void doingWidth(bool flag) { m_doingWidth=flag; }
|
||||
bool doingWidth() const { return m_doingWidth; }
|
||||
bool isQuad() const { return (width()>VL_WORDSIZE && width()<=VL_QUADSIZE); }
|
||||
bool isWide() const { return (width()>VL_QUADSIZE); }
|
||||
|
||||
@@ -976,10 +1023,13 @@ struct AstNodeUniop : public AstNodeMath {
|
||||
setOp1p(lhsp); }
|
||||
ASTNODE_BASE_FUNCS(NodeUniop)
|
||||
AstNode* lhsp() const { return op1p()->castNode(); }
|
||||
void lhsp(AstNode* nodep) { return setOp1p(nodep); }
|
||||
// METHODS
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) = 0; // Set out to evaluation of a AstConst'ed lhs
|
||||
virtual bool cleanLhs() = 0;
|
||||
virtual bool sizeMattersLhs() = 0; // True if output result depends on lhs size
|
||||
virtual bool signedFlavor() const { return false; } // Signed flavor of nodes with both flavors?
|
||||
virtual bool doubleFlavor() const { return false; } // D flavor of nodes with both flavors?
|
||||
virtual int instrCount() const { return widthInstrs(); }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(AstNode*) const { return true; }
|
||||
@@ -1002,6 +1052,7 @@ struct AstNodeBiop : public AstNodeMath {
|
||||
virtual bool sizeMattersLhs() = 0; // True if output result depends on lhs size
|
||||
virtual bool sizeMattersRhs() = 0; // True if output result depends on rhs size
|
||||
virtual bool signedFlavor() const { return false; } // Signed flavor of nodes with both flavors?
|
||||
virtual bool doubleFlavor() const { return false; } // D flavor of nodes with both flavors?
|
||||
virtual int instrCount() const { return widthInstrs(); }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(AstNode*) const { return true; }
|
||||
@@ -1274,7 +1325,6 @@ private:
|
||||
string m_name; // Name of task
|
||||
string m_cname; // Name of task if DPI import
|
||||
bool m_taskPublic:1; // Public task
|
||||
bool m_didSigning:1; // V3Signed completed; can skip iteration
|
||||
bool m_attrIsolateAssign:1;// User isolate_assignments attribute
|
||||
bool m_prototype:1; // Just a prototype
|
||||
bool m_dpiExport:1; // DPI exported
|
||||
@@ -1285,7 +1335,7 @@ private:
|
||||
public:
|
||||
AstNodeFTask(FileLine* fileline, const string& name, AstNode* stmtsp)
|
||||
: AstNode(fileline)
|
||||
, m_name(name), m_taskPublic(false), m_didSigning(false)
|
||||
, m_name(name), m_taskPublic(false)
|
||||
, m_attrIsolateAssign(false), m_prototype(false)
|
||||
, m_dpiExport(false), m_dpiImport(false), m_dpiContext(false)
|
||||
, m_dpiTask(false), m_pure(false) {
|
||||
@@ -1312,8 +1362,6 @@ public:
|
||||
void scopeNamep(AstNode* nodep) { setNOp4p(nodep); }
|
||||
void taskPublic(bool flag) { m_taskPublic=flag; }
|
||||
bool taskPublic() const { return m_taskPublic; }
|
||||
void didSigning(bool flag) { m_didSigning=flag; }
|
||||
bool didSigning() const { return m_didSigning; }
|
||||
void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; }
|
||||
bool attrIsolateAssign() const { return m_attrIsolateAssign; }
|
||||
void prototype(bool flag) { m_prototype = flag; }
|
||||
|
||||
+12
-6
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -113,6 +113,10 @@ string AstVar::vlArgType(bool named, bool forReturn) const {
|
||||
arg += "const char*";
|
||||
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::SCOPEPTR) {
|
||||
arg += "const VerilatedScope*";
|
||||
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::DOUBLE) {
|
||||
arg += "double";
|
||||
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::FLOAT) {
|
||||
arg += "float";
|
||||
} else if (strtype) {
|
||||
if (isInOnly()) arg += "const ";
|
||||
arg += "string";
|
||||
@@ -185,7 +189,7 @@ string AstVar::cPubArgType(bool named, bool forReturn) const {
|
||||
} else if (isWide()) {
|
||||
arg += "uint32_t"; // []'s added later
|
||||
} else {
|
||||
arg += "uint64_t";
|
||||
arg += "vluint64_t";
|
||||
}
|
||||
if (isWide()) {
|
||||
if (forReturn) v3error("Unsupported: Public functions with >64 bit outputs; make an output of a public task instead");
|
||||
@@ -202,7 +206,6 @@ string AstVar::dpiArgType(bool named, bool forReturn) const {
|
||||
if (forReturn) named=false;
|
||||
string arg;
|
||||
if (!basicp()) arg = "UNKNOWN";
|
||||
if (isWide()) v3error("Unsupported: DPI functions with vectored outputs > 32-bits");
|
||||
if (basicp()->isBitLogic()) {
|
||||
if (widthMin() == 1) {
|
||||
arg = "unsigned char";
|
||||
@@ -238,7 +241,7 @@ string AstVar::scType() const {
|
||||
return "uint32_t";
|
||||
}
|
||||
} else {
|
||||
return "uint64_t";
|
||||
return "vluint64_t";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -500,6 +503,7 @@ void AstNode::dump(ostream& os) {
|
||||
<<((editCount()>=editCountLast())?"#>":">")
|
||||
<<" {"<<dec<<fileline()->lineno()<<"}"
|
||||
<<" "<<(isSigned()?"s":"")
|
||||
<<(isDouble()?"d":"")
|
||||
<<"w"<<(widthSized()?"":"u")<<width();
|
||||
if (!widthSized()) os<<"/"<<widthMin();
|
||||
if (name()!="") os<<" "<<AstNode::quoteName(name());
|
||||
@@ -522,7 +526,7 @@ void AstBasicDType::dump(ostream& str) {
|
||||
str<<" ["<<keyword().ascii()<<"]";
|
||||
if (implicit()) str<<" [IMPLICIT]";
|
||||
}
|
||||
void AstCast::dump(ostream& str) {
|
||||
void AstCCast::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
str<<" sz"<<size();
|
||||
}
|
||||
@@ -609,8 +613,10 @@ void AstVar::dump(ostream& str) {
|
||||
else if (isInput()) str<<" [I]";
|
||||
else if (isOutput()) str<<" [O]";
|
||||
}
|
||||
if (isUsedClock()) str<<" [C]";
|
||||
if (isConst()) str<<" [CONST]";
|
||||
if (isUsedClock()) str<<" [CLK]";
|
||||
if (isSigPublic()) str<<" [P]";
|
||||
if (isUsedLoopIdx()) str<<" [LOOP]";
|
||||
if (attrClockEn()) str<<" [aCLKEN]";
|
||||
if (attrIsolateAssign()) str<<" [aISO]";
|
||||
if (attrFileDescr()) str<<" [aFD]";
|
||||
|
||||
+392
-31
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -46,19 +46,25 @@ struct AstConst : public AstNodeMath {
|
||||
private:
|
||||
V3Number m_num; // Constant value
|
||||
public:
|
||||
class Unsized32 {}; // for creator type-overload selection
|
||||
AstConst(FileLine* fl, const V3Number& num)
|
||||
:AstNodeMath(fl)
|
||||
,m_num(num) {
|
||||
width(m_num.width(), m_num.sized()?0:m_num.minWidth());
|
||||
isSigned(m_num.isSigned());
|
||||
numeric(m_num.isDouble() ? AstNumeric::DOUBLE
|
||||
: m_num.isSigned() ? AstNumeric::SIGNED
|
||||
: AstNumeric::UNSIGNED);
|
||||
}
|
||||
AstConst(FileLine* fl, uint32_t num)
|
||||
:AstNodeMath(fl)
|
||||
,m_num(V3Number(fl,32,num)) { width(m_num.width(), m_num.sized()?0:m_num.minWidth()); }
|
||||
class Unsized32 {}; // for creator type-overload selection
|
||||
AstConst(FileLine* fl, Unsized32, uint32_t num) // Unsized 32-bit integer of specified value
|
||||
:AstNodeMath(fl)
|
||||
,m_num(V3Number(fl,32,num)) { m_num.width(32,false); width(32,m_num.minWidth()); }
|
||||
class RealDouble {}; // for creator type-overload selection
|
||||
AstConst(FileLine* fl, RealDouble, double num)
|
||||
:AstNodeMath(fl)
|
||||
,m_num(V3Number(fl,64)) { m_num.setDouble(num); numeric(AstNumeric::DOUBLE); }
|
||||
class LogicFalse {};
|
||||
AstConst(FileLine* fl, LogicFalse) // Shorthand const 0, know the dtype should be a logic of size 1
|
||||
:AstNodeMath(fl)
|
||||
@@ -258,7 +264,8 @@ private:
|
||||
m_keyword = AstBasicDTypeKwd::LOGIC;
|
||||
}
|
||||
if (signst == signedst_NOP && keyword().isSigned()) signst = signedst_SIGNED;
|
||||
setSignedState(signst);
|
||||
if (keyword().isDouble()) numeric(AstNumeric::DOUBLE);
|
||||
else setSignedState(signst);
|
||||
if (!rangep) { // Set based on keyword properties
|
||||
// V3Width will pull from this width
|
||||
if (keyword().width() > 1 && !isOpaque()) rangep = new AstRange(fileline(), keyword().width()-1, 0);
|
||||
@@ -278,7 +285,8 @@ public:
|
||||
AstRange* rangep() const { return op1p()->castRange(); } // op1 = Range of variable
|
||||
void rangep(AstRange* nodep) { setNOp1p(nodep); }
|
||||
void setSignedState(AstSignedState signst) {
|
||||
if (signst!=signedst_NOP) isSigned(signst==signedst_SIGNED);
|
||||
if (signst==signedst_UNSIGNED) numeric(AstNumeric::UNSIGNED);
|
||||
else if (signst==signedst_SIGNED) numeric(AstNumeric::SIGNED);
|
||||
}
|
||||
// METHODS
|
||||
virtual AstBasicDType* basicp() const { return (AstBasicDType*)this; } // (Slow) recurse down to find basic data type
|
||||
@@ -300,6 +308,25 @@ public:
|
||||
void implicit(bool flag) { m_implicit = flag; }
|
||||
};
|
||||
|
||||
struct AstConstDType : public AstNodeDType {
|
||||
// const data type, ie "const some_dtype var_name [2:0]"
|
||||
// ConstDType are removed in V3LinkLValue and become AstVar::isConst.
|
||||
// When more generic types are supported AstConstDType will be propagated further.
|
||||
AstConstDType(FileLine* fl, AstNodeDType* dtypep)
|
||||
: AstNodeDType(fl) {
|
||||
setOp1p(dtypep);
|
||||
widthSignedFrom(dtypep);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(ConstDType, CONSTDTYPE)
|
||||
AstNodeDType* dtypep() const { return op1p()->castNodeDType(); } // op1 = Range of variable
|
||||
void dtypep(AstNodeDType* nodep) { setOp1p(nodep); }
|
||||
// METHODS
|
||||
virtual AstBasicDType* basicp() const { return dtypep()->basicp(); } // (Slow) recurse down to find basic data type
|
||||
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
|
||||
virtual int widthAlignBytes() const { return dtypep()->widthAlignBytes(); }
|
||||
virtual int widthTotalBytes() const { return dtypep()->widthTotalBytes(); }
|
||||
};
|
||||
|
||||
struct AstRefDType : public AstNodeDType {
|
||||
private:
|
||||
AstTypedef* m_defp;
|
||||
@@ -364,9 +391,10 @@ public:
|
||||
struct AstEnumItemRef : public AstNodeMath {
|
||||
private:
|
||||
AstEnumItem* m_itemp; // [AfterLink] Pointer to item
|
||||
AstPackage* m_packagep; // Package hierarchy
|
||||
public:
|
||||
AstEnumItemRef(FileLine* fl, AstEnumItem* itemp)
|
||||
: AstNodeMath(fl), m_itemp(itemp) {
|
||||
AstEnumItemRef(FileLine* fl, AstEnumItem* itemp, AstPackage* packagep)
|
||||
: AstNodeMath(fl), m_itemp(itemp), m_packagep(packagep) {
|
||||
if (m_itemp) widthSignedFrom(m_itemp);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(EnumItemRef, ENUMITEMREF)
|
||||
@@ -381,6 +409,8 @@ public:
|
||||
virtual string emitVerilog() { V3ERROR_NA; return ""; } // Implemented specially
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual bool cleanOut() { return true; }
|
||||
AstPackage* packagep() const { return m_packagep; }
|
||||
void packagep(AstPackage* nodep) { m_packagep=nodep; }
|
||||
};
|
||||
|
||||
struct AstEnumDType : public AstNodeDType {
|
||||
@@ -553,6 +583,7 @@ private:
|
||||
bool m_sigUserRWPublic:1; // User C code accesses this signal, read-write
|
||||
bool m_usedClock:1; // Signal used as a clock
|
||||
bool m_usedParam:1; // Parameter is referenced (on link; later signals not setup)
|
||||
bool m_usedLoopIdx:1; // Variable subject of for unrolling
|
||||
bool m_funcLocal:1; // Local variable for a function
|
||||
bool m_funcReturn:1; // Return variable for a function
|
||||
bool m_attrClockEn:1;// User clock enable attribute
|
||||
@@ -567,7 +598,7 @@ private:
|
||||
m_input=false; m_output=false; m_tristate=false;
|
||||
m_primaryIO=false;
|
||||
m_sc=false; m_scClocked=false; m_scSensitive=false;
|
||||
m_usedClock=false; m_usedParam=false;
|
||||
m_usedClock=false; m_usedParam=false; m_usedLoopIdx=false;
|
||||
m_sigPublic=false; m_sigModPublic=false; m_sigUserRdPublic=false; m_sigUserRWPublic=false;
|
||||
m_funcLocal=false; m_funcReturn=false;
|
||||
m_attrClockEn=false; m_attrIsolateAssign=false; m_attrSFormat=false;
|
||||
@@ -581,6 +612,7 @@ public:
|
||||
init();
|
||||
combineType(type); setOp1p(dtypep);
|
||||
if (dtypep && dtypep->basicp()) {
|
||||
numericFrom(dtypep);
|
||||
width(dtypep->basicp()->width(), 0);
|
||||
} else width(1, 0);
|
||||
}
|
||||
@@ -600,6 +632,7 @@ public:
|
||||
if (examplep->dtypep()) {
|
||||
setOp1p(examplep->dtypep()->cloneTree(true));
|
||||
}
|
||||
numericFrom(examplep);
|
||||
width(examplep->width(), examplep->widthMin());
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(Var, VAR)
|
||||
@@ -635,6 +668,7 @@ public:
|
||||
void attrSFormat(bool flag) { m_attrSFormat = flag; }
|
||||
void usedClock(bool flag) { m_usedClock = flag; }
|
||||
void usedParam(bool flag) { m_usedParam = flag; }
|
||||
void usedLoopIdx(bool flag) { m_usedLoopIdx = flag; }
|
||||
void sigPublic(bool flag) { m_sigPublic = flag; }
|
||||
void sigModPublic(bool flag) { m_sigModPublic = flag; }
|
||||
void sigUserRdPublic(bool flag) { m_sigUserRdPublic = flag; if (flag) sigPublic(true); }
|
||||
@@ -665,7 +699,7 @@ public:
|
||||
bool isToggleCoverable() const { return ((isIO() || isSignal())
|
||||
&& (isIO() || isBitLogic())
|
||||
// Wrapper would otherwise duplicate wrapped module's coverage
|
||||
&& !isSc() && !isPrimaryIO()); }
|
||||
&& !isSc() && !isPrimaryIO() && !isConst()); }
|
||||
bool isStatementTemp() const { return (varType()==AstVarType::STMTTEMP); }
|
||||
bool isMovableToBlock() const { return (varType()==AstVarType::BLOCKTEMP || isFuncLocal()); }
|
||||
bool isPure() const { return (varType()==AstVarType::XTEMP); }
|
||||
@@ -675,6 +709,7 @@ public:
|
||||
bool isBitLogic() const { AstBasicDType* bdtypep = basicp(); return bdtypep && bdtypep->isBitLogic(); }
|
||||
bool isUsedClock() const { return m_usedClock; }
|
||||
bool isUsedParam() const { return m_usedParam; }
|
||||
bool isUsedLoopIdx() const { return m_usedLoopIdx; }
|
||||
bool isSc() const { return m_sc; }
|
||||
bool isScQuad() const;
|
||||
bool isScBv() const;
|
||||
@@ -909,7 +944,9 @@ public:
|
||||
,m_name(name), m_svImplicit(false) {
|
||||
m_pinNum = pinNum;
|
||||
m_modVarp = NULL;
|
||||
setNOp1p(exprp); }
|
||||
setNOp1p(exprp);
|
||||
if (exprp) widthSignedFrom(exprp);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(Pin, PIN)
|
||||
virtual void dump(ostream& str);
|
||||
virtual bool broken() const { return (m_modVarp && !m_modVarp->brokeExists()); }
|
||||
@@ -918,7 +955,7 @@ public:
|
||||
bool dotStar() const { return name() == ".*"; } // Special fake name for .* connections until linked
|
||||
int pinNum() const { return m_pinNum; }
|
||||
void exprp(AstNode* nodep) { addOp1p(nodep); }
|
||||
AstNode* exprp() const { return op1p()->castNode(); } // op1 = Expression connected to pin
|
||||
AstNode* exprp() const { return op1p()->castNode(); } // op1 = Expression connected to pin, NULL if unconnected
|
||||
AstVar* modVarp() const { return m_modVarp; } // [After Link] Pointer to variable
|
||||
void modVarp(AstVar* varp) { m_modVarp=varp; }
|
||||
bool svImplicit() const { return m_svImplicit; }
|
||||
@@ -1420,6 +1457,15 @@ struct AstCondBound : public AstNodeCond {
|
||||
ASTNODE_NODE_FUNCS(CondBound, CONDBOUND)
|
||||
};
|
||||
|
||||
struct AstCondD : public AstNodeCond {
|
||||
// Conditional ?: statement, double rhs/lhs/out
|
||||
// Parents: MATH
|
||||
// Children: MATH
|
||||
AstCondD(FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p)
|
||||
: AstNodeCond(fl, condp, expr1p, expr2p) { numeric(AstNumeric::DOUBLE); }
|
||||
ASTNODE_NODE_FUNCS(CondD, CONDD)
|
||||
};
|
||||
|
||||
struct AstCoverDecl : public AstNodeStmt {
|
||||
// Coverage analysis point declaration
|
||||
// Parents: {statement list}
|
||||
@@ -1538,11 +1584,15 @@ private:
|
||||
AstCaseType m_casex; // 0=case, 1=casex, 2=casez
|
||||
bool m_fullPragma; // Synthesis full_case
|
||||
bool m_parallelPragma; // Synthesis parallel_case
|
||||
bool m_uniquePragma; // unique case
|
||||
bool m_unique0Pragma; // unique0 case
|
||||
bool m_priorityPragma; // priority case
|
||||
public:
|
||||
AstCase(FileLine* fileline, AstCaseType casex, AstNode* exprp, AstNode* casesp)
|
||||
: AstNodeCase(fileline, exprp, casesp) {
|
||||
m_casex=casex;
|
||||
m_fullPragma=false; m_parallelPragma=false;
|
||||
m_uniquePragma=false; m_unique0Pragma=false; m_priorityPragma=false;
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(Case, CASE)
|
||||
virtual string verilogKwd() const { return casez()?"casez":casex()?"casex":"case"; }
|
||||
@@ -1554,6 +1604,12 @@ public:
|
||||
void fullPragma(bool flag) { m_fullPragma=flag; }
|
||||
bool parallelPragma() const { return m_parallelPragma; }
|
||||
void parallelPragma(bool flag) { m_parallelPragma=flag; }
|
||||
bool uniquePragma() const { return m_uniquePragma; }
|
||||
void uniquePragma(bool flag) { m_uniquePragma=flag; }
|
||||
bool unique0Pragma() const { return m_unique0Pragma; }
|
||||
void unique0Pragma(bool flag) { m_unique0Pragma=flag; }
|
||||
bool priorityPragma() const { return m_priorityPragma; }
|
||||
void priorityPragma(bool flag) { m_priorityPragma=flag; }
|
||||
};
|
||||
|
||||
struct AstCaseItem : public AstNode {
|
||||
@@ -1580,7 +1636,7 @@ public:
|
||||
void ignoreOverlap(bool flag) { m_ignoreOverlap = flag; }
|
||||
};
|
||||
|
||||
class AstSFormatF : public AstNode {
|
||||
struct AstSFormatF : public AstNode {
|
||||
// Convert format to string, generally under a AstDisplay or AstSFormat
|
||||
// Also used as "real" function for /*verilator sformat*/ functions
|
||||
string m_text;
|
||||
@@ -1669,6 +1725,22 @@ struct AstSFormat : public AstNode {
|
||||
void lhsp(AstNode* nodep) { setOp3p(nodep); }
|
||||
};
|
||||
|
||||
struct AstSysIgnore : public AstNode {
|
||||
// Parents: stmtlist
|
||||
// Children: varrefs or exprs
|
||||
AstSysIgnore(FileLine* fileline, AstNode* exprsp)
|
||||
: AstNode (fileline) { addNOp1p(exprsp); }
|
||||
ASTNODE_NODE_FUNCS(SysIgnore, SYSIGNORE)
|
||||
virtual string verilogKwd() const { return "$ignored"; }
|
||||
virtual bool isGateOptimizable() const { return false; } // Though deleted before opt
|
||||
virtual bool isPredictOptimizable() const { return false; } // Though deleted before opt
|
||||
virtual bool isSplittable() const { return false; } // Though deleted before opt
|
||||
virtual bool isOutputter() const { return true; } // Though deleted before opt
|
||||
virtual int instrCount() const { return instrCountPli(); }
|
||||
AstNode* exprsp() const { return op1p()->castNode(); } // op1 = Expressions to output
|
||||
void exprsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to output
|
||||
};
|
||||
|
||||
struct AstFClose : public AstNodeStmt {
|
||||
// Parents: stmtlist
|
||||
// Children: file which must be a varref
|
||||
@@ -1932,6 +2004,18 @@ struct AstContinue : public AstNodeStmt {
|
||||
virtual bool isSplittable() const { return false; } // SPECIAL: We don't process code after breaks
|
||||
};
|
||||
|
||||
struct AstDisable : public AstNodeStmt {
|
||||
private:
|
||||
string m_name; // Name of block
|
||||
public:
|
||||
AstDisable(FileLine* fileline, const string& name)
|
||||
: AstNodeStmt(fileline), m_name(name) {}
|
||||
ASTNODE_NODE_FUNCS(Disable, DISABLE)
|
||||
virtual string name() const { return m_name; } // * = Block name
|
||||
void name(const string& flag) { m_name=flag; }
|
||||
virtual bool isSplittable() const { return false; } // SPECIAL: We don't process code after breaks
|
||||
};
|
||||
|
||||
struct AstReturn : public AstNodeStmt {
|
||||
AstReturn(FileLine* fileline, AstNode* lhsp=NULL)
|
||||
: AstNodeStmt (fileline) {
|
||||
@@ -1952,10 +2036,22 @@ struct AstGenIf : public AstNodeIf {
|
||||
};
|
||||
|
||||
struct AstIf : public AstNodeIf {
|
||||
private:
|
||||
bool m_uniquePragma; // unique case
|
||||
bool m_unique0Pragma; // unique0 case
|
||||
bool m_priorityPragma; // priority case
|
||||
public:
|
||||
AstIf(FileLine* fileline, AstNode* condp, AstNode* ifsp, AstNode* elsesp)
|
||||
: AstNodeIf(fileline, condp, ifsp, elsesp) {
|
||||
m_uniquePragma=false; m_unique0Pragma=false; m_priorityPragma=false;
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(If, IF)
|
||||
bool uniquePragma() const { return m_uniquePragma; }
|
||||
void uniquePragma(bool flag) { m_uniquePragma=flag; }
|
||||
bool unique0Pragma() const { return m_unique0Pragma; }
|
||||
void unique0Pragma(bool flag) { m_unique0Pragma=flag; }
|
||||
bool priorityPragma() const { return m_priorityPragma; }
|
||||
void priorityPragma(bool flag) { m_priorityPragma=flag; }
|
||||
};
|
||||
|
||||
struct AstJumpLabel : public AstNodeStmt {
|
||||
@@ -2363,6 +2459,20 @@ struct AstTime : public AstNodeTermop {
|
||||
virtual bool same(AstNode* samep) const { return true; }
|
||||
};
|
||||
|
||||
struct AstTimeD : public AstNodeTermop {
|
||||
AstTimeD(FileLine* fl) : AstNodeTermop(fl) {
|
||||
numeric(AstNumeric::DOUBLE); }
|
||||
ASTNODE_NODE_FUNCS(TimeD, TIMED)
|
||||
virtual string emitVerilog() { return "%f$realtime"; }
|
||||
virtual string emitC() { return "VL_TIME_D()"; }
|
||||
virtual bool cleanOut() { return true; }
|
||||
virtual bool isGateOptimizable() const { return false; }
|
||||
virtual bool isPredictOptimizable() const { return false; }
|
||||
virtual int instrCount() const { return instrCountTime(); }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(AstNode* samep) const { return true; }
|
||||
};
|
||||
|
||||
struct AstUCFunc : public AstNodeMath {
|
||||
// User's $c function
|
||||
// Perhaps this should be a AstNodeListop; but there's only one list math right now
|
||||
@@ -2388,19 +2498,32 @@ struct AstUCFunc : public AstNodeMath {
|
||||
//======================================================================
|
||||
// Unary ops
|
||||
|
||||
struct AstUnaryMin : public AstNodeUniop {
|
||||
AstUnaryMin(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
struct AstNegate : public AstNodeUniop {
|
||||
AstNegate(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
if (lhsp) widthSignedFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(UnaryMin, UNARYMIN)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opUnaryMin(lhs); }
|
||||
ASTNODE_NODE_FUNCS(Negate, NEGATE)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opNegate(lhs); }
|
||||
virtual string emitVerilog() { return "%f(- %l)"; }
|
||||
virtual string emitC() { return "VL_UNARYMIN_%lq(%lW, %P, %li)"; }
|
||||
virtual string emitC() { return "VL_NEGATE_%lq(%lW, %P, %li)"; }
|
||||
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return true;}
|
||||
};
|
||||
struct AstNegateD : public AstNodeUniop {
|
||||
AstNegateD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
numeric(AstNumeric::DOUBLE); }
|
||||
ASTNODE_NODE_FUNCS(NegateD, NEGATED)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opNegateD(lhs); }
|
||||
virtual string emitVerilog() { return "%f(- %l)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual string emitSimpleOperator() { return "-"; }
|
||||
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return false;}
|
||||
virtual int instrCount() const { return instrCountDouble(); }
|
||||
virtual bool doubleFlavor() const { return true; }
|
||||
};
|
||||
struct AstRedAnd : public AstNodeUniop {
|
||||
AstRedAnd(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
width(1,1); }
|
||||
width(1,1); numeric(AstNumeric::UNSIGNED); }
|
||||
ASTNODE_NODE_FUNCS(RedAnd, REDAND)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedAnd(lhs); }
|
||||
virtual string emitVerilog() { return "%f(& %l)"; }
|
||||
@@ -2410,7 +2533,7 @@ struct AstRedAnd : public AstNodeUniop {
|
||||
};
|
||||
struct AstRedOr : public AstNodeUniop {
|
||||
AstRedOr(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
width(1,1); }
|
||||
width(1,1); numeric(AstNumeric::UNSIGNED); }
|
||||
ASTNODE_NODE_FUNCS(RedOr, REDOR)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedOr(lhs); }
|
||||
virtual string emitVerilog() { return "%f(| %l)"; }
|
||||
@@ -2420,7 +2543,7 @@ struct AstRedOr : public AstNodeUniop {
|
||||
};
|
||||
struct AstRedXor : public AstNodeUniop {
|
||||
AstRedXor(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
width(1,1); }
|
||||
width(1,1); numeric(AstNumeric::UNSIGNED); }
|
||||
ASTNODE_NODE_FUNCS(RedXor, REDXOR)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedXor(lhs); }
|
||||
virtual string emitVerilog() { return "%f(^ %l)"; }
|
||||
@@ -2434,7 +2557,7 @@ struct AstRedXor : public AstNodeUniop {
|
||||
struct AstRedXnor : public AstNodeUniop {
|
||||
// AstRedXnors are replaced with AstRedXors in V3Const.
|
||||
AstRedXnor(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
width(1,1); }
|
||||
width(1,1); numeric(AstNumeric::UNSIGNED); }
|
||||
ASTNODE_NODE_FUNCS(RedXnor, REDXNOR)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedXnor(lhs); }
|
||||
virtual string emitVerilog() { return "%f(~^ %l)"; }
|
||||
@@ -2492,7 +2615,7 @@ struct AstExtendS : public AstNodeUniop {
|
||||
struct AstSigned : public AstNodeUniop {
|
||||
// $signed(lhs)
|
||||
AstSigned(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
isSigned(true);
|
||||
numeric(AstNumeric::SIGNED);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(Signed, SIGNED)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); out.isSigned(false); }
|
||||
@@ -2505,7 +2628,7 @@ struct AstSigned : public AstNodeUniop {
|
||||
struct AstUnsigned : public AstNodeUniop {
|
||||
// $unsigned(lhs)
|
||||
AstUnsigned(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
isSigned(false);
|
||||
numeric(AstNumeric::UNSIGNED);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(Unsigned, UNSIGNED)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); out.isSigned(false); }
|
||||
@@ -2515,6 +2638,63 @@ struct AstUnsigned : public AstNodeUniop {
|
||||
virtual bool sizeMattersLhs() {return true;} // Eliminated before matters
|
||||
virtual int instrCount() const { return 0; }
|
||||
};
|
||||
struct AstRToIS : public AstNodeUniop {
|
||||
// $rtoi(lhs)
|
||||
AstRToIS(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
width(32,32); }
|
||||
ASTNODE_NODE_FUNCS(RToIS, RTOIS)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRToIS(lhs); }
|
||||
virtual string emitVerilog() { return "%f$rtoi(%l)"; }
|
||||
virtual string emitC() { return "VL_RTOI_I_D(%li)"; }
|
||||
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;} // Eliminated before matters
|
||||
virtual bool sizeMattersLhs() {return false;} // Eliminated before matters
|
||||
virtual int instrCount() const { return instrCountDouble(); }
|
||||
};
|
||||
struct AstRToIRoundS : public AstNodeUniop {
|
||||
AstRToIRoundS(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
width(32,32); }
|
||||
ASTNODE_NODE_FUNCS(RToIRoundS, RTOIROUNDS)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRToIRoundS(lhs); }
|
||||
virtual string emitVerilog() { return "%f$rtoi_rounded(%l)"; }
|
||||
virtual string emitC() { return "VL_RTOIROUND_I_D(%li)"; }
|
||||
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;} // Eliminated before matters
|
||||
virtual bool sizeMattersLhs() {return false;} // Eliminated before matters
|
||||
virtual int instrCount() const { return instrCountDouble(); }
|
||||
};
|
||||
struct AstIToRD : public AstNodeUniop {
|
||||
AstIToRD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
numeric(AstNumeric::DOUBLE); }
|
||||
ASTNODE_NODE_FUNCS(IToRD, ITORD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opIToRD(lhs); }
|
||||
virtual string emitVerilog() { return "%f$itor(%l)"; }
|
||||
virtual string emitC() { return "VL_ITOR_D_I(%li)"; }
|
||||
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;} // Eliminated before matters
|
||||
virtual bool sizeMattersLhs() {return false;} // Eliminated before matters
|
||||
virtual int instrCount() const { return instrCountDouble(); }
|
||||
};
|
||||
struct AstRealToBits : public AstNodeUniop {
|
||||
AstRealToBits(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
width(64,64); }
|
||||
ASTNODE_NODE_FUNCS(RealToBits, REALTOBITS)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRealToBits(lhs); }
|
||||
virtual string emitVerilog() { return "%f$realtobits(%l)"; }
|
||||
virtual string emitC() { return "VL_CVT_Q_D(%li)"; }
|
||||
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;} // Eliminated before matters
|
||||
virtual bool sizeMattersLhs() {return false;} // Eliminated before matters
|
||||
virtual int instrCount() const { return instrCountDouble(); }
|
||||
};
|
||||
struct AstBitsToRealD : public AstNodeUniop {
|
||||
AstBitsToRealD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
numeric(AstNumeric::DOUBLE); }
|
||||
ASTNODE_NODE_FUNCS(BitsToRealD, BITSTOREALD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opBitsToRealD(lhs); }
|
||||
virtual string emitVerilog() { return "%f$bitstoreal(%l)"; }
|
||||
virtual string emitC() { return "VL_CVT_D_Q(%li)"; }
|
||||
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;} // Eliminated before matters
|
||||
virtual bool sizeMattersLhs() {return false;} // Eliminated before matters
|
||||
virtual int instrCount() const { return instrCountDouble(); }
|
||||
};
|
||||
|
||||
struct AstCLog2 : public AstNodeUniop {
|
||||
AstCLog2(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {}
|
||||
ASTNODE_NODE_FUNCS(CLog2, CLOG2)
|
||||
@@ -2572,27 +2752,42 @@ struct AstOneHot0 : public AstNodeUniop {
|
||||
virtual int instrCount() const { return widthInstrs()*3; }
|
||||
};
|
||||
|
||||
struct AstCast : public AstNodeUniop {
|
||||
// Cast to appropriate data type
|
||||
struct AstCast : public AstNode {
|
||||
// Cast to appropriate data type - note lhsp is value, to match AstTypedef, AstCCast, etc
|
||||
AstCast(FileLine* fl, AstNode* lhsp, AstNodeDType* dtypep) : AstNode(fl) {
|
||||
setOp1p(lhsp); setOp2p(dtypep);
|
||||
if (dtypep) { widthSignedFrom(dtypep); }
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(Cast, CAST)
|
||||
virtual string emitVerilog() { return "((%r)'(%l))"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual bool cleanOut() { V3ERROR_NA; return true;} virtual bool cleanLhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;}
|
||||
AstNode* lhsp() const { return op1p(); }
|
||||
AstNodeDType* dtypep() const { return op2p()->castNodeDType(); }
|
||||
};
|
||||
|
||||
struct AstCCast : public AstNodeUniop {
|
||||
// Cast to C-based data type
|
||||
private:
|
||||
int m_size;
|
||||
public:
|
||||
AstCast(FileLine* fl, AstNode* lhsp, int setwidth) : AstNodeUniop(fl, lhsp) {
|
||||
AstCCast(FileLine* fl, AstNode* lhsp, int setwidth) : AstNodeUniop(fl, lhsp) {
|
||||
m_size=setwidth;
|
||||
if (setwidth) { width(setwidth,setwidth); }
|
||||
}
|
||||
AstCast(FileLine* fl, AstNode* lhsp, AstNode* widthFromp) : AstNodeUniop(fl, lhsp) {
|
||||
AstCCast(FileLine* fl, AstNode* lhsp, AstNode* widthFromp) : AstNodeUniop(fl, lhsp) {
|
||||
if (widthFromp) { widthSignedFrom(widthFromp); }
|
||||
m_size=width();
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(Cast, CAST)
|
||||
ASTNODE_NODE_FUNCS(CCast, CCAST)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); }
|
||||
virtual string emitVerilog() { return "%f$_CAST(%l)"; }
|
||||
virtual string emitC() { return "VL_CAST_%nq%lq(%nw,%lw, %P, %li)"; }
|
||||
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} // Special cased in V3Cast
|
||||
virtual V3Hash sameHash() const { return V3Hash(size()); }
|
||||
virtual bool same(AstNode* samep) const { return size()==samep->castCast()->size(); }
|
||||
virtual bool same(AstNode* samep) const { return size()==samep->castCCast()->size(); }
|
||||
virtual void dump(ostream& str=cout);
|
||||
//
|
||||
int size() const { return m_size; }
|
||||
@@ -2617,7 +2812,7 @@ struct AstFEof : public AstNodeUniop {
|
||||
ASTNODE_NODE_FUNCS(FEof, FEOF)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { V3ERROR_NA; }
|
||||
virtual string emitVerilog() { return "%f$feof(%l)"; }
|
||||
virtual string emitC() { return "(%li ? feof(VL_CVT_Q_FP(%li)) : true)"; }
|
||||
virtual string emitC() { return "(%li ? feof(VL_CVT_I_FP(%li)) : true)"; }
|
||||
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;}
|
||||
virtual int instrCount() const { return widthInstrs()*16; }
|
||||
@@ -2630,7 +2825,7 @@ struct AstFGetC : public AstNodeUniop {
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { V3ERROR_NA; }
|
||||
virtual string emitVerilog() { return "%f$fgetc(%l)"; }
|
||||
// Non-existent filehandle returns EOF
|
||||
virtual string emitC() { return "(%li ? fgetc(VL_CVT_Q_FP(%li)) : -1)"; }
|
||||
virtual string emitC() { return "(%li ? fgetc(VL_CVT_I_FP(%li)) : -1)"; }
|
||||
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;}
|
||||
virtual int instrCount() const { return widthInstrs()*64; }
|
||||
@@ -2752,6 +2947,20 @@ struct AstEq : public AstNodeBiCom {
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
};
|
||||
struct AstEqD : public AstNodeBiCom {
|
||||
AstEqD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
|
||||
width(1,1); }
|
||||
ASTNODE_NODE_FUNCS(EqD, EQD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opEqD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f== %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual string emitSimpleOperator() { return "=="; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
virtual int instrCount() const { return instrCountDouble(); }
|
||||
virtual bool doubleFlavor() const { return true; }
|
||||
};
|
||||
struct AstNeq : public AstNodeBiCom {
|
||||
AstNeq(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
|
||||
width(1,1); }
|
||||
@@ -2764,6 +2973,20 @@ struct AstNeq : public AstNodeBiCom {
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
};
|
||||
struct AstNeqD : public AstNodeBiCom {
|
||||
AstNeqD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
|
||||
width(1,1); }
|
||||
ASTNODE_NODE_FUNCS(NeqD, NEQD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opNeqD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f!= %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual string emitSimpleOperator() { return "!="; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
virtual int instrCount() const { return instrCountDouble(); }
|
||||
virtual bool doubleFlavor() const { return true; }
|
||||
};
|
||||
struct AstLt : public AstNodeBiop {
|
||||
AstLt(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
width(1,1); }
|
||||
@@ -2776,6 +2999,20 @@ struct AstLt : public AstNodeBiop {
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
};
|
||||
struct AstLtD : public AstNodeBiop {
|
||||
AstLtD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
width(1,1); }
|
||||
ASTNODE_NODE_FUNCS(LtD, LTD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLtD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f< %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual string emitSimpleOperator() { return "<"; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
virtual int instrCount() const { return instrCountDouble(); }
|
||||
virtual bool doubleFlavor() const { return true; }
|
||||
};
|
||||
struct AstLtS : public AstNodeBiop {
|
||||
AstLtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
width(1,1); }
|
||||
@@ -2801,6 +3038,20 @@ struct AstGt : public AstNodeBiop {
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
};
|
||||
struct AstGtD : public AstNodeBiop {
|
||||
AstGtD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
width(1,1); }
|
||||
ASTNODE_NODE_FUNCS(GtD, GTD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGtD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f> %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual string emitSimpleOperator() { return ">"; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
virtual int instrCount() const { return instrCountDouble(); }
|
||||
virtual bool doubleFlavor() const { return true; }
|
||||
};
|
||||
struct AstGtS : public AstNodeBiop {
|
||||
AstGtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
width(1,1); }
|
||||
@@ -2826,6 +3077,20 @@ struct AstGte : public AstNodeBiop {
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
};
|
||||
struct AstGteD : public AstNodeBiop {
|
||||
AstGteD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
width(1,1); }
|
||||
ASTNODE_NODE_FUNCS(GteD, GTED)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGteD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f>= %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual string emitSimpleOperator() { return ">="; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
virtual int instrCount() const { return instrCountDouble(); }
|
||||
virtual bool doubleFlavor() const { return true; }
|
||||
};
|
||||
struct AstGteS : public AstNodeBiop {
|
||||
AstGteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
width(1,1); }
|
||||
@@ -2851,6 +3116,20 @@ struct AstLte : public AstNodeBiop {
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
};
|
||||
struct AstLteD : public AstNodeBiop {
|
||||
AstLteD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
width(1,1); }
|
||||
ASTNODE_NODE_FUNCS(LteD, LTED)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLteD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f<= %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual string emitSimpleOperator() { return "<="; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
virtual int instrCount() const { return instrCountDouble(); }
|
||||
virtual bool doubleFlavor() const { return true; }
|
||||
};
|
||||
struct AstLteS : public AstNodeBiop {
|
||||
AstLteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
width(1,1); }
|
||||
@@ -2919,6 +3198,20 @@ struct AstAdd : public AstNodeBiComAsv {
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
|
||||
};
|
||||
struct AstAddD : public AstNodeBiComAsv {
|
||||
AstAddD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
|
||||
numeric(AstNumeric::DOUBLE); }
|
||||
ASTNODE_NODE_FUNCS(AddD, ADDD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opAddD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f+ %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual string emitSimpleOperator() { return "+"; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
virtual int instrCount() const { return instrCountDouble(); }
|
||||
virtual bool doubleFlavor() const { return true; }
|
||||
};
|
||||
struct AstSub : public AstNodeBiop {
|
||||
AstSub(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
if (lhsp) widthSignedFrom(lhsp); }
|
||||
@@ -2931,6 +3224,20 @@ struct AstSub : public AstNodeBiop {
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
|
||||
};
|
||||
struct AstSubD : public AstNodeBiop {
|
||||
AstSubD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
numeric(AstNumeric::DOUBLE); }
|
||||
ASTNODE_NODE_FUNCS(SubD, SUBD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opSubD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f- %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual string emitSimpleOperator() { return "-"; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
virtual int instrCount() const { return instrCountDouble(); }
|
||||
virtual bool doubleFlavor() const { return true; }
|
||||
};
|
||||
struct AstMul : public AstNodeBiComAsv {
|
||||
AstMul(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
|
||||
if (lhsp) widthSignedFrom(lhsp); }
|
||||
@@ -2944,6 +3251,20 @@ struct AstMul : public AstNodeBiComAsv {
|
||||
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
|
||||
virtual int instrCount() const { return widthInstrs()*instrCountMul(); }
|
||||
};
|
||||
struct AstMulD : public AstNodeBiComAsv {
|
||||
AstMulD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
|
||||
numeric(AstNumeric::DOUBLE); }
|
||||
ASTNODE_NODE_FUNCS(MulD, MULD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opMulD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f* %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual string emitSimpleOperator() { return "*"; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
|
||||
virtual int instrCount() const { return instrCountDouble(); }
|
||||
virtual bool doubleFlavor() const { return true; }
|
||||
};
|
||||
struct AstMulS : public AstNodeBiComAsv {
|
||||
AstMulS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
|
||||
if (lhsp) widthSignedFrom(lhsp); }
|
||||
@@ -2970,6 +3291,20 @@ struct AstDiv : public AstNodeBiop {
|
||||
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
|
||||
virtual int instrCount() const { return widthInstrs()*instrCountDiv(); }
|
||||
};
|
||||
struct AstDivD : public AstNodeBiop {
|
||||
AstDivD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
numeric(AstNumeric::DOUBLE); }
|
||||
ASTNODE_NODE_FUNCS(DivD, DIVD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opDivD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f/ %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual string emitSimpleOperator() { return "/"; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
virtual int instrCount() const { return instrCountDoubleDiv(); }
|
||||
virtual bool doubleFlavor() const { return true; }
|
||||
};
|
||||
struct AstDivS : public AstNodeBiop {
|
||||
AstDivS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
if (lhsp) widthSignedFrom(lhsp); }
|
||||
@@ -3020,6 +3355,19 @@ struct AstPow : public AstNodeBiop {
|
||||
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return false;}
|
||||
virtual int instrCount() const { return widthInstrs()*instrCountMul(); }
|
||||
};
|
||||
struct AstPowD : public AstNodeBiop {
|
||||
AstPowD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
numeric(AstNumeric::DOUBLE); }
|
||||
ASTNODE_NODE_FUNCS(PowD, POWD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opPowD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f** %r)"; }
|
||||
virtual string emitC() { return "pow(%li,%ri)"; }
|
||||
virtual bool cleanOut() {return false;}
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
virtual int instrCount() const { return instrCountDoubleDiv(); }
|
||||
virtual bool doubleFlavor() const { return true; }
|
||||
};
|
||||
struct AstPowS : public AstNodeBiop {
|
||||
AstPowS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
if (lhsp) widthSignedFrom(lhsp); }
|
||||
@@ -3109,6 +3457,19 @@ struct AstReplicate : public AstNodeBiop {
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
virtual int instrCount() const { return widthInstrs()*2; }
|
||||
};
|
||||
struct AstBufIf1 : public AstNodeBiop {
|
||||
// lhs is enable, rhs is data to drive
|
||||
AstBufIf1(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
if (lhsp) widthSignedFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(BufIf1, BUFIF1)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opBufIf1(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "bufif(%r,%l)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return "";} // Lclean || Rclean
|
||||
virtual string emitSimpleOperator() { V3ERROR_NA; return false;} // Lclean || Rclean
|
||||
virtual bool cleanOut() {V3ERROR_NA; return "";} // Lclean || Rclean
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
};
|
||||
struct AstFGetS : public AstNodeBiop {
|
||||
AstFGetS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {}
|
||||
ASTNODE_NODE_FUNCS(FGetS, FGETS)
|
||||
|
||||
+18
-1
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -53,6 +53,7 @@ private:
|
||||
string m_namedScope; // Name of begin blocks above us
|
||||
string m_unnamedScope; // Name of begin blocks, including unnamed blocks
|
||||
int m_repeatNum; // Repeat counter
|
||||
int m_ifDepth; // Current if depth
|
||||
|
||||
// METHODS
|
||||
static int debug() {
|
||||
@@ -152,6 +153,21 @@ private:
|
||||
// any BEGINs, but V3Coverage adds them all under the module itself.
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
// VISITORS - LINT CHECK
|
||||
virtual void visit(AstIf* nodep, AstNUser*) { // Note not AstNodeIf; other types don't get covered
|
||||
// Check IFDEPTH warning - could be in other transform files if desire
|
||||
int prevIfDepth = m_ifDepth;
|
||||
if (m_ifDepth == -1 || v3Global.opt.ifDepth()<1) { // Turned off
|
||||
} else if (nodep->uniquePragma() || nodep->unique0Pragma() || nodep->priorityPragma()) {
|
||||
m_ifDepth = -1;
|
||||
} else if (++m_ifDepth > v3Global.opt.ifDepth()) {
|
||||
nodep->v3warn(IFDEPTH,"Deep 'if' statement; suggest unique/priority to avoid slow logic");
|
||||
nodep->fileline()->modifyWarnOff(V3ErrorCode::IFDEPTH, true); // Warn only once
|
||||
m_ifDepth = -1;
|
||||
}
|
||||
nodep->iterateChildren(*this);
|
||||
m_ifDepth = prevIfDepth;
|
||||
}
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
@@ -161,6 +177,7 @@ public:
|
||||
m_modp = NULL;
|
||||
m_ftaskp = NULL;
|
||||
m_repeatNum = 0;
|
||||
m_ifDepth = 0;
|
||||
nodep->accept(*this);
|
||||
}
|
||||
virtual ~BeginVisitor() {}
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+7
-3
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -148,17 +148,19 @@ private:
|
||||
|
||||
bool isCaseTreeFast(AstCase* nodep) {
|
||||
int width = 0;
|
||||
bool opaque = false;
|
||||
m_caseItems = 0;
|
||||
m_caseNoOverlapsAllCovered = true;
|
||||
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
|
||||
for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) {
|
||||
if (icondp->width() > width) width = icondp->width();
|
||||
if (icondp->isDouble()) opaque = true;
|
||||
if (!icondp->castConst()) width = CASE_BARF; // Can't parse; not a constant
|
||||
m_caseItems++;
|
||||
}
|
||||
}
|
||||
m_caseWidth = width;
|
||||
if (width==0 || width > CASE_OVERLAP_WIDTH) {
|
||||
if (width==0 || width > CASE_OVERLAP_WIDTH || opaque) {
|
||||
m_caseNoOverlapsAllCovered = false;
|
||||
return false; // Too wide for analysis
|
||||
}
|
||||
@@ -348,7 +350,9 @@ private:
|
||||
and1p = cexprp->cloneTree(false);
|
||||
and2p = icondp;
|
||||
}
|
||||
AstEq* condp = new AstEq(itemp->fileline(), and1p, and2p);
|
||||
AstNodeBiop* condp = (and1p->isDouble()
|
||||
? (new AstEqD(itemp->fileline(), and1p, and2p))->castNodeBiop()
|
||||
: (new AstEq(itemp->fileline(), and1p, and2p))->castNodeBiop());
|
||||
if (!ifexprp) {
|
||||
ifexprp = condp;
|
||||
} else {
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+7
-7
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2004-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2004-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -77,7 +77,7 @@ private:
|
||||
AstNRelinker relinkHandle;
|
||||
nodep->unlinkFrBack(&relinkHandle);
|
||||
//
|
||||
AstCast* castp = new AstCast (nodep->fileline(), nodep, needsize);
|
||||
AstCCast* castp = new AstCCast (nodep->fileline(), nodep, needsize);
|
||||
castp->width(needsize, nodep->widthMin());
|
||||
relinkHandle.relink(castp);
|
||||
//if (debug()>8) castp->dumpTree(cout,"-castins: ");
|
||||
@@ -97,13 +97,13 @@ private:
|
||||
insertCast(nodep, castSize(nodep->backp()));
|
||||
}
|
||||
}
|
||||
void insureLower32Cast(AstCast* nodep) {
|
||||
void insureLower32Cast(AstCCast* nodep) {
|
||||
// If we have uint64 = CAST(uint64(x)) then the upcasting
|
||||
// really needs to be CAST(uint64(CAST(uint32(x))).
|
||||
// Otherwise a (uint64)(a>b) would return wrong value, as
|
||||
// less than has undeterministic signedness.
|
||||
if (nodep->isQuad() && !nodep->lhsp()->isQuad()
|
||||
&& !nodep->lhsp()->castCast()) {
|
||||
&& !nodep->lhsp()->castCCast()) {
|
||||
insertCast(nodep->lhsp(), VL_WORDSIZE);
|
||||
}
|
||||
}
|
||||
@@ -130,12 +130,12 @@ private:
|
||||
if (nodep->sizeMattersRhs()) insureCast(nodep->rhsp());
|
||||
if (nodep->sizeMattersThs()) insureCast(nodep->thsp());
|
||||
}
|
||||
virtual void visit(AstCast* nodep, AstNUser*) {
|
||||
virtual void visit(AstCCast* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
insureLower32Cast(nodep);
|
||||
nodep->user1(1);
|
||||
}
|
||||
virtual void visit(AstUnaryMin* nodep, AstNUser*) {
|
||||
virtual void visit(AstNegate* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
nodep->user1(nodep->lhsp()->user1());
|
||||
if (nodep->lhsp()->widthMin()==1) {
|
||||
@@ -149,7 +149,7 @@ private:
|
||||
}
|
||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||
if (!nodep->lvalue()
|
||||
&& !nodep->backp()->castCast()
|
||||
&& !nodep->backp()->castCCast()
|
||||
&& nodep->backp()->castNodeMath()
|
||||
&& nodep->backp()->width()
|
||||
&& castSize(nodep) != castSize(nodep->varp())) {
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2004-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2004-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+46
-17
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -46,6 +46,8 @@
|
||||
#include "V3EmitV.h"
|
||||
#include "V3File.h"
|
||||
|
||||
#define CDC_WEIGHT_ASYNC 0x1000 // Weight for edges that feed async logic
|
||||
|
||||
//######################################################################
|
||||
|
||||
class CdcBaseVisitor : public AstNVisitor {
|
||||
@@ -65,9 +67,9 @@ class CdcEitherVertex : public V3GraphVertex {
|
||||
AstNode* m_nodep;
|
||||
AstSenTree* m_srcDomainp;
|
||||
AstSenTree* m_dstDomainp;
|
||||
bool m_srcDomainSet;
|
||||
bool m_dstDomainSet;
|
||||
bool m_asyncPath;
|
||||
bool m_srcDomainSet:1;
|
||||
bool m_dstDomainSet:1;
|
||||
bool m_asyncPath:1;
|
||||
public:
|
||||
CdcEitherVertex(V3Graph* graphp, AstScope* scopep, AstNode* nodep)
|
||||
: V3GraphVertex(graphp), m_scopep(scopep), m_nodep(nodep)
|
||||
@@ -109,11 +111,12 @@ public:
|
||||
};
|
||||
|
||||
class CdcLogicVertex : public CdcEitherVertex {
|
||||
bool m_hazard;
|
||||
bool m_isFlop;
|
||||
bool m_hazard:1;
|
||||
bool m_isFlop:1;
|
||||
public:
|
||||
CdcLogicVertex(V3Graph* graphp, AstScope* scopep, AstNode* nodep, AstSenTree* sensenodep)
|
||||
: CdcEitherVertex(graphp,scopep,nodep), m_hazard(false), m_isFlop(false)
|
||||
: CdcEitherVertex(graphp,scopep,nodep)
|
||||
, m_hazard(false), m_isFlop(false)
|
||||
{ srcDomainp(sensenodep); dstDomainp(sensenodep); }
|
||||
virtual ~CdcLogicVertex() {}
|
||||
// Accessors
|
||||
@@ -132,7 +135,7 @@ class CdcDumpVisitor : public CdcBaseVisitor {
|
||||
private:
|
||||
// NODE STATE
|
||||
//Entire netlist:
|
||||
// {statement}Node::user3p -> bool, indicating not hazard
|
||||
// {statement}Node::user3 -> bool, indicating not hazard
|
||||
ofstream* m_ofp; // Output file
|
||||
string m_prefix;
|
||||
|
||||
@@ -290,9 +293,12 @@ private:
|
||||
void setNodeHazard(AstNode* nodep) {
|
||||
// Need to not clear if warnings are off (rather than when report it)
|
||||
// as bypassing this warning may turn up another path that isn't warning off'ed.
|
||||
// We can't modifyWarnOff here, as one instantiation might not be an issue until we find a hitting flop
|
||||
// Furthermore, a module like a "Or" module would only get flagged once,
|
||||
// even though the signals feeding it are radically different.
|
||||
if (!m_domainp || m_domainp->hasCombo()) { // Source flop logic in a posedge block is OK for reset (not async though)
|
||||
if (m_logicVertexp && !nodep->fileline()->warnIsOff(V3ErrorCode::CDCRSTLOGIC)) {
|
||||
UINFO(9,"Set hazard "<<nodep<<endl);
|
||||
UINFO(8,"Set hazard "<<nodep<<endl);
|
||||
m_logicVertexp->setHazard(nodep);
|
||||
}
|
||||
}
|
||||
@@ -310,7 +316,9 @@ private:
|
||||
UINFO(3,__FUNCTION__<<": "<<endl);
|
||||
//if (debug()>6) m_graph.dump();
|
||||
if (debug()>6) m_graph.dumpDotFilePrefixed("cdc_pre");
|
||||
m_graph.removeRedundantEdgesSum(&V3GraphEdge::followAlwaysTrue);
|
||||
//
|
||||
m_graph.removeRedundantEdges(&V3GraphEdge::followAlwaysTrue); // This will MAX across edge weights
|
||||
//
|
||||
m_graph.dumpDotFilePrefixed("cdc_simp");
|
||||
//
|
||||
analyzeReset();
|
||||
@@ -335,7 +343,7 @@ private:
|
||||
if (CdcVarVertex* vvertexp = dynamic_cast<CdcVarVertex*>(itp)) {
|
||||
if (vvertexp->cntAsyncRst()) {
|
||||
m_userGeneration++; // Effectively a userClearVertices()
|
||||
UINFO(9, " Trace One async: "<<vvertexp<<endl);
|
||||
UINFO(8, " Trace One async: "<<vvertexp<<endl);
|
||||
// Twice, as we need to detect, then propagate
|
||||
CdcEitherVertex* markp = traceAsyncRecurse(vvertexp, false);
|
||||
if (markp) { // Mark is non-NULL if something bad on this path
|
||||
@@ -351,7 +359,8 @@ private:
|
||||
}
|
||||
|
||||
CdcEitherVertex* traceAsyncRecurse(CdcEitherVertex* vertexp, bool mark) {
|
||||
// Return vertex of any hazardous stuff attached, or NULL if OK
|
||||
// First pass: Return vertex of any hazardous stuff attached, or NULL if OK
|
||||
// If first pass returns true, second pass calls asyncPath() on appropriate nodes
|
||||
if (vertexp->user()>=m_userGeneration) return false; // Processed - prevent loop
|
||||
vertexp->user(m_userGeneration);
|
||||
|
||||
@@ -406,12 +415,15 @@ private:
|
||||
CdcEitherVertex* eToVertexp = (CdcEitherVertex*)edgep->top();
|
||||
if (!eToVertexp) targetp = eToVertexp;
|
||||
if (CdcLogicVertex* vvertexp = dynamic_cast<CdcLogicVertex*>(eToVertexp)) {
|
||||
if (vvertexp->isFlop()) {
|
||||
if (vvertexp->isFlop() // IE the target flop that is upsetting us
|
||||
&& edgep->weight() >= CDC_WEIGHT_ASYNC) { // And this signal feeds an async reset line
|
||||
targetp = eToVertexp;
|
||||
//UINFO(9," targetasync "<<targetp->name()<<" "<<" from "<<vertexp->name()<<endl);
|
||||
break;
|
||||
}
|
||||
} // else it might be random logic that's not relevant
|
||||
}
|
||||
//UINFO(9," finalflop "<<targetp->name()<<" "<<targetp->nodep()->fileline()<<endl);
|
||||
warnAndFile(markp->nodep(),V3ErrorCode::CDCRSTLOGIC,"Logic in path that feeds async reset, via signal: "+nodep->prettyName());
|
||||
dumpAsyncRecurse(targetp, "", " ",0);
|
||||
}
|
||||
@@ -464,6 +476,12 @@ private:
|
||||
|
||||
void edgeReport() {
|
||||
// Make report of all signal names and what clock edges they have
|
||||
//
|
||||
// Due to flattening, many interesting direct-connect signals are
|
||||
// lost, so we can't make a report showing I/Os for a low level
|
||||
// module. Disabling flattening though makes us consider each
|
||||
// signal in it's own unique clock domain.
|
||||
|
||||
UINFO(3,__FUNCTION__<<": "<<endl);
|
||||
|
||||
// Trace all sources and sinks
|
||||
@@ -493,6 +511,10 @@ private:
|
||||
|
||||
ostringstream os;
|
||||
os.setf(ios::left);
|
||||
// Module name - doesn't work due to flattening having lost the original
|
||||
// so we assume the modulename matches the filebasename
|
||||
string fname = vvertexp->varScp()->fileline()->filebasename() + ":";
|
||||
os<<" "<<setw(20)<<fname;
|
||||
os<<" "<<setw(8)<<whatp;
|
||||
os<<" "<<setw(40)<<vvertexp->varScp()->prettyName();
|
||||
os<<" SRC=";
|
||||
@@ -613,8 +635,9 @@ private:
|
||||
if (!varscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp\n");
|
||||
CdcVarVertex* varvertexp = makeVarVertex(varscp);
|
||||
UINFO(5," VARREF to "<<varscp<<endl);
|
||||
// We use weight of one; if we ref the var more than once, when we simplify,
|
||||
// the weight will increase
|
||||
// We use weight of one for normal edges,
|
||||
// Weight of CDC_WEIGHT_ASYNC to indicate feeds async (for reporting)
|
||||
// When simplify we'll take the MAX weight
|
||||
if (nodep->lvalue()) {
|
||||
new V3GraphEdge(&m_graph, m_logicVertexp, varvertexp, 1);
|
||||
if (m_inDly) {
|
||||
@@ -623,7 +646,13 @@ private:
|
||||
varvertexp->srcDomainSet(true);
|
||||
}
|
||||
} else {
|
||||
new V3GraphEdge(&m_graph, varvertexp, m_logicVertexp, 1);
|
||||
if (varvertexp->cntAsyncRst()) {
|
||||
//UINFO(9," edgeasync "<<varvertexp->name()<<" to "<<m_logicVertexp<<endl);
|
||||
new V3GraphEdge(&m_graph, varvertexp, m_logicVertexp, CDC_WEIGHT_ASYNC);
|
||||
} else {
|
||||
//UINFO(9," edgena "<<varvertexp->name()<<" to "<<m_logicVertexp<<endl);
|
||||
new V3GraphEdge(&m_graph, varvertexp, m_logicVertexp, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -720,7 +749,7 @@ public:
|
||||
|
||||
nodep->accept(*this);
|
||||
analyze();
|
||||
//edgeReport(); // Not useful at the moment
|
||||
if (debug()>=1) edgeReport(); // Not useful to users at the moment
|
||||
|
||||
if (0) { *m_ofp<<"\nDBG-test-dumper\n"; V3EmitV::verilogPrefixedTree(nodep, *m_ofp, "DBG ",40,NULL,true); *m_ofp<<endl; }
|
||||
}
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2008-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2008-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+30
-17
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2010-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2010-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -60,7 +60,8 @@ class V3ConfigIgnores {
|
||||
IgnLines::const_iterator m_lastIt; // Point with next linenumber > current line number
|
||||
IgnLines::const_iterator m_lastEnd; // Point with end()
|
||||
|
||||
IgnFiles m_ignFiles; // Ignores for each filename
|
||||
IgnFiles m_ignWilds; // Ignores for each wildcarded filename
|
||||
IgnFiles m_ignFiles; // Ignores for each non-wildcarded filename
|
||||
|
||||
static V3ConfigIgnores s_singleton; // Singleton (not via local static, as that's slow)
|
||||
|
||||
@@ -68,13 +69,13 @@ class V3ConfigIgnores {
|
||||
~V3ConfigIgnores() {}
|
||||
|
||||
// METHODS
|
||||
inline IgnLines* findLines(const string& filename) {
|
||||
IgnFiles::iterator it = m_ignFiles.find(filename);
|
||||
if (it != m_ignFiles.end()) {
|
||||
inline IgnLines* findWilds(const string& wildname) {
|
||||
IgnFiles::iterator it = m_ignWilds.find(wildname);
|
||||
if (it != m_ignWilds.end()) {
|
||||
return &(it->second);
|
||||
} else {
|
||||
m_ignFiles.insert(make_pair(filename, IgnLines()));
|
||||
it = m_ignFiles.find(filename);
|
||||
m_ignWilds.insert(make_pair(wildname, IgnLines()));
|
||||
it = m_ignWilds.find(wildname);
|
||||
return &(it->second);
|
||||
}
|
||||
}
|
||||
@@ -82,23 +83,35 @@ class V3ConfigIgnores {
|
||||
// Given a filename, find all wildcard matches against it and build
|
||||
// hash with the specific filename. This avoids having to wildmatch
|
||||
// more than once against any filename.
|
||||
IgnLines* linesp = findLines(filename);
|
||||
m_lastIt = linesp->begin();
|
||||
m_lastEnd = linesp->end();
|
||||
IgnFiles::iterator it = m_ignFiles.find(filename);
|
||||
if (it == m_ignFiles.end()) {
|
||||
// Haven't seen this filename before
|
||||
m_ignFiles.insert(make_pair(filename, IgnLines()));
|
||||
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())) {
|
||||
for (IgnLines::iterator lit = fnit->second.begin(); lit != fnit->second.end(); ++lit) {
|
||||
it->second.insert(*lit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
m_lastIt = it->second.begin();
|
||||
m_lastEnd = it->second.end();
|
||||
}
|
||||
|
||||
public:
|
||||
inline static V3ConfigIgnores& singleton() { return s_singleton; }
|
||||
|
||||
void addIgnore(V3ErrorCode code, string filename, int lineno, bool on) {
|
||||
void addIgnore(V3ErrorCode code, string wildname, int lineno, bool on) {
|
||||
// Insert
|
||||
IgnLines* linesp = findLines(filename);
|
||||
UINFO(9,"config addIgnore "<<filename<<":"<<lineno<<", "<<code<<", "<<on<<endl);
|
||||
IgnLines* linesp = findWilds(wildname);
|
||||
UINFO(9,"config addIgnore "<<wildname<<":"<<lineno<<", "<<code<<", "<<on<<endl);
|
||||
linesp->insert(V3ConfigLine(code, lineno, on));
|
||||
if (m_lastFilename == filename) {
|
||||
// Flush the match cache, due to a change in the rules.
|
||||
m_lastFilename = " ";
|
||||
}
|
||||
// Flush the match cache, due to a change in the rules.
|
||||
m_ignFiles.clear();
|
||||
m_lastFilename = " ";
|
||||
}
|
||||
inline void applyIgnores(FileLine* filelinep) {
|
||||
// HOT routine, called each parsed token line
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2010-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2010-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+374
-218
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -37,7 +37,6 @@
|
||||
#include "V3Const.h"
|
||||
#include "V3Ast.h"
|
||||
#include "V3Width.h"
|
||||
#include "V3Signed.h"
|
||||
#include "V3Simulate.h"
|
||||
|
||||
//######################################################################
|
||||
@@ -93,7 +92,7 @@ public:
|
||||
class ConstVisitor : public AstNVisitor {
|
||||
private:
|
||||
// NODE STATE
|
||||
// ** only when m_warn/m_expensive is set. If state is needed other times,
|
||||
// ** only when m_warn/m_doExpensive is set. If state is needed other times,
|
||||
// ** must track down everywhere V3Const is called and make sure no overlaps.
|
||||
// AstVar::user4p -> Used by ConstVarMarkVisitor/ConstVarFindVisitor
|
||||
// AstJumpLabel::user4 -> bool. Set when AstJumpGo uses this label
|
||||
@@ -103,8 +102,9 @@ private:
|
||||
bool m_required; // If true, must become a constant
|
||||
bool m_wremove; // Inside scope, no assignw removal
|
||||
bool m_warn; // Output warnings
|
||||
bool m_cpp; // C++ conversions only
|
||||
bool m_expensive; // Enable computationally expensive optimizations
|
||||
bool m_doExpensive; // Enable computationally expensive optimizations
|
||||
bool m_doNConst; // Enable non-constant-child simplifications
|
||||
bool m_doV; // Verilog, not C++ conversion
|
||||
AstNodeModule* m_modp; // Current module
|
||||
AstNode* m_scopep; // Current scope
|
||||
|
||||
@@ -289,13 +289,61 @@ private:
|
||||
// SEL(EXTEND(any,width,...),(width-1),0) -> ...
|
||||
// Since select's return unsigned, this is always an extend
|
||||
AstExtend* extendp = nodep->fromp()->castExtend();
|
||||
return (!m_cpp
|
||||
&& extendp
|
||||
&& nodep->lsbp()->castConst()
|
||||
&& nodep->widthp()->castConst()
|
||||
&& nodep->lsbConst()==0
|
||||
&& (int)nodep->widthConst()==extendp->lhsp()->width()
|
||||
);
|
||||
if (!(m_doV
|
||||
&& extendp
|
||||
&& nodep->lsbp()->castConst()
|
||||
&& nodep->widthp()->castConst()
|
||||
&& nodep->lsbConst()==0
|
||||
&& (int)nodep->widthConst()==extendp->lhsp()->width()
|
||||
)) return false;
|
||||
replaceWChild(nodep, extendp->lhsp()); nodep=NULL;
|
||||
return true;
|
||||
}
|
||||
bool operandSelBiLower(AstSel* nodep) {
|
||||
// SEL(ADD(a,b),(width-1),0) -> ADD(SEL(a),SEL(b))
|
||||
// Add or any operation which doesn't care if we discard top bits
|
||||
AstNodeBiop* bip = nodep->fromp()->castNodeBiop();
|
||||
if (!(m_doV
|
||||
&& bip
|
||||
&& nodep->lsbp()->castConst()
|
||||
&& nodep->widthp()->castConst()
|
||||
&& nodep->lsbConst()==0
|
||||
)) return false;
|
||||
if (debug()>=9) nodep->dumpTree(cout,"SEL(BI)-in:");
|
||||
AstNode* bilhsp = bip->lhsp()->unlinkFrBack();
|
||||
AstNode* birhsp = bip->rhsp()->unlinkFrBack();
|
||||
bip->lhsp(new AstSel(nodep->fileline(), bilhsp, 0, nodep->widthConst()));
|
||||
bip->rhsp(new AstSel(nodep->fileline(), birhsp, 0, nodep->widthConst()));
|
||||
if (debug()>=9) bip->dumpTree(cout,"SEL(BI)-ou:");
|
||||
replaceWChild(nodep, bip); nodep=NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operandBiExtendConst(AstNodeBiop* nodep) {
|
||||
// Loop unrolling likes standalone compares
|
||||
// EQ(EXTEND(xx{width3}), const{width32}) -> EQ(xx{3},const{3})
|
||||
// Beware that the constant must have zero bits (+ 1 if signed) or compare
|
||||
// would be incorrect
|
||||
AstExtend* extendp = nodep->lhsp()->castExtend();
|
||||
if (!extendp) return false;
|
||||
AstNode* smallerp = extendp->lhsp();
|
||||
int subsize = smallerp->width();
|
||||
AstConst* constp = nodep->rhsp()->castConst();
|
||||
if (!constp) return false;
|
||||
if (!constp->num().isBitsZero(constp->width()-1, subsize)) return false;
|
||||
//
|
||||
if (debug()>=9) nodep->dumpTree(cout,"BI(EXTEND)-in:");
|
||||
smallerp->unlinkFrBack();
|
||||
extendp->unlinkFrBack()->deleteTree(); // aka nodep->lhsp.
|
||||
nodep->lhsp(smallerp);
|
||||
|
||||
constp->unlinkFrBack();
|
||||
V3Number num (constp->fileline(), subsize);
|
||||
num.opAssign(constp->num());
|
||||
nodep->rhsp(new AstConst(constp->fileline(), num));
|
||||
constp->deleteTree(); constp=NULL;
|
||||
if (debug()>=9) nodep->dumpTree(cout,"BI(EXTEND)-ou:");
|
||||
return true;
|
||||
}
|
||||
|
||||
AstNode* afterComment(AstNode* nodep) {
|
||||
@@ -724,7 +772,7 @@ private:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (!m_cpp && nodep->lhsp()->castConcat()) {
|
||||
else if (m_doV && nodep->lhsp()->castConcat()) {
|
||||
bool need_temp = false;
|
||||
if (m_warn && !nodep->castAssignDly()) { // Is same var on LHS and RHS?
|
||||
// Note only do this (need user4) when m_warn, which is
|
||||
@@ -855,10 +903,10 @@ private:
|
||||
// Run it - may be unoptimizable due to large for loop, etc
|
||||
simvis.mainParamEmulate(nodep);
|
||||
if (!simvis.optimizable()) {
|
||||
AstNode* errorp = simvis.whyNotNodep(); if (!errorp) errorp = nodep;
|
||||
AstNode* errorp = simvis.whyNotNodep(); if (!errorp) errorp = nodep;
|
||||
nodep->v3error("Expecting expression to be constant, but can't determine constant for "
|
||||
<<nodep->prettyTypeName()<<endl
|
||||
<<V3Error::msgPrefix()<<errorp->fileline()<<"... Location of non-constant "
|
||||
<<V3Error::msgPrefix(V3ErrorCode::EC_ERROR,false)<<errorp->fileline()<<"... Location of non-constant "
|
||||
<<errorp->prettyTypeName()<<": "<<simvis.whyNotMessage());
|
||||
replaceZero(nodep); nodep=NULL;
|
||||
} else {
|
||||
@@ -1060,16 +1108,50 @@ private:
|
||||
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
|
||||
void replaceSelIntoBiop(AstSel* nodep) {
|
||||
// SEL(BUFIF1(a,b),1,bit) => BUFIF1(SEL(a,1,bit),SEL(b,1,bit))
|
||||
AstNodeBiop* fromp = nodep->fromp()->unlinkFrBack()->castNodeBiop();
|
||||
if (!fromp) nodep->v3fatalSrc("Called on non biop");
|
||||
AstNode* lsbp = nodep->lsbp()->unlinkFrBack();
|
||||
AstNode* widthp = nodep->widthp()->unlinkFrBack();
|
||||
//
|
||||
AstNode* bilhsp = fromp->lhsp()->unlinkFrBack();
|
||||
AstNode* birhsp = fromp->rhsp()->unlinkFrBack();
|
||||
//
|
||||
fromp->lhsp(new AstSel(nodep->fileline(),
|
||||
bilhsp, lsbp->cloneTree(true), widthp->cloneTree(true)));
|
||||
fromp->rhsp(new AstSel(nodep->fileline(),
|
||||
birhsp, lsbp, widthp));
|
||||
fromp->widthSignedFrom(nodep);
|
||||
nodep->replaceWith(fromp); nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
void replaceSelIntoUniop(AstSel* nodep) {
|
||||
// SEL(NOT(a),1,bit) => NOT(SEL(a,bit))
|
||||
AstNodeUniop* fromp = nodep->fromp()->unlinkFrBack()->castNodeUniop();
|
||||
if (!fromp) nodep->v3fatalSrc("Called on non biop");
|
||||
AstNode* lsbp = nodep->lsbp()->unlinkFrBack();
|
||||
AstNode* widthp = nodep->widthp()->unlinkFrBack();
|
||||
//
|
||||
AstNode* bilhsp = fromp->lhsp()->unlinkFrBack();
|
||||
//
|
||||
fromp->lhsp(new AstSel(nodep->fileline(),
|
||||
bilhsp, lsbp->cloneTree(true), widthp->cloneTree(true)));
|
||||
fromp->widthSignedFrom(nodep);
|
||||
nodep->replaceWith(fromp); nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
|
||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (!nodep->varp()) nodep->v3fatalSrc("Not linked");
|
||||
bool did=false;
|
||||
if (!m_cpp && nodep->varp()->hasSimpleInit() && !nodep->backp()->castAttrOf()) {
|
||||
if (m_doV && nodep->varp()->hasSimpleInit() && !nodep->backp()->castAttrOf()) {
|
||||
//if (debug()) nodep->varp()->valuep()->dumpTree(cout," visitvaref: ");
|
||||
nodep->varp()->valuep()->iterateAndNext(*this);
|
||||
if (operandConst(nodep->varp()->valuep())
|
||||
&& !nodep->lvalue()
|
||||
&& ((v3Global.opt.oConst() && !m_params // Can reduce constant wires into equations
|
||||
&& ((!m_params // Can reduce constant wires into equations
|
||||
&& m_doNConst
|
||||
&& v3Global.opt.oConst()
|
||||
&& !nodep->varp()->isSigPublic())
|
||||
|| nodep->varp()->isParam())) {
|
||||
AstConst* constp = nodep->varp()->valuep()->castConst();
|
||||
@@ -1106,7 +1188,7 @@ private:
|
||||
// Someday if lower is constant, convert to quoted "string".
|
||||
|
||||
virtual void visit(AstAttrOf* nodep, AstNUser*) {
|
||||
// Don't iterate children, don't want to loose VarRef.
|
||||
// Don't iterate children, don't want to lose VarRef.
|
||||
if (nodep->attrType()==AstAttrType::EXPR_BITS) {
|
||||
if (!nodep->fromp() || !nodep->fromp()->widthMin()) nodep->v3fatalSrc("Unsized expression");
|
||||
V3Number num (nodep->fileline(), 32, nodep->fromp()->widthMin());
|
||||
@@ -1121,8 +1203,9 @@ private:
|
||||
}
|
||||
virtual void visit(AstSenItem* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (nodep->sensp()->castConst()
|
||||
|| (nodep->varrefp() && nodep->varrefp()->varp()->isParam())) {
|
||||
if (m_doNConst
|
||||
&& (nodep->sensp()->castConst()
|
||||
|| (nodep->varrefp() && nodep->varrefp()->varp()->isParam()))) {
|
||||
// Constants in sensitivity lists may be removed (we'll simplify later)
|
||||
if (nodep->isClocked()) { // A constant can never get a pos/negexge
|
||||
if (onlySenItemInSenTree(nodep)) {
|
||||
@@ -1135,7 +1218,7 @@ private:
|
||||
nodep->replaceWith(new AstSenItem(nodep->fileline(), AstSenItem::Combo()));
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
} else if (nodep->sensp()->castNot()) {
|
||||
} else if (m_doNConst && nodep->sensp()->castNot()) {
|
||||
// V3Gate may propagate NOTs into clocks... Just deal with it
|
||||
AstNode* sensp = nodep->sensp();
|
||||
AstNode* lastSensp = sensp;
|
||||
@@ -1202,7 +1285,7 @@ private:
|
||||
|
||||
virtual void visit(AstSenTree* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (m_expensive) {
|
||||
if (m_doExpensive) {
|
||||
//cout<<endl; nodep->dumpTree(cout,"ssin: ");
|
||||
// Optimize ideas for the future:
|
||||
// SENTREE(... SENGATE(x,a), SENGATE(SENITEM(x),b) ...) => SENGATE(x,OR(a,b))
|
||||
@@ -1305,22 +1388,21 @@ private:
|
||||
// Zero elimination
|
||||
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
replaceNodeAssign(nodep);
|
||||
if (m_doNConst && replaceNodeAssign(nodep)) return;
|
||||
}
|
||||
virtual void visit(AstAssignAlias* nodep, AstNUser*) {
|
||||
// Don't perform any optimizations, keep the alias around
|
||||
}
|
||||
virtual void visit(AstAssignW* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (replaceNodeAssign(nodep)) return;
|
||||
if (m_doNConst && replaceNodeAssign(nodep)) return;
|
||||
AstNodeVarRef* varrefp = nodep->lhsp()->castVarRef(); // Not VarXRef, as different refs may set different values to each hierarchy
|
||||
if (m_wremove
|
||||
if (m_wremove && !m_params && m_doNConst
|
||||
&& m_modp && operandConst(nodep->rhsp())
|
||||
&& !nodep->rhsp()->castConst()->num().isFourState()
|
||||
&& varrefp // Don't do messes with BITREFs/ARRAYREFs
|
||||
&& !varrefp->varp()->valuep() // Not already constified
|
||||
&& !varrefp->varScopep() // Not scoped (or each scope may have different initial value)
|
||||
&& !m_params) {
|
||||
&& !varrefp->varScopep()) { // Not scoped (or each scope may have different initial value)
|
||||
// ASSIGNW (VARREF, const) -> INITIAL ( ASSIGN (VARREF, const) )
|
||||
UINFO(4,"constAssignW "<<nodep<<endl);
|
||||
// Make a initial assignment
|
||||
@@ -1340,77 +1422,79 @@ private:
|
||||
|
||||
virtual void visit(AstNodeIf* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (AstConst* constp = nodep->condp()->castConst()) {
|
||||
AstNode* keepp = NULL;
|
||||
if (constp->isZero()) {
|
||||
UINFO(4,"IF(0,{any},{x}) => {x}: "<<nodep<<endl);
|
||||
keepp = nodep->elsesp();
|
||||
} else {
|
||||
UINFO(4,"IF(!0,{x},{any}) => {x}: "<<nodep<<endl);
|
||||
keepp = nodep->ifsp();
|
||||
if (m_doNConst) {
|
||||
if (AstConst* constp = nodep->condp()->castConst()) {
|
||||
AstNode* keepp = NULL;
|
||||
if (constp->isZero()) {
|
||||
UINFO(4,"IF(0,{any},{x}) => {x}: "<<nodep<<endl);
|
||||
keepp = nodep->elsesp();
|
||||
} else {
|
||||
UINFO(4,"IF(!0,{x},{any}) => {x}: "<<nodep<<endl);
|
||||
keepp = nodep->ifsp();
|
||||
}
|
||||
if (keepp) {
|
||||
keepp->unlinkFrBackWithNext();
|
||||
nodep->replaceWith(keepp);
|
||||
} else {
|
||||
nodep->unlinkFrBack();
|
||||
}
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
if (keepp) {
|
||||
keepp->unlinkFrBackWithNext();
|
||||
nodep->replaceWith(keepp);
|
||||
} else {
|
||||
nodep->unlinkFrBack();
|
||||
else if (!afterComment(nodep->ifsp()) && !afterComment(nodep->elsesp())) {
|
||||
// Empty block, remove it
|
||||
// Note if we support more C++ then there might be side effects in the condition itself
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
}
|
||||
else if (!afterComment(nodep->ifsp())) {
|
||||
UINFO(4,"IF({x}) NULL {...} => IF(NOT{x}}: "<<nodep<<endl);
|
||||
AstNode* condp = nodep->condp();
|
||||
AstNode* elsesp = nodep->elsesp();
|
||||
condp->unlinkFrBackWithNext();
|
||||
elsesp->unlinkFrBackWithNext();
|
||||
if (nodep->ifsp()) { nodep->ifsp()->unlinkFrBackWithNext()->deleteTree(); } // Must have been comment
|
||||
nodep->condp(new AstLogNot(condp->fileline(), condp)); // LogNot, as C++ optimization also possible
|
||||
nodep->addIfsp(elsesp);
|
||||
}
|
||||
else if (((nodep->condp()->castNot() && nodep->condp()->width()==1)
|
||||
|| (nodep->condp()->castLogNot()))
|
||||
&& nodep->ifsp() && nodep->elsesp()) {
|
||||
UINFO(4,"IF(NOT {x}) => IF(x) swapped if/else"<<nodep<<endl);
|
||||
AstNode* condp = nodep->condp()->castNot()->lhsp()->unlinkFrBackWithNext();
|
||||
AstNode* ifsp = nodep->ifsp()->unlinkFrBackWithNext();
|
||||
AstNode* elsesp = nodep->elsesp()->unlinkFrBackWithNext();
|
||||
AstIf* ifp = new AstIf(nodep->fileline(), condp, elsesp, ifsp);
|
||||
ifp->branchPred(nodep->branchPred().invert());
|
||||
nodep->replaceWith(ifp);
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
else if (ifSameAssign(nodep)) {
|
||||
UINFO(4,"IF({a}) ASSIGN({b},{c}) else ASSIGN({b},{d}) => ASSIGN({b}, {a}?{c}:{d})"<<endl);
|
||||
AstNodeAssign* ifp = nodep->ifsp()->castNodeAssign();
|
||||
AstNodeAssign* elsep = nodep->elsesp()->castNodeAssign();
|
||||
ifp->unlinkFrBack();
|
||||
AstNode* condp = nodep->condp()->unlinkFrBack();
|
||||
AstNode* truep = ifp->rhsp()->unlinkFrBack();
|
||||
AstNode* falsep = elsep->rhsp()->unlinkFrBack();
|
||||
ifp->rhsp(new AstCond(truep->fileline(),
|
||||
condp, truep, falsep));
|
||||
nodep->replaceWith(ifp);
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
else if (0 // Disabled, as vpm assertions are faster without due to short-circuiting
|
||||
&& operandIfIf(nodep)) {
|
||||
UINFO(0,"IF({a}) IF({b}) => IF({a} && {b})"<<endl);
|
||||
AstNodeIf* lowerIfp = nodep->ifsp()->castNodeIf();
|
||||
AstNode* condp = nodep->condp()->unlinkFrBack();
|
||||
AstNode* lowerIfsp = lowerIfp->ifsp()->unlinkFrBackWithNext();
|
||||
AstNode* lowerCondp = lowerIfp->condp()->unlinkFrBackWithNext();
|
||||
nodep->condp(new AstLogAnd(lowerIfp->fileline(),
|
||||
condp, lowerCondp));
|
||||
lowerIfp->replaceWith(lowerIfsp);
|
||||
lowerIfp->deleteTree(); lowerIfp=NULL;
|
||||
}
|
||||
else if (operandBoolShift(nodep->condp())) {
|
||||
replaceBoolShift(nodep->condp());
|
||||
}
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
else if (!afterComment(nodep->ifsp()) && !afterComment(nodep->elsesp())) {
|
||||
// Empty block, remove it
|
||||
// Note if we support more C++ then there might be side effects in the condition itself
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
}
|
||||
else if (!afterComment(nodep->ifsp())) {
|
||||
UINFO(4,"IF({x}) NULL {...} => IF(NOT{x}}: "<<nodep<<endl);
|
||||
AstNode* condp = nodep->condp();
|
||||
AstNode* elsesp = nodep->elsesp();
|
||||
condp->unlinkFrBackWithNext();
|
||||
elsesp->unlinkFrBackWithNext();
|
||||
if (nodep->ifsp()) { nodep->ifsp()->unlinkFrBackWithNext()->deleteTree(); } // Must have been comment
|
||||
nodep->condp(new AstLogNot(condp->fileline(), condp)); // LogNot, as C++ optimization also possible
|
||||
nodep->addIfsp(elsesp);
|
||||
}
|
||||
else if (((nodep->condp()->castNot() && nodep->condp()->width()==1)
|
||||
|| (nodep->condp()->castLogNot()))
|
||||
&& nodep->ifsp() && nodep->elsesp()) {
|
||||
UINFO(4,"IF(NOT {x}) => IF(x) swapped if/else"<<nodep<<endl);
|
||||
AstNode* condp = nodep->condp()->castNot()->lhsp()->unlinkFrBackWithNext();
|
||||
AstNode* ifsp = nodep->ifsp()->unlinkFrBackWithNext();
|
||||
AstNode* elsesp = nodep->elsesp()->unlinkFrBackWithNext();
|
||||
AstIf* ifp = new AstIf(nodep->fileline(), condp, elsesp, ifsp);
|
||||
ifp->branchPred(nodep->branchPred().invert());
|
||||
nodep->replaceWith(ifp);
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
else if (ifSameAssign(nodep)) {
|
||||
UINFO(4,"IF({a}) ASSIGN({b},{c}) else ASSIGN({b},{d}) => ASSIGN({b}, {a}?{c}:{d})"<<endl);
|
||||
AstNodeAssign* ifp = nodep->ifsp()->castNodeAssign();
|
||||
AstNodeAssign* elsep = nodep->elsesp()->castNodeAssign();
|
||||
ifp->unlinkFrBack();
|
||||
AstNode* condp = nodep->condp()->unlinkFrBack();
|
||||
AstNode* truep = ifp->rhsp()->unlinkFrBack();
|
||||
AstNode* falsep = elsep->rhsp()->unlinkFrBack();
|
||||
ifp->rhsp(new AstCond(truep->fileline(),
|
||||
condp, truep, falsep));
|
||||
nodep->replaceWith(ifp);
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
else if (0 // Disabled, as vpm assertions are faster without due to short-circuiting
|
||||
&& operandIfIf(nodep)) {
|
||||
UINFO(0,"IF({a}) IF({b}) => IF({a} && {b})"<<endl);
|
||||
AstNodeIf* lowerIfp = nodep->ifsp()->castNodeIf();
|
||||
AstNode* condp = nodep->condp()->unlinkFrBack();
|
||||
AstNode* lowerIfsp = lowerIfp->ifsp()->unlinkFrBackWithNext();
|
||||
AstNode* lowerCondp = lowerIfp->condp()->unlinkFrBackWithNext();
|
||||
nodep->condp(new AstLogAnd(lowerIfp->fileline(),
|
||||
condp, lowerCondp));
|
||||
lowerIfp->replaceWith(lowerIfsp);
|
||||
lowerIfp->deleteTree(); lowerIfp=NULL;
|
||||
}
|
||||
else if (operandBoolShift(nodep->condp())) {
|
||||
replaceBoolShift(nodep->condp());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1423,7 +1507,7 @@ private:
|
||||
for (AstNode* argp = nodep->exprsp(); argp; argp=argp->nextp()) {
|
||||
if (argp->castConst()) { anyconst=true; break; }
|
||||
}
|
||||
if (anyconst) {
|
||||
if (m_doNConst && anyconst) {
|
||||
//UINFO(9," Display in "<<nodep->text()<<endl);
|
||||
string dispout = "";
|
||||
string fmt = "";
|
||||
@@ -1434,7 +1518,7 @@ private:
|
||||
if (!inPct && ch=='%') {
|
||||
inPct = true;
|
||||
fmt = ch;
|
||||
} else if (inPct && isdigit(ch)) {
|
||||
} else if (inPct && (isdigit(ch) || ch=='.')) {
|
||||
fmt += ch;
|
||||
} else if (inPct) {
|
||||
inPct = false;
|
||||
@@ -1486,14 +1570,16 @@ private:
|
||||
|
||||
virtual void visit(AstWhile* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (nodep->condp()->isZero()) {
|
||||
UINFO(4,"WHILE(0) => nop "<<nodep<<endl);
|
||||
if (nodep->precondsp()) nodep->replaceWith(nodep->precondsp());
|
||||
else nodep->unlinkFrBack();
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
else if (operandBoolShift(nodep->condp())) {
|
||||
replaceBoolShift(nodep->condp());
|
||||
if (m_doNConst) {
|
||||
if (nodep->condp()->isZero()) {
|
||||
UINFO(4,"WHILE(0) => nop "<<nodep<<endl);
|
||||
if (nodep->precondsp()) nodep->replaceWith(nodep->precondsp());
|
||||
else nodep->unlinkFrBack();
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
else if (operandBoolShift(nodep->condp())) {
|
||||
replaceBoolShift(nodep->condp());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1501,12 +1587,20 @@ private:
|
||||
// If output of a presel didn't get consted, chances are V3Param didn't visit properly
|
||||
virtual void visit(AstNodePreSel* nodep, AstNUser*) {}
|
||||
|
||||
// Ignored, can eliminate early
|
||||
virtual void visit(AstSysIgnore* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (m_doNConst) {
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//-----
|
||||
// Jump elimination
|
||||
|
||||
virtual void visit(AstJumpGo* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (m_expensive) { nodep->labelp()->user4(true); }
|
||||
if (m_doExpensive) { nodep->labelp()->user4(true); }
|
||||
}
|
||||
|
||||
virtual void visit(AstJumpLabel* nodep, AstNUser*) {
|
||||
@@ -1515,7 +1609,7 @@ private:
|
||||
// Note this assumes all AstJumpGos are underneath the given label; V3Broken asserts this
|
||||
nodep->iterateChildren(*this);
|
||||
// AstJumpGo's below here that point to this node will set user4
|
||||
if (m_expensive && !nodep->user4()) {
|
||||
if (m_doExpensive && !nodep->user4()) {
|
||||
UINFO(4,"JUMPLABEL => unused "<<nodep<<endl);
|
||||
AstNode* underp = NULL;
|
||||
if (nodep->stmtsp()) underp = nodep->stmtsp()->unlinkFrBackWithNext();
|
||||
@@ -1546,78 +1640,81 @@ private:
|
||||
|
||||
// Lint Checks
|
||||
// v--- *1* These ops are always first, as we warn before replacing
|
||||
// v--- *V* This op is a verilog op, ignore when in m_cpp mode
|
||||
// v--- *V* This op is a verilog op, only in m_doV mode
|
||||
// v--- *C* This op works on all constant children, allowed in m_doConst mode
|
||||
TREEOP1("AstSel{warnSelect(nodep)}", "NEVER");
|
||||
// Generic constants on both side. Do this first to avoid other replacements
|
||||
TREEOP("AstNodeBiop {$lhsp.castConst, $rhsp.castConst}", "replaceConst(nodep)");
|
||||
TREEOP("AstNodeUniop{$lhsp.castConst, !nodep->isOpaque()}", "replaceConst(nodep)");
|
||||
TREEOPC("AstNodeBiop {$lhsp.castConst, $rhsp.castConst}", "replaceConst(nodep)");
|
||||
TREEOPC("AstNodeUniop{$lhsp.castConst, !nodep->isOpaque()}", "replaceConst(nodep)");
|
||||
// Zero on one side or the other
|
||||
TREEOP("AstAdd {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP("AstAnd {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP("AstLogAnd{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP("AstLogOr {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP("AstDiv {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP("AstDivS {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP("AstMul {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP("AstMulS {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP("AstPow {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP("AstPowS {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP("AstOr {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP("AstShiftL{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP("AstShiftR{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP("AstShiftRS{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP("AstXor {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP("AstXnor {$lhsp.isZero, $rhsp}", "AstNot{$rhsp}");
|
||||
TREEOP("AstSub {$lhsp.isZero, $rhsp}", "AstUnaryMin{$rhsp}");
|
||||
TREEOP("AstAdd {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||
TREEOP("AstAnd {$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
|
||||
TREEOP("AstLogAnd{$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
|
||||
TREEOP("AstLogOr {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||
TREEOP("AstMul {$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
|
||||
TREEOP("AstMulS {$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
|
||||
TREEOP("AstOr {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||
TREEOP("AstShiftL{$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||
TREEOP("AstShiftR{$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||
TREEOP("AstShiftRS{$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||
TREEOP("AstSub {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||
TREEOP("AstXor {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||
TREEOP("AstXnor {$lhsp, $rhsp.isZero}", "AstNot{$lhsp}");
|
||||
TREEOP ("AstAdd {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP ("AstAnd {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP ("AstLogAnd{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP ("AstLogOr {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP ("AstDiv {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP ("AstDivS {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP ("AstMul {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP ("AstMulS {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP ("AstPow {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP ("AstPowS {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP ("AstOr {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP ("AstShiftL{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP ("AstShiftR{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP ("AstShiftRS{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP ("AstXor {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP ("AstXnor {$lhsp.isZero, $rhsp}", "AstNot{$rhsp}");
|
||||
TREEOP ("AstSub {$lhsp.isZero, $rhsp}", "AstNegate{$rhsp}");
|
||||
TREEOP ("AstAdd {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||
TREEOP ("AstAnd {$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
|
||||
TREEOP ("AstLogAnd{$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
|
||||
TREEOP ("AstLogOr {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||
TREEOP ("AstMul {$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
|
||||
TREEOP ("AstMulS {$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
|
||||
TREEOP ("AstOr {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||
TREEOP ("AstShiftL{$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||
TREEOP ("AstShiftR{$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||
TREEOP ("AstShiftRS{$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||
TREEOP ("AstSub {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||
TREEOP ("AstXor {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||
TREEOP ("AstXnor {$lhsp, $rhsp.isZero}", "AstNot{$lhsp}");
|
||||
// Non-zero on one side or the other
|
||||
TREEOP("AstAnd {$lhsp.isAllOnes, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP("AstLogAnd{$lhsp.isNeqZero, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP("AstOr {$lhsp.isAllOnes, $rhsp}", "replaceWLhs(nodep)"); //->allOnes
|
||||
TREEOP("AstLogOr {$lhsp.isNeqZero, $rhsp}", "replaceNum(nodep,1)");
|
||||
TREEOP("AstAnd {$lhsp, $rhsp.isAllOnes}", "replaceWLhs(nodep)");
|
||||
TREEOP("AstLogAnd{$lhsp, $rhsp.isNeqZero}", "replaceWLhs(nodep)");
|
||||
TREEOP("AstOr {$lhsp, $rhsp.isAllOnes}", "replaceWRhs(nodep)"); //->allOnes
|
||||
TREEOP("AstLogOr {$lhsp, $rhsp.isNeqZero}", "replaceNum(nodep,1)");
|
||||
TREEOP("AstXor {$lhsp.isAllOnes, $rhsp}", "AstNot{$rhsp}");
|
||||
TREEOP("AstXnor {$lhsp.isAllOnes, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP("AstMul {$lhsp.isOne, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP("AstMulS {$lhsp.isOne, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP("AstDiv {$lhsp, $rhsp.isOne}", "replaceWLhs(nodep)");
|
||||
TREEOP("AstDivS {$lhsp, $rhsp.isOne}", "replaceWLhs(nodep)");
|
||||
TREEOP("AstMul {operandIsPowTwo($lhsp), $rhsp}", "replaceMulShift(nodep)"); // a*2^n -> a<<n
|
||||
TREEOP("AstDiv {$lhsp, operandIsPowTwo($rhsp)}", "replaceDivShift(nodep)"); // a/2^n -> a>>n
|
||||
TREEOP("AstPow {operandIsTwo($lhsp), $rhsp}", "replacePowShift(nodep)"); // 2**a == 1<<a
|
||||
TREEOP("AstPowS {operandIsTwo($lhsp), $rhsp}", "replacePowShift(nodep)"); // 2**a == 1<<a
|
||||
TREEOP ("AstAnd {$lhsp.isAllOnes, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP ("AstLogAnd{$lhsp.isNeqZero, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP ("AstOr {$lhsp.isAllOnes, $rhsp}", "replaceWLhs(nodep)"); //->allOnes
|
||||
TREEOP ("AstLogOr {$lhsp.isNeqZero, $rhsp}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstAnd {$lhsp, $rhsp.isAllOnes}", "replaceWLhs(nodep)");
|
||||
TREEOP ("AstLogAnd{$lhsp, $rhsp.isNeqZero}", "replaceWLhs(nodep)");
|
||||
TREEOP ("AstOr {$lhsp, $rhsp.isAllOnes}", "replaceWRhs(nodep)"); //->allOnes
|
||||
TREEOP ("AstLogOr {$lhsp, $rhsp.isNeqZero}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstXor {$lhsp.isAllOnes, $rhsp}", "AstNot{$rhsp}");
|
||||
TREEOP ("AstXnor {$lhsp.isAllOnes, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP ("AstMul {$lhsp.isOne, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP ("AstMulS {$lhsp.isOne, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP ("AstDiv {$lhsp, $rhsp.isOne}", "replaceWLhs(nodep)");
|
||||
TREEOP ("AstDivS {$lhsp, $rhsp.isOne}", "replaceWLhs(nodep)");
|
||||
TREEOP ("AstMul {operandIsPowTwo($lhsp), $rhsp}", "replaceMulShift(nodep)"); // a*2^n -> a<<n
|
||||
TREEOP ("AstDiv {$lhsp, operandIsPowTwo($rhsp)}", "replaceDivShift(nodep)"); // a/2^n -> a>>n
|
||||
TREEOP ("AstPow {operandIsTwo($lhsp), $rhsp}", "replacePowShift(nodep)"); // 2**a == 1<<a
|
||||
TREEOP ("AstPowS {operandIsTwo($lhsp), $rhsp}", "replacePowShift(nodep)"); // 2**a == 1<<a
|
||||
// Trinary ops
|
||||
// Note V3Case::Sel requires Cond to always be conditionally executed in C to prevent core dump!
|
||||
TREEOP("AstNodeCond{$condp.isZero, $expr1p, $expr2p}", "replaceWChild(nodep,$expr2p)");
|
||||
TREEOP("AstNodeCond{$condp.isNeqZero, $expr1p, $expr2p}", "replaceWChild(nodep,$expr1p)");
|
||||
TREEOP("AstNodeCond{$condp, operandsSame($expr1p,,$expr2p)}","replaceWChild(nodep,$expr1p)");
|
||||
TREEOP("AstCond{$condp->castNot(), $expr1p, $expr2p}", "AstCond{$condp->op1p(), $expr2p, $expr1p}");
|
||||
TREEOP("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p.isAllOnes, $expr2p}", "AstOr {$condp, $expr2p}"); // a?1:b == a|b
|
||||
TREEOP("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p, $expr2p.isZero}", "AstAnd{$condp, $expr1p}"); // a?b:0 == a&b
|
||||
TREEOP("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p, $expr2p.isAllOnes}", "AstOr {AstNot{$condp}, $expr1p}"); // a?b:1 == ~a|b
|
||||
TREEOP("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p.isZero, $expr2p}", "AstAnd{AstNot{$condp}, $expr2p}"); // a?0:b == ~a&b
|
||||
TREEOP("AstNodeCond{!$condp.width1, operandBoolShift(nodep->condp())}", "replaceBoolShift(nodep->condp())");
|
||||
TREEOP ("AstNodeCond{$condp.isZero, $expr1p, $expr2p}", "replaceWChild(nodep,$expr2p)");
|
||||
TREEOP ("AstNodeCond{$condp.isNeqZero, $expr1p, $expr2p}", "replaceWChild(nodep,$expr1p)");
|
||||
TREEOPC("AstNodeCond{$condp.isZero, $expr1p.castConst, $expr2p.castConst}", "replaceWChild(nodep,$expr2p)");
|
||||
TREEOPC("AstNodeCond{$condp.isNeqZero, $expr1p.castConst, $expr2p.castConst}", "replaceWChild(nodep,$expr1p)");
|
||||
TREEOP ("AstNodeCond{$condp, operandsSame($expr1p,,$expr2p)}","replaceWChild(nodep,$expr1p)");
|
||||
TREEOP ("AstCond{$condp->castNot(), $expr1p, $expr2p}", "AstCond{$condp->op1p(), $expr2p, $expr1p}");
|
||||
TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p.isAllOnes, $expr2p}", "AstOr {$condp, $expr2p}"); // a?1:b == a|b
|
||||
TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p, $expr2p.isZero}", "AstAnd{$condp, $expr1p}"); // a?b:0 == a&b
|
||||
TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p, $expr2p.isAllOnes}", "AstOr {AstNot{$condp}, $expr1p}"); // a?b:1 == ~a|b
|
||||
TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p.isZero, $expr2p}", "AstAnd{AstNot{$condp}, $expr2p}"); // a?0:b == ~a&b
|
||||
TREEOP ("AstNodeCond{!$condp.width1, operandBoolShift(nodep->condp())}", "replaceBoolShift(nodep->condp())");
|
||||
// Prefer constants on left, since that often needs a shift, it lets constant red remove the shift
|
||||
TREEOP("AstNodeBiCom{!$lhsp.castConst, $rhsp.castConst}", "swapSides(nodep)");
|
||||
TREEOP("AstNodeBiComAsv{operandAsvConst(nodep)}", "replaceAsv(nodep)");
|
||||
TREEOP("AstNodeBiComAsv{operandAsvSame(nodep)}", "replaceAsv(nodep)");
|
||||
TREEOP("AstNodeBiComAsv{operandAsvLUp(nodep)}", "replaceAsvLUp(nodep)");
|
||||
TREEOP("AstNodeBiComAsv{operandAsvRUp(nodep)}", "replaceAsvRUp(nodep)");
|
||||
TREEOP ("AstNodeBiCom{!$lhsp.castConst, $rhsp.castConst}", "swapSides(nodep)");
|
||||
TREEOP ("AstNodeBiComAsv{operandAsvConst(nodep)}", "replaceAsv(nodep)");
|
||||
TREEOP ("AstNodeBiComAsv{operandAsvSame(nodep)}", "replaceAsv(nodep)");
|
||||
TREEOP ("AstNodeBiComAsv{operandAsvLUp(nodep)}", "replaceAsvLUp(nodep)");
|
||||
TREEOP ("AstNodeBiComAsv{operandAsvRUp(nodep)}", "replaceAsvRUp(nodep)");
|
||||
// v--- *1* as These ops are always first, as we warn before replacing
|
||||
TREEOP1("AstLt {$lhsp, $rhsp.isZero}", "replaceNumSigned(nodep,0)");
|
||||
TREEOP1("AstGte {$lhsp, $rhsp.isZero}", "replaceNumSigned(nodep,1)");
|
||||
@@ -1666,33 +1763,46 @@ private:
|
||||
TREEOP ("AstShiftL{operandShiftShift(nodep)}", "replaceShiftShift(nodep)");
|
||||
TREEOP ("AstShiftR{operandShiftShift(nodep)}", "replaceShiftShift(nodep)");
|
||||
TREEOP ("AstWordSel{operandWordOOB(nodep)}", "replaceZero(nodep)");
|
||||
// Compress out EXTENDs to appease loop unroller
|
||||
TREEOPV("AstEq {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
|
||||
TREEOPV("AstNeq {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
|
||||
TREEOPV("AstGt {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
|
||||
TREEOPV("AstGte {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
|
||||
TREEOPV("AstLt {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
|
||||
TREEOPV("AstLte {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
|
||||
// Identical operands on both sides
|
||||
// AstLogAnd/AstLogOr already converted to AstAnd/AstOr for these rules
|
||||
// AstAdd->ShiftL(#,1) but uncommon
|
||||
TREEOP("AstAnd {operandsSame($lhsp,,$rhsp)}", "replaceWLhs(nodep)");
|
||||
TREEOP("AstChangeXor{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP("AstDiv {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP("AstDivS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP("AstOr {operandsSame($lhsp,,$rhsp)}", "replaceWLhs(nodep)");
|
||||
TREEOP("AstSub {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP("AstXnor {operandsSame($lhsp,,$rhsp)}", "replaceAllOnes(nodep)");
|
||||
TREEOP("AstXor {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP("AstEq {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); // We let X==X -> 1, although in a true 4-state sim it's X.
|
||||
TREEOP("AstEqCase {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP("AstEqWild {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP("AstGt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP("AstGtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP("AstGte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP("AstGteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP("AstLt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP("AstLtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP("AstLte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP("AstLteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP("AstNeq {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP("AstNeqCase{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP("AstNeqWild{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP("AstLogAnd {operandsSame($lhsp,,$rhsp), $lhsp.width1}", "replaceWLhs(nodep)");
|
||||
TREEOP("AstLogOr {operandsSame($lhsp,,$rhsp), $lhsp.width1}", "replaceWLhs(nodep)");
|
||||
TREEOP ("AstAnd {operandsSame($lhsp,,$rhsp)}", "replaceWLhs(nodep)");
|
||||
TREEOP ("AstChangeXor{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstDiv {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstDivS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstOr {operandsSame($lhsp,,$rhsp)}", "replaceWLhs(nodep)");
|
||||
TREEOP ("AstSub {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstXnor {operandsSame($lhsp,,$rhsp)}", "replaceAllOnes(nodep)");
|
||||
TREEOP ("AstXor {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstEq {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); // We let X==X -> 1, although in a true 4-state sim it's X.
|
||||
TREEOP ("AstEqD {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); // We let X==X -> 1, although in a true 4-state sim it's X.
|
||||
TREEOP ("AstEqCase {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstEqWild {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstGt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstGtD {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstGtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstGte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstGteD {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstGteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstLt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstLtD {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstLtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstLte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstLteD {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstLteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstNeq {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstNeqD {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstNeqCase{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstNeqWild{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstLogAnd {operandsSame($lhsp,,$rhsp), $lhsp.width1}", "replaceWLhs(nodep)");
|
||||
TREEOP ("AstLogOr {operandsSame($lhsp,,$rhsp), $lhsp.width1}", "replaceWLhs(nodep)");
|
||||
///=== Verilog operators
|
||||
// Comparison against 1'b0/1'b1; must be careful about widths.
|
||||
// These use Not, so must be Verilog only
|
||||
@@ -1743,18 +1853,33 @@ private:
|
||||
TREEOPV("AstReplicate{$lhsp, $rhsp.isOne, $lhsp->width()==nodep->width()}", "replaceWLhs(nodep)"); // {1{lhs}}->lhs
|
||||
// Next rule because AUTOINST puts the width of bits in
|
||||
// to pins, even when the widths are exactly the same across the hierarchy.
|
||||
TREEOPV("AstSel{operandSelExtend(nodep)}", "replaceWChild(nodep, nodep->fromp()->castExtend()->lhsp())");
|
||||
TREEOPV("AstSel{operandSelExtend(nodep)}", "DONE");
|
||||
TREEOPV("AstSel{operandSelFull(nodep)}", "replaceWChild(nodep, nodep->fromp())");
|
||||
TREEOPV("AstSel{$fromp.castSel}", "replaceSelSel(nodep)");
|
||||
TREEOPV("AstSel{$fromp.castConst, $lsbp.castConst, $widthp.castConst, }", "replaceConst(nodep)");
|
||||
TREEOPV("AstSel{$fromp.castAdd, operandSelBiLower(nodep)}", "DONE");
|
||||
TREEOPV("AstSel{$fromp.castAnd, operandSelBiLower(nodep)}", "DONE");
|
||||
TREEOPV("AstSel{$fromp.castOr, operandSelBiLower(nodep)}", "DONE");
|
||||
TREEOPV("AstSel{$fromp.castSub, operandSelBiLower(nodep)}", "DONE");
|
||||
TREEOPV("AstSel{$fromp.castXnor,operandSelBiLower(nodep)}", "DONE");
|
||||
TREEOPV("AstSel{$fromp.castXor, operandSelBiLower(nodep)}", "DONE");
|
||||
TREEOPC("AstSel{$fromp.castConst, $lsbp.castConst, $widthp.castConst, }", "replaceConst(nodep)");
|
||||
TREEOPV("AstSel{$fromp.castConcat, $lsbp.castConst, $widthp.castConst, }", "replaceSelConcat(nodep)");
|
||||
TREEOPV("AstSel{$fromp.castReplicate, $lsbp.castConst, $widthp.isOne, }", "replaceSelReplicate(nodep)");
|
||||
// V3Tristate requires selects below BufIf1.
|
||||
// Also do additional operators that are bit-independent, but only definite
|
||||
// win if bit select is a constant (otherwise we may need to compute bit index several times)
|
||||
TREEOPV("AstSel{$fromp.castBufIf1}", "replaceSelIntoBiop(nodep)");
|
||||
TREEOPV("AstSel{$fromp.castNot}", "replaceSelIntoUniop(nodep)");
|
||||
TREEOPV("AstSel{$fromp.castAnd,$lhsp.castConst}", "replaceSelIntoUniop(nodep)");
|
||||
TREEOPV("AstSel{$fromp.castOr,$lhsp.castConst}", "replaceSelIntoUniop(nodep)");
|
||||
TREEOPV("AstSel{$fromp.castXor,$lhsp.castConst}", "replaceSelIntoUniop(nodep)");
|
||||
TREEOPV("AstSel{$fromp.castXnor,$lhsp.castConst}", "replaceSelIntoUniop(nodep)");
|
||||
// Conversions
|
||||
TREEOPV("AstRedXnor{$lhsp}", "AstNot{AstRedXor{$lhsp}}"); // Just eliminate XNOR's
|
||||
TREEOPV("AstLogIf {$lhsp, $rhsp}", "AstLogOr{AstLogNot{$lhsp},$rhsp}");
|
||||
TREEOPV("AstLogIff{$lhsp, $rhsp}", "AstLogNot{AstXor{$lhsp,$rhsp}}");
|
||||
// Strings
|
||||
TREEOP ("AstCvtPackString{$lhsp.castConst}", "replaceConstString(nodep, nodep->lhsp()->castConst()->num().toString())");
|
||||
TREEOPC("AstCvtPackString{$lhsp.castConst}", "replaceConstString(nodep, nodep->lhsp()->castConst()->num().toString())");
|
||||
|
||||
|
||||
// Possible futures:
|
||||
@@ -1781,15 +1906,37 @@ private:
|
||||
}
|
||||
|
||||
public:
|
||||
// Processing Mode Enum
|
||||
enum ProcMode {
|
||||
PROC_PARAMS,
|
||||
PROC_LIVE,
|
||||
PROC_V_WARN,
|
||||
PROC_V_NOWARN,
|
||||
PROC_V_EXPENSIVE,
|
||||
PROC_CPP
|
||||
};
|
||||
|
||||
// CONSTUCTORS
|
||||
ConstVisitor(bool params, bool expensive, bool warn, bool cpp) {
|
||||
m_params = params; m_required = params;
|
||||
m_expensive = expensive;
|
||||
m_warn = warn;
|
||||
m_cpp = cpp;
|
||||
m_wremove = true;
|
||||
ConstVisitor(ProcMode pmode) {
|
||||
m_params = false;
|
||||
m_required = false;
|
||||
m_doExpensive = false;
|
||||
m_doNConst = false;
|
||||
m_doV = false;
|
||||
m_warn = false;
|
||||
m_wremove = true; // Overridden in visitors
|
||||
m_modp = NULL;
|
||||
m_scopep = NULL;
|
||||
//
|
||||
switch (pmode) {
|
||||
case PROC_PARAMS: m_doV = true; m_doNConst = true; m_params = true; m_required = true; break;
|
||||
case PROC_LIVE: break;
|
||||
case PROC_V_WARN: m_doV = true; m_doNConst = true; m_warn = true; break;
|
||||
case PROC_V_NOWARN: m_doV = true; m_doNConst = true; break;
|
||||
case PROC_V_EXPENSIVE: m_doV = true; m_doNConst = true; m_doExpensive = true; break;
|
||||
case PROC_CPP: m_doV = false; m_doNConst = true; break;
|
||||
default: v3fatalSrc("Bad case"); break;
|
||||
}
|
||||
}
|
||||
virtual ~ConstVisitor() {}
|
||||
AstNode* mainAcceptEdit(AstNode* nodep) {
|
||||
@@ -1806,7 +1953,7 @@ AstNode* V3Const::constifyParamsEdit(AstNode* nodep) {
|
||||
// Resize even if the node already has a width, because burried in the treee we may
|
||||
// have a node we just created with signing, etc, that isn't sized yet.
|
||||
nodep = V3Width::widthParamsEdit(nodep); // Make sure we've sized everything first
|
||||
ConstVisitor visitor (true,false,false,false);
|
||||
ConstVisitor visitor (ConstVisitor::PROC_PARAMS);
|
||||
if (AstVar* varp=nodep->castVar()) {
|
||||
// If a var wants to be constified, it's really a param, and
|
||||
// we want the value to be constant. We aren't passed just the
|
||||
@@ -1820,34 +1967,43 @@ AstNode* V3Const::constifyParamsEdit(AstNode* nodep) {
|
||||
return nodep;
|
||||
}
|
||||
|
||||
void V3Const::constifyAll(AstNetlist* nodep) {
|
||||
// Only call from Verilator.cpp, as it uses user#'s
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
ConstVisitor visitor (false,true,false,false);
|
||||
(void)visitor.mainAcceptEdit(nodep);
|
||||
}
|
||||
|
||||
void V3Const::constifyAllLint(AstNetlist* nodep) {
|
||||
// Only call from Verilator.cpp, as it uses user#'s
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
ConstVisitor visitor (false,false,true,false);
|
||||
ConstVisitor visitor (ConstVisitor::PROC_V_WARN);
|
||||
(void)visitor.mainAcceptEdit(nodep);
|
||||
}
|
||||
|
||||
void V3Const::constifyCpp(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
ConstVisitor visitor (false,false,false,true);
|
||||
ConstVisitor visitor (ConstVisitor::PROC_CPP);
|
||||
(void)visitor.mainAcceptEdit(nodep);
|
||||
}
|
||||
|
||||
AstNode* V3Const::constifyEdit(AstNode* nodep) {
|
||||
ConstVisitor visitor (false,false,false,false);
|
||||
ConstVisitor visitor (ConstVisitor::PROC_V_NOWARN);
|
||||
nodep = visitor.mainAcceptEdit(nodep);
|
||||
return nodep;
|
||||
}
|
||||
|
||||
void V3Const::constifyAllLive(AstNetlist* nodep) {
|
||||
// Only call from Verilator.cpp, as it uses user#'s
|
||||
// This only pushes constants up, doesn't make any other edits
|
||||
// IE doesn't prune dead statements, as we need to do some usability checks after this
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
ConstVisitor visitor (ConstVisitor::PROC_LIVE);
|
||||
(void)visitor.mainAcceptEdit(nodep);
|
||||
}
|
||||
|
||||
void V3Const::constifyAll(AstNetlist* nodep) {
|
||||
// Only call from Verilator.cpp, as it uses user#'s
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
ConstVisitor visitor (ConstVisitor::PROC_V_EXPENSIVE);
|
||||
(void)visitor.mainAcceptEdit(nodep);
|
||||
}
|
||||
|
||||
AstNode* V3Const::constifyExpensiveEdit(AstNode* nodep) {
|
||||
ConstVisitor visitor (false,true,false,false);
|
||||
ConstVisitor visitor (ConstVisitor::PROC_V_EXPENSIVE);
|
||||
nodep = visitor.mainAcceptEdit(nodep);
|
||||
return nodep;
|
||||
}
|
||||
|
||||
+3
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -34,6 +34,8 @@ public:
|
||||
// Force this cell node's parameter list to become a constant
|
||||
// Return new node that may have replaced nodep
|
||||
static AstNode* constifyParamsEdit(AstNode* nodep);
|
||||
// Only do constant pushing, without removing dead logic
|
||||
static void constifyAllLive(AstNetlist* nodep);
|
||||
// Everything that's possible
|
||||
static void constifyAll(AstNetlist* nodep);
|
||||
// Also, warn
|
||||
|
||||
+7
-5
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -81,10 +81,12 @@ private:
|
||||
string prettyName = nodep->prettyName();
|
||||
if (!nodep->isToggleCoverable())
|
||||
return "Not relevant signal type";
|
||||
if (prettyName.c_str()[0] == '_')
|
||||
return "Leading underscore";
|
||||
if (prettyName.find("._") != string::npos)
|
||||
return "Inlined leading underscore";
|
||||
if (!v3Global.opt.coverageUnderscore()) {
|
||||
if (prettyName.c_str()[0] == '_')
|
||||
return "Leading underscore";
|
||||
if (prettyName.find("._") != string::npos)
|
||||
return "Inlined leading underscore";
|
||||
}
|
||||
if ((nodep->width()*nodep->arrayElements()) > 256) return "Wide bus/array > 256 bits";
|
||||
// We allow this, though tracing doesn't
|
||||
// if (nodep->arrayp(1)) return "Unsupported: Multi-dimensional array";
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+7
-1
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -122,6 +122,12 @@ private:
|
||||
nodep->packagep()->user1Inc();
|
||||
}
|
||||
}
|
||||
virtual void visit(AstEnumItemRef* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (nodep->packagep()) {
|
||||
nodep->packagep()->user1Inc();
|
||||
}
|
||||
}
|
||||
virtual void visit(AstVarScope* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
m_vscsp.push_back(nodep);
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+2
-4
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -345,9 +345,7 @@ private:
|
||||
m_nextDlyp = NULL;
|
||||
}
|
||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||
if (!nodep->user2()) { // Not done yet
|
||||
nodep->user2(true);
|
||||
|
||||
if (!nodep->user2Inc()) { // Not done yet
|
||||
if (m_inDly && nodep->lvalue()) {
|
||||
UINFO(4,"AssignDlyVar: "<<nodep<<endl);
|
||||
markVarUsage(nodep->varScopep(), VU_DLY);
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+28
-12
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -127,6 +127,7 @@ public:
|
||||
nodep->lhsp()->iterateAndNext(*this); puts(", ");
|
||||
} else if (nodep->isWide()
|
||||
&& nodep->lhsp()->castVarRef()
|
||||
&& !nodep->rhsp()->castCMath()
|
||||
&& !nodep->rhsp()->castVarRef()
|
||||
&& !nodep->rhsp()->castArraySel()) {
|
||||
// Wide functions assign into the array directly, don't need separate assign statement
|
||||
@@ -343,13 +344,11 @@ public:
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstFClose* nodep, AstNUser*) {
|
||||
puts("if (");
|
||||
puts("VL_FCLOSE_I(");
|
||||
nodep->filep()->iterateAndNext(*this);
|
||||
puts(") { fclose (VL_CVT_Q_FP(");
|
||||
nodep->filep()->iterateAndNext(*this);
|
||||
puts(")); ");
|
||||
puts("); ");
|
||||
nodep->filep()->iterateAndNext(*this); // For saftey, so user doesn't later WRITE with it.
|
||||
puts("=0; }\n");
|
||||
puts("=0;\n");
|
||||
}
|
||||
virtual void visit(AstFFlush* nodep, AstNUser*) {
|
||||
if (!nodep->filep()) {
|
||||
@@ -357,7 +356,7 @@ public:
|
||||
} else {
|
||||
puts("if (");
|
||||
nodep->filep()->iterateAndNext(*this);
|
||||
puts(") { fflush (VL_CVT_Q_FP(");
|
||||
puts(") { fflush (VL_CVT_I_FP(");
|
||||
nodep->filep()->iterateAndNext(*this);
|
||||
puts(")); }\n");
|
||||
}
|
||||
@@ -475,7 +474,7 @@ public:
|
||||
}
|
||||
visit(nodep->castNodeBiop(), vup);
|
||||
}
|
||||
virtual void visit(AstCast* nodep, AstNUser*) {
|
||||
virtual void visit(AstCCast* nodep, AstNUser*) {
|
||||
// Extending a value of the same word width is just a NOP.
|
||||
if (nodep->size()>VL_WORDSIZE) {
|
||||
puts("(QData)(");
|
||||
@@ -546,6 +545,8 @@ public:
|
||||
ofp()->printf(",0x%08" VL_PRI64 "x", (vluint64_t)(nodep->num().dataWord(word)));
|
||||
}
|
||||
ofp()->printf(",0x%08" VL_PRI64 "x)", (vluint64_t)(nodep->num().dataWord(0)));
|
||||
} else if (nodep->isDouble()) {
|
||||
ofp()->printf("%g", nodep->num().toDouble());
|
||||
} else if (nodep->isQuad()) {
|
||||
vluint64_t num = nodep->toUQuad();
|
||||
if (num<10) ofp()->printf("VL_ULL(%" VL_PRI64 "d)", num);
|
||||
@@ -1211,6 +1212,7 @@ void EmitCStmts::displayNode(AstNode* nodep, AstScopeName* scopenamep,
|
||||
switch (tolower(pos[0])) {
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
case '.':
|
||||
// Digits, like %5d, etc.
|
||||
vfmt += pos[0];
|
||||
inPct = true; // Get more digits
|
||||
@@ -1229,6 +1231,9 @@ void EmitCStmts::displayNode(AstNode* nodep, AstScopeName* scopenamep,
|
||||
case 'h':
|
||||
case 'x': displayArg(nodep,&elistp,isScan, vfmt,'x'); break;
|
||||
case 's': displayArg(nodep,&elistp,isScan, vfmt,'s'); break;
|
||||
case 'e': displayArg(nodep,&elistp,isScan, vfmt,'e'); break;
|
||||
case 'f': displayArg(nodep,&elistp,isScan, vfmt,'f'); break;
|
||||
case 'g': displayArg(nodep,&elistp,isScan, vfmt,'g'); break;
|
||||
case 'm': {
|
||||
if (!scopenamep) nodep->v3fatalSrc("Display with %m but no AstScopeName");
|
||||
string suffix = scopenamep->scopePrettyName();
|
||||
@@ -1619,7 +1624,12 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
|
||||
if (v3Global.needHInlines()) { // Set by V3EmitCInlines; should have been called before us
|
||||
puts("#include \""+topClassName()+"__Inlines.h\"\n");
|
||||
}
|
||||
// No __Dpi.h needed, we've shimmed it all into the interface
|
||||
if (v3Global.dpi()) {
|
||||
// do this before including our main .h file so that any references to
|
||||
// types defined in svdpi.h are available
|
||||
puts("#include \""+ topClassName() +"__Dpi.h\"\n");
|
||||
puts("\n");
|
||||
}
|
||||
|
||||
// Declare foreign instances up front to make C++ happy
|
||||
puts("class "+symClassName()+";\n");
|
||||
@@ -1797,8 +1807,10 @@ void EmitCImp::emitImp(AstNodeModule* modp) {
|
||||
|
||||
// Us
|
||||
puts("#include \""+ symClassName() +".h\"\n");
|
||||
|
||||
if (v3Global.dpi()) {
|
||||
puts("#include \""+ topClassName() +"__Dpi.h\"\n");
|
||||
puts("\n");
|
||||
puts("#include \"verilated_dpi.h\"\n");
|
||||
}
|
||||
|
||||
if (optSystemPerl() && (splitFilenum() || !m_fast)) {
|
||||
@@ -2003,7 +2015,9 @@ class EmitCTrace : EmitCStmts {
|
||||
return varp->isSc() && varp->isScBv();
|
||||
}
|
||||
void emitTraceInitOne(AstTraceDecl* nodep) {
|
||||
if (nodep->isWide()) {
|
||||
if (nodep->isDouble()) {
|
||||
puts("vcdp->declDouble");
|
||||
} else if (nodep->isWide()) {
|
||||
puts("vcdp->declArray");
|
||||
} else if (nodep->isQuad()) {
|
||||
puts("vcdp->declQuad ");
|
||||
@@ -2032,7 +2046,9 @@ class EmitCTrace : EmitCStmts {
|
||||
string full = ((m_funcp->funcType() == AstCFuncType::TRACE_FULL
|
||||
|| m_funcp->funcType() == AstCFuncType::TRACE_FULL_SUB)
|
||||
? "full":"chg");
|
||||
if (nodep->isWide() || emitTraceIsScBv(nodep)) {
|
||||
if (nodep->isDouble()) {
|
||||
puts("vcdp->"+full+"Double");
|
||||
} else if (nodep->isWide() || emitTraceIsScBv(nodep)) {
|
||||
puts("vcdp->"+full+"Array");
|
||||
} else if (nodep->isQuad()) {
|
||||
puts("vcdp->"+full+"Quad ");
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+3
-1
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -519,6 +519,8 @@ void EmitCSyms::emitDpiHdr() {
|
||||
puts("// Manually include this file where DPI .c import functions are declared to insure\n");
|
||||
puts("// the C functions match the expectations of the DPI imports.\n");
|
||||
puts("\n");
|
||||
puts("#include \"svdpi.h\"\n");
|
||||
puts("\n");
|
||||
puts("#ifdef __cplusplus\n");
|
||||
puts("extern \"C\" {\n");
|
||||
puts("#endif\n");
|
||||
|
||||
+10
-5
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2004-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2004-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -84,10 +84,15 @@ public:
|
||||
if (v3Global.opt.systemPerl()) {
|
||||
putMakeClassEntry(of, "Sp.cpp"); // Note Sp.cpp includes SpTraceVcdC
|
||||
}
|
||||
else if (v3Global.opt.trace()) {
|
||||
putMakeClassEntry(of, "verilated_vcd_c.cpp");
|
||||
if (v3Global.opt.systemC()) {
|
||||
putMakeClassEntry(of, "verilated_vcd_sc.cpp");
|
||||
else {
|
||||
if (v3Global.opt.coverage()) {
|
||||
putMakeClassEntry(of, "SpCoverage.cpp");
|
||||
}
|
||||
if (v3Global.opt.trace()) {
|
||||
putMakeClassEntry(of, "verilated_vcd_c.cpp");
|
||||
if (v3Global.opt.systemC()) {
|
||||
putMakeClassEntry(of, "verilated_vcd_sc.cpp");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user