Compare commits

...
83 Commits
Author SHA1 Message Date
Wilson Snyder ad53833040 Version bump 2011-07-28 19:53:54 -04:00
Wilson Snyder bc8c85668a Support coverage in -cc and -sc output modes. 2011-07-28 19:41:05 -04:00
Wilson Snyder d12a3dde45 Fix cast compile warning 2011-07-28 07:59:30 -04:00
Wilson Snyder 301c878c0f Merge branch 'master' of ssh://git-verilator-wsnyder/git/verilator 2011-07-28 07:56:44 -04:00
Wilson Snyder bd55bfa071 Support more vpi file functions 2011-07-28 07:05:40 -04:00
Wilson Snyder 6d2f09b579 Fix vpi_register_cb using bad s_cb_data, bug370. 2011-07-27 13:03:49 -04:00
Wilson Snyder 4bfea7f54d Merge branch 'master' of ssh://git-verilator-wsnyder/git/verilator 2011-07-26 18:30:25 -04:00
Wilson Snyder 55906486d8 Support 'real' numbers and related functions. 2011-07-24 15:01:51 -04:00
Wilson Snyder d5478e6e08 tests: Print status to stderr 2011-07-24 15:01:36 -04:00
Wilson Snyder d88d85c172 Internals: Real2: Create numeric class; no functional change intended 2011-07-23 19:58:34 -04:00
Wilson Snyder 59c3c536c7 Internals: Real1: properly lex doubles 2011-07-23 08:25:41 -04:00
Wilson Snyder a007458cb8 Internals: Rename float/double to match real branch. No functional change. 2011-07-21 22:10:25 -04:00
Wilson Snyder d051912f21 Internals: Rename functions to match real branch. No functional change. 2011-07-21 21:32:31 -04:00
Wilson Snyder a547158a50 bisonpre: Merge from Verilog-Perl 2011-07-21 20:34:33 -04:00
Wilson Snyder 95f2351aa0 Tests: %t formatting 2011-07-21 19:37:53 -04:00
Wilson Snyder 698aaffb0b Fix missing leading zeros in %0d, bug367 2011-07-14 07:39:11 -04:00
Wilson Snyder 73eccecbf8 Merge branch 'master' of ssh://git-verilator-wsnyder/git/verilator 2011-07-11 08:10:28 -04:00
Wilson Snyder ae4a261463 Internals: Rename UnaryMin to Negate. No functional change. 2011-07-08 06:03:07 -04:00
Wilson Snyder c9f0d0cec2 Recognize pragma synthesys to match vhier 2011-07-07 13:30:27 -04:00
Wilson Snyder 4fa1e45d45 Internals: Move width internals to inside class; move WidthCommit. No functional change 2011-07-06 19:03:40 -04:00
Wilson Snyder 1b3d252bfe Internals: Cleanup Dead code 2011-07-06 18:46:41 -04:00
Wilson Snyder a9ba4a9fcd Internals: Cleanups in V3Signed towards reals; no functional change 2011-07-05 21:05:35 -04:00
Wilson Snyder 7f49619875 Fix VL_FCLOSE declaration, broke two commits ago, bug363 2011-07-05 20:42:33 -04:00
Wilson Snyder 696660639a Support 'const' variables in limited cases; similar to enums. 2011-07-02 12:45:26 -04:00
Wilson Snyder da4323062d Commentary 2011-07-01 15:23:09 -04:00
Wilson Snyder a901e171b2 Support $fopen and I/O with integer instead of `verilator_file_descriptor. 2011-07-01 13:41:21 -04:00
Wilson Snyder 6e41d532fe Use 'vluint64_t' for SystemC instead of (same sized) 'uint64' for MSVC++. 2011-06-29 19:19:01 -04:00
Wilson Snyder 4fc78ffb58 Merge branch 'master' of ssh://git-verilator-wsnyder/git/verilator 2011-06-29 14:22:59 -04:00
Wilson Snyder 8137f41fc3 Support disable for loop escapes. 2011-06-28 21:26:49 -04:00
Wilson Snyder 2e9471797d Version to devel 2011-06-28 21:11:29 -04:00
Wilson Snyder 344248cea0 Version bump 2011-06-28 20:52:04 -04:00
Wilson Snyder 2789e3dba5 Fix 96 bit DPI input/outputs, bug359 2011-06-28 20:45:50 -04:00
Wilson Snyder cca759a41e Tests: Example embedding 2011-05-22 08:43:36 -04:00
Wilson Snyder 4f7b3d8882 Fix out of memory on slice syntax error, bug354. 2011-05-21 08:19:33 -04:00
Wilson Snyder 2b330b78b7 Support bit vectors > 64 bits wide in DPI import and exports. 2011-05-20 21:33:31 -04:00
Wilson Snyder d47ca1912b tests: Fix invocation scripts for new site standard 2011-05-20 20:47:15 -04:00
Wilson Snyder 3fd2108b10 Merge branch 'master' of ssh://git-verilator-wsnyder/git/verilator 2011-05-20 15:34:30 -04:00
Wilson Snyder 96e2a407f4 Merge branch 'master' of ssh://git-verilator-wsnyder/git/verilator 2011-05-20 13:40:18 -04:00
Wilson Snyder cdf18c96f4 driver: Allow getting verilator flags in tests 2011-05-19 21:25:23 -04:00
Wilson Snyder 53acaa05b8 Commentary 2011-05-18 07:10:12 -04:00
Wilson Snyder fb85679068 Fix DPI bit vector compile errors, bug347. 2011-05-12 07:35:28 -04:00
Wilson Snyder 9558e14479 Fix DPI undeclared svBitVecVal compile error, bug346. Additional change. 2011-05-12 06:59:13 -04:00
Wilson Snyder 4af0af93bf Fix DPI undeclared svBitVecVal compile error, bug346. 2011-05-12 06:32:29 -04:00
Wilson Snyder df4bc950fe Cleanup trailing whitespace 2011-05-09 23:58:38 -04:00
Wilson Snyder 250394f72b Fix compiler warnings on SPARC, bug288 2011-05-09 23:49:17 -04:00
Wilson Snyder ca83fd6dc1 CDC: edge report under debug 2011-04-20 10:11:35 -04:00
Wilson Snyder d5e9e7cd2b Remove dead code 2011-04-19 19:02:03 -05:00
Wilson Snyder 9a96f621ef Fix CDCRSTLOGIC report showing endpoint flops without resets. 2011-04-18 10:47:02 -04:00
Wilson Snyder 5d7ce096c6 Fix error on enum references to other packages, bug339. 2011-04-13 19:34:14 -04:00
Wilson Snyder c9f8109c06 Pre-version 2011-04-13 19:33:58 -04:00
Wilson Snyder a20b4f2864 Version bump 2011-04-06 07:33:44 -04:00
Wilson Snyder 44a19d2a0a Fix missing test files 2011-04-06 07:33:32 -04:00
Wilson Snyder 02f3beb8db Add V3Number rotate functions; unused as yet 2011-03-30 21:31:29 -04:00
Wilson Snyder 3269cc3d90 Add +libext+.sv default 2011-03-30 21:30:36 -04:00
Wilson Snyder fb70a1f4ab Add --Wno-fatal to turn off abort on warnings. 2011-03-22 18:09:39 -04:00
Wilson Snyder df0aa483ce Support ${...} and $(...) env variables in .vc files 2011-03-21 12:25:31 -04:00
Wilson Snyder c83f12a55c Support simple cast operators, bug335. 2011-03-17 22:25:49 -04:00
Wilson Snyder 9704f59566 Internals: Rename AstCast to AstCCast 2011-03-17 21:09:52 -04:00
Wilson Snyder 2923893d34 Support loop unrolling on width mismatches, bug 333 2011-03-12 07:45:04 -05:00
Wilson Snyder 890dab0742 Write logfile on each failure 2011-03-12 07:44:29 -05:00
Wilson Snyder 607e26b041 Commentary 2011-03-08 06:49:45 -05:00
Wilson Snyder ea75290f65 Add error on circular parameter definitions, bug329 2011-03-07 20:44:19 -05:00
Wilson Snyder a176054118 Add --trace-max-width and --trace-max-array, bug 319. 2011-02-23 21:58:27 -05:00
Wilson Snyder 9a697dc5f5 Accelerate bit-selected inversions. 2011-02-23 21:36:38 -05:00
Wilson Snyder cfdb852843 Fix concatenates and vectored bufif1, bug326. 2011-02-23 21:21:59 -05:00
Wilson Snyder 2e67a91982 Support $bits(data_type), bug327. 2011-02-23 19:04:15 -05:00
Wilson Snyder 074ca9330d Make width violation on function outputs a fatal error 2011-02-18 20:52:26 -05:00
Wilson Snyder f0d7cdcb20 Commentary 2011-02-18 07:11:03 -05:00
Wilson Snyder 40d961e059 Version bump 2011-02-14 19:05:55 -05:00
Wilson Snyder e5de759236 Report error on function call output tied to constant.
Fix internal error on functions called as SV tasks.
2011-02-14 19:25:30 -05:00
Wilson Snyder e26a75c59d Fix internal error on non-inlined inout pins. 2011-02-07 19:15:58 -05:00
Wilson Snyder 8701145b40 Fix error on constants connected to outputs, bug323. 2011-01-31 07:05:04 -05:00
Wilson Snyder a2558886c8 Report errors on empty pins, bug321 2011-01-29 18:00:48 -05:00
Wilson Snyder f818ee86ae Report errors on duplicated pins, bug321. 2011-01-29 17:01:06 -05:00
Wilson Snyder ad0dbdaa9c CDC: Print nice net names instead of ___5f 2011-01-19 11:44:23 -05:00
Wilson Snyder a9f14b294f Internals: Cdc notes; marking submodules won't work 2011-01-18 21:37:53 -05:00
Wilson Snyder a435ae98f9 Throw UNUSED/UNDRIVEN only once per net in a parametrized module. 2011-01-18 21:28:51 -05:00
Wilson Snyder 481b261458 Internals: add a few userIncs, No functional change 2011-01-18 21:19:12 -05:00
Wilson Snyder 48df52d743 Reduce use of CRELINE so line numbers more closely match first parsed location 2011-01-18 21:12:31 -05:00
Wilson Snyder 0af0d3b171 Cleanup CDC reports, remove TOP-> signal prefixes 2011-01-17 14:58:58 -05:00
Wilson Snyder 8287cf35e7 Fix warnings to point to lowest net usage, not upper level ports. 2011-01-17 14:10:01 -05:00
Wilson Snyder fab7924cc2 Fix block comment not separating identifiers, bug311. 2011-01-11 18:46:21 -05:00
Wilson Snyder 0ab739e8b1 Fix false BLKSEQ on non-unrolled for loop indexes. 2011-01-06 06:46:19 -05:00
163 changed files with 5485 additions and 1919 deletions
+75
View File
@@ -3,6 +3,81 @@ Revision history for Verilator
The contributors that suggested a given feature are shown in []. [by ...] The contributors that suggested a given feature are shown in []. [by ...]
indicates the contributor was also the author of the fix; Thanks! indicates the contributor was also the author of the fix; Thanks!
* Verilator 3.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 * Verilator 3.810 2011/01/03
** Add limited support for VPI access to public signals, see docs. ** Add limited support for VPI access to public signals, see docs.
+4
View File
@@ -67,6 +67,10 @@ Usability:
#### non-comment lines, ##### ops, ### KB model size #### non-comment lines, ##### ops, ### KB model size
* Default the --l2name to remove extra "v" level of hierarchy (flag to make "top") * 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: Internal Code:
* Eliminate the AstNUser* passed to all visitors; its only needed in V3Width, * Eliminate the AstNUser* passed to all visitors; its only needed in V3Width,
and removing it will speed up and simplify all the other code. and removing it will speed up and simplify all the other code.
+126 -54
View File
@@ -252,7 +252,7 @@ descriptions in the next sections for more information.
--exe Link to create executable --exe Link to create executable
-F <file> Parse options from a file, relatively -F <file> Parse options from a file, relatively
-f <file> Parse options from a file -f <file> Parse options from a file
--gdbbt Run Verilator under GDB for backtrace --gdbbt Run Verilator under GDB for backtrace
--help Display this help --help Display this help
-I<dir> Directory to search for includes -I<dir> Directory to search for includes
--if-depth <value> Tune IFDEPTH warning --if-depth <value> Tune IFDEPTH warning
@@ -268,7 +268,7 @@ descriptions in the next sections for more information.
--MP Create phony dependency targets --MP Create phony dependency targets
--Mdir <directory> Name of output object directory --Mdir <directory> Name of output object directory
--mod-prefix <topname> Name to prepend to lower classes --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 --no-skip-identical Disable skipping identical output
+notimingchecks Ignored +notimingchecks Ignored
-O0 Disable optimizations -O0 Disable optimizations
@@ -292,6 +292,8 @@ descriptions in the next sections for more information.
--top-module <topname> Name of top level input module --top-module <topname> Name of top level input module
--trace Enable waveform creation --trace Enable waveform creation
--trace-depth <levels> Depth of tracing --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 --trace-underscore Enable tracing of _signals
-U<var> Undefine preprocessor define -U<var> Undefine preprocessor define
--unroll-count <loops> Tune maximum loop iterations --unroll-count <loops> Tune maximum loop iterations
@@ -304,6 +306,7 @@ descriptions in the next sections for more information.
-Wno-<message> Disable warning -Wno-<message> Disable warning
-Wno-lint Disable all lint warnings -Wno-lint Disable all lint warnings
-Wno-style Disable all style warnings -Wno-style Disable all style warnings
-Wno-fatal Disable fatal exit on warnings
-x-assign <mode> Initially assign Xs to this value -x-assign <mode> Initially assign Xs to this value
-y <dir> Directory to search for modules -y <dir> Directory to search for modules
@@ -534,14 +537,18 @@ the command line that implement the main loop for your simulation.
Read the specified file, and act as if all text inside it was specified as 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 command line parameters. Any relative paths are relative to the directory
containing the specified file. Note -F is fairly standard across Verilog containing the specified file. See also -f. Note -F is fairly standard
tools. across Verilog tools.
=item -f I<file> =item -f I<file>
Read the specified file, and act as if all text inside it was specified as 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 current command line parameters. Any relative paths are relative to the current
directory. Note -f is fairly standard across Verilog tools. 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 =item --gdbbt
@@ -610,7 +617,7 @@ appropriate `begin_keywords.
Specify the extensions that should be used for finding modules. If for 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 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 =item --lint-only
@@ -706,7 +713,7 @@ Backward compatible alias for "--pins-bv 65". Note that's a 65, not a 64.
=item --pins-bv I<width> =item --pins-bv I<width>
Specifies SystemC inputs/outputs of greater than or equal to I<width> bits 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 "--pins-bv 65". Versions before Verilator 3.671 defaulted to "--pins-bv
33". The more sc_bv is used, the worse for performance. 33". The more sc_bv is used, the worse for performance.
@@ -816,6 +823,18 @@ Specify the number of levels deep to enable tracing, for example
entire model. Using a small number will decrease visibility, but greatly entire model. Using a small number will decrease visibility, but greatly
improve runtime and trace file size. 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 =item --trace-underscore
Enable tracing of signals that start with an underscore. Normally, these Enable tracing of signals that start with an underscore. Normally, these
@@ -865,11 +884,11 @@ example C<-Werror-NOUNOPTFLAT>.
=item -Wfuture-I<message> =item -Wfuture-I<message>
Suppress unknown Verilator comments or warning messages with the given Rarely needed. Suppress unknown Verilator comments or warning messages
message code. This is used to allow code written with pragmas for a later with the given message code. This is used to allow code written with
version of Verilator to run under a older version; add -Wfuture- arguments pragmas for a later version of Verilator to run under a older version; add
for each message code or comment that the new version supports which the -Wfuture- arguments for each message code or comment that the new version
older version does not support. supports which the older version does not support.
=item -Wno-I<message> =item -Wno-I<message>
@@ -894,6 +913,14 @@ already disabled). This is equivalent to "-Wno-DECLFILENAME -Wno-DEFPARAM
-Wno-INCABSPATH -Wno-SYNCASYNCNET -Wno-UNDRIVEN -Wno-UNUSED -Wno-INCABSPATH -Wno-SYNCASYNCNET -Wno-UNDRIVEN -Wno-UNUSED
-Wno-VARHIDDEN". -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> =item -Wwarn-I<message>
Enables the specified warning message. Enables the specified warning message.
@@ -903,8 +930,8 @@ Enables the specified warning message.
Enable all lint related warning messages (note by default they are already Enable all lint related warning messages (note by default they are already
enabled), but do not affect style messages. This is equivalent to enabled), but do not affect style messages. This is equivalent to
"-Wwarn-CASEINCOMPLETE -Wwarn-CASEOVERLAP -Wwarn-CASEX -Wwarn-CASEWITHX "-Wwarn-CASEINCOMPLETE -Wwarn-CASEOVERLAP -Wwarn-CASEX -Wwarn-CASEWITHX
-Wwarn-CMPCONST -Wwarn-IMPLICIT -Wwarn-LITENDIAN -Wwarn-UNSIGNED -Wwarn-CMPCONST -Wwarn-IMPLICIT -Wwarn-LITENDIAN -Wwarn-REALCVT
-Wwarn-WIDTH". -Wwarn-UNSIGNED -Wwarn-WIDTH".
=item -Wwarn-style =item -Wwarn-style
@@ -954,7 +981,7 @@ We'll compile this example into C++.
cat <<EOF >our.v cat <<EOF >our.v
module our; module our;
initial begin \$display("Hello World"); \$finish; end initial begin $display("Hello World"); $finish; end
endmodule endmodule
EOF EOF
@@ -976,7 +1003,7 @@ your operating system (as an RPM), first you need to point to the kit:
export PATH=$VERILATOR_ROOT/bin:$PATH export PATH=$VERILATOR_ROOT/bin:$PATH
Now we run Verilator on our little example. Now we run Verilator on our little example.
verilator -Wall --cc our.v --exe sim_main.cpp verilator -Wall --cc our.v --exe sim_main.cpp
We can see the source code under the "obj_dir" directory. See the FILES We can see the source code under the "obj_dir" directory. See the FILES
@@ -1019,7 +1046,7 @@ This is an example similar to the above, but using SystemPerl.
module our (clk); module our (clk);
input clk; // Clock is required to get initial activation input clk; // Clock is required to get initial activation
always @ (posedge clk) always @ (posedge clk)
begin \$display("Hello World"); \$finish; end begin $display("Hello World"); $finish; end
endmodule endmodule
EOF EOF
@@ -1325,7 +1352,7 @@ will plug directly into a SystemC netlist.
The SC_MODULE gets the same pinout as the Verilog module, with the 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 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 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.) (Uints simulate the fastest so are used where possible.)
Lower modules are not pure SystemC code. This is a feature, as using the Lower modules are not pure SystemC code. This is a feature, as using the
@@ -1410,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 like format specifier followed by any number of arguments to satisfy the
format. 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 =head2 DPI Header Isolation
Verilator places the IEEE standard header files such as svdpi.h into a Verilator places the IEEE standard header files such as svdpi.h into a
@@ -1421,7 +1480,7 @@ svdpi.h and similar standard files with different contents, the vltstd
directory should not be included to prevent picking up incompatible directory should not be included to prevent picking up incompatible
definitions. definitions.
=head2 Public Functions =head2 Public Functions
Instead of DPI exporting, there's also Verilator public functions, which Instead of DPI exporting, there's also Verilator public functions, which
are slightly faster, but less compatible. are slightly faster, but less compatible.
@@ -1602,7 +1661,7 @@ please file a bug if a feature you need is missing.
Verilator supports ==? and !=? operators, ++ and -- in some contexts, Verilator supports ==? and !=? operators, ++ and -- in some contexts,
$bits, $countones, $error, $fatal, $info, $isunknown, $onehot, $onehot0, $bits, $countones, $error, $fatal, $info, $isunknown, $onehot, $onehot0,
$unit, $warning, always_comb, always_ff, always_latch, bit, byte, chandle, $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 program, shortint, time, typedef, var, void, priority case/if, and unique
case/if. case/if.
@@ -1652,8 +1711,8 @@ assertion clocks.
=head2 Synthesis Directive Assertion Support =head2 Synthesis Directive Assertion Support
With the --assert switch, Verilator reads any "//synopsys full_case" or "// With the --assert switch, Verilator reads any "//synopsys full_case" or "//
synopsys parallel_case" directives. The same applies to any "//cadence" or synopsys parallel_case" directives. The same applies to any "// ambit
"// ambit synthesis" directives of the same form. synthesis", "//cadence" or "//pragma" directives of the same form.
When these synthesis directives are discovered, Verilator will either When these synthesis directives are discovered, Verilator will either
formally prove the directive to be true, or failing that, will insert the formally prove the directive to be true, or failing that, will insert the
@@ -2037,7 +2096,7 @@ that Verilator will print a list of known scopes to help your debugging.
=head2 Floating Point =head2 Floating Point
Floating Point numbers are not synthesizable, and so not supported. Floating Point (real) numbers are supported.
=head2 Latches =head2 Latches
@@ -2080,7 +2139,7 @@ of the form:
inout driver; inout driver;
wire driver = (enable) ? output_value : 1'bz; wire driver = (enable) ? output_value : 1'bz;
Will be converted to Will be converted to
input driver__in; // Value being driven in from "external" drivers input driver__in; // Value being driven in from "external" drivers
@@ -2189,11 +2248,23 @@ Increment/decrement can only be used as standalone statements or in for
loops. They cannot be used as side effect operators inside more complicate loops. They cannot be used as side effect operators inside more complicate
expressions ("a = b++;"). expressions ("a = b++;").
=item cast operator
Casting is supported only between simple scalar types, signed and unsigned,
not arrays nor structs.
=item chandle =item chandle
Treated as a "longint"; does not yet warn about operations that are Treated as a "longint"; does not yet warn about operations that are
specified as illegal on chandles. 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 =item priority if, unique if
Priority and unique if's are treated as normal ifs and not asserted to be Priority and unique if's are treated as normal ifs and not asserted to be
@@ -2242,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 File descriptors passed to the file PLI calls must be file descriptors, not
MCDs, which includes the mode parameter to $fopen being mandatory. 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 =item $fscanf, $sscanf
@@ -2270,10 +2336,6 @@ Read memory commands should work properly. Note Verilator and the Verilog
specification does not include support for readmem to multi-dimensional specification does not include support for readmem to multi-dimensional
arrays. arrays.
=item $realtime
Treated as $time.
=item $test$plusargs, $value$plusargs =item $test$plusargs, $value$plusargs
Supported, but the instantiating C++/SystemC testbench must call Supported, but the instantiating C++/SystemC testbench must call
@@ -2553,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 unique file by the same name. Otherwise, make sure all library files are
read in as libraries with -v, instead of automatically with -y. 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 =item REDEFMACRO
Warns that you have redefined the same macro with a different value, for Warns that you have redefined the same macro with a different value, for
@@ -2987,8 +3054,8 @@ network disk. Network disks are generally far slower.
=item How do I do coverage analysis? =item How do I do coverage analysis?
Verilator supports both block (line) coverage and user inserted functional Verilator supports both block (line) coverage and user inserted functional
coverage. Both currently require SystemPerl output mode and the SystemPerl coverage. Both require the SystemPerl package to be installed but do not
package. require use of the SystemPerl output mode.
First, run verilator with the --coverage option. If you're using your own 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 makefile, compile the model with the GCC flag -DSP_COVERAGE_ENABLE (if
@@ -3111,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 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 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. compiler will properly up-convert smaller entities.
Signals wider than 64 bits are stored as an array of 32-bit uint32_t's. Signals wider than 64 bits are stored as an array of 32-bit uint32_t's.
@@ -3232,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. Jeff Dutton, Ralf Karge, David Hewson, Wim Michiels, and Gene Weber.
Some of the people who have provided ideas and feedback for Verilator 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, Baxter, Jeremy Bennett, David Black, Gregg Bouchard, Christopher Boumenot,
Byron Bradley, Bryan Brady, Lane Brooks, John Brownlee, Lawrence Butcher, Nick Bowler, Byron Bradley, Bryan Brady, Lane Brooks, John Brownlee,
Chris Candler, Lauren Carlson, Donal Casey, Robert A. Clark, Allan Lawrence Butcher, Chris Candler, Lauren Carlson, Donal Casey, Terry Chen,
Cochrane, Gunter Dannoritzer, Bernard Deadman, John Deroo, John Dickol, Robert A. Clark, Allan Cochrane, Gunter Dannoritzer, Ashutosh Das, Bernard
Danny Ding, Alex Duller, Jeff Dutton, Robert Farrell, Eugen Fekete, Andrea Deadman, John Deroo, John Dickol, Danny Ding, Ivan Djordjevic, Alex Duller,
Foletto, Bob Fredieu, Shankar Giri, Sam Gladstone, Chitlesh Goorah, Thomas Jeff Dutton, Chandan Egbert, Joe Eiler, Ahmed El-Mahmoudy, Robert Farrell,
Hawkins, David Hewson, Jae Hossell, Ben Jackson, Mike Kagen, Guy-Armand Eugen Fekete, Andrea Foletto, Bob Fredieu, Shankar Giri, Sam Gladstone,
Kamendje, Vasu Kandadi, Patricio Kaplan, Ralf Karge, Dan Katz, Sol Katzman, Amir Gonnen, Chitlesh Goorah, Neil Hamilton, Thomas Hawkins, David Hewson,
Jonathan Kimmitt, Gernot Koch, Soon Koh, Steve Kolecki, Steve Lang, Jae Hossell, Ben Jackson, Iztok Jeras, Mike Kagen, Guy-Armand Kamendje,
Stephane Laurent, Charlie Lind, Dan Lussier, Fred Ma, Duraid Madina, Mark Vasu Kandadi, Patricio Kaplan, Ralf Karge, Dan Katz, Sol Katzman, Jonathan
Marshall, Wim Michiels, Dennis Muhlestein, John Murphy, Richard Myers, Kimmitt, Gernot Koch, Soon Koh, Steve Kolecki, Steve Lang, Stephane
Dimitris Nalbantis, Paul Nitza, Pete Nixon, Lisa Noack, Mark Nodine, Laurent, Christian Leber, Charlie Lind, Paul Liu, Dan Lussier, Fred Ma,
Andreas Olofsson, Niranjan Prabhu, Oleg Rodionov, John Sanguinetti, Mike Duraid Madina, Mark Marshall, Jason McMullan, Wim Michiels, Dennis
Shinkarovsky, Rafael Shirakawa, Rodney Sinclair, Brian Small, Art Stamness, Muhlestein, John Murphy, Richard Myers, Dimitris Nalbantis, Paul Nitza,
John Stroebel, Emerson Suguimoto, Renga Sundararajan, Stefan Thiede, Gary Pete Nixon, Lisa Noack, Mark Nodine, Andreas Olofsson, Brad Parker, Dominic
Thomas, Steve Tong, Holger Waechtler, Shawn Wang, Greg Waters, Eugene Plunkett, Niranjan Prabhu, Usha Priyadharshini, Oleg Rodionov, John
Weber, Leon Wildman, Gerald Williams, Jeff Winston, Johan Wouters, and Ding Sanguinetti, Salman Sheikh, Mike Shinkarovsky, Rafael Shirakawa, Jeffrey
Xiaoliang. 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. Thanks all.
+53 -12
View File
@@ -26,7 +26,6 @@
#define _VERILATED_CPP_ #define _VERILATED_CPP_
#include "verilated_imp.h" #include "verilated_imp.h"
#include <cctype> #include <cctype>
#include <vector>
#define VL_VALUE_STRING_MAX_WIDTH 1024 ///< Max static char array for VL_VALUE_STRING #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 // Note also assumes variables < 64 are not wide, this assumption is
// sometimes not true in low-level routines written here in verilated.cpp // 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 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 inPct = false;
bool widthSet = false; bool widthSet = false;
int width = 0; int width = 0;
const char* pos = formatp; const char* pos = formatp;
for (; *pos; ++pos) { for (; *pos; ++pos) {
if (!inPct && pos[0]=='%') { if (!inPct && pos[0]=='%') {
pctp = pos;
inPct = true; inPct = true;
widthSet = false; widthSet = false;
width = 0; width = 0;
@@ -312,6 +314,9 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
widthSet = true; widthSet = true;
width = width*10 + (fmt - '0'); width = width*10 + (fmt - '0');
break; break;
case '.':
inPct = true; // Get more digits
break;
case '%': case '%':
output += '%'; output += '%';
break; break;
@@ -325,6 +330,16 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
output += cstrp; output += cstrp;
break; 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: { default: {
// Deal with all read-and-print somethings // Deal with all read-and-print somethings
const int lbits = va_arg(ap, int); 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 case 'd': { // Signed decimal
int digits=sprintf(tmp,"%" VL_PRI64 "d",(vlsint64_t)(VL_EXTENDS_QQ(lbits,lbits,ld))); int digits=sprintf(tmp,"%" VL_PRI64 "d",(vlsint64_t)(VL_EXTENDS_QQ(lbits,lbits,ld)));
int needmore = width-digits; 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; output += tmp;
break; break;
} }
case 'u': { // Unsigned decimal case 'u': { // Unsigned decimal
int digits=sprintf(tmp,"%" VL_PRI64 "u",ld); int digits=sprintf(tmp,"%" VL_PRI64 "u",ld);
int needmore = width-digits; 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; output += tmp;
break; break;
} }
@@ -628,6 +655,10 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
//=========================================================================== //===========================================================================
// File I/O // 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) { void _VL_VINT_TO_STRING(int obits, char* destoutp, WDataInP sourcep) {
// See also VL_DATA_TO_STRING_NW // See also VL_DATA_TO_STRING_NW
int lsb=obits-1; 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; } for (; i<bytes; i++) { *op++ = 0; }
} }
IData VL_FGETS_IXQ(int obits, void* destp, QData fpq) { IData VL_FGETS_IXI(int obits, void* destp, IData fpi) {
FILE* fp = VL_CVT_Q_FP(fpq); FILE* fp = VL_CVT_I_FP(fpi);
if (VL_UNLIKELY(!fp)) return 0; if (VL_UNLIKELY(!fp)) return 0;
// The string needs to be padded with 0's in unused spaces in front of // 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; 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); IData fnw[2]; VL_SET_WQ(fnw, filename);
return VL_FOPEN_WI(2, fnw, mode); 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]; char filenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1];
_VL_VINT_TO_STRING(fnwords*VL_WORDSIZE, filenamez, filenamep); _VL_VINT_TO_STRING(fnwords*VL_WORDSIZE, filenamez, filenamep);
char modez[5]; char modez[5];
_VL_VINT_TO_STRING(VL_WORDSIZE, modez, &mode); _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, ...) { 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()); VL_PRINTF("%s", output.c_str());
} }
void VL_FWRITEF(QData fpq, const char* formatp, ...) { void VL_FWRITEF(IData fpi, const char* formatp, ...) {
FILE* fp = VL_CVT_Q_FP(fpq); FILE* fp = VL_CVT_I_FP(fpi);
if (VL_UNLIKELY(!fp)) return; if (VL_UNLIKELY(!fp)) return;
va_list ap; va_list ap;
@@ -739,8 +780,8 @@ void VL_FWRITEF(QData fpq, const char* formatp, ...) {
fputs(output.c_str(), fp); fputs(output.c_str(), fp);
} }
IData VL_FSCANF_IX(QData fpq, const char* formatp, ...) { IData VL_FSCANF_IX(IData fpi, const char* formatp, ...) {
FILE* fp = VL_CVT_Q_FP(fpq); FILE* fp = VL_CVT_I_FP(fpi);
if (VL_UNLIKELY(!fp)) return 0; if (VL_UNLIKELY(!fp)) return 0;
va_list ap; va_list ap;
+39 -24
View File
@@ -35,6 +35,7 @@
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <cmath>
// <iostream> avoided to reduce compile time // <iostream> avoided to reduce compile time
// <string> avoided and instead in verilated_heavy.h to reduce compile time // <string> avoided and instead in verilated_heavy.h to reduce compile time
using namespace std; 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); extern WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, bool is_modulus);
/// File I/O /// 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 IData VL_FOPEN_S(const char* filenamep, const char* mode);
extern QData VL_FOPEN_QI(QData ofilename, IData mode); extern IData VL_FOPEN_WI(int fnwords, WDataInP ofilename, IData mode);
inline QData VL_FOPEN_II(IData ofilename, IData mode) { return VL_FOPEN_QI(ofilename,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, extern void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
WDataInP ofilename, void* memp, IData start, IData end); 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); } VL_READMEM_Q(hex, width,depth,array_lsb,fnwords, ofilename,memp,start,end); }
extern void VL_WRITEF(const char* formatp, ...); 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_IIX(int lbits, IData ld, const char* formatp, ...);
extern IData VL_SSCANF_IQX(int lbits, QData 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, ...); 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_QW(lwp) ( ((QData)(lwp[0])) | ((QData)(lwp[1])<<((QData)(VL_WORDSIZE)) ))
#define _VL_SET_QII(ld,rd) ( ((QData)(ld)<<VL_ULL(32)) | (QData)(rd) ) #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 // 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 /// 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; } 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* /// 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; } 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 // Sign extend such that if MSB set, we get ffff_ffff, else 0s
// (Requires clean input) // (Requires clean input)
@@ -402,9 +415,11 @@ void _VL_DEBUG_PRINT_W(int lbits, WDataInP iwp);
#if defined(SYSTEMC_VERSION) && (SYSTEMC_VERSION>20011000) #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_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_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 #else
# define VL_TIME_I() ((IData)(sc_time_stamp()*VL_TIME_MULTIPLIER)) # 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_Q() ((QData)(sc_time_stamp()*VL_TIME_MULTIPLIER))
# define VL_TIME_D() ((double)(sc_time_stamp()*VL_TIME_MULTIPLIER))
extern double sc_time_stamp(); extern double sc_time_stamp();
#endif #endif
@@ -947,11 +962,11 @@ static inline WDataOutP VL_SUB_W(int words, WDataOutP owp,WDataInP lwp,WDataInP
// Optimization bug in GCC 2.96 and presumably all-pre GCC 3 versions need this workaround, // Optimization bug in GCC 2.96 and presumably all-pre GCC 3 versions need this workaround,
// we can't just // we can't just
//# define VL_UNARYMIN_I(data) (-(data)) //# define VL_NEGATE_I(data) (-(data))
static inline IData VL_UNARYMIN_I(IData data) { return -data; } static inline IData VL_NEGATE_I(IData data) { return -data; }
static inline QData VL_UNARYMIN_Q(QData 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; QData carry = 0;
for (int i=0; i<words; i++) { for (int i=0; i<words; i++) {
carry = carry + (QData)(IData)(~lwp[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]); IData lneg = VL_SIGN_I(lbits,lwp[words-1]);
if (lneg) { // Negate lhs if (lneg) { // Negate lhs
lwusp = lwstore; lwusp = lwstore;
VL_UNARYMIN_W(words, lwstore, lwp); VL_NEGATE_W(words, lwstore, lwp);
lwstore[words-1] &= VL_MASK_I(lbits); // Clean it lwstore[words-1] &= VL_MASK_I(lbits); // Clean it
} }
IData rneg = VL_SIGN_I(lbits,rwp[words-1]); IData rneg = VL_SIGN_I(lbits,rwp[words-1]);
if (rneg) { // Negate rhs if (rneg) { // Negate rhs
rwusp = rwstore; rwusp = rwstore;
VL_UNARYMIN_W(words, rwstore, rwp); VL_NEGATE_W(words, rwstore, rwp);
rwstore[words-1] &= VL_MASK_I(lbits); // Clean it rwstore[words-1] &= VL_MASK_I(lbits); // Clean it
} }
VL_MUL_W(words,owp,lwusp,rwusp); 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 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; QData carry = 0;
for (int i=0; i<words; i++) { for (int i=0; i<words; i++) {
carry = carry + (QData)(IData)(~owp[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]; IData rwstore[VL_MULS_MAX_WORDS];
WDataInP ltup = lwp; WDataInP ltup = lwp;
WDataInP rtup = rwp; WDataInP rtup = rwp;
if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), lwstore, lwp)); } 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_UNARYMIN_W(VL_WORDS_I(lbits), rwstore, rwp)); } if (rsign) { rtup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), rwstore, rwp)); }
if ((lsign && !rsign) || (!lsign && rsign)) { if ((lsign && !rsign) || (!lsign && rsign)) {
IData qNoSign[VL_MULS_MAX_WORDS]; IData qNoSign[VL_MULS_MAX_WORDS];
VL_DIV_WWW(lbits,qNoSign,ltup,rtup); 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; return owp;
} else { } else {
return VL_DIV_WWW(lbits,owp,ltup,rtup); 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]; IData rwstore[VL_MULS_MAX_WORDS];
WDataInP ltup = lwp; WDataInP ltup = lwp;
WDataInP rtup = rwp; WDataInP rtup = rwp;
if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), lwstore, lwp)); } 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_UNARYMIN_W(VL_WORDS_I(lbits), rwstore, rwp)); } 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 if (lsign) { // Only dividend sign matters for modulus
IData qNoSign[VL_MULS_MAX_WORDS]; IData qNoSign[VL_MULS_MAX_WORDS];
VL_MODDIV_WWW(lbits,qNoSign,ltup,rtup); 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; return owp;
} else { } else {
return VL_MODDIV_WWW(lbits,owp,ltup,rtup); 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 #undef _END
// Debugging //======================================================================
#endif /*_VERILATED_H_*/ #endif /*_VERILATED_H_*/
+4
View File
@@ -116,6 +116,10 @@ ifeq ($(VM_SP),1)
$(SP_PREPROC) -M sp_preproc.d --tree $(VM_PREFIX).sp_tree \ $(SP_PREPROC) -M sp_preproc.d --tree $(VM_PREFIX).sp_tree \
--preproc $(VK_CLASSES_SP) --preproc $(VK_CLASSES_SP)
else else
ifeq ($(VM_COVERAGE),1)
CPPFLAGS += -I$(SYSTEMPERL_INCLUDE)
VPATH += $(SYSTEMPERL_INCLUDE)
endif
preproc: preproc:
endif endif
+2 -6
View File
@@ -27,11 +27,7 @@
`define coverage_block_off `define coverage_block_off
`endif `endif
// Hide file descriptor difference // Hide file descriptor difference - deprecated - for older versions
`ifdef verilator `define verilator_file_descriptor integer
`define verilator_file_descriptor reg [63:0]
`else
`define verilator_file_descriptor integer
`endif
`endif // guard `endif // guard
+1
View File
@@ -25,6 +25,7 @@
#define _VERILATED_DPI_CPP_ #define _VERILATED_DPI_CPP_
#include "verilatedos.h" #include "verilatedos.h"
#include "verilated_dpi.h"
#include "verilated_imp.h" #include "verilated_imp.h"
// On MSVC++ we need svdpi.h to declare exports, not imports // On MSVC++ we need svdpi.h to declare exports, not imports
+64
View File
@@ -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_
+39 -1
View File
@@ -35,6 +35,7 @@
#include <map> #include <map>
#include <vector> #include <vector>
#include <deque>
#include <string> #include <string>
class VerilatedScope; class VerilatedScope;
@@ -62,9 +63,18 @@ class VerilatedImp {
ExportNameMap m_exportMap; ///< Map of <export_func_proto, func number> ExportNameMap m_exportMap; ///< Map of <export_func_proto, func number>
int m_exportNext; ///< Next export funcnum 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 public: // But only for verilated*.cpp
// CONSTRUCTORS // 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() {} ~VerilatedImp() {}
// METHODS - arguments // 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 // 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. // 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 #endif // Guard
+40 -20
View File
@@ -95,9 +95,12 @@ typedef PLI_INT32 (*VerilatedPliCb)(struct t_cb_data *);
class VerilatedVpioCb : public VerilatedVpio { class VerilatedVpioCb : public VerilatedVpio {
t_cb_data m_cbData; t_cb_data m_cbData;
s_vpi_value m_value;
QData m_time; QData m_time;
public: public:
VerilatedVpioCb(const t_cb_data* cbDatap, QData time) : m_cbData(*cbDatap), m_time(time) {} VerilatedVpioCb(const t_cb_data* cbDatap, QData time) : m_cbData(*cbDatap), m_time(time) {
m_cbData.value = &m_value;
}
virtual ~VerilatedVpioCb() {} virtual ~VerilatedVpioCb() {}
static inline VerilatedVpioCb* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioCb*>((VerilatedVpio*)h); } static inline VerilatedVpioCb* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioCb*>((VerilatedVpio*)h); }
vluint32_t reason() const { return m_cbData.reason; } vluint32_t reason() const { return m_cbData.reason; }
@@ -326,6 +329,7 @@ public:
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: value_callback %p %s v[0]=%d\n", VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: value_callback %p %s v[0]=%d\n",
vop,varop->fullname(), *((CData*)newDatap));); vop,varop->fullname(), *((CData*)newDatap)););
memcpy(prevDatap, newDatap, varop->entSize()); memcpy(prevDatap, newDatap, varop->entSize());
vpi_get_value(vop->cb_datap()->obj, vop->cb_datap()->value);
(vop->cb_rtnp()) (vop->cb_datap()); (vop->cb_rtnp()) (vop->cb_datap());
} }
} }
@@ -735,19 +739,26 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
// I/O routines // I/O routines
//-PLI_UINT32 vpi_mcd_open(PLI_BYTE8 *fileName) { PLI_UINT32 vpi_mcd_open(PLI_BYTE8 *filenamep) {
//- _VL_VPI_UNIMP(); return 0; return VL_FOPEN_S(filenamep,"wb");
//-} }
//-PLI_UINT32 vpi_mcd_close(PLI_UINT32 mcd) {
//- _VL_VPI_UNIMP(); return 0; PLI_UINT32 vpi_mcd_close(PLI_UINT32 mcd) {
//-} VL_FCLOSE_I(mcd); return 0;
//-PLI_BYTE8 *vpi_mcd_name(PLI_UINT32 cd) { }
//- _VL_VPI_UNIMP(); return 0;
//-} //-PLI_BYTE8 *vpi_mcd_name(PLI_UINT32 mcd) {
//-PLI_INT32 vpi_mcd_printf(PLI_UINT32 mcd, PLI_BYTE8 *format, ...) {
//- _VL_VPI_UNIMP(); return 0; //- _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, ...) { PLI_INT32 vpi_printf(PLI_BYTE8 *formatp, ...) {
va_list ap; va_list ap;
va_start(ap,formatp); va_start(ap,formatp);
@@ -760,15 +771,24 @@ PLI_INT32 vpi_vprintf(PLI_BYTE8* formatp, va_list ap) {
return VL_VPRINTF(formatp, ap); return VL_VPRINTF(formatp, ap);
} }
//-PLI_INT32 vpi_mcd_vprintf(PLI_UINT32 mcd, PLI_BYTE8 *format, va_list ap) { PLI_INT32 vpi_mcd_vprintf(PLI_UINT32 mcd, PLI_BYTE8 *format, va_list ap) {
//- _VL_VPI_UNIMP(); return 0; FILE* fp = VL_CVT_I_FP(mcd);
//-} if (VL_UNLIKELY(!fp)) return 0;
//-PLI_INT32 vpi_flush(void) { int chars = vfprintf(fp, format, ap);
//- _VL_VPI_UNIMP(); return 0; return chars;
//-} }
//-PLI_INT32 vpi_mcd_flush(PLI_UINT32 mcd) {
//- _VL_VPI_UNIMP(); return 0; 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 // utility routines
+1 -13
View File
@@ -8,21 +8,9 @@ use strict;
#====================================================================== #======================================================================
# main # main
delete $ENV{MODULE_VERSION}; eval `modulecmd perl add axiom-athdl`;
_setup_modules();
module('add','axiom-athdl');
exec('atsim',@ARGV); 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__ __END__
+1 -13
View File
@@ -8,21 +8,9 @@ use strict;
#====================================================================== #======================================================================
# main # main
delete $ENV{MODULE_VERSION}; eval `modulecmd perl add cds-ius`;
_setup_modules();
module('add','cadence-ius');
exec('iccr',@ARGV); 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__ __END__
+1 -13
View File
@@ -8,21 +8,9 @@ use strict;
#====================================================================== #======================================================================
# main # main
delete $ENV{MODULE_VERSION}; eval `modulecmd perl add cds-ius`;
_setup_modules();
module('add','cadence-ius');
exec('ncverilog',@ARGV); 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__ __END__
+1 -13
View File
@@ -8,21 +8,9 @@ use strict;
#====================================================================== #======================================================================
# main # main
delete $ENV{MODULE_VERSION}; eval `modulecmd perl add synopsys-vcs`;
_setup_modules();
module('add','synopsys-vcs');
exec('vcs',@ARGV); 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__ __END__
+1 -1
View File
@@ -256,7 +256,7 @@ sub gentree {
'TRACE' => sub { p "TRACE what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, '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 ")"; }, '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; }, '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(); }, 'VAR' => sub { p_var(); },
'VARPIN' => sub { p "VARPIN what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, 'VARPIN' => sub { p "VARPIN what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
'VARREF' => sub { a1; }, 'VARREF' => sub { a1; },
-1
View File
@@ -209,7 +209,6 @@ RAW_OBJS = \
V3PreShell.o \ V3PreShell.o \
V3Premit.o \ V3Premit.o \
V3Scope.o \ V3Scope.o \
V3Signed.o \
V3Slice.o \ V3Slice.o \
V3Split.o \ V3Split.o \
V3SplitAs.o \ V3SplitAs.o \
+5 -2
View File
@@ -74,7 +74,9 @@ void AstNode::init() {
m_clonep = NULL; m_clonep = NULL;
m_cloneCnt = 0; m_cloneCnt = 0;
// Attributes // Attributes
m_signed = false; m_numeric = (int)AstNumeric::UNSIGNED;
m_didWidth = false;
m_doingWidth = false;
m_width = 0; m_width = 0;
m_widthMin = 0; m_widthMin = 0;
m_user1p = NULL; 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,4) == "TOP.") pretty.replace(0,4,"");
if (pretty.substr(0,5) == "TOP->") pretty.replace(0,5,"");
return pretty; return pretty;
} }
@@ -872,7 +875,7 @@ bool AstNode::sameTreeIter(AstNode* node2p, bool ignNext) {
if (this==NULL || node2p==NULL) return false; if (this==NULL || node2p==NULL) return false;
if (this->type() != node2p->type() if (this->type() != node2p->type()
|| this->width() != node2p->width() || this->width() != node2p->width()
|| this->isSigned() != node2p->isSigned() || this->numeric() != node2p->numeric()
|| !this->same(node2p)) { || !this->same(node2p)) {
return false; return false;
} }
+63 -15
View File
@@ -56,6 +56,36 @@ public:
//###################################################################### //######################################################################
class AstNumeric {
public:
enum en {
UNSIGNED,
SIGNED,
DOUBLE
// Limited to 2 bits, unless change V3Ast's packing function
};
enum en m_e;
const char* ascii() const {
static const char* names[] = {
"UNSIGNED","SIGNED","DOUBLE"
};
return names[m_e];
};
inline AstNumeric () {}
inline AstNumeric (en _e) : m_e(_e) {}
explicit inline AstNumeric (int _e) : m_e(static_cast<en>(_e)) {}
operator en () const { return m_e; }
inline bool isDouble() const { return m_e==DOUBLE; }
inline bool isSigned() const { return m_e==SIGNED; }
inline bool isUnsigned() const { return m_e==UNSIGNED; }
};
inline bool operator== (AstNumeric lhs, AstNumeric rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator== (AstNumeric lhs, AstNumeric::en rhs) { return (lhs.m_e == rhs); }
inline bool operator== (AstNumeric::en lhs, AstNumeric rhs) { return (lhs == rhs.m_e); }
inline ostream& operator<<(ostream& os, AstNumeric rhs) { return os<<rhs.ascii(); }
//######################################################################
class AstPragmaType { class AstPragmaType {
public: public:
enum en { enum en {
@@ -209,7 +239,7 @@ class AstBasicDTypeKwd {
public: public:
enum en { enum en {
BIT, BYTE, CHANDLE, INT, INTEGER, LOGIC, LONGINT, BIT, BYTE, CHANDLE, INT, INTEGER, LOGIC, LONGINT,
REAL, REALTIME, SHORTINT, SHORTREAL, TIME, DOUBLE, SHORTINT, FLOAT, TIME,
// Closer to a class type, but limited usage // Closer to a class type, but limited usage
STRING, STRING,
// Internal types for mid-steps // Internal types for mid-steps
@@ -221,7 +251,7 @@ public:
const char* ascii() const { const char* ascii() const {
static const char* names[] = { static const char* names[] = {
"bit", "byte", "chandle", "int", "integer", "logic", "longint", "bit", "byte", "chandle", "int", "integer", "logic", "longint",
"real", "realtime", "shortint", "shortreal", "time", "real", "shortint", "shortreal", "time",
"string", "string",
"VerilatedScope*", "char*", "VerilatedScope*", "char*",
"LOGIC_IMPLICIT" "LOGIC_IMPLICIT"
@@ -231,7 +261,7 @@ public:
const char* dpiType() const { const char* dpiType() const {
static const char* names[] = { static const char* names[] = {
"unsigned char", "char", "void*", "int", "int", "svLogic", "long long", "unsigned char", "char", "void*", "int", "int", "svLogic", "long long",
"double", "double", "short int", "float", "long long", "double", "short int", "float", "long long",
"const char*", "const char*",
"dpiScope", "const char*", "dpiScope", "const char*",
"" ""
@@ -251,6 +281,8 @@ public:
case INTEGER: return 32; case INTEGER: return 32;
case LOGIC: return 1; case LOGIC: return 1;
case LONGINT: return 64; case LONGINT: return 64;
case DOUBLE: return 64;
case FLOAT: return 32;
case SHORTINT: return 16; case SHORTINT: return 16;
case TIME: return 64; case TIME: return 64;
case STRING: return 64; // Just the pointer, for today case STRING: return 64; // Just the pointer, for today
@@ -265,7 +297,7 @@ public:
} }
bool isZeroInit() const { // Otherwise initializes to X 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 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 bool isSloppy() const { // Don't be as anal about width warnings
return !(m_e==LOGIC || m_e==BIT); return !(m_e==LOGIC || m_e==BIT);
@@ -274,10 +306,13 @@ public:
return (m_e==LOGIC || m_e==BIT); return (m_e==LOGIC || m_e==BIT);
} }
bool isDpiUnsupported() const { 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 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); } 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 static int s_cloneCntGbl; // Count of which userp is set
// Attributes // 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 // // Space for more bools here
int m_width; // Bit width of operation int m_width; // Bit width of operation
@@ -780,6 +817,8 @@ public:
static int instrCountLd() { return 2; } ///< Instruction cycles to load memory static int instrCountLd() { return 2; } ///< Instruction cycles to load memory
static int instrCountMul() { return 3; } ///< Instruction cycles to multiply integers static int instrCountMul() { return 3; } ///< Instruction cycles to multiply integers
static int instrCountPli() { return 20; } ///< Instruction cycles to call pli routines 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 instrCountCall() { return instrCountBranch()+10; } ///< Instruction cycles to call subroutine
static int instrCountTime() { return instrCountCall()+5; } ///< Instruction cycles to determine simulation time 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; } bool widthSized() const { return !m_widthMin || m_widthMin==m_width; }
void width(int width, int sized) { m_width=width; m_widthMin=sized; } 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 widthFrom(AstNode* fromp) { if (fromp) { m_width=fromp->m_width; m_widthMin=fromp->m_widthMin; }}
void widthSignedFrom(AstNode* fromp) { widthFrom(fromp); signedFrom(fromp); } void widthSignedFrom(AstNode* fromp) { widthFrom(fromp); numericFrom(fromp); }
void signedFrom(AstNode* fromp) { if (fromp) { m_signed=fromp->m_signed; }} void numericFrom(AstNode* fromp) { numeric(fromp->numeric()); }
void isSigned(bool flag) { m_signed=flag; } void numeric(AstNumeric flag) { m_numeric = (int)flag; if (flag.isDouble()) width(64,64); }
bool isSigned() const { return m_signed; } 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 isQuad() const { return (width()>VL_WORDSIZE && width()<=VL_QUADSIZE); }
bool isWide() const { return (width()>VL_QUADSIZE); } bool isWide() const { return (width()>VL_QUADSIZE); }
@@ -976,10 +1023,13 @@ struct AstNodeUniop : public AstNodeMath {
setOp1p(lhsp); } setOp1p(lhsp); }
ASTNODE_BASE_FUNCS(NodeUniop) ASTNODE_BASE_FUNCS(NodeUniop)
AstNode* lhsp() const { return op1p()->castNode(); } AstNode* lhsp() const { return op1p()->castNode(); }
void lhsp(AstNode* nodep) { return setOp1p(nodep); }
// METHODS // METHODS
virtual void numberOperate(V3Number& out, const V3Number& lhs) = 0; // Set out to evaluation of a AstConst'ed lhs virtual void numberOperate(V3Number& out, const V3Number& lhs) = 0; // Set out to evaluation of a AstConst'ed lhs
virtual bool cleanLhs() = 0; virtual bool cleanLhs() = 0;
virtual bool sizeMattersLhs() = 0; // True if output result depends on lhs size 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 int instrCount() const { return widthInstrs(); }
virtual V3Hash sameHash() const { return V3Hash(); } virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(AstNode*) const { return true; } 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 sizeMattersLhs() = 0; // True if output result depends on lhs size
virtual bool sizeMattersRhs() = 0; // True if output result depends on rhs 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 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 int instrCount() const { return widthInstrs(); }
virtual V3Hash sameHash() const { return V3Hash(); } virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(AstNode*) const { return true; } virtual bool same(AstNode*) const { return true; }
@@ -1274,7 +1325,6 @@ private:
string m_name; // Name of task string m_name; // Name of task
string m_cname; // Name of task if DPI import string m_cname; // Name of task if DPI import
bool m_taskPublic:1; // Public task 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_attrIsolateAssign:1;// User isolate_assignments attribute
bool m_prototype:1; // Just a prototype bool m_prototype:1; // Just a prototype
bool m_dpiExport:1; // DPI exported bool m_dpiExport:1; // DPI exported
@@ -1285,7 +1335,7 @@ private:
public: public:
AstNodeFTask(FileLine* fileline, const string& name, AstNode* stmtsp) AstNodeFTask(FileLine* fileline, const string& name, AstNode* stmtsp)
: AstNode(fileline) : AstNode(fileline)
, m_name(name), m_taskPublic(false), m_didSigning(false) , m_name(name), m_taskPublic(false)
, m_attrIsolateAssign(false), m_prototype(false) , m_attrIsolateAssign(false), m_prototype(false)
, m_dpiExport(false), m_dpiImport(false), m_dpiContext(false) , m_dpiExport(false), m_dpiImport(false), m_dpiContext(false)
, m_dpiTask(false), m_pure(false) { , m_dpiTask(false), m_pure(false) {
@@ -1312,8 +1362,6 @@ public:
void scopeNamep(AstNode* nodep) { setNOp4p(nodep); } void scopeNamep(AstNode* nodep) { setNOp4p(nodep); }
void taskPublic(bool flag) { m_taskPublic=flag; } void taskPublic(bool flag) { m_taskPublic=flag; }
bool taskPublic() const { return m_taskPublic; } 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; } void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; }
bool attrIsolateAssign() const { return m_attrIsolateAssign; } bool attrIsolateAssign() const { return m_attrIsolateAssign; }
void prototype(bool flag) { m_prototype = flag; } void prototype(bool flag) { m_prototype = flag; }
+11 -5
View File
@@ -113,6 +113,10 @@ string AstVar::vlArgType(bool named, bool forReturn) const {
arg += "const char*"; arg += "const char*";
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::SCOPEPTR) { } else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::SCOPEPTR) {
arg += "const VerilatedScope*"; arg += "const VerilatedScope*";
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::DOUBLE) {
arg += "double";
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::FLOAT) {
arg += "float";
} else if (strtype) { } else if (strtype) {
if (isInOnly()) arg += "const "; if (isInOnly()) arg += "const ";
arg += "string"; arg += "string";
@@ -185,7 +189,7 @@ string AstVar::cPubArgType(bool named, bool forReturn) const {
} else if (isWide()) { } else if (isWide()) {
arg += "uint32_t"; // []'s added later arg += "uint32_t"; // []'s added later
} else { } else {
arg += "uint64_t"; arg += "vluint64_t";
} }
if (isWide()) { if (isWide()) {
if (forReturn) v3error("Unsupported: Public functions with >64 bit outputs; make an output of a public task instead"); 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; if (forReturn) named=false;
string arg; string arg;
if (!basicp()) arg = "UNKNOWN"; if (!basicp()) arg = "UNKNOWN";
if (isWide()) v3error("Unsupported: DPI functions with vectored outputs > 32-bits");
if (basicp()->isBitLogic()) { if (basicp()->isBitLogic()) {
if (widthMin() == 1) { if (widthMin() == 1) {
arg = "unsigned char"; arg = "unsigned char";
@@ -238,7 +241,7 @@ string AstVar::scType() const {
return "uint32_t"; return "uint32_t";
} }
} else { } else {
return "uint64_t"; return "vluint64_t";
} }
} }
@@ -500,6 +503,7 @@ void AstNode::dump(ostream& os) {
<<((editCount()>=editCountLast())?"#>":">") <<((editCount()>=editCountLast())?"#>":">")
<<" {"<<dec<<fileline()->lineno()<<"}" <<" {"<<dec<<fileline()->lineno()<<"}"
<<" "<<(isSigned()?"s":"") <<" "<<(isSigned()?"s":"")
<<(isDouble()?"d":"")
<<"w"<<(widthSized()?"":"u")<<width(); <<"w"<<(widthSized()?"":"u")<<width();
if (!widthSized()) os<<"/"<<widthMin(); if (!widthSized()) os<<"/"<<widthMin();
if (name()!="") os<<" "<<AstNode::quoteName(name()); if (name()!="") os<<" "<<AstNode::quoteName(name());
@@ -522,7 +526,7 @@ void AstBasicDType::dump(ostream& str) {
str<<" ["<<keyword().ascii()<<"]"; str<<" ["<<keyword().ascii()<<"]";
if (implicit()) str<<" [IMPLICIT]"; if (implicit()) str<<" [IMPLICIT]";
} }
void AstCast::dump(ostream& str) { void AstCCast::dump(ostream& str) {
this->AstNode::dump(str); this->AstNode::dump(str);
str<<" sz"<<size(); str<<" sz"<<size();
} }
@@ -609,8 +613,10 @@ void AstVar::dump(ostream& str) {
else if (isInput()) str<<" [I]"; else if (isInput()) str<<" [I]";
else if (isOutput()) str<<" [O]"; else if (isOutput()) str<<" [O]";
} }
if (isUsedClock()) str<<" [C]"; if (isConst()) str<<" [CONST]";
if (isUsedClock()) str<<" [CLK]";
if (isSigPublic()) str<<" [P]"; if (isSigPublic()) str<<" [P]";
if (isUsedLoopIdx()) str<<" [LOOP]";
if (attrClockEn()) str<<" [aCLKEN]"; if (attrClockEn()) str<<" [aCLKEN]";
if (attrIsolateAssign()) str<<" [aISO]"; if (attrIsolateAssign()) str<<" [aISO]";
if (attrFileDescr()) str<<" [aFD]"; if (attrFileDescr()) str<<" [aFD]";
+349 -29
View File
@@ -46,19 +46,25 @@ struct AstConst : public AstNodeMath {
private: private:
V3Number m_num; // Constant value V3Number m_num; // Constant value
public: public:
class Unsized32 {}; // for creator type-overload selection
AstConst(FileLine* fl, const V3Number& num) AstConst(FileLine* fl, const V3Number& num)
:AstNodeMath(fl) :AstNodeMath(fl)
,m_num(num) { ,m_num(num) {
width(m_num.width(), m_num.sized()?0:m_num.minWidth()); 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) AstConst(FileLine* fl, uint32_t num)
:AstNodeMath(fl) :AstNodeMath(fl)
,m_num(V3Number(fl,32,num)) { width(m_num.width(), m_num.sized()?0:m_num.minWidth()); } ,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 AstConst(FileLine* fl, Unsized32, uint32_t num) // Unsized 32-bit integer of specified value
:AstNodeMath(fl) :AstNodeMath(fl)
,m_num(V3Number(fl,32,num)) { m_num.width(32,false); width(32,m_num.minWidth()); } ,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 {}; class LogicFalse {};
AstConst(FileLine* fl, LogicFalse) // Shorthand const 0, know the dtype should be a logic of size 1 AstConst(FileLine* fl, LogicFalse) // Shorthand const 0, know the dtype should be a logic of size 1
:AstNodeMath(fl) :AstNodeMath(fl)
@@ -258,7 +264,8 @@ private:
m_keyword = AstBasicDTypeKwd::LOGIC; m_keyword = AstBasicDTypeKwd::LOGIC;
} }
if (signst == signedst_NOP && keyword().isSigned()) signst = signedst_SIGNED; 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 if (!rangep) { // Set based on keyword properties
// V3Width will pull from this width // V3Width will pull from this width
if (keyword().width() > 1 && !isOpaque()) rangep = new AstRange(fileline(), keyword().width()-1, 0); 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 AstRange* rangep() const { return op1p()->castRange(); } // op1 = Range of variable
void rangep(AstRange* nodep) { setNOp1p(nodep); } void rangep(AstRange* nodep) { setNOp1p(nodep); }
void setSignedState(AstSignedState signst) { 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 // METHODS
virtual AstBasicDType* basicp() const { return (AstBasicDType*)this; } // (Slow) recurse down to find basic data type 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; } 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 { struct AstRefDType : public AstNodeDType {
private: private:
AstTypedef* m_defp; AstTypedef* m_defp;
@@ -364,9 +391,10 @@ public:
struct AstEnumItemRef : public AstNodeMath { struct AstEnumItemRef : public AstNodeMath {
private: private:
AstEnumItem* m_itemp; // [AfterLink] Pointer to item AstEnumItem* m_itemp; // [AfterLink] Pointer to item
AstPackage* m_packagep; // Package hierarchy
public: public:
AstEnumItemRef(FileLine* fl, AstEnumItem* itemp) AstEnumItemRef(FileLine* fl, AstEnumItem* itemp, AstPackage* packagep)
: AstNodeMath(fl), m_itemp(itemp) { : AstNodeMath(fl), m_itemp(itemp), m_packagep(packagep) {
if (m_itemp) widthSignedFrom(m_itemp); if (m_itemp) widthSignedFrom(m_itemp);
} }
ASTNODE_NODE_FUNCS(EnumItemRef, ENUMITEMREF) ASTNODE_NODE_FUNCS(EnumItemRef, ENUMITEMREF)
@@ -381,6 +409,8 @@ public:
virtual string emitVerilog() { V3ERROR_NA; return ""; } // Implemented specially virtual string emitVerilog() { V3ERROR_NA; return ""; } // Implemented specially
virtual string emitC() { V3ERROR_NA; return ""; } virtual string emitC() { V3ERROR_NA; return ""; }
virtual bool cleanOut() { return true; } virtual bool cleanOut() { return true; }
AstPackage* packagep() const { return m_packagep; }
void packagep(AstPackage* nodep) { m_packagep=nodep; }
}; };
struct AstEnumDType : public AstNodeDType { struct AstEnumDType : public AstNodeDType {
@@ -582,6 +612,7 @@ public:
init(); init();
combineType(type); setOp1p(dtypep); combineType(type); setOp1p(dtypep);
if (dtypep && dtypep->basicp()) { if (dtypep && dtypep->basicp()) {
numericFrom(dtypep);
width(dtypep->basicp()->width(), 0); width(dtypep->basicp()->width(), 0);
} else width(1, 0); } else width(1, 0);
} }
@@ -601,6 +632,7 @@ public:
if (examplep->dtypep()) { if (examplep->dtypep()) {
setOp1p(examplep->dtypep()->cloneTree(true)); setOp1p(examplep->dtypep()->cloneTree(true));
} }
numericFrom(examplep);
width(examplep->width(), examplep->widthMin()); width(examplep->width(), examplep->widthMin());
} }
ASTNODE_NODE_FUNCS(Var, VAR) ASTNODE_NODE_FUNCS(Var, VAR)
@@ -667,7 +699,7 @@ public:
bool isToggleCoverable() const { return ((isIO() || isSignal()) bool isToggleCoverable() const { return ((isIO() || isSignal())
&& (isIO() || isBitLogic()) && (isIO() || isBitLogic())
// Wrapper would otherwise duplicate wrapped module's coverage // Wrapper would otherwise duplicate wrapped module's coverage
&& !isSc() && !isPrimaryIO()); } && !isSc() && !isPrimaryIO() && !isConst()); }
bool isStatementTemp() const { return (varType()==AstVarType::STMTTEMP); } bool isStatementTemp() const { return (varType()==AstVarType::STMTTEMP); }
bool isMovableToBlock() const { return (varType()==AstVarType::BLOCKTEMP || isFuncLocal()); } bool isMovableToBlock() const { return (varType()==AstVarType::BLOCKTEMP || isFuncLocal()); }
bool isPure() const { return (varType()==AstVarType::XTEMP); } bool isPure() const { return (varType()==AstVarType::XTEMP); }
@@ -912,7 +944,9 @@ public:
,m_name(name), m_svImplicit(false) { ,m_name(name), m_svImplicit(false) {
m_pinNum = pinNum; m_pinNum = pinNum;
m_modVarp = NULL; m_modVarp = NULL;
setNOp1p(exprp); } setNOp1p(exprp);
if (exprp) widthSignedFrom(exprp);
}
ASTNODE_NODE_FUNCS(Pin, PIN) ASTNODE_NODE_FUNCS(Pin, PIN)
virtual void dump(ostream& str); virtual void dump(ostream& str);
virtual bool broken() const { return (m_modVarp && !m_modVarp->brokeExists()); } virtual bool broken() const { return (m_modVarp && !m_modVarp->brokeExists()); }
@@ -921,7 +955,7 @@ public:
bool dotStar() const { return name() == ".*"; } // Special fake name for .* connections until linked bool dotStar() const { return name() == ".*"; } // Special fake name for .* connections until linked
int pinNum() const { return m_pinNum; } int pinNum() const { return m_pinNum; }
void exprp(AstNode* nodep) { addOp1p(nodep); } 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 AstVar* modVarp() const { return m_modVarp; } // [After Link] Pointer to variable
void modVarp(AstVar* varp) { m_modVarp=varp; } void modVarp(AstVar* varp) { m_modVarp=varp; }
bool svImplicit() const { return m_svImplicit; } bool svImplicit() const { return m_svImplicit; }
@@ -1423,6 +1457,15 @@ struct AstCondBound : public AstNodeCond {
ASTNODE_NODE_FUNCS(CondBound, CONDBOUND) 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 { struct AstCoverDecl : public AstNodeStmt {
// Coverage analysis point declaration // Coverage analysis point declaration
// Parents: {statement list} // Parents: {statement list}
@@ -1593,7 +1636,7 @@ public:
void ignoreOverlap(bool flag) { m_ignoreOverlap = flag; } 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 // Convert format to string, generally under a AstDisplay or AstSFormat
// Also used as "real" function for /*verilator sformat*/ functions // Also used as "real" function for /*verilator sformat*/ functions
string m_text; string m_text;
@@ -1961,6 +2004,18 @@ struct AstContinue : public AstNodeStmt {
virtual bool isSplittable() const { return false; } // SPECIAL: We don't process code after breaks 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 { struct AstReturn : public AstNodeStmt {
AstReturn(FileLine* fileline, AstNode* lhsp=NULL) AstReturn(FileLine* fileline, AstNode* lhsp=NULL)
: AstNodeStmt (fileline) { : AstNodeStmt (fileline) {
@@ -2404,6 +2459,20 @@ struct AstTime : public AstNodeTermop {
virtual bool same(AstNode* samep) const { return true; } 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 { struct AstUCFunc : public AstNodeMath {
// User's $c function // User's $c function
// Perhaps this should be a AstNodeListop; but there's only one list math right now // Perhaps this should be a AstNodeListop; but there's only one list math right now
@@ -2429,19 +2498,32 @@ struct AstUCFunc : public AstNodeMath {
//====================================================================== //======================================================================
// Unary ops // Unary ops
struct AstUnaryMin : public AstNodeUniop { struct AstNegate : public AstNodeUniop {
AstUnaryMin(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) { AstNegate(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
if (lhsp) widthSignedFrom(lhsp); } if (lhsp) widthSignedFrom(lhsp); }
ASTNODE_NODE_FUNCS(UnaryMin, UNARYMIN) ASTNODE_NODE_FUNCS(Negate, NEGATE)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opUnaryMin(lhs); } virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opNegate(lhs); }
virtual string emitVerilog() { return "%f(- %l)"; } 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 cleanOut() {return false;} virtual bool cleanLhs() {return false;}
virtual bool sizeMattersLhs() {return true;} 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 { struct AstRedAnd : public AstNodeUniop {
AstRedAnd(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) { AstRedAnd(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
width(1,1); } width(1,1); numeric(AstNumeric::UNSIGNED); }
ASTNODE_NODE_FUNCS(RedAnd, REDAND) ASTNODE_NODE_FUNCS(RedAnd, REDAND)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedAnd(lhs); } virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedAnd(lhs); }
virtual string emitVerilog() { return "%f(& %l)"; } virtual string emitVerilog() { return "%f(& %l)"; }
@@ -2451,7 +2533,7 @@ struct AstRedAnd : public AstNodeUniop {
}; };
struct AstRedOr : public AstNodeUniop { struct AstRedOr : public AstNodeUniop {
AstRedOr(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) { AstRedOr(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
width(1,1); } width(1,1); numeric(AstNumeric::UNSIGNED); }
ASTNODE_NODE_FUNCS(RedOr, REDOR) ASTNODE_NODE_FUNCS(RedOr, REDOR)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedOr(lhs); } virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedOr(lhs); }
virtual string emitVerilog() { return "%f(| %l)"; } virtual string emitVerilog() { return "%f(| %l)"; }
@@ -2461,7 +2543,7 @@ struct AstRedOr : public AstNodeUniop {
}; };
struct AstRedXor : public AstNodeUniop { struct AstRedXor : public AstNodeUniop {
AstRedXor(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) { AstRedXor(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
width(1,1); } width(1,1); numeric(AstNumeric::UNSIGNED); }
ASTNODE_NODE_FUNCS(RedXor, REDXOR) ASTNODE_NODE_FUNCS(RedXor, REDXOR)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedXor(lhs); } virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedXor(lhs); }
virtual string emitVerilog() { return "%f(^ %l)"; } virtual string emitVerilog() { return "%f(^ %l)"; }
@@ -2475,7 +2557,7 @@ struct AstRedXor : public AstNodeUniop {
struct AstRedXnor : public AstNodeUniop { struct AstRedXnor : public AstNodeUniop {
// AstRedXnors are replaced with AstRedXors in V3Const. // AstRedXnors are replaced with AstRedXors in V3Const.
AstRedXnor(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) { AstRedXnor(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
width(1,1); } width(1,1); numeric(AstNumeric::UNSIGNED); }
ASTNODE_NODE_FUNCS(RedXnor, REDXNOR) ASTNODE_NODE_FUNCS(RedXnor, REDXNOR)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedXnor(lhs); } virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedXnor(lhs); }
virtual string emitVerilog() { return "%f(~^ %l)"; } virtual string emitVerilog() { return "%f(~^ %l)"; }
@@ -2533,7 +2615,7 @@ struct AstExtendS : public AstNodeUniop {
struct AstSigned : public AstNodeUniop { struct AstSigned : public AstNodeUniop {
// $signed(lhs) // $signed(lhs)
AstSigned(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) { AstSigned(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
isSigned(true); numeric(AstNumeric::SIGNED);
} }
ASTNODE_NODE_FUNCS(Signed, SIGNED) ASTNODE_NODE_FUNCS(Signed, SIGNED)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); out.isSigned(false); } virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); out.isSigned(false); }
@@ -2546,7 +2628,7 @@ struct AstSigned : public AstNodeUniop {
struct AstUnsigned : public AstNodeUniop { struct AstUnsigned : public AstNodeUniop {
// $unsigned(lhs) // $unsigned(lhs)
AstUnsigned(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) { AstUnsigned(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
isSigned(false); numeric(AstNumeric::UNSIGNED);
} }
ASTNODE_NODE_FUNCS(Unsigned, UNSIGNED) ASTNODE_NODE_FUNCS(Unsigned, UNSIGNED)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); out.isSigned(false); } virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); out.isSigned(false); }
@@ -2556,6 +2638,63 @@ struct AstUnsigned : public AstNodeUniop {
virtual bool sizeMattersLhs() {return true;} // Eliminated before matters virtual bool sizeMattersLhs() {return true;} // Eliminated before matters
virtual int instrCount() const { return 0; } 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 { struct AstCLog2 : public AstNodeUniop {
AstCLog2(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {} AstCLog2(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(CLog2, CLOG2) ASTNODE_NODE_FUNCS(CLog2, CLOG2)
@@ -2613,27 +2752,42 @@ struct AstOneHot0 : public AstNodeUniop {
virtual int instrCount() const { return widthInstrs()*3; } virtual int instrCount() const { return widthInstrs()*3; }
}; };
struct AstCast : public AstNodeUniop { struct AstCast : public AstNode {
// Cast to appropriate data type // 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: private:
int m_size; int m_size;
public: public:
AstCast(FileLine* fl, AstNode* lhsp, int setwidth) : AstNodeUniop(fl, lhsp) { AstCCast(FileLine* fl, AstNode* lhsp, int setwidth) : AstNodeUniop(fl, lhsp) {
m_size=setwidth; m_size=setwidth;
if (setwidth) { width(setwidth,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); } if (widthFromp) { widthSignedFrom(widthFromp); }
m_size=width(); 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 void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); }
virtual string emitVerilog() { return "%f$_CAST(%l)"; } virtual string emitVerilog() { return "%f$_CAST(%l)"; }
virtual string emitC() { return "VL_CAST_%nq%lq(%nw,%lw, %P, %li)"; } virtual string emitC() { return "VL_CAST_%nq%lq(%nw,%lw, %P, %li)"; }
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return true;} virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return true;}
virtual bool sizeMattersLhs() {return false;} // Special cased in V3Cast virtual bool sizeMattersLhs() {return false;} // Special cased in V3Cast
virtual V3Hash sameHash() const { return V3Hash(size()); } 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); virtual void dump(ostream& str=cout);
// //
int size() const { return m_size; } int size() const { return m_size; }
@@ -2658,7 +2812,7 @@ struct AstFEof : public AstNodeUniop {
ASTNODE_NODE_FUNCS(FEof, FEOF) ASTNODE_NODE_FUNCS(FEof, FEOF)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { V3ERROR_NA; } virtual void numberOperate(V3Number& out, const V3Number& lhs) { V3ERROR_NA; }
virtual string emitVerilog() { return "%f$feof(%l)"; } 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 cleanOut() {return true;} virtual bool cleanLhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersLhs() {return false;}
virtual int instrCount() const { return widthInstrs()*16; } virtual int instrCount() const { return widthInstrs()*16; }
@@ -2671,7 +2825,7 @@ struct AstFGetC : public AstNodeUniop {
virtual void numberOperate(V3Number& out, const V3Number& lhs) { V3ERROR_NA; } virtual void numberOperate(V3Number& out, const V3Number& lhs) { V3ERROR_NA; }
virtual string emitVerilog() { return "%f$fgetc(%l)"; } virtual string emitVerilog() { return "%f$fgetc(%l)"; }
// Non-existent filehandle returns EOF // 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 cleanOut() {return false;} virtual bool cleanLhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersLhs() {return false;}
virtual int instrCount() const { return widthInstrs()*64; } virtual int instrCount() const { return widthInstrs()*64; }
@@ -2793,6 +2947,20 @@ struct AstEq : public AstNodeBiCom {
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;} virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;} virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
}; };
struct 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 { struct AstNeq : public AstNodeBiCom {
AstNeq(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) { AstNeq(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
width(1,1); } width(1,1); }
@@ -2805,6 +2973,20 @@ struct AstNeq : public AstNodeBiCom {
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;} virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;} virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
}; };
struct 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 { struct AstLt : public AstNodeBiop {
AstLt(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) { AstLt(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
width(1,1); } width(1,1); }
@@ -2817,6 +2999,20 @@ struct AstLt : public AstNodeBiop {
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;} virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;} virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
}; };
struct 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 { struct AstLtS : public AstNodeBiop {
AstLtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) { AstLtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
width(1,1); } width(1,1); }
@@ -2842,6 +3038,20 @@ struct AstGt : public AstNodeBiop {
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;} virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;} virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
}; };
struct 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 { struct AstGtS : public AstNodeBiop {
AstGtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) { AstGtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
width(1,1); } width(1,1); }
@@ -2867,6 +3077,20 @@ struct AstGte : public AstNodeBiop {
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;} virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;} virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
}; };
struct 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 { struct AstGteS : public AstNodeBiop {
AstGteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) { AstGteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
width(1,1); } width(1,1); }
@@ -2892,6 +3116,20 @@ struct AstLte : public AstNodeBiop {
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;} virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;} virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
}; };
struct 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 { struct AstLteS : public AstNodeBiop {
AstLteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) { AstLteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
width(1,1); } width(1,1); }
@@ -2960,6 +3198,20 @@ struct AstAdd : public AstNodeBiComAsv {
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;} virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;} 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 { struct AstSub : public AstNodeBiop {
AstSub(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) { AstSub(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
if (lhsp) widthSignedFrom(lhsp); } if (lhsp) widthSignedFrom(lhsp); }
@@ -2972,6 +3224,20 @@ struct AstSub : public AstNodeBiop {
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;} virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;} 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 { struct AstMul : public AstNodeBiComAsv {
AstMul(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) { AstMul(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
if (lhsp) widthSignedFrom(lhsp); } if (lhsp) widthSignedFrom(lhsp); }
@@ -2985,6 +3251,20 @@ struct AstMul : public AstNodeBiComAsv {
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;} virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
virtual int instrCount() const { return widthInstrs()*instrCountMul(); } 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 { struct AstMulS : public AstNodeBiComAsv {
AstMulS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) { AstMulS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
if (lhsp) widthSignedFrom(lhsp); } if (lhsp) widthSignedFrom(lhsp); }
@@ -3011,6 +3291,20 @@ struct AstDiv : public AstNodeBiop {
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;} virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
virtual int instrCount() const { return widthInstrs()*instrCountDiv(); } 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 { struct AstDivS : public AstNodeBiop {
AstDivS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) { AstDivS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
if (lhsp) widthSignedFrom(lhsp); } if (lhsp) widthSignedFrom(lhsp); }
@@ -3061,6 +3355,19 @@ struct AstPow : public AstNodeBiop {
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return false;} virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return widthInstrs()*instrCountMul(); } 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 { struct AstPowS : public AstNodeBiop {
AstPowS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) { AstPowS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
if (lhsp) widthSignedFrom(lhsp); } if (lhsp) widthSignedFrom(lhsp); }
@@ -3150,6 +3457,19 @@ struct AstReplicate : public AstNodeBiop {
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;} virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return widthInstrs()*2; } 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 { struct AstFGetS : public AstNodeBiop {
AstFGetS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {} AstFGetS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {}
ASTNODE_NODE_FUNCS(FGetS, FGETS) ASTNODE_NODE_FUNCS(FGetS, FGETS)
+1 -1
View File
@@ -162,7 +162,7 @@ private:
m_ifDepth = -1; m_ifDepth = -1;
} else if (++m_ifDepth > v3Global.opt.ifDepth()) { } else if (++m_ifDepth > v3Global.opt.ifDepth()) {
nodep->v3warn(IFDEPTH,"Deep 'if' statement; suggest unique/priority to avoid slow logic"); nodep->v3warn(IFDEPTH,"Deep 'if' statement; suggest unique/priority to avoid slow logic");
nodep->fileline()->warnOn(V3ErrorCode::IFDEPTH, false); // Warn only once nodep->fileline()->modifyWarnOff(V3ErrorCode::IFDEPTH, true); // Warn only once
m_ifDepth = -1; m_ifDepth = -1;
} }
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
+6 -2
View File
@@ -148,17 +148,19 @@ private:
bool isCaseTreeFast(AstCase* nodep) { bool isCaseTreeFast(AstCase* nodep) {
int width = 0; int width = 0;
bool opaque = false;
m_caseItems = 0; m_caseItems = 0;
m_caseNoOverlapsAllCovered = true; m_caseNoOverlapsAllCovered = true;
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) { for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) { for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) {
if (icondp->width() > width) width = icondp->width(); if (icondp->width() > width) width = icondp->width();
if (icondp->isDouble()) opaque = true;
if (!icondp->castConst()) width = CASE_BARF; // Can't parse; not a constant if (!icondp->castConst()) width = CASE_BARF; // Can't parse; not a constant
m_caseItems++; m_caseItems++;
} }
} }
m_caseWidth = width; m_caseWidth = width;
if (width==0 || width > CASE_OVERLAP_WIDTH) { if (width==0 || width > CASE_OVERLAP_WIDTH || opaque) {
m_caseNoOverlapsAllCovered = false; m_caseNoOverlapsAllCovered = false;
return false; // Too wide for analysis return false; // Too wide for analysis
} }
@@ -348,7 +350,9 @@ private:
and1p = cexprp->cloneTree(false); and1p = cexprp->cloneTree(false);
and2p = icondp; 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) { if (!ifexprp) {
ifexprp = condp; ifexprp = condp;
} else { } else {
+6 -6
View File
@@ -77,7 +77,7 @@ private:
AstNRelinker relinkHandle; AstNRelinker relinkHandle;
nodep->unlinkFrBack(&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()); castp->width(needsize, nodep->widthMin());
relinkHandle.relink(castp); relinkHandle.relink(castp);
//if (debug()>8) castp->dumpTree(cout,"-castins: "); //if (debug()>8) castp->dumpTree(cout,"-castins: ");
@@ -97,13 +97,13 @@ private:
insertCast(nodep, castSize(nodep->backp())); insertCast(nodep, castSize(nodep->backp()));
} }
} }
void insureLower32Cast(AstCast* nodep) { void insureLower32Cast(AstCCast* nodep) {
// If we have uint64 = CAST(uint64(x)) then the upcasting // If we have uint64 = CAST(uint64(x)) then the upcasting
// really needs to be CAST(uint64(CAST(uint32(x))). // really needs to be CAST(uint64(CAST(uint32(x))).
// Otherwise a (uint64)(a>b) would return wrong value, as // Otherwise a (uint64)(a>b) would return wrong value, as
// less than has undeterministic signedness. // less than has undeterministic signedness.
if (nodep->isQuad() && !nodep->lhsp()->isQuad() if (nodep->isQuad() && !nodep->lhsp()->isQuad()
&& !nodep->lhsp()->castCast()) { && !nodep->lhsp()->castCCast()) {
insertCast(nodep->lhsp(), VL_WORDSIZE); insertCast(nodep->lhsp(), VL_WORDSIZE);
} }
} }
@@ -130,12 +130,12 @@ private:
if (nodep->sizeMattersRhs()) insureCast(nodep->rhsp()); if (nodep->sizeMattersRhs()) insureCast(nodep->rhsp());
if (nodep->sizeMattersThs()) insureCast(nodep->thsp()); if (nodep->sizeMattersThs()) insureCast(nodep->thsp());
} }
virtual void visit(AstCast* nodep, AstNUser*) { virtual void visit(AstCCast* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
insureLower32Cast(nodep); insureLower32Cast(nodep);
nodep->user1(1); nodep->user1(1);
} }
virtual void visit(AstUnaryMin* nodep, AstNUser*) { virtual void visit(AstNegate* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
nodep->user1(nodep->lhsp()->user1()); nodep->user1(nodep->lhsp()->user1());
if (nodep->lhsp()->widthMin()==1) { if (nodep->lhsp()->widthMin()==1) {
@@ -149,7 +149,7 @@ private:
} }
virtual void visit(AstVarRef* nodep, AstNUser*) { virtual void visit(AstVarRef* nodep, AstNUser*) {
if (!nodep->lvalue() if (!nodep->lvalue()
&& !nodep->backp()->castCast() && !nodep->backp()->castCCast()
&& nodep->backp()->castNodeMath() && nodep->backp()->castNodeMath()
&& nodep->backp()->width() && nodep->backp()->width()
&& castSize(nodep) != castSize(nodep->varp())) { && castSize(nodep) != castSize(nodep->varp())) {
+45 -16
View File
@@ -46,6 +46,8 @@
#include "V3EmitV.h" #include "V3EmitV.h"
#include "V3File.h" #include "V3File.h"
#define CDC_WEIGHT_ASYNC 0x1000 // Weight for edges that feed async logic
//###################################################################### //######################################################################
class CdcBaseVisitor : public AstNVisitor { class CdcBaseVisitor : public AstNVisitor {
@@ -65,9 +67,9 @@ class CdcEitherVertex : public V3GraphVertex {
AstNode* m_nodep; AstNode* m_nodep;
AstSenTree* m_srcDomainp; AstSenTree* m_srcDomainp;
AstSenTree* m_dstDomainp; AstSenTree* m_dstDomainp;
bool m_srcDomainSet; bool m_srcDomainSet:1;
bool m_dstDomainSet; bool m_dstDomainSet:1;
bool m_asyncPath; bool m_asyncPath:1;
public: public:
CdcEitherVertex(V3Graph* graphp, AstScope* scopep, AstNode* nodep) CdcEitherVertex(V3Graph* graphp, AstScope* scopep, AstNode* nodep)
: V3GraphVertex(graphp), m_scopep(scopep), m_nodep(nodep) : V3GraphVertex(graphp), m_scopep(scopep), m_nodep(nodep)
@@ -109,11 +111,12 @@ public:
}; };
class CdcLogicVertex : public CdcEitherVertex { class CdcLogicVertex : public CdcEitherVertex {
bool m_hazard; bool m_hazard:1;
bool m_isFlop; bool m_isFlop:1;
public: public:
CdcLogicVertex(V3Graph* graphp, AstScope* scopep, AstNode* nodep, AstSenTree* sensenodep) 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); } { srcDomainp(sensenodep); dstDomainp(sensenodep); }
virtual ~CdcLogicVertex() {} virtual ~CdcLogicVertex() {}
// Accessors // Accessors
@@ -132,7 +135,7 @@ class CdcDumpVisitor : public CdcBaseVisitor {
private: private:
// NODE STATE // NODE STATE
//Entire netlist: //Entire netlist:
// {statement}Node::user3p -> bool, indicating not hazard // {statement}Node::user3 -> bool, indicating not hazard
ofstream* m_ofp; // Output file ofstream* m_ofp; // Output file
string m_prefix; string m_prefix;
@@ -290,9 +293,12 @@ private:
void setNodeHazard(AstNode* nodep) { void setNodeHazard(AstNode* nodep) {
// Need to not clear if warnings are off (rather than when report it) // 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. // 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_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)) { if (m_logicVertexp && !nodep->fileline()->warnIsOff(V3ErrorCode::CDCRSTLOGIC)) {
UINFO(9,"Set hazard "<<nodep<<endl); UINFO(8,"Set hazard "<<nodep<<endl);
m_logicVertexp->setHazard(nodep); m_logicVertexp->setHazard(nodep);
} }
} }
@@ -310,7 +316,9 @@ private:
UINFO(3,__FUNCTION__<<": "<<endl); UINFO(3,__FUNCTION__<<": "<<endl);
//if (debug()>6) m_graph.dump(); //if (debug()>6) m_graph.dump();
if (debug()>6) m_graph.dumpDotFilePrefixed("cdc_pre"); 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"); m_graph.dumpDotFilePrefixed("cdc_simp");
// //
analyzeReset(); analyzeReset();
@@ -335,7 +343,7 @@ private:
if (CdcVarVertex* vvertexp = dynamic_cast<CdcVarVertex*>(itp)) { if (CdcVarVertex* vvertexp = dynamic_cast<CdcVarVertex*>(itp)) {
if (vvertexp->cntAsyncRst()) { if (vvertexp->cntAsyncRst()) {
m_userGeneration++; // Effectively a userClearVertices() 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 // Twice, as we need to detect, then propagate
CdcEitherVertex* markp = traceAsyncRecurse(vvertexp, false); CdcEitherVertex* markp = traceAsyncRecurse(vvertexp, false);
if (markp) { // Mark is non-NULL if something bad on this path if (markp) { // Mark is non-NULL if something bad on this path
@@ -351,7 +359,8 @@ private:
} }
CdcEitherVertex* traceAsyncRecurse(CdcEitherVertex* vertexp, bool mark) { 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 if (vertexp->user()>=m_userGeneration) return false; // Processed - prevent loop
vertexp->user(m_userGeneration); vertexp->user(m_userGeneration);
@@ -406,12 +415,15 @@ private:
CdcEitherVertex* eToVertexp = (CdcEitherVertex*)edgep->top(); CdcEitherVertex* eToVertexp = (CdcEitherVertex*)edgep->top();
if (!eToVertexp) targetp = eToVertexp; if (!eToVertexp) targetp = eToVertexp;
if (CdcLogicVertex* vvertexp = dynamic_cast<CdcLogicVertex*>(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; targetp = eToVertexp;
//UINFO(9," targetasync "<<targetp->name()<<" "<<" from "<<vertexp->name()<<endl);
break; break;
} }
} // else it might be random logic that's not relevant } // 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()); warnAndFile(markp->nodep(),V3ErrorCode::CDCRSTLOGIC,"Logic in path that feeds async reset, via signal: "+nodep->prettyName());
dumpAsyncRecurse(targetp, "", " ",0); dumpAsyncRecurse(targetp, "", " ",0);
} }
@@ -464,6 +476,12 @@ private:
void edgeReport() { void edgeReport() {
// Make report of all signal names and what clock edges they have // 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); UINFO(3,__FUNCTION__<<": "<<endl);
// Trace all sources and sinks // Trace all sources and sinks
@@ -493,6 +511,10 @@ private:
ostringstream os; ostringstream os;
os.setf(ios::left); 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(8)<<whatp;
os<<" "<<setw(40)<<vvertexp->varScp()->prettyName(); os<<" "<<setw(40)<<vvertexp->varScp()->prettyName();
os<<" SRC="; os<<" SRC=";
@@ -613,8 +635,9 @@ private:
if (!varscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp\n"); if (!varscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp\n");
CdcVarVertex* varvertexp = makeVarVertex(varscp); CdcVarVertex* varvertexp = makeVarVertex(varscp);
UINFO(5," VARREF to "<<varscp<<endl); UINFO(5," VARREF to "<<varscp<<endl);
// We use weight of one; if we ref the var more than once, when we simplify, // We use weight of one for normal edges,
// the weight will increase // Weight of CDC_WEIGHT_ASYNC to indicate feeds async (for reporting)
// When simplify we'll take the MAX weight
if (nodep->lvalue()) { if (nodep->lvalue()) {
new V3GraphEdge(&m_graph, m_logicVertexp, varvertexp, 1); new V3GraphEdge(&m_graph, m_logicVertexp, varvertexp, 1);
if (m_inDly) { if (m_inDly) {
@@ -623,7 +646,13 @@ private:
varvertexp->srcDomainSet(true); varvertexp->srcDomainSet(true);
} }
} else { } 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); nodep->accept(*this);
analyze(); 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; } if (0) { *m_ofp<<"\nDBG-test-dumper\n"; V3EmitV::verilogPrefixedTree(nodep, *m_ofp, "DBG ",40,NULL,true); *m_ofp<<endl; }
} }
+118 -11
View File
@@ -37,7 +37,6 @@
#include "V3Const.h" #include "V3Const.h"
#include "V3Ast.h" #include "V3Ast.h"
#include "V3Width.h" #include "V3Width.h"
#include "V3Signed.h"
#include "V3Simulate.h" #include "V3Simulate.h"
//###################################################################### //######################################################################
@@ -290,13 +289,61 @@ private:
// SEL(EXTEND(any,width,...),(width-1),0) -> ... // SEL(EXTEND(any,width,...),(width-1),0) -> ...
// Since select's return unsigned, this is always an extend // Since select's return unsigned, this is always an extend
AstExtend* extendp = nodep->fromp()->castExtend(); AstExtend* extendp = nodep->fromp()->castExtend();
return (m_doV if (!(m_doV
&& extendp && extendp
&& nodep->lsbp()->castConst() && nodep->lsbp()->castConst()
&& nodep->widthp()->castConst() && nodep->widthp()->castConst()
&& nodep->lsbConst()==0 && nodep->lsbConst()==0
&& (int)nodep->widthConst()==extendp->lhsp()->width() && (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) { AstNode* afterComment(AstNode* nodep) {
@@ -1061,6 +1108,38 @@ private:
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL; 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*) { virtual void visit(AstVarRef* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (!nodep->varp()) nodep->v3fatalSrc("Not linked"); if (!nodep->varp()) nodep->v3fatalSrc("Not linked");
@@ -1439,7 +1518,7 @@ private:
if (!inPct && ch=='%') { if (!inPct && ch=='%') {
inPct = true; inPct = true;
fmt = ch; fmt = ch;
} else if (inPct && isdigit(ch)) { } else if (inPct && (isdigit(ch) || ch=='.')) {
fmt += ch; fmt += ch;
} else if (inPct) { } else if (inPct) {
inPct = false; inPct = false;
@@ -1584,7 +1663,7 @@ private:
TREEOP ("AstShiftRS{$lhsp.isZero, $rhsp}", "replaceZero(nodep)"); TREEOP ("AstShiftRS{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
TREEOP ("AstXor {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)"); TREEOP ("AstXor {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
TREEOP ("AstXnor {$lhsp.isZero, $rhsp}", "AstNot{$rhsp}"); TREEOP ("AstXnor {$lhsp.isZero, $rhsp}", "AstNot{$rhsp}");
TREEOP ("AstSub {$lhsp.isZero, $rhsp}", "AstUnaryMin{$rhsp}"); TREEOP ("AstSub {$lhsp.isZero, $rhsp}", "AstNegate{$rhsp}");
TREEOP ("AstAdd {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)"); TREEOP ("AstAdd {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
TREEOP ("AstAnd {$lhsp, $rhsp.isZero}", "replaceZero(nodep)"); TREEOP ("AstAnd {$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
TREEOP ("AstLogAnd{$lhsp, $rhsp.isZero}", "replaceZero(nodep)"); TREEOP ("AstLogAnd{$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
@@ -1684,6 +1763,13 @@ private:
TREEOP ("AstShiftL{operandShiftShift(nodep)}", "replaceShiftShift(nodep)"); TREEOP ("AstShiftL{operandShiftShift(nodep)}", "replaceShiftShift(nodep)");
TREEOP ("AstShiftR{operandShiftShift(nodep)}", "replaceShiftShift(nodep)"); TREEOP ("AstShiftR{operandShiftShift(nodep)}", "replaceShiftShift(nodep)");
TREEOP ("AstWordSel{operandWordOOB(nodep)}", "replaceZero(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 // Identical operands on both sides
// AstLogAnd/AstLogOr already converted to AstAnd/AstOr for these rules // AstLogAnd/AstLogOr already converted to AstAnd/AstOr for these rules
// AstAdd->ShiftL(#,1) but uncommon // AstAdd->ShiftL(#,1) but uncommon
@@ -1696,17 +1782,23 @@ private:
TREEOP ("AstXnor {operandsSame($lhsp,,$rhsp)}", "replaceAllOnes(nodep)"); TREEOP ("AstXnor {operandsSame($lhsp,,$rhsp)}", "replaceAllOnes(nodep)");
TREEOP ("AstXor {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstXor {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstEq {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); // We let X==X -> 1, although in a true 4-state sim it's X. TREEOP ("AstEq {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); // We let X==X -> 1, although in a true 4-state sim it's X.
TREEOP ("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 ("AstEqCase {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstEqWild {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); TREEOP ("AstEqWild {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstGt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstGt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstGtD {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstGtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstGtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstGte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); TREEOP ("AstGte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstGteD {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstGteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); TREEOP ("AstGteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstLt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstLt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstLtD {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstLtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstLtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstLte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); 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 ("AstLteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstNeq {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstNeq {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstNeqD {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstNeqCase{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstNeqCase{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstNeqWild{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstNeqWild{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstLogAnd {operandsSame($lhsp,,$rhsp), $lhsp.width1}", "replaceWLhs(nodep)"); TREEOP ("AstLogAnd {operandsSame($lhsp,,$rhsp), $lhsp.width1}", "replaceWLhs(nodep)");
@@ -1761,12 +1853,27 @@ private:
TREEOPV("AstReplicate{$lhsp, $rhsp.isOne, $lhsp->width()==nodep->width()}", "replaceWLhs(nodep)"); // {1{lhs}}->lhs TREEOPV("AstReplicate{$lhsp, $rhsp.isOne, $lhsp->width()==nodep->width()}", "replaceWLhs(nodep)"); // {1{lhs}}->lhs
// Next rule because AUTOINST puts the width of bits in // Next rule because AUTOINST puts the width of bits in
// to pins, even when the widths are exactly the same across the hierarchy. // 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{operandSelFull(nodep)}", "replaceWChild(nodep, nodep->fromp())");
TREEOPV("AstSel{$fromp.castSel}", "replaceSelSel(nodep)"); TREEOPV("AstSel{$fromp.castSel}", "replaceSelSel(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)"); TREEOPC("AstSel{$fromp.castConst, $lsbp.castConst, $widthp.castConst, }", "replaceConst(nodep)");
TREEOPV("AstSel{$fromp.castConcat, $lsbp.castConst, $widthp.castConst, }", "replaceSelConcat(nodep)"); TREEOPV("AstSel{$fromp.castConcat, $lsbp.castConst, $widthp.castConst, }", "replaceSelConcat(nodep)");
TREEOPV("AstSel{$fromp.castReplicate, $lsbp.castConst, $widthp.isOne, }", "replaceSelReplicate(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 // Conversions
TREEOPV("AstRedXnor{$lhsp}", "AstNot{AstRedXor{$lhsp}}"); // Just eliminate XNOR's TREEOPV("AstRedXnor{$lhsp}", "AstNot{AstRedXor{$lhsp}}"); // Just eliminate XNOR's
TREEOPV("AstLogIf {$lhsp, $rhsp}", "AstLogOr{AstLogNot{$lhsp},$rhsp}"); TREEOPV("AstLogIf {$lhsp, $rhsp}", "AstLogOr{AstLogNot{$lhsp},$rhsp}");
+6
View File
@@ -122,6 +122,12 @@ private:
nodep->packagep()->user1Inc(); nodep->packagep()->user1Inc();
} }
} }
virtual void visit(AstEnumItemRef* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (nodep->packagep()) {
nodep->packagep()->user1Inc();
}
}
virtual void visit(AstVarScope* nodep, AstNUser*) { virtual void visit(AstVarScope* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
m_vscsp.push_back(nodep); m_vscsp.push_back(nodep);
+1 -3
View File
@@ -345,9 +345,7 @@ private:
m_nextDlyp = NULL; m_nextDlyp = NULL;
} }
virtual void visit(AstVarRef* nodep, AstNUser*) { virtual void visit(AstVarRef* nodep, AstNUser*) {
if (!nodep->user2()) { // Not done yet if (!nodep->user2Inc()) { // Not done yet
nodep->user2(true);
if (m_inDly && nodep->lvalue()) { if (m_inDly && nodep->lvalue()) {
UINFO(4,"AssignDlyVar: "<<nodep<<endl); UINFO(4,"AssignDlyVar: "<<nodep<<endl);
markVarUsage(nodep->varScopep(), VU_DLY); markVarUsage(nodep->varScopep(), VU_DLY);
+27 -11
View File
@@ -127,6 +127,7 @@ public:
nodep->lhsp()->iterateAndNext(*this); puts(", "); nodep->lhsp()->iterateAndNext(*this); puts(", ");
} else if (nodep->isWide() } else if (nodep->isWide()
&& nodep->lhsp()->castVarRef() && nodep->lhsp()->castVarRef()
&& !nodep->rhsp()->castCMath()
&& !nodep->rhsp()->castVarRef() && !nodep->rhsp()->castVarRef()
&& !nodep->rhsp()->castArraySel()) { && !nodep->rhsp()->castArraySel()) {
// Wide functions assign into the array directly, don't need separate assign statement // Wide functions assign into the array directly, don't need separate assign statement
@@ -343,13 +344,11 @@ public:
puts(");\n"); puts(");\n");
} }
virtual void visit(AstFClose* nodep, AstNUser*) { virtual void visit(AstFClose* nodep, AstNUser*) {
puts("if ("); puts("VL_FCLOSE_I(");
nodep->filep()->iterateAndNext(*this); nodep->filep()->iterateAndNext(*this);
puts(") { fclose (VL_CVT_Q_FP("); puts("); ");
nodep->filep()->iterateAndNext(*this);
puts(")); ");
nodep->filep()->iterateAndNext(*this); // For saftey, so user doesn't later WRITE with it. 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*) { virtual void visit(AstFFlush* nodep, AstNUser*) {
if (!nodep->filep()) { if (!nodep->filep()) {
@@ -357,7 +356,7 @@ public:
} else { } else {
puts("if ("); puts("if (");
nodep->filep()->iterateAndNext(*this); nodep->filep()->iterateAndNext(*this);
puts(") { fflush (VL_CVT_Q_FP("); puts(") { fflush (VL_CVT_I_FP(");
nodep->filep()->iterateAndNext(*this); nodep->filep()->iterateAndNext(*this);
puts(")); }\n"); puts(")); }\n");
} }
@@ -475,7 +474,7 @@ public:
} }
visit(nodep->castNodeBiop(), vup); 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. // Extending a value of the same word width is just a NOP.
if (nodep->size()>VL_WORDSIZE) { if (nodep->size()>VL_WORDSIZE) {
puts("(QData)("); 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(word)));
} }
ofp()->printf(",0x%08" VL_PRI64 "x)", (vluint64_t)(nodep->num().dataWord(0))); 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()) { } else if (nodep->isQuad()) {
vluint64_t num = nodep->toUQuad(); vluint64_t num = nodep->toUQuad();
if (num<10) ofp()->printf("VL_ULL(%" VL_PRI64 "d)", num); 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])) { switch (tolower(pos[0])) {
case '0': case '1': case '2': case '3': case '4': case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': case '5': case '6': case '7': case '8': case '9':
case '.':
// Digits, like %5d, etc. // Digits, like %5d, etc.
vfmt += pos[0]; vfmt += pos[0];
inPct = true; // Get more digits inPct = true; // Get more digits
@@ -1229,6 +1231,9 @@ void EmitCStmts::displayNode(AstNode* nodep, AstScopeName* scopenamep,
case 'h': case 'h':
case 'x': displayArg(nodep,&elistp,isScan, vfmt,'x'); break; case 'x': displayArg(nodep,&elistp,isScan, vfmt,'x'); break;
case 's': displayArg(nodep,&elistp,isScan, vfmt,'s'); 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': { case 'm': {
if (!scopenamep) nodep->v3fatalSrc("Display with %m but no AstScopeName"); if (!scopenamep) nodep->v3fatalSrc("Display with %m but no AstScopeName");
string suffix = scopenamep->scopePrettyName(); 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 if (v3Global.needHInlines()) { // Set by V3EmitCInlines; should have been called before us
puts("#include \""+topClassName()+"__Inlines.h\"\n"); 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 // Declare foreign instances up front to make C++ happy
puts("class "+symClassName()+";\n"); puts("class "+symClassName()+";\n");
@@ -1797,8 +1807,10 @@ void EmitCImp::emitImp(AstNodeModule* modp) {
// Us // Us
puts("#include \""+ symClassName() +".h\"\n"); puts("#include \""+ symClassName() +".h\"\n");
if (v3Global.dpi()) { if (v3Global.dpi()) {
puts("#include \""+ topClassName() +"__Dpi.h\"\n"); puts("\n");
puts("#include \"verilated_dpi.h\"\n");
} }
if (optSystemPerl() && (splitFilenum() || !m_fast)) { if (optSystemPerl() && (splitFilenum() || !m_fast)) {
@@ -2003,7 +2015,9 @@ class EmitCTrace : EmitCStmts {
return varp->isSc() && varp->isScBv(); return varp->isSc() && varp->isScBv();
} }
void emitTraceInitOne(AstTraceDecl* nodep) { void emitTraceInitOne(AstTraceDecl* nodep) {
if (nodep->isWide()) { if (nodep->isDouble()) {
puts("vcdp->declDouble");
} else if (nodep->isWide()) {
puts("vcdp->declArray"); puts("vcdp->declArray");
} else if (nodep->isQuad()) { } else if (nodep->isQuad()) {
puts("vcdp->declQuad "); puts("vcdp->declQuad ");
@@ -2032,7 +2046,9 @@ class EmitCTrace : EmitCStmts {
string full = ((m_funcp->funcType() == AstCFuncType::TRACE_FULL string full = ((m_funcp->funcType() == AstCFuncType::TRACE_FULL
|| m_funcp->funcType() == AstCFuncType::TRACE_FULL_SUB) || m_funcp->funcType() == AstCFuncType::TRACE_FULL_SUB)
? "full":"chg"); ? "full":"chg");
if (nodep->isWide() || emitTraceIsScBv(nodep)) { if (nodep->isDouble()) {
puts("vcdp->"+full+"Double");
} else if (nodep->isWide() || emitTraceIsScBv(nodep)) {
puts("vcdp->"+full+"Array"); puts("vcdp->"+full+"Array");
} else if (nodep->isQuad()) { } else if (nodep->isQuad()) {
puts("vcdp->"+full+"Quad "); puts("vcdp->"+full+"Quad ");
+2
View File
@@ -519,6 +519,8 @@ void EmitCSyms::emitDpiHdr() {
puts("// Manually include this file where DPI .c import functions are declared to insure\n"); 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("// the C functions match the expectations of the DPI imports.\n");
puts("\n"); puts("\n");
puts("#include \"svdpi.h\"\n");
puts("\n");
puts("#ifdef __cplusplus\n"); puts("#ifdef __cplusplus\n");
puts("extern \"C\" {\n"); puts("extern \"C\" {\n");
puts("#endif\n"); puts("#endif\n");
+9 -4
View File
@@ -84,10 +84,15 @@ public:
if (v3Global.opt.systemPerl()) { if (v3Global.opt.systemPerl()) {
putMakeClassEntry(of, "Sp.cpp"); // Note Sp.cpp includes SpTraceVcdC putMakeClassEntry(of, "Sp.cpp"); // Note Sp.cpp includes SpTraceVcdC
} }
else if (v3Global.opt.trace()) { else {
putMakeClassEntry(of, "verilated_vcd_c.cpp"); if (v3Global.opt.coverage()) {
if (v3Global.opt.systemC()) { putMakeClassEntry(of, "SpCoverage.cpp");
putMakeClassEntry(of, "verilated_vcd_sc.cpp"); }
if (v3Global.opt.trace()) {
putMakeClassEntry(of, "verilated_vcd_c.cpp");
if (v3Global.opt.systemC()) {
putMakeClassEntry(of, "verilated_vcd_sc.cpp");
}
} }
} }
} }
+13 -6
View File
@@ -74,7 +74,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
virtual void visit(AstNodeFTask* nodep, AstNUser*) { virtual void visit(AstNodeFTask* nodep, AstNUser*) {
putfs(nodep, nodep->isFunction() ? "function":"task"); putfs(nodep, nodep->isFunction() ? "function":"task");
puts(" "); puts(" ");
puts(nodep->name()); puts(nodep->prettyName());
puts(";\n"); puts(";\n");
putqs(nodep, "begin\n"); // Only putfs the first time for each visitor; later for same node is putqs putqs(nodep, "begin\n"); // Only putfs the first time for each visitor; later for same node is putqs
nodep->stmtsp()->iterateAndNext(*this); nodep->stmtsp()->iterateAndNext(*this);
@@ -217,6 +217,9 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
} }
puts(");\n"); puts(");\n");
} }
virtual void visit(AstDisable* nodep, AstNUser*) {
putbs("disable "+nodep->name()+";\n");
}
virtual void visit(AstDisplay* nodep, AstNUser*) { virtual void visit(AstDisplay* nodep, AstNUser*) {
visitNodeDisplay(nodep, nodep->filep(), nodep->fmtp()->text(), nodep->fmtp()->exprsp()); visitNodeDisplay(nodep, nodep->filep(), nodep->fmtp()->text(), nodep->fmtp()->exprsp());
} }
@@ -472,17 +475,21 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
virtual void visit(AstTypedef* nodep, AstNUser*) { virtual void visit(AstTypedef* nodep, AstNUser*) {
putfs(nodep,"typedef "); putfs(nodep,"typedef ");
nodep->dtypep()->iterateAndNext(*this); puts(" "); nodep->dtypep()->iterateAndNext(*this); puts(" ");
puts(nodep->name()); puts(nodep->prettyName());
puts(";\n"); puts(";\n");
} }
virtual void visit(AstBasicDType* nodep, AstNUser*) { virtual void visit(AstBasicDType* nodep, AstNUser*) {
if (nodep->isSigned()) putfs(nodep,"signed "); if (nodep->isSigned()) putfs(nodep,"signed ");
putfs(nodep,nodep->prettyName()); putfs(nodep,nodep->prettyName());
if (nodep->rangep()) { nodep->rangep()->iterateAndNext(*this); puts(" "); } if (nodep->rangep()) { puts(" "); nodep->rangep()->iterateAndNext(*this); puts(" "); }
}
virtual void visit(AstConstDType* nodep, AstNUser*) {
putfs(nodep,"const ");
nodep->dtypep()->iterateAndNext(*this);
} }
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) { virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
if (nodep->dotted()!="") { putfs(nodep,nodep->dotted()); puts("."); puts(nodep->name()); } if (nodep->dotted()!="") { putfs(nodep,nodep->dotted()); puts("."); puts(nodep->prettyName()); }
else { putfs(nodep,nodep->name()); } else { putfs(nodep,nodep->prettyName()); }
puts("("); puts("(");
nodep->pinsp()->iterateAndNext(*this); nodep->pinsp()->iterateAndNext(*this);
puts(")"); puts(")");
@@ -520,7 +527,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
putfs(nodep,nodep->verilogKwd()); putfs(nodep,nodep->verilogKwd());
puts(" "); puts(" ");
nodep->dtypep()->iterateAndNext(*this); puts(" "); nodep->dtypep()->iterateAndNext(*this); puts(" ");
puts(nodep->name()); puts(nodep->prettyName());
puts(";\n"); puts(";\n");
} }
virtual void visit(AstActive* nodep, AstNUser*) { virtual void visit(AstActive* nodep, AstNUser*) {
+1 -1
View File
@@ -309,7 +309,7 @@ void V3Error::abortIfErrors() {
} }
void V3Error::abortIfWarnings() { void V3Error::abortIfWarnings() {
if (errorOrWarnCount()) { if (v3Global.opt.warnFatal() ? errorOrWarnCount() : errorCount()) {
v3fatal ("Exiting due to "<<dec<<errorOrWarnCount()<<" warning(s)\n"); v3fatal ("Exiting due to "<<dec<<errorOrWarnCount()<<" warning(s)\n");
} }
} }
+3 -1
View File
@@ -73,6 +73,7 @@ public:
LITENDIAN, // Little bit endian vector LITENDIAN, // Little bit endian vector
MODDUP, // Duplicate module MODDUP, // Duplicate module
MULTIDRIVEN, // Driven from multiple blocks MULTIDRIVEN, // Driven from multiple blocks
REALCVT, // Real conversion
REDEFMACRO, // Redefining existing define macro REDEFMACRO, // Redefining existing define macro
STMTDLY, // Delayed statement STMTDLY, // Delayed statement
SYMRSVDWORD, // Symbol is Reserved Word SYMRSVDWORD, // Symbol is Reserved Word
@@ -111,7 +112,7 @@ public:
"IFDEPTH", "IMPERFECTSCH", "IMPLICIT", "IMPURE", "INCABSPATH", "IFDEPTH", "IMPERFECTSCH", "IMPLICIT", "IMPURE", "INCABSPATH",
"LITENDIAN", "MODDUP", "LITENDIAN", "MODDUP",
"MULTIDRIVEN", "MULTIDRIVEN",
"REDEFMACRO", "REALCVT", "REDEFMACRO",
"STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET", "STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET",
"UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNSIGNED", "UNUSED", "UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNSIGNED", "UNUSED",
"VARHIDDEN", "WIDTH", "WIDTHCONCAT", "VARHIDDEN", "WIDTH", "WIDTHCONCAT",
@@ -135,6 +136,7 @@ public:
|| m_e==CMPCONST || m_e==CMPCONST
|| m_e==IMPLICIT || m_e==IMPLICIT
|| m_e==LITENDIAN || m_e==LITENDIAN
|| m_e==REALCVT
|| m_e==UNSIGNED || m_e==UNSIGNED
|| m_e==WIDTH); } || m_e==WIDTH); }
// Warnings that are style only // Warnings that are style only
+22 -23
View File
@@ -127,18 +127,18 @@ private:
} else if (nodep->isQuad() && word==0) { } else if (nodep->isQuad() && word==0) {
AstNode* quadfromp = nodep->cloneTree(true); AstNode* quadfromp = nodep->cloneTree(true);
quadfromp->width(VL_QUADSIZE,quadfromp->widthMin()); quadfromp->width(VL_QUADSIZE,quadfromp->widthMin());
return new AstCast (nodep->fileline(), return new AstCCast (nodep->fileline(),
quadfromp, quadfromp,
VL_WORDSIZE); VL_WORDSIZE);
} else if (nodep->isQuad() && word==1) { } else if (nodep->isQuad() && word==1) {
AstNode* quadfromp = nodep->cloneTree(true); AstNode* quadfromp = nodep->cloneTree(true);
quadfromp->width(VL_QUADSIZE,quadfromp->widthMin()); quadfromp->width(VL_QUADSIZE,quadfromp->widthMin());
return new AstCast (nodep->fileline(), return new AstCCast (nodep->fileline(),
new AstShiftR (nodep->fileline(), new AstShiftR (nodep->fileline(),
quadfromp, quadfromp,
new AstConst (nodep->fileline(), VL_WORDSIZE), new AstConst (nodep->fileline(), VL_WORDSIZE),
VL_WORDSIZE), VL_WORDSIZE),
VL_WORDSIZE); VL_WORDSIZE);
} else if (!nodep->isWide() && !nodep->isQuad() && word==0) { } else if (!nodep->isWide() && !nodep->isQuad() && word==0) {
return nodep->cloneTree(true); return nodep->cloneTree(true);
} else { // Out of bounds } else { // Out of bounds
@@ -324,7 +324,7 @@ private:
nodep->v3fatalSrc("extending larger thing into smaller?"); nodep->v3fatalSrc("extending larger thing into smaller?");
} else { } else {
UINFO(8," EXTEND(q<-l) "<<nodep<<endl); UINFO(8," EXTEND(q<-l) "<<nodep<<endl);
newp = new AstCast (nodep->fileline(), lhsp, nodep); newp = new AstCCast (nodep->fileline(), lhsp, nodep);
} }
} else { // Long } else { // Long
if (lhsp->isQuad() || lhsp->isWide()) { if (lhsp->isQuad() || lhsp->isWide()) {
@@ -366,7 +366,7 @@ private:
AstNode* lowwordp = new AstWordSel (nodep->fromp()->fileline(), AstNode* lowwordp = new AstWordSel (nodep->fromp()->fileline(),
nodep->fromp()->cloneTree(true), nodep->fromp()->cloneTree(true),
newSelBitWord(nodep->lsbp(), 0)); newSelBitWord(nodep->lsbp(), 0));
if (nodep->isQuad() && !lowwordp->isQuad()) lowwordp = new AstCast(nodep->fileline(), lowwordp, nodep); if (nodep->isQuad() && !lowwordp->isQuad()) lowwordp = new AstCCast(nodep->fileline(), lowwordp, nodep);
AstNode* lowp = new AstShiftR (nodep->fileline(), AstNode* lowp = new AstShiftR (nodep->fileline(),
lowwordp, lowwordp,
newSelBitBit(nodep->lsbp()), newSelBitBit(nodep->lsbp()),
@@ -379,7 +379,7 @@ private:
new AstWordSel (nodep->fromp()->fileline(), new AstWordSel (nodep->fromp()->fileline(),
nodep->fromp()->cloneTree(true), nodep->fromp()->cloneTree(true),
newSelBitWord(nodep->lsbp(), 1)); newSelBitWord(nodep->lsbp(), 1));
if (nodep->isQuad() && !midwordp->isQuad()) midwordp = new AstCast(nodep->fileline(), midwordp, nodep); if (nodep->isQuad() && !midwordp->isQuad()) midwordp = new AstCCast(nodep->fileline(), midwordp, nodep);
// If we're selecting bit zero, then all 32 bits in word 1 get shifted << by 32 bits // If we're selecting bit zero, then all 32 bits in word 1 get shifted << by 32 bits
// else we need to form the lower word, so we << by 31 or less // else we need to form the lower word, so we << by 31 or less
// nbitsfromlow <= (lsb==0) ? 64-bitbit(lsb) : 32-bitbit(lsb) // nbitsfromlow <= (lsb==0) ? 64-bitbit(lsb) : 32-bitbit(lsb)
@@ -417,7 +417,7 @@ private:
new AstWordSel (nodep->fromp()->fileline(), new AstWordSel (nodep->fromp()->fileline(),
nodep->fromp()->cloneTree(true), nodep->fromp()->cloneTree(true),
newSelBitWord(nodep->lsbp(), 2)); newSelBitWord(nodep->lsbp(), 2));
if (nodep->isQuad() && !hiwordp->isQuad()) hiwordp = new AstCast(nodep->fileline(), hiwordp, nodep); if (nodep->isQuad() && !hiwordp->isQuad()) hiwordp = new AstCCast(nodep->fileline(), hiwordp, nodep);
AstNode* himayp = AstNode* himayp =
new AstShiftL (nodep->fileline(), new AstShiftL (nodep->fileline(),
hiwordp, hiwordp,
@@ -445,14 +445,14 @@ private:
UINFO(8," SEL->SHIFT "<<nodep<<endl); UINFO(8," SEL->SHIFT "<<nodep<<endl);
AstNode* fromp = nodep->fromp()->unlinkFrBack(); AstNode* fromp = nodep->fromp()->unlinkFrBack();
AstNode* lsbp = nodep->lsbp()->unlinkFrBack(); AstNode* lsbp = nodep->lsbp()->unlinkFrBack();
if (nodep->isQuad() && !fromp->isQuad()) fromp = new AstCast(nodep->fileline(), fromp, nodep); if (nodep->isQuad() && !fromp->isQuad()) fromp = new AstCCast(nodep->fileline(), fromp, nodep);
AstNode* newp = new AstShiftR (nodep->fileline(), AstNode* newp = new AstShiftR (nodep->fileline(),
fromp, fromp,
dropCondBound(lsbp), dropCondBound(lsbp),
nodep->width()); nodep->width());
newp->widthSignedFrom(nodep); newp->widthSignedFrom(nodep);
if (!nodep->isQuad() && fromp->isQuad()) { if (!nodep->isQuad() && fromp->isQuad()) {
newp = new AstCast (newp->fileline(), newp, nodep); newp = new AstCCast (newp->fileline(), newp, nodep);
} }
newp->widthSignedFrom(nodep); newp->widthSignedFrom(nodep);
replaceWithDelete(nodep,newp); nodep=NULL; replaceWithDelete(nodep,newp); nodep=NULL;
@@ -546,7 +546,7 @@ private:
destp->deleteTree(); destp=NULL; destp->deleteTree(); destp=NULL;
} else { } else {
UINFO(8," ASSIGNSEL(const,narrow) "<<nodep<<endl); UINFO(8," ASSIGNSEL(const,narrow) "<<nodep<<endl);
if (destp->isQuad() && !rhsp->isQuad()) rhsp = new AstCast(nodep->fileline(), rhsp, nodep); if (destp->isQuad() && !rhsp->isQuad()) rhsp = new AstCCast(nodep->fileline(), rhsp, nodep);
AstNode* oldvalp = destp->cloneTree(true); AstNode* oldvalp = destp->cloneTree(true);
fixCloneLvalue(oldvalp); fixCloneLvalue(oldvalp);
if (!ones) oldvalp = new AstAnd (lhsp->fileline(), if (!ones) oldvalp = new AstAnd (lhsp->fileline(),
@@ -620,7 +620,7 @@ private:
V3Number maskwidth (nodep->fileline(), destp->widthMin()); V3Number maskwidth (nodep->fileline(), destp->widthMin());
for (int bit=0; bit<(int)lhsp->widthConst(); bit++) maskwidth.setBit(bit,1); for (int bit=0; bit<(int)lhsp->widthConst(); bit++) maskwidth.setBit(bit,1);
if (destp->isQuad() && !rhsp->isQuad()) rhsp = new AstCast(nodep->fileline(), rhsp, nodep); if (destp->isQuad() && !rhsp->isQuad()) rhsp = new AstCCast(nodep->fileline(), rhsp, nodep);
if (!ones) if (!ones)
oldvalp = new AstAnd (lhsp->fileline(), oldvalp = new AstAnd (lhsp->fileline(),
new AstNot (lhsp->fileline(), new AstNot (lhsp->fileline(),
@@ -655,8 +655,8 @@ private:
AstNode* lhsp = nodep->lhsp()->unlinkFrBack(); AstNode* lhsp = nodep->lhsp()->unlinkFrBack();
AstNode* rhsp = nodep->rhsp()->unlinkFrBack(); AstNode* rhsp = nodep->rhsp()->unlinkFrBack();
int rhsshift = rhsp->widthMin(); int rhsshift = rhsp->widthMin();
if (nodep->isQuad() && !lhsp->isQuad()) lhsp = new AstCast(nodep->fileline(), lhsp, nodep); if (nodep->isQuad() && !lhsp->isQuad()) lhsp = new AstCCast(nodep->fileline(), lhsp, nodep);
if (nodep->isQuad() && !rhsp->isQuad()) rhsp = new AstCast(nodep->fileline(), rhsp, nodep); if (nodep->isQuad() && !rhsp->isQuad()) rhsp = new AstCCast(nodep->fileline(), rhsp, nodep);
AstNode* newp = new AstOr (nodep->fileline(), AstNode* newp = new AstOr (nodep->fileline(),
new AstShiftL (nodep->fileline(), new AstShiftL (nodep->fileline(),
lhsp, lhsp,
@@ -696,14 +696,13 @@ private:
int lhswidth = lhsp->widthMin(); int lhswidth = lhsp->widthMin();
if (lhswidth==1) { if (lhswidth==1) {
UINFO(8," REPLICATE(w1) "<<nodep<<endl); UINFO(8," REPLICATE(w1) "<<nodep<<endl);
newp = new AstUnaryMin (nodep->fileline(), newp = new AstNegate (nodep->fileline(), lhsp);
lhsp);
} else { } else {
UINFO(8," REPLICATE "<<nodep<<endl); UINFO(8," REPLICATE "<<nodep<<endl);
AstConst* constp = nodep->rhsp()->castConst(); AstConst* constp = nodep->rhsp()->castConst();
if (!constp) nodep->v3fatalSrc("Replication value isn't a constant. Checked earlier!"); if (!constp) nodep->v3fatalSrc("Replication value isn't a constant. Checked earlier!");
uint32_t times = constp->toUInt(); uint32_t times = constp->toUInt();
if (nodep->isQuad() && !lhsp->isQuad()) lhsp = new AstCast(nodep->fileline(), lhsp, nodep); if (nodep->isQuad() && !lhsp->isQuad()) lhsp = new AstCCast(nodep->fileline(), lhsp, nodep);
newp = lhsp->cloneTree(true); newp = lhsp->cloneTree(true);
for (unsigned repnum=1; repnum<times; repnum++) { for (unsigned repnum=1; repnum<times; repnum++) {
int rhsshift = repnum*lhswidth; int rhsshift = repnum*lhswidth;
@@ -731,7 +730,7 @@ private:
for (int w=0; w<rhsp->widthWords(); w++) { for (int w=0; w<rhsp->widthWords(); w++) {
AstNode* newp; AstNode* newp;
if (lhswidth==1) { if (lhswidth==1) {
newp = new AstUnaryMin (nodep->fileline(), lhsp->cloneTree(true)); newp = new AstNegate (nodep->fileline(), lhsp->cloneTree(true));
newp->width(VL_WORDSIZE,VL_WORDSIZE); newp->width(VL_WORDSIZE,VL_WORDSIZE);
} else { } else {
newp = newAstWordSelClone (lhsp, w); newp = newAstWordSelClone (lhsp, w);
+6
View File
@@ -719,6 +719,12 @@ private:
// Prevent a infinite loop... // Prevent a infinite loop...
substp->v3fatalSrc("Replacing node with itself; perhaps circular logic?"); substp->v3fatalSrc("Replacing node with itself; perhaps circular logic?");
} }
// Which fileline() to use?
// If replacing with logic, an error/warning is likely to want to point to the logic
// IE what we're replacing with.
// However a VARREF should point to the original as it's otherwise confusing
// to throw warnings that point to a PIN rather than where the pin us used.
if (substp->castVarRef()) substp->fileline(nodep->fileline());
nodep->replaceWith(substp); nodep->replaceWith(substp);
nodep->deleteTree(); nodep=NULL; nodep->deleteTree(); nodep=NULL;
} }
+5 -1
View File
@@ -140,6 +140,10 @@ private:
if (!connectRefp->castConst() && !connectRefp->castVarRef()) { if (!connectRefp->castConst() && !connectRefp->castVarRef()) {
pinp->v3fatalSrc("Unknown interconnect type; pinReconnectSimple should have cleared up\n"); pinp->v3fatalSrc("Unknown interconnect type; pinReconnectSimple should have cleared up\n");
} }
if (pinNewVarp->isOutOnly() && connectRefp->castConst()) {
pinp->v3error("Output port is connected to a constant pin, electrical short");
}
// Propagate any attributes across the interconnect // Propagate any attributes across the interconnect
pinNewVarp->propagateAttrFrom(pinOldVarp); pinNewVarp->propagateAttrFrom(pinOldVarp);
if (connectRefp->castVarRef()) { if (connectRefp->castVarRef()) {
@@ -180,7 +184,7 @@ private:
// user2p is either a const or a var. // user2p is either a const or a var.
AstConst* exprconstp = nodep->user2p()->castNode()->castConst(); AstConst* exprconstp = nodep->user2p()->castNode()->castConst();
AstVarRef* exprvarrefp = nodep->user2p()->castNode()->castVarRef(); AstVarRef* exprvarrefp = nodep->user2p()->castNode()->castVarRef();
UINFO(1,"connectto: "<<nodep->user2p()->castNode()<<endl); UINFO(8,"connectto: "<<nodep->user2p()->castNode()<<endl);
if (!exprconstp && !exprvarrefp) { if (!exprconstp && !exprvarrefp) {
nodep->v3fatalSrc("Unknown interconnect type; pinReconnectSimple should have cleared up\n"); nodep->v3fatalSrc("Unknown interconnect type; pinReconnectSimple should have cleared up\n");
} }
+22 -3
View File
@@ -55,9 +55,11 @@ private:
// AstNodeModule::user4p() // V3SymTable* Module's Symbol table // AstNodeModule::user4p() // V3SymTable* Module's Symbol table
// AstNodeFTask::user4p() // V3SymTable* Local Symbol table // AstNodeFTask::user4p() // V3SymTable* Local Symbol table
// AstBegin::user4p() // V3SymTable* Local Symbol table // AstBegin::user4p() // V3SymTable* Local Symbol table
// AstVar::user5p() // AstPin* True if port attached to a pin
AstUser2InUse m_inuser2; AstUser2InUse m_inuser2;
AstUser3InUse m_inuser3; AstUser3InUse m_inuser3;
AstUser4InUse m_inuser4; AstUser4InUse m_inuser4;
AstUser5InUse m_inuser5;
// ENUMS // ENUMS
enum IdState { // Which loop through the tree enum IdState { // Which loop through the tree
@@ -132,7 +134,7 @@ private:
nodep->packagep(packageFor(varp)); nodep->packagep(packageFor(varp));
} }
else if (AstEnumItem* valuep = foundp->castEnumItem()) { else if (AstEnumItem* valuep = foundp->castEnumItem()) {
AstNode* newp = new AstEnumItemRef(nodep->fileline(), valuep); AstNode* newp = new AstEnumItemRef(nodep->fileline(), valuep, packageFor(valuep));
nodep->replaceWith(newp); nodep->replaceWith(newp);
nodep->deleteTree(); nodep=NULL; nodep->deleteTree(); nodep=NULL;
return true; // Edited return true; // Edited
@@ -426,7 +428,7 @@ private:
if (dtypep) dtypep->unlinkFrBack(); if (dtypep) dtypep->unlinkFrBack();
else dtypep = new AstBasicDType(nodep->fileline(), AstBasicDTypeKwd::LOGIC); else dtypep = new AstBasicDType(nodep->fileline(), AstBasicDTypeKwd::LOGIC);
AstVar* newvarp = new AstVar(nodep->fileline(), AstVarType::OUTPUT, nodep->name(), dtypep); AstVar* newvarp = new AstVar(nodep->fileline(), AstVarType::OUTPUT, nodep->name(), dtypep);
newvarp->isSigned(nodep->isSigned()); if (nodep->isSigned()) newvarp->numeric(AstNumeric::SIGNED);
newvarp->funcReturn(true); newvarp->funcReturn(true);
newvarp->trace(false); // Not user visible newvarp->trace(false); // Not user visible
newvarp->attrIsolateAssign(nodep->attrIsolateAssign()); newvarp->attrIsolateAssign(nodep->attrIsolateAssign());
@@ -498,6 +500,7 @@ private:
if (!taskp) { nodep->v3error("Can't find definition of task/function: "<<nodep->prettyName()); } if (!taskp) { nodep->v3error("Can't find definition of task/function: "<<nodep->prettyName()); }
nodep->taskp(taskp); nodep->taskp(taskp);
nodep->packagep(packageFor(taskp)); nodep->packagep(packageFor(taskp));
if (taskp->castTask() && nodep->castFuncRef()) nodep->v3error("Illegal call of a task as a function: "<<nodep->prettyName());
} }
} }
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
@@ -551,6 +554,7 @@ private:
virtual void visit(AstCell* nodep, AstNUser*) { virtual void visit(AstCell* nodep, AstNUser*) {
// Cell: Resolve its filename. If necessary, parse it. // Cell: Resolve its filename. If necessary, parse it.
m_cellp = nodep; m_cellp = nodep;
AstNode::user5ClearTree();
if (m_idState==ID_FIND) { if (m_idState==ID_FIND) {
// Add to list of all cells, for error checking and defparam's // Add to list of all cells, for error checking and defparam's
findAndInsertAndCheck(nodep, nodep->name()); findAndInsertAndCheck(nodep, nodep->name());
@@ -635,11 +639,26 @@ private:
nodep->v3error("Pin is not an in/out/inout/param: "<<nodep->prettyName()); nodep->v3error("Pin is not an in/out/inout/param: "<<nodep->prettyName());
} else { } else {
nodep->modVarp(refp); nodep->modVarp(refp);
if (refp->user5p() && refp->user5p()->castNode()!=nodep) {
nodep->v3error("Duplicate pin connection: "<<nodep->prettyName());
refp->user5p()->castNode()->v3error("... Location of original pin connection");
} else {
refp->user5p(nodep);
}
}
if (!nodep->exprp()) {
// It's an empty pin connection, done with it.
// (We used to not create pins for these, but we'd miss
// warns. Perhaps they should live even further...)
pushDeletep(nodep->unlinkFrBack()); nodep=NULL;
return;
} }
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
// Deal with implicit definitions - do before ID_RESOLVE stage as may be referenced above declaration // Deal with implicit definitions - do before ID_RESOLVE stage as may be referenced above declaration
if (m_idState==ID_PARAM && !nodep->svImplicit()) { // SV 19.11.3: .name pins don't allow implicit decls if (m_idState==ID_PARAM
&& nodep->exprp() // Else specifically unconnected pin
&& !nodep->svImplicit()) { // SV 19.11.3: .name pins don't allow implicit decls
pinImplicitExprRecurse(nodep->exprp()); pinImplicitExprRecurse(nodep->exprp());
} }
// Early return() above when deleted // Early return() above when deleted
+12
View File
@@ -193,6 +193,18 @@ private:
new V3GraphEdge(&m_graph, vertex(m_modp), vertex(modp), 1, false); new V3GraphEdge(&m_graph, vertex(m_modp), vertex(modp), 1, false);
} }
} }
// Remove AstCell(AstPin("",NULL)), it's a side effect of how we parse "()"
// the empty middle is identical to the empty rule that must find pins in "(,)".
if (nodep->pinsp() && !nodep->pinsp()->nextp()
&& nodep->pinsp()->name() == ""
&& !nodep->pinsp()->exprp()) {
pushDeletep(nodep->pinsp()->unlinkFrBackWithNext());
}
if (nodep->paramsp() && !nodep->paramsp()->nextp()
&& nodep->paramsp()->name() == ""
&& !nodep->paramsp()->exprp()) {
pushDeletep(nodep->paramsp()->unlinkFrBackWithNext());
}
// Convert .* to list of pins // Convert .* to list of pins
bool pinStar = false; bool pinStar = false;
for (AstPin* nextp, *pinp = nodep->pinsp(); pinp; pinp=nextp) { for (AstPin* nextp, *pinp = nodep->pinsp(); pinp; pinp=nextp) {
+39 -4
View File
@@ -50,6 +50,7 @@ private:
AstModule* m_modp; // Current module AstModule* m_modp; // Current module
AstNodeFTask* m_ftaskp; // Current function/task AstNodeFTask* m_ftaskp; // Current function/task
AstWhile* m_loopp; // Current loop AstWhile* m_loopp; // Current loop
bool m_loopInc; // In loop increment
int m_repeatNum; // Repeat counter int m_repeatNum; // Repeat counter
BeginStack m_beginStack; // All begin blocks above current node BeginStack m_beginStack; // All begin blocks above current node
@@ -134,15 +135,16 @@ private:
// Spec says value is integral, if negative is ignored // Spec says value is integral, if negative is ignored
AstVar* varp = new AstVar(nodep->fileline(), AstVarType::BLOCKTEMP, name, AstVar* varp = new AstVar(nodep->fileline(), AstVarType::BLOCKTEMP, name,
AstLogicPacked(), 32); AstLogicPacked(), 32);
varp->isSigned(true); varp->numeric(AstNumeric::SIGNED);
varp->dtypep()->isSigned(true); varp->dtypep()->numeric(AstNumeric::SIGNED);
varp->usedLoopIdx(true);
m_modp->addStmtp(varp); m_modp->addStmtp(varp);
AstNode* initsp = new AstAssign(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, true), AstNode* initsp = new AstAssign(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, true),
countp); countp);
AstNode* decp = new AstAssign(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, true), AstNode* decp = new AstAssign(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, true),
new AstSub(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false), new AstSub(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false),
new AstConst(nodep->fileline(), 1))); new AstConst(nodep->fileline(), 1)));
AstNode* zerosp = new AstConst(nodep->fileline(), 0); zerosp->isSigned(true); AstNode* zerosp = new AstConst(nodep->fileline(), 0); zerosp->numeric(AstNumeric::SIGNED);
AstNode* condp = new AstGtS(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false), AstNode* condp = new AstGtS(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false),
zerosp); zerosp);
AstNode* bodysp = nodep->bodysp(); if (bodysp) bodysp->unlinkFrBackWithNext(); AstNode* bodysp = nodep->bodysp(); if (bodysp) bodysp->unlinkFrBackWithNext();
@@ -158,8 +160,15 @@ private:
virtual void visit(AstWhile* nodep, AstNUser*) { virtual void visit(AstWhile* nodep, AstNUser*) {
// Don't need to track AstRepeat/AstFor as they have already been converted // Don't need to track AstRepeat/AstFor as they have already been converted
AstWhile* lastLoopp = m_loopp; AstWhile* lastLoopp = m_loopp;
bool lastInc = m_loopInc;
m_loopp = nodep; m_loopp = nodep;
nodep->iterateChildren(*this); m_loopInc = false;
nodep->precondsp()->iterateAndNext(*this);
nodep->condp()->iterateAndNext(*this);
nodep->bodysp()->iterateAndNext(*this);
m_loopInc = true;
nodep->incsp()->iterateAndNext(*this);
m_loopInc = lastInc;
m_loopp = lastLoopp; m_loopp = lastLoopp;
} }
virtual void visit(AstReturn* nodep, AstNUser*) { virtual void visit(AstReturn* nodep, AstNUser*) {
@@ -202,7 +211,32 @@ private:
} }
nodep->unlinkFrBack(); pushDeletep(nodep); nodep=NULL; nodep->unlinkFrBack(); pushDeletep(nodep); nodep=NULL;
} }
virtual void visit(AstDisable* nodep, AstNUser*) {
UINFO(8," DISABLE "<<nodep<<endl);
nodep->iterateChildren(*this);
AstBegin* beginp = NULL;
for (BeginStack::reverse_iterator it = m_beginStack.rbegin(); it != m_beginStack.rend(); ++it) {
UINFO(9," UNDERBLK "<<*it<<endl);
if ((*it)->name() == nodep->name()) {
beginp = *it;
break;
}
}
//if (debug()>=9) { UINFO(0,"\n"); beginp->dumpTree(cout," labeli: "); }
if (!beginp) { nodep->v3error("disable isn't underneath a begin with name: "<<nodep->name()); }
else {
// Jump to the end of the named begin
AstJumpLabel* labelp = findAddLabel(beginp, false);
nodep->addNextHere(new AstJumpGo(nodep->fileline(), labelp));
}
nodep->unlinkFrBack(); pushDeletep(nodep); nodep=NULL;
//if (debug()>=9) { UINFO(0,"\n"); beginp->dumpTree(cout," labelo: "); }
}
virtual void visit(AstVarRef* nodep, AstNUser*) {
if (m_loopInc && nodep->varp()) nodep->varp()->usedLoopIdx(true);
}
virtual void visit(AstConst* nodep, AstNUser*) {}
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
@@ -212,6 +246,7 @@ public:
m_modp = NULL; m_modp = NULL;
m_ftaskp = NULL; m_ftaskp = NULL;
m_loopp = NULL; m_loopp = NULL;
m_loopInc = false;
m_repeatNum = 0; m_repeatNum = 0;
nodep->accept(*this); nodep->accept(*this);
} }
+11
View File
@@ -45,6 +45,7 @@ private:
// STATE // STATE
bool m_setRefLvalue; // Set VarRefs to lvalues for pin assignments bool m_setRefLvalue; // Set VarRefs to lvalues for pin assignments
AstInitial* m_initialp; // In an initial block
AstNodeFTask* m_ftaskp; // Function or task we're inside AstNodeFTask* m_ftaskp; // Function or task we're inside
// METHODS // METHODS
@@ -67,6 +68,10 @@ private:
nodep->v3error("Assigning to input variable: "<<nodep->prettyName()); nodep->v3error("Assigning to input variable: "<<nodep->prettyName());
} }
} }
if (nodep->lvalue() && nodep->varp()->isConst()
&& !m_initialp) { // Too loose, but need to allow our generated first assignment
nodep->v3error("Assigning to const variable: "<<nodep->prettyName());
}
} }
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
@@ -222,6 +227,11 @@ private:
} }
m_setRefLvalue = last_setRefLvalue; m_setRefLvalue = last_setRefLvalue;
} }
virtual void visit(AstInitial* nodep, AstNUser*) {
m_initialp = nodep;
nodep->iterateChildren(*this);
m_initialp = NULL;
}
virtual void visit(AstNodeFTask* nodep, AstNUser*) { virtual void visit(AstNodeFTask* nodep, AstNUser*) {
m_ftaskp = nodep; m_ftaskp = nodep;
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
@@ -259,6 +269,7 @@ public:
LinkLValueVisitor(AstNode* nodep, bool start) { LinkLValueVisitor(AstNode* nodep, bool start) {
m_setRefLvalue = start; m_setRefLvalue = start;
m_ftaskp = NULL; m_ftaskp = NULL;
m_initialp = NULL;
nodep->accept(*this); nodep->accept(*this);
} }
virtual ~LinkLValueVisitor() {} virtual ~LinkLValueVisitor() {}
+32 -1
View File
@@ -33,6 +33,7 @@
#include <cstdarg> #include <cstdarg>
#include <unistd.h> #include <unistd.h>
#include <map> #include <map>
#include <set>
#include <algorithm> #include <algorithm>
#include <vector> #include <vector>
@@ -47,11 +48,14 @@ class LinkParseVisitor : public AstNVisitor {
private: private:
// NODE STATE // NODE STATE
// Cleared on netlist // Cleared on netlist
// AstNode::user() -> bool. True if processed // AstNode::user1() -> bool. True if processed
// AstNode::user2() -> bool. True if fileline recomputed
AstUser1InUse m_inuser1; AstUser1InUse m_inuser1;
AstUser2InUse m_inuser2;
// TYPES // TYPES
typedef map <pair<void*,string>,AstTypedef*> ImplTypedefMap; typedef map <pair<void*,string>,AstTypedef*> ImplTypedefMap;
typedef set <FileLine*> FileLineSet;
// STATE // STATE
string m_dotText; // Dotted module text we are building for a dotted node, passed up string m_dotText; // Dotted module text we are building for a dotted node, passed up
@@ -60,6 +64,7 @@ private:
AstText* m_baseTextp; // Lowest TEXT node that needs replacement with varref AstText* m_baseTextp; // Lowest TEXT node that needs replacement with varref
AstVar* m_varp; // Variable we're under AstVar* m_varp; // Variable we're under
ImplTypedefMap m_implTypedef; // Created typedefs for each <container,name> ImplTypedefMap m_implTypedef; // Created typedefs for each <container,name>
FileLineSet m_filelines; // Filelines that have been seen
// METHODS // METHODS
static int debug() { static int debug() {
@@ -68,6 +73,21 @@ private:
return level; return level;
} }
void cleanFileline(AstNode* nodep) {
if (!nodep->user2Inc()) { // Process once
// We make all filelines unique per AstNode. This allows us to
// later turn off messages on a fileline when an issue is found
// so that messages on replicated blocks occur only once,
// without suppressing other token's messages as a side effect.
// We could have verilog.l create a new one on every token,
// but that's a lot more structures than only doing AST nodes.
if (m_filelines.find(nodep->fileline()) != m_filelines.end()) {
nodep->fileline(new FileLine(nodep->fileline()));
}
m_filelines.insert(nodep->fileline());
}
}
void checkExpected(AstNode* nodep) { void checkExpected(AstNode* nodep) {
if (m_exp != AstParseRefExp::PX_NONE) { if (m_exp != AstParseRefExp::PX_NONE) {
nodep->v3fatalSrc("Tree syntax error: Not expecting "<<nodep->type()<<" under a "<<nodep->backp()->type()); nodep->v3fatalSrc("Tree syntax error: Not expecting "<<nodep->type()<<" under a "<<nodep->backp()->type());
@@ -78,6 +98,7 @@ private:
// VISITs // VISITs
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) { virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
if (!nodep->user1Inc()) { // Process only once. if (!nodep->user1Inc()) { // Process only once.
cleanFileline(nodep);
UINFO(5," "<<nodep<<endl); UINFO(5," "<<nodep<<endl);
checkExpected(nodep); checkExpected(nodep);
// Due to a need to get the arguments, the ParseRefs are under here, // Due to a need to get the arguments, the ParseRefs are under here,
@@ -141,6 +162,7 @@ private:
} }
virtual void visit(AstDot* nodep, AstNUser*) { virtual void visit(AstDot* nodep, AstNUser*) {
UINFO(5," "<<nodep<<endl); UINFO(5," "<<nodep<<endl);
cleanFileline(nodep);
if (m_inModDot) { // Already under dot, so this is {modulepart} DOT {modulepart} if (m_inModDot) { // Already under dot, so this is {modulepart} DOT {modulepart}
m_dotText = ""; m_dotText = "";
nodep->lhsp()->iterateAndNext(*this); nodep->lhsp()->iterateAndNext(*this);
@@ -165,6 +187,7 @@ private:
} }
virtual void visit(AstSelBit* nodep, AstNUser*) { virtual void visit(AstSelBit* nodep, AstNUser*) {
if (!nodep->user1Inc()) { // Process only once. if (!nodep->user1Inc()) { // Process only once.
cleanFileline(nodep);
if (m_inModDot) { // Already under dot, so this is {modulepart} DOT {modulepart} if (m_inModDot) { // Already under dot, so this is {modulepart} DOT {modulepart}
m_dotText = ""; m_dotText = "";
nodep->lhsp()->iterateAndNext(*this); nodep->lhsp()->iterateAndNext(*this);
@@ -193,6 +216,7 @@ private:
virtual void visit(AstNodePreSel* nodep, AstNUser*) { virtual void visit(AstNodePreSel* nodep, AstNUser*) {
// Excludes simple AstSel, see above // Excludes simple AstSel, see above
if (!nodep->user1Inc()) { // Process only once. if (!nodep->user1Inc()) { // Process only once.
cleanFileline(nodep);
if (m_inModDot) { // Already under dot, so this is {modulepart} DOT {modulepart} if (m_inModDot) { // Already under dot, so this is {modulepart} DOT {modulepart}
nodep->v3error("Syntax Error: Range ':', '+:' etc are not allowed in the cell part of a dotted reference"); nodep->v3error("Syntax Error: Range ':', '+:' etc are not allowed in the cell part of a dotted reference");
} else if (m_exp==AstParseRefExp::PX_FUNC) { } else if (m_exp==AstParseRefExp::PX_FUNC) {
@@ -215,6 +239,7 @@ private:
} }
virtual void visit(AstText* nodep, AstNUser*) { virtual void visit(AstText* nodep, AstNUser*) {
if (!nodep->user1Inc()) { // Process only once. if (!nodep->user1Inc()) { // Process only once.
cleanFileline(nodep);
if (m_exp != AstParseRefExp::PX_NONE) { if (m_exp != AstParseRefExp::PX_NONE) {
UINFO(7," "<<nodep<<endl); UINFO(7," "<<nodep<<endl);
if (m_inModDot) { // Dotted part, just pass up if (m_inModDot) { // Dotted part, just pass up
@@ -228,6 +253,7 @@ private:
} }
virtual void visit(AstEnumItem* nodep, AstNUser*) { virtual void visit(AstEnumItem* nodep, AstNUser*) {
// Expand ranges // Expand ranges
cleanFileline(nodep);
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (nodep->rangep()) { if (nodep->rangep()) {
if (!nodep->rangep()->msbp()->castConst() if (!nodep->rangep()->msbp()->castConst()
@@ -251,12 +277,14 @@ private:
virtual void visit(AstVar* nodep, AstNUser*) { virtual void visit(AstVar* nodep, AstNUser*) {
cleanFileline(nodep);
m_varp = nodep; m_varp = nodep;
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
m_varp = NULL; m_varp = NULL;
} }
virtual void visit(AstAttrOf* nodep, AstNUser*) { virtual void visit(AstAttrOf* nodep, AstNUser*) {
cleanFileline(nodep);
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (nodep->attrType() == AstAttrType::VAR_CLOCK) { if (nodep->attrType() == AstAttrType::VAR_CLOCK) {
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable"); if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
@@ -303,6 +331,7 @@ private:
virtual void visit(AstAlwaysPublic* nodep, AstNUser*) { virtual void visit(AstAlwaysPublic* nodep, AstNUser*) {
// AlwaysPublic was attached under a var, but it's a statement that should be // AlwaysPublic was attached under a var, but it's a statement that should be
// at the same level as the var // at the same level as the var
cleanFileline(nodep);
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (m_varp) { if (m_varp) {
nodep->unlinkFrBack(); nodep->unlinkFrBack();
@@ -315,6 +344,7 @@ private:
} }
virtual void visit(AstDefImplicitDType* nodep, AstNUser*) { virtual void visit(AstDefImplicitDType* nodep, AstNUser*) {
cleanFileline(nodep);
UINFO(8," DEFIMPLICIT "<<nodep<<endl); UINFO(8," DEFIMPLICIT "<<nodep<<endl);
// Must remember what names we've already created, and combine duplicates // Must remember what names we've already created, and combine duplicates
// so that for "var enum {...} a,b" a & b will share a common typedef // so that for "var enum {...} a,b" a & b will share a common typedef
@@ -351,6 +381,7 @@ private:
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep, AstNUser*) {
// Default: Just iterate // Default: Just iterate
cleanFileline(nodep);
checkExpected(nodep); // So we detect node types we forgot to list here checkExpected(nodep); // So we detect node types we forgot to list here
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
+4
View File
@@ -95,6 +95,9 @@ private:
nodep->dtypeSkipRefp()->castArrayDType())) { nodep->dtypeSkipRefp()->castArrayDType())) {
nodep->v3error("Unsupported: Inputs and outputs must be simple data types"); nodep->v3error("Unsupported: Inputs and outputs must be simple data types");
} }
if (nodep->dtypeSkipRefp()->castConstDType()) {
nodep->isConst(true);
}
if (m_ftaskp) nodep->funcLocal(true); if (m_ftaskp) nodep->funcLocal(true);
if (nodep->isSigModPublic()) { if (nodep->isSigModPublic()) {
nodep->sigModPublic(false); // We're done with this attribute nodep->sigModPublic(false); // We're done with this attribute
@@ -254,6 +257,7 @@ private:
switch (tolower(ch)) { switch (tolower(ch)) {
case '0': case '1': case '2': case '3': case '4': case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': case '5': case '6': case '7': case '8': case '9':
case '.':
inPct = true; inPct = true;
break; break;
case '%': break; // %% - just output a % case '%': break; // %% - just output a %
+189 -19
View File
@@ -27,6 +27,8 @@
#include <algorithm> #include <algorithm>
#include "V3Number.h" #include "V3Number.h"
#define MAX_SPRINTF_DOUBLE_SIZE 100 // Maximum characters with a sprintf %e/%f/%g (probably < 30)
//###################################################################### //######################################################################
// Read class functions // Read class functions
// CREATION // CREATION
@@ -44,6 +46,7 @@ void V3Number::width(int width, bool sized) {
void V3Number::init (FileLine* fileline, int swidth) { void V3Number::init (FileLine* fileline, int swidth) {
m_fileline = fileline; m_fileline = fileline;
m_signed = false; m_signed = false;
m_double = false;
m_autoExtend = false; m_autoExtend = false;
m_fromString = false; m_fromString = false;
width(swidth); width(swidth);
@@ -298,6 +301,24 @@ V3Number& V3Number::setLong(uint32_t value) {
m_value[0] = value; m_value[0] = value;
return *this; return *this;
} }
V3Number& V3Number::setLongS(vlsint32_t value) {
for (int i=0; i<words(); i++) m_value[i]=m_valueX[i] = 0;
union { uint32_t u; vlsint32_t s; } u;
u.s = value;
m_value[0] = u.u;
return *this;
}
V3Number& V3Number::setDouble(double value) {
if (VL_UNLIKELY(width()!=64)) {
m_fileline->v3fatalSrc("Real operation on wrong sized number");
}
m_double = true;
union { double d; uint32_t u[2]; } u;
u.d = value;
for (int i=2; i<words(); i++) m_value[i]=m_valueX[i] = 0;
m_value[0] = u.u[0]; m_value[1] = u.u[1];
return *this;
}
V3Number& V3Number::setSingleBits(char value) { V3Number& V3Number::setSingleBits(char value) {
for (int i=1/*upper*/; i<words(); i++) m_value[i]=m_valueX[i] = 0; for (int i=1/*upper*/; i<words(); i++) m_value[i]=m_valueX[i] = 0;
m_value[0] = (value=='1'||value=='x'||value==1||value==3); m_value[0] = (value=='1'||value=='x'||value==1||value==3);
@@ -306,12 +327,12 @@ V3Number& V3Number::setSingleBits(char value) {
} }
V3Number& V3Number::setAllBits0() { V3Number& V3Number::setAllBits0() {
for (int i=0; i<words(); i++) { m_value[i] = m_valueX[i]=0; } for (int i=0; i<words(); i++) { m_value[i] = m_valueX[i]=0; }
return *this; return *this;
} }
V3Number& V3Number::setAllBits1() { V3Number& V3Number::setAllBits1() {
for (int i=0; i<words(); i++) { m_value[i]= ~0; m_valueX[i] = 0; } for (int i=0; i<words(); i++) { m_value[i]= ~0; m_valueX[i] = 0; }
return *this; return *this;
} }
V3Number& V3Number::setAllBitsX() { V3Number& V3Number::setAllBitsX() {
for (int i=0; i<words(); i++) { m_value[i]=m_valueX[i] = ~0; } for (int i=0; i<words(); i++) { m_value[i]=m_valueX[i] = ~0; }
@@ -333,6 +354,10 @@ V3Number& V3Number::setMask(int nbits) {
string V3Number::ascii(bool prefixed, bool cleanVerilog) const { string V3Number::ascii(bool prefixed, bool cleanVerilog) const {
ostringstream out; ostringstream out;
if (isDouble()) {
out<<toDouble();
return out.str();
}
if (prefixed) { if (prefixed) {
if (sized()) { if (sized()) {
out<<width()<<"'"; out<<width()<<"'";
@@ -375,6 +400,9 @@ bool V3Number::displayedFmtLegal(char format) {
case 'b': return true; case 'b': return true;
case 'c': return true; case 'c': return true;
case 'd': return true; // Unsigned decimal case 'd': return true; // Unsigned decimal
case 'e': return true;
case 'f': return true;
case 'g': return true;
case 'h': return true; case 'h': return true;
case 'o': return true; case 'o': return true;
case 's': return true; case 's': return true;
@@ -390,7 +418,7 @@ string V3Number::displayed(const string& vformat) const {
UASSERT(pos != vformat.end() && pos[0]=='%', "display with non format argument "<<*this); UASSERT(pos != vformat.end() && pos[0]=='%', "display with non format argument "<<*this);
pos++; pos++;
string fmtsize; string fmtsize;
for (; pos != vformat.end() && isdigit(pos[0]); pos++) { for (; pos != vformat.end() && (isdigit(pos[0]) || pos[0]=='.'); pos++) {
fmtsize += pos[0]; fmtsize += pos[0];
} }
string str; string str;
@@ -472,9 +500,20 @@ string V3Number::displayed(const string& vformat) const {
str = cvtToStr(toUQuad()); str = cvtToStr(toUQuad());
} }
int intfmtsize = atoi(fmtsize.c_str()); int intfmtsize = atoi(fmtsize.c_str());
while ((int)(str.length()) < intfmtsize) str = " "+str; bool zeropad = fmtsize.length()>0 && fmtsize[0]=='0';
while ((int)(str.length()) < intfmtsize) {
if (zeropad) str = "0"+str;
else str = " "+str;
}
return str; return str;
} }
case 'e':
case 'f':
case 'g': {
char tmp[MAX_SPRINTF_DOUBLE_SIZE];
sprintf(tmp, vformat.c_str(), toDouble());
return tmp;
}
default: default:
m_fileline->v3fatalSrc("Unknown $display format code for number: %"<<pos[0]); m_fileline->v3fatalSrc("Unknown $display format code for number: %"<<pos[0]);
return "ERR"; return "ERR";
@@ -490,6 +529,18 @@ uint32_t V3Number::toUInt() const {
return m_value[0]; return m_value[0];
} }
double V3Number::toDouble() const {
if (VL_UNLIKELY(!isDouble())) {
m_fileline->v3fatalSrc("Real conversion on non real number");
}
if (VL_UNLIKELY(width()!=64)) {
m_fileline->v3fatalSrc("Real operation on wrong sized number");
}
union { double d; uint32_t u[2]; } u;
u.u[0] = m_value[0]; u.u[1] = m_value[1];
return u.d;
}
vlsint32_t V3Number::toSInt() const { vlsint32_t V3Number::toSInt() const {
if (isSigned()) { if (isSigned()) {
uint32_t v = toUInt(); uint32_t v = toUInt();
@@ -555,6 +606,12 @@ bool V3Number::isNeqZero() const {
} }
return false; return false;
} }
bool V3Number::isBitsZero(int msb, int lsb) const {
for (int i=lsb; i<=msb; i++) {
if (VL_UNLIKELY(!bitIs0(i))) return false;
}
return true;
}
bool V3Number::isEqOne() const { bool V3Number::isEqOne() const {
if (m_value[0]!=1 || m_valueX[0]) return false; if (m_value[0]!=1 || m_valueX[0]) return false;
for (int i=1; i<words(); i++) { for (int i=1; i<words(); i++) {
@@ -1005,6 +1062,30 @@ V3Number& V3Number::opLteS (const V3Number& lhs, const V3Number& rhs) {
return opGteS(rhs,lhs); return opGteS(rhs,lhs);
} }
V3Number& V3Number::opRotR (const V3Number& lhs, const V3Number& rhs) {
// L(lhs) bit return
if (rhs.isFourState()) return setAllBitsX();
setZero();
uint32_t rhsval = rhs.toUInt();
for (int bit=0; bit<this->width(); bit++) {
setBit(bit,lhs.bitIs((bit + rhsval) % this->width()));
}
return *this;
}
V3Number& V3Number::opRotL (const V3Number& lhs, const V3Number& rhs) {
// L(lhs) bit return
if (rhs.isFourState()) return setAllBitsX();
setZero();
uint32_t rhsval = rhs.toUInt();
for (int bit=0; bit<this->width(); bit++) {
if (bit >= (int)rhsval) {
setBit(bit,lhs.bitIs((bit - rhsval) % this->width()));
}
}
return *this;
}
V3Number& V3Number::opShiftR (const V3Number& lhs, const V3Number& rhs) { V3Number& V3Number::opShiftR (const V3Number& lhs, const V3Number& rhs) {
// L(lhs) bit return // L(lhs) bit return
if (rhs.isFourState()) return setAllBitsX(); if (rhs.isFourState()) return setAllBitsX();
@@ -1019,7 +1100,7 @@ V3Number& V3Number::opShiftR (const V3Number& lhs, const V3Number& rhs) {
V3Number& V3Number::opShiftRS (const V3Number& lhs, const V3Number& rhs) { V3Number& V3Number::opShiftRS (const V3Number& lhs, const V3Number& rhs) {
// L(lhs) bit return // L(lhs) bit return
// The spec says a unsigned >>> still acts as a normal >>. // The spec says a unsigned >>> still acts as a normal >>.
// We presume it is signed; as that's V3Signed's job to convert to opShiftR // We presume it is signed; as that's V3Width's job to convert to opShiftR
if (rhs.isFourState()) return setAllBitsX(); if (rhs.isFourState()) return setAllBitsX();
setZero(); setZero();
uint32_t rhsval = rhs.toUInt(); uint32_t rhsval = rhs.toUInt();
@@ -1032,8 +1113,8 @@ V3Number& V3Number::opShiftRS (const V3Number& lhs, const V3Number& rhs) {
V3Number& V3Number::opShiftL (const V3Number& lhs, const V3Number& rhs) { V3Number& V3Number::opShiftL (const V3Number& lhs, const V3Number& rhs) {
// L(lhs) bit return // L(lhs) bit return
if (rhs.isFourState()) return setAllBitsX(); if (rhs.isFourState()) return setAllBitsX();
uint32_t rhsval = rhs.toUInt();
setZero(); setZero();
uint32_t rhsval = rhs.toUInt();
for (int bit=0; bit<this->width(); bit++) { for (int bit=0; bit<this->width(); bit++) {
if (bit >= (int)rhsval) { if (bit >= (int)rhsval) {
setBit(bit,lhs.bitIs(bit - rhsval)); setBit(bit,lhs.bitIs(bit - rhsval));
@@ -1045,7 +1126,16 @@ V3Number& V3Number::opShiftL (const V3Number& lhs, const V3Number& rhs) {
//====================================================================== //======================================================================
// Ops - Arithmetic // Ops - Arithmetic
V3Number& V3Number::opUnaryMin (const V3Number& lhs) { V3Number& V3Number::opAbsS (const V3Number& lhs) {
// op i, L(lhs) bit return
if (lhs.isFourState()) return setAllBitsX();
if (lhs.isNegative()) {
return opNegate(lhs);
} else {
return opAssign(lhs);
}
}
V3Number& V3Number::opNegate (const V3Number& lhs) {
// op i, L(lhs) bit return // op i, L(lhs) bit return
if (lhs.isFourState()) return setAllBitsX(); if (lhs.isFourState()) return setAllBitsX();
V3Number notlhs (lhs.m_fileline, width()); V3Number notlhs (lhs.m_fileline, width());
@@ -1073,7 +1163,7 @@ V3Number& V3Number::opSub (const V3Number& lhs, const V3Number& rhs) {
// i op j, max(L(lhs),L(rhs)) bit return, if any 4-state, 4-state return // i op j, max(L(lhs),L(rhs)) bit return, if any 4-state, 4-state return
if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX(); if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX();
V3Number negrhs (rhs.m_fileline, rhs.width()); V3Number negrhs (rhs.m_fileline, rhs.width());
negrhs.opUnaryMin(rhs); negrhs.opNegate(rhs);
return opAdd(lhs, negrhs); return opAdd(lhs, negrhs);
} }
V3Number& V3Number::opMul (const V3Number& lhs, const V3Number& rhs) { V3Number& V3Number::opMul (const V3Number& lhs, const V3Number& rhs) {
@@ -1101,12 +1191,12 @@ V3Number& V3Number::opMul (const V3Number& lhs, const V3Number& rhs) {
V3Number& V3Number::opMulS (const V3Number& lhs, const V3Number& rhs) { V3Number& V3Number::opMulS (const V3Number& lhs, const V3Number& rhs) {
// Signed multiply // Signed multiply
if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX(); if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX();
V3Number lhsNoSign = lhs; if (lhs.isNegative()) lhsNoSign.opUnaryMin(lhs); V3Number lhsNoSign = lhs; if (lhs.isNegative()) lhsNoSign.opNegate(lhs);
V3Number rhsNoSign = rhs; if (rhs.isNegative()) rhsNoSign.opUnaryMin(rhs); V3Number rhsNoSign = rhs; if (rhs.isNegative()) rhsNoSign.opNegate(rhs);
V3Number qNoSign = opMul(lhsNoSign,rhsNoSign); V3Number qNoSign = opMul(lhsNoSign,rhsNoSign);
if ((lhs.isNegative() && !rhs.isNegative()) if ((lhs.isNegative() && !rhs.isNegative())
|| (!lhs.isNegative() && rhs.isNegative())) { || (!lhs.isNegative() && rhs.isNegative())) {
opUnaryMin(qNoSign); opNegate(qNoSign);
} else { } else {
opAssign(qNoSign); opAssign(qNoSign);
} }
@@ -1130,13 +1220,13 @@ V3Number& V3Number::opDivS (const V3Number& lhs, const V3Number& rhs) {
//UINFO(9, ">>divs-start "<<lhs<<" "<<rhs<<endl); //UINFO(9, ">>divs-start "<<lhs<<" "<<rhs<<endl);
if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX(); if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX();
if (rhs.isEqZero()) return setAllBitsX(); if (rhs.isEqZero()) return setAllBitsX();
V3Number lhsNoSign = lhs; if (lhs.isNegative()) lhsNoSign.opUnaryMin(lhs); V3Number lhsNoSign = lhs; if (lhs.isNegative()) lhsNoSign.opNegate(lhs);
V3Number rhsNoSign = rhs; if (rhs.isNegative()) rhsNoSign.opUnaryMin(rhs); V3Number rhsNoSign = rhs; if (rhs.isNegative()) rhsNoSign.opNegate(rhs);
V3Number qNoSign = opDiv(lhsNoSign,rhsNoSign); V3Number qNoSign = opDiv(lhsNoSign,rhsNoSign);
//UINFO(9, " >divs-mid "<<lhs<<" "<<rhs<<" "<<qNoSign<<endl); //UINFO(9, " >divs-mid "<<lhs<<" "<<rhs<<" "<<qNoSign<<endl);
if ((lhs.isNegative() && !rhs.isNegative()) if ((lhs.isNegative() && !rhs.isNegative())
|| (!lhs.isNegative() && rhs.isNegative())) { || (!lhs.isNegative() && rhs.isNegative())) {
opUnaryMin(qNoSign); opNegate(qNoSign);
} else { } else {
opAssign(qNoSign); opAssign(qNoSign);
} }
@@ -1159,11 +1249,11 @@ V3Number& V3Number::opModDivS (const V3Number& lhs, const V3Number& rhs) {
// Signed moddiv // Signed moddiv
if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX(); if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX();
if (rhs.isEqZero()) return setAllBitsX(); if (rhs.isEqZero()) return setAllBitsX();
V3Number lhsNoSign = lhs; if (lhs.isNegative()) lhsNoSign.opUnaryMin(lhs); V3Number lhsNoSign = lhs; if (lhs.isNegative()) lhsNoSign.opNegate(lhs);
V3Number rhsNoSign = rhs; if (rhs.isNegative()) rhsNoSign.opUnaryMin(rhs); V3Number rhsNoSign = rhs; if (rhs.isNegative()) rhsNoSign.opNegate(rhs);
V3Number qNoSign = opModDiv(lhsNoSign,rhsNoSign); V3Number qNoSign = opModDiv(lhsNoSign,rhsNoSign);
if (lhs.isNegative()) { // Just lhs' sign (*DIFFERENT FROM PERL, which uses rhs sign*) if (lhs.isNegative()) { // Just lhs' sign (*DIFFERENT FROM PERL, which uses rhs sign*)
opUnaryMin(qNoSign); opNegate(qNoSign);
} else { } else {
opAssign(qNoSign); opAssign(qNoSign);
} }
@@ -1318,6 +1408,15 @@ V3Number& V3Number::opPowS (const V3Number& lhs, const V3Number& rhs) {
return setAllBitsX(); return setAllBitsX();
} }
V3Number& V3Number::opBufIf1 (const V3Number& ens, const V3Number& if1s) {
setZero();
for(int bit=0; bit<this->width(); bit++) {
if (ens.bitIs1(bit)) { setBit(bit, if1s.bitIs(bit)); }
else setBit(bit,'z');
}
return *this;
}
V3Number& V3Number::opAssign (const V3Number& lhs) { V3Number& V3Number::opAssign (const V3Number& lhs) {
// Note may be a width change during the assign // Note may be a width change during the assign
setZero(); setZero();
@@ -1386,3 +1485,74 @@ V3Number& V3Number::opCond (const V3Number& lhs, const V3Number& if1s, const V3
} }
return *this; return *this;
} }
//======================================================================
// Ops - Floating point
V3Number& V3Number::opIToRD (const V3Number& lhs) {
return setDouble(lhs.toSInt());
}
V3Number& V3Number::opRToIS (const V3Number& lhs) {
double v = trunc(lhs.toDouble());
vlsint32_t i = (vlsint32_t)v; // C converts from double to vlsint32
return setLongS(i);
}
V3Number& V3Number::opRToIRoundS (const V3Number& lhs) {
double v = round(lhs.toDouble());
vlsint32_t i = (vlsint32_t)v; // C converts from double to vlsint32
return setLongS(i);
}
V3Number& V3Number::opRealToBits (const V3Number& lhs) {
// Conveniently our internal format is identical so we can copy bits...
if (lhs.width()!=64 || this->width()!=64) {
m_fileline->v3fatalSrc("Real operation on wrong sized number");
}
return opAssign(lhs);
}
V3Number& V3Number::opBitsToRealD (const V3Number& lhs) {
// Conveniently our internal format is identical so we can copy bits...
if (lhs.width()!=64 || this->width()!=64) {
m_fileline->v3fatalSrc("Real operation on wrong sized number");
}
return opAssign(lhs);
}
V3Number& V3Number::opNegateD (const V3Number& lhs) {
return setDouble(- lhs.toDouble());
}
V3Number& V3Number::opAddD (const V3Number& lhs, const V3Number& rhs) {
return setDouble(lhs.toDouble() + rhs.toDouble());
}
V3Number& V3Number::opSubD (const V3Number& lhs, const V3Number& rhs) {
return setDouble(lhs.toDouble() - rhs.toDouble());
}
V3Number& V3Number::opMulD (const V3Number& lhs, const V3Number& rhs) {
return setDouble(lhs.toDouble() * rhs.toDouble());
}
V3Number& V3Number::opDivD (const V3Number& lhs, const V3Number& rhs) {
// On exceptions, we just generate 'inf' through floating point
// IEEE says it's implementation defined what happens
return setDouble(lhs.toDouble() / rhs.toDouble());
}
V3Number& V3Number::opPowD (const V3Number& lhs, const V3Number& rhs) {
// On exceptions, we just generate 'inf' through floating point
// IEEE says it's implementation defined what happens
return setDouble(pow(lhs.toDouble(), rhs.toDouble()));
}
V3Number& V3Number::opEqD (const V3Number& lhs, const V3Number& rhs) {
return setSingleBits(lhs.toDouble() == rhs.toDouble());
}
V3Number& V3Number::opNeqD (const V3Number& lhs, const V3Number& rhs) {
return setSingleBits(lhs.toDouble() != rhs.toDouble());
}
V3Number& V3Number::opGtD (const V3Number& lhs, const V3Number& rhs) {
return setSingleBits(lhs.toDouble() > rhs.toDouble());
}
V3Number& V3Number::opGteD (const V3Number& lhs, const V3Number& rhs) {
return setSingleBits(lhs.toDouble() >= rhs.toDouble());
}
V3Number& V3Number::opLtD (const V3Number& lhs, const V3Number& rhs) {
return setSingleBits(lhs.toDouble() < rhs.toDouble());
}
V3Number& V3Number::opLteD (const V3Number& lhs, const V3Number& rhs) {
return setSingleBits(lhs.toDouble() <= rhs.toDouble());
}
+30 -1
View File
@@ -35,6 +35,7 @@ class V3Number {
int m_width; // Width as specified/calculated. int m_width; // Width as specified/calculated.
bool m_sized:1; // True if the user specified the width, else we track it. bool m_sized:1; // True if the user specified the width, else we track it.
bool m_signed:1; // True if signed value bool m_signed:1; // True if signed value
bool m_double:1; // True if double real value
bool m_fromString:1; // True if from string bool m_fromString:1; // True if from string
bool m_autoExtend:1; // True if SystemVerilog extend-to-any-width bool m_autoExtend:1; // True if SystemVerilog extend-to-any-width
FileLine* m_fileline; FileLine* m_fileline;
@@ -50,6 +51,8 @@ public:
V3Number& setZero(); V3Number& setZero();
V3Number& setQuad(vluint64_t value); V3Number& setQuad(vluint64_t value);
V3Number& setLong(uint32_t value); V3Number& setLong(uint32_t value);
V3Number& setLongS(vlsint32_t value);
V3Number& setDouble(double value);
void setBit (int bit, char value) { // Note must be pre-zeroed! void setBit (int bit, char value) { // Note must be pre-zeroed!
if (bit>=m_width) return; if (bit>=m_width) return;
if (value=='0'||value==0) m_value [bit/32] &= ~(1UL<<(bit&31)); if (value=='0'||value==0) m_value [bit/32] &= ~(1UL<<(bit&31));
@@ -132,12 +135,14 @@ public:
bool autoExtend() const { return m_autoExtend; } bool autoExtend() const { return m_autoExtend; }
bool isFromString() const { return m_fromString; } bool isFromString() const { return m_fromString; }
bool isSigned() const { return m_signed; } // Only correct for parsing of numbers from strings, otherwise not used (use AstConst::isSigned()) bool isSigned() const { return m_signed; } // Only correct for parsing of numbers from strings, otherwise not used (use AstConst::isSigned())
bool isDouble() const { return m_double; } // Only correct for parsing of numbers from strings, otherwise not used (use AstConst::isSigned())
bool isNegative() const { return bitIs1(width()-1); } bool isNegative() const { return bitIs1(width()-1); }
bool isFourState() const { for (int i=0;i<words();i++) {if (m_valueX[i]) return true;} return false; } bool isFourState() const { for (int i=0;i<words();i++) {if (m_valueX[i]) return true;} return false; }
bool hasZ() const { for(int i=0;i<words();i++) {if((~m_value[i]) & m_valueX[i]) return true;} return false;} bool hasZ() const { for(int i=0;i<words();i++) {if((~m_value[i]) & m_valueX[i]) return true;} return false;}
bool isAllZ() const { for(int i=0;i<width();i++) { if(!bitIsZ(i)){return false;} } return true; } bool isAllZ() const { for(int i=0;i<width();i++) { if(!bitIsZ(i)){return false;} } return true; }
bool isEqZero() const; bool isEqZero() const;
bool isNeqZero() const; bool isNeqZero() const;
bool isBitsZero(int msb, int lsb) const;
bool isEqOne() const; bool isEqOne() const;
bool isEqAllOnes(int optwidth=0) const; bool isEqAllOnes(int optwidth=0) const;
bool isCaseEq(const V3Number& rhsp) const; // operator== bool isCaseEq(const V3Number& rhsp) const; // operator==
@@ -150,6 +155,7 @@ public:
vluint64_t toUQuad() const; vluint64_t toUQuad() const;
vlsint64_t toSQuad() const; vlsint64_t toSQuad() const;
string toString() const; string toString() const;
double toDouble() const;
uint32_t toHash() const; uint32_t toHash() const;
uint32_t dataWord(int word) const; uint32_t dataWord(int word) const;
uint32_t countOnes() const; uint32_t countOnes() const;
@@ -195,12 +201,14 @@ public:
V3Number& opCaseNeq (const V3Number& lhs, const V3Number& rhs); V3Number& opCaseNeq (const V3Number& lhs, const V3Number& rhs);
V3Number& opWildEq (const V3Number& lhs, const V3Number& rhs); V3Number& opWildEq (const V3Number& lhs, const V3Number& rhs);
V3Number& opWildNeq (const V3Number& lhs, const V3Number& rhs); V3Number& opWildNeq (const V3Number& lhs, const V3Number& rhs);
V3Number& opBufIf1 (const V3Number& lhs, const V3Number& rhs);
// "standard" math // "standard" math
V3Number& opNot (const V3Number& lhs); V3Number& opNot (const V3Number& lhs);
V3Number& opLogNot (const V3Number& lhs); V3Number& opLogNot (const V3Number& lhs);
V3Number& opLogAnd (const V3Number& lhs, const V3Number& rhs); V3Number& opLogAnd (const V3Number& lhs, const V3Number& rhs);
V3Number& opLogOr (const V3Number& lhs, const V3Number& rhs); V3Number& opLogOr (const V3Number& lhs, const V3Number& rhs);
V3Number& opUnaryMin(const V3Number& lhs); V3Number& opAbsS (const V3Number& lhs);
V3Number& opNegate (const V3Number& lhs);
V3Number& opAdd (const V3Number& lhs, const V3Number& rhs); V3Number& opAdd (const V3Number& lhs, const V3Number& rhs);
V3Number& opSub (const V3Number& lhs, const V3Number& rhs); V3Number& opSub (const V3Number& lhs, const V3Number& rhs);
V3Number& opMul (const V3Number& lhs, const V3Number& rhs); V3Number& opMul (const V3Number& lhs, const V3Number& rhs);
@@ -216,6 +224,8 @@ public:
V3Number& opXor (const V3Number& lhs, const V3Number& rhs); V3Number& opXor (const V3Number& lhs, const V3Number& rhs);
V3Number& opXnor (const V3Number& lhs, const V3Number& rhs); V3Number& opXnor (const V3Number& lhs, const V3Number& rhs);
V3Number& opOr (const V3Number& lhs, const V3Number& rhs); V3Number& opOr (const V3Number& lhs, const V3Number& rhs);
V3Number& opRotR (const V3Number& lhs, const V3Number& rhs);
V3Number& opRotL (const V3Number& lhs, const V3Number& rhs);
V3Number& opShiftR (const V3Number& lhs, const V3Number& rhs); V3Number& opShiftR (const V3Number& lhs, const V3Number& rhs);
V3Number& opShiftRS (const V3Number& lhs, const V3Number& rhs); // Arithmetic w/carry V3Number& opShiftRS (const V3Number& lhs, const V3Number& rhs); // Arithmetic w/carry
V3Number& opShiftL (const V3Number& lhs, const V3Number& rhs); V3Number& opShiftL (const V3Number& lhs, const V3Number& rhs);
@@ -231,6 +241,25 @@ public:
V3Number& opLte (const V3Number& lhs, const V3Number& rhs); V3Number& opLte (const V3Number& lhs, const V3Number& rhs);
V3Number& opLteS (const V3Number& lhs, const V3Number& rhs); // Signed V3Number& opLteS (const V3Number& lhs, const V3Number& rhs); // Signed
// "D" - double (aka real) math
V3Number& opIToRD (const V3Number& lhs);
V3Number& opRToIS (const V3Number& lhs);
V3Number& opRToIRoundS (const V3Number& lhs);
V3Number& opRealToBits (const V3Number& lhs);
V3Number& opBitsToRealD(const V3Number& lhs);
V3Number& opNegateD (const V3Number& lhs);
V3Number& opAddD (const V3Number& lhs, const V3Number& rhs);
V3Number& opSubD (const V3Number& lhs, const V3Number& rhs);
V3Number& opMulD (const V3Number& lhs, const V3Number& rhs);
V3Number& opDivD (const V3Number& lhs, const V3Number& rhs);
V3Number& opPowD (const V3Number& lhs, const V3Number& rhs);
// Comparisons
V3Number& opEqD (const V3Number& lhs, const V3Number& rhs);
V3Number& opNeqD (const V3Number& lhs, const V3Number& rhs);
V3Number& opGtD (const V3Number& lhs, const V3Number& rhs);
V3Number& opGteD (const V3Number& lhs, const V3Number& rhs);
V3Number& opLtD (const V3Number& lhs, const V3Number& rhs);
V3Number& opLteD (const V3Number& lhs, const V3Number& rhs);
}; };
inline ostream& operator<<(ostream& os, V3Number rhs) { return os<<rhs.ascii(); } inline ostream& operator<<(ostream& os, V3Number rhs) { return os<<rhs.ascii(); }
+3 -3
View File
@@ -51,7 +51,7 @@ void test(string lhss, string op, string rhss, string exps) {
else if (op=="repl") gotnum.opRepl (lhnum,rhnum); else if (op=="repl") gotnum.opRepl (lhnum,rhnum);
else if (op=="~") gotnum.opNot (lhnum); else if (op=="~") gotnum.opNot (lhnum);
else if (op=="!") gotnum.opLogNot (lhnum); else if (op=="!") gotnum.opLogNot (lhnum);
else if (op=="unaryMin") gotnum.opUnaryMin (lhnum); else if (op=="negate") gotnum.opNegate (lhnum);
else if (op=="+") gotnum.opAdd (lhnum,rhnum); else if (op=="+") gotnum.opAdd (lhnum,rhnum);
else if (op=="-") gotnum.opSub (lhnum,rhnum); else if (op=="-") gotnum.opSub (lhnum,rhnum);
else if (op=="*") gotnum.opMul (lhnum,rhnum); else if (op=="*") gotnum.opMul (lhnum,rhnum);
@@ -96,8 +96,8 @@ int main() {
test("32'b0x","|","32'b10","32'b1x"); test("32'b0x","|","32'b10","32'b1x");
test("32'b10","&","32'b11","32'b10"); test("32'b10","&","32'b11","32'b10");
test("32'b10","+","32'b10","32'b100"); test("32'b10","+","32'b10","32'b100");
test("3'b000","unaryMin","","3'b000"); test("3'b000","negate","","3'b000");
test("3'b001","unaryMin","","3'b111"); test("3'b001","negate","","3'b111");
test("32'b11","-","32'b001","32'b10"); test("32'b11","-","32'b001","32'b10");
test("3'b000","-","3'b111","3'b001"); test("3'b000","-","3'b111","3'b001");
test("3'b000","-","3'b000","3'b000"); test("3'b000","-","3'b000","3'b000");
+35 -4
View File
@@ -194,18 +194,33 @@ string V3Options::filenameNonExt (const string& filename) {
string V3Options::filenameSubstitute (const string& filename) { string V3Options::filenameSubstitute (const string& filename) {
string out; string out;
enum { NONE, PAREN, CURLY } brackets = NONE;
for (string::size_type pos = 0; pos < filename.length(); ++pos) { for (string::size_type pos = 0; pos < filename.length(); ++pos) {
if (filename[pos] == '$') { if ((filename[pos] == '$') && (pos+1 < filename.length())) {
switch (filename[pos+1]) {
case '{': brackets = CURLY; break;
case '(': brackets = PAREN; break;
default: brackets = NONE; break;
}
if (brackets != NONE) pos = pos+1;
string::size_type endpos = pos+1; string::size_type endpos = pos+1;
while ((endpos+1) < filename.length() while (((endpos+1) < filename.length()) &&
&& (isalnum(filename[endpos+1]) || filename[endpos+1]=='_')) (((brackets==NONE) && (isalnum(filename[endpos+1]) || filename[endpos+1]=='_')) ||
((brackets==CURLY) && (filename[endpos+1]!='}')) ||
((brackets==PAREN) && (filename[endpos+1]!=')'))))
++endpos; ++endpos;
// Catch bracket errors
if (((brackets==CURLY) && (filename[endpos+1]!='}')) ||
((brackets==PAREN) && (filename[endpos+1]!=')'))) {
v3fatal("Unmatched brackets in variable substitution in file: "+filename);
}
string envvar = filename.substr(pos+1,endpos-pos); string envvar = filename.substr(pos+1,endpos-pos);
const char* envvalue = NULL; const char* envvalue = NULL;
if (envvar != "") envvalue = getenv(envvar.c_str()); if (envvar != "") envvalue = getenv(envvar.c_str());
if (envvalue) { if (envvalue) {
out += envvalue; out += envvalue;
pos = endpos; if (brackets==NONE) pos = endpos;
else pos = endpos+1;
} else { } else {
out += filename[pos]; // *pos == '$' out += filename[pos]; // *pos == '$'
} }
@@ -214,6 +229,7 @@ string V3Options::filenameSubstitute (const string& filename) {
} }
} }
return out; return out;
} }
bool V3Options::filenameIsRel(const string& filename) { bool V3Options::filenameIsRel(const string& filename) {
@@ -756,6 +772,14 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
shift; shift;
m_traceDepth = atoi(argv[i]); m_traceDepth = atoi(argv[i]);
} }
else if ( !strcmp (sw, "-trace-max-array") && (i+1)<argc ) {
shift;
m_traceMaxArray = atoi(argv[i]);
}
else if ( !strcmp (sw, "-trace-max-width") && (i+1)<argc ) {
shift;
m_traceMaxWidth = atoi(argv[i]);
}
else if ( !strncmp (sw, "-U", 2)) { else if ( !strncmp (sw, "-U", 2)) {
V3PreShell::undef (string (sw+strlen("-U"))); V3PreShell::undef (string (sw+strlen("-U")));
} }
@@ -807,6 +831,9 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
else if (!strcmp (sw, "-Wno-style")) { else if (!strcmp (sw, "-Wno-style")) {
FileLine::globalWarnStyleOff(true); FileLine::globalWarnStyleOff(true);
} }
else if (!strcmp (sw, "-Wno-fatal")) {
m_warnFatal = false;
}
else { else {
string msg = sw+strlen("-Wno-"); string msg = sw+strlen("-Wno-");
if (!(FileLine::globalWarnOff(msg, true))) { if (!(FileLine::globalWarnOff(msg, true))) {
@@ -1056,6 +1083,7 @@ V3Options::V3Options() {
m_makeDepend = true; m_makeDepend = true;
m_makePhony = false; m_makePhony = false;
m_outFormatOk = false; m_outFormatOk = false;
m_warnFatal = true;
m_pinsBv = 65; m_pinsBv = 65;
m_profileCFuncs = false; m_profileCFuncs = false;
m_preprocOnly = false; m_preprocOnly = false;
@@ -1077,6 +1105,8 @@ V3Options::V3Options() {
m_outputSplitCFuncs = 0; m_outputSplitCFuncs = 0;
m_outputSplitCTrace = 0; m_outputSplitCTrace = 0;
m_traceDepth = 0; m_traceDepth = 0;
m_traceMaxArray = 32;
m_traceMaxWidth = 256;
m_unrollCount = 64; m_unrollCount = 64;
m_unrollStmts = 30000; m_unrollStmts = 30000;
@@ -1095,6 +1125,7 @@ V3Options::V3Options() {
// Default +libext+ // Default +libext+
addLibExt(""); // So include "filename.v" will find the same file addLibExt(""); // So include "filename.v" will find the same file
addLibExt(".v"); addLibExt(".v");
addLibExt(".sv");
// Default -I // Default -I
addIncDir("."); // Looks better than {long_cwd_path}/... addIncDir("."); // Looks better than {long_cwd_path}/...
} }
+6
View File
@@ -113,6 +113,7 @@ class V3Options {
bool m_l2Name; // main switch: --l2name bool m_l2Name; // main switch: --l2name
bool m_lintOnly; // main switch: --lint-only bool m_lintOnly; // main switch: --lint-only
bool m_outFormatOk; // main switch: --cc, --sc or --sp was specified bool m_outFormatOk; // main switch: --cc, --sc or --sp was specified
bool m_warnFatal; // main switch: --warnFatal
bool m_pinsUint8; // main switch: --pins-uint8 bool m_pinsUint8; // main switch: --pins-uint8
bool m_profileCFuncs;// main switch: --profile-cfuncs bool m_profileCFuncs;// main switch: --profile-cfuncs
bool m_psl; // main switch: --psl bool m_psl; // main switch: --psl
@@ -134,6 +135,8 @@ class V3Options {
int m_outputSplitCTrace;// main switch: --output-split-ctrace int m_outputSplitCTrace;// main switch: --output-split-ctrace
int m_pinsBv; // main switch: --pins-bv int m_pinsBv; // main switch: --pins-bv
int m_traceDepth; // main switch: --trace-depth int m_traceDepth; // main switch: --trace-depth
int m_traceMaxArray;// main switch: --trace-max-array
int m_traceMaxWidth;// main switch: --trace-max-width
int m_unrollCount; // main switch: --unroll-count int m_unrollCount; // main switch: --unroll-count
int m_unrollStmts; // main switch: --unroll-stmts int m_unrollStmts; // main switch: --unroll-stmts
@@ -238,6 +241,7 @@ class V3Options {
bool traceUnderscore() const { return m_traceUnderscore; } bool traceUnderscore() const { return m_traceUnderscore; }
bool outFormatOk() const { return m_outFormatOk; } bool outFormatOk() const { return m_outFormatOk; }
bool keepTempFiles() const { return (V3Error::debugDefault()!=0); } bool keepTempFiles() const { return (V3Error::debugDefault()!=0); }
bool warnFatal() const { return m_warnFatal; }
bool pinsUint8() const { return m_pinsUint8; } bool pinsUint8() const { return m_pinsUint8; }
bool profileCFuncs() const { return m_profileCFuncs; } bool profileCFuncs() const { return m_profileCFuncs; }
bool psl() const { return m_psl; } bool psl() const { return m_psl; }
@@ -255,6 +259,8 @@ class V3Options {
int outputSplitCTrace() const { return m_outputSplitCTrace; } int outputSplitCTrace() const { return m_outputSplitCTrace; }
int pinsBv() const { return m_pinsBv; } int pinsBv() const { return m_pinsBv; }
int traceDepth() const { return m_traceDepth; } int traceDepth() const { return m_traceDepth; }
int traceMaxArray() const { return m_traceMaxArray; }
int traceMaxWidth() const { return m_traceMaxWidth; }
int unrollCount() const { return m_unrollCount; } int unrollCount() const { return m_unrollCount; }
int unrollStmts() const { return m_unrollStmts; } int unrollStmts() const { return m_unrollStmts; }
+1 -3
View File
@@ -43,7 +43,6 @@
#include "V3Case.h" #include "V3Case.h"
#include "V3Const.h" #include "V3Const.h"
#include "V3Width.h" #include "V3Width.h"
#include "V3Signed.h"
#include "V3Unroll.h" #include "V3Unroll.h"
//###################################################################### //######################################################################
@@ -131,8 +130,7 @@ private:
// Make sure all parameters are constantified // Make sure all parameters are constantified
virtual void visit(AstVar* nodep, AstNUser*) { virtual void visit(AstVar* nodep, AstNUser*) {
if (!nodep->user5()) { if (!nodep->user5Inc()) { // Process once
nodep->user5(1); // Mark done
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (nodep->isParam()) { if (nodep->isParam()) {
if (!nodep->hasSimpleInit()) { nodep->v3fatalSrc("Parameter without initial value"); } if (!nodep->hasSimpleInit()) { nodep->v3fatalSrc("Parameter without initial value"); }
+1
View File
@@ -254,6 +254,7 @@ public:
void verilatorCmtLintSave(); void verilatorCmtLintSave();
void verilatorCmtLintRestore(); void verilatorCmtLintRestore();
void verilatorCmtBad(const char* text); void verilatorCmtBad(const char* text);
double parseDouble(const char* text, size_t length);
void pushBeginKeywords(int state) { m_inBeginKwd++; m_lastVerilogState=state; } void pushBeginKeywords(int state) { m_inBeginKwd++; m_lastVerilogState=state; }
bool popBeginKeywords() { if (m_inBeginKwd) { m_inBeginKwd--; return true; } else return false; } bool popBeginKeywords() { if (m_inBeginKwd) { m_inBeginKwd--; return true; } else return false; }
int lastVerilogState() { return m_lastVerilogState; } int lastVerilogState() { return m_lastVerilogState; }
+9 -1
View File
@@ -393,6 +393,9 @@ void V3PreProcImp::comment(const string& text) {
} else if (0==(strncmp(cp,"cadence",strlen("cadence")))) { } else if (0==(strncmp(cp,"cadence",strlen("cadence")))) {
cp+=strlen("cadence"); cp+=strlen("cadence");
synth = true; synth = true;
} else if (0==(strncmp(cp,"pragma",strlen("pragma")))) {
cp+=strlen("pragma");
synth = true;
} else if (0==(strncmp(cp,"ambit synthesis",strlen("ambit synthesis")))) { } else if (0==(strncmp(cp,"ambit synthesis",strlen("ambit synthesis")))) {
cp+=strlen("ambit synthesis"); cp+=strlen("ambit synthesis");
synth = true; synth = true;
@@ -848,8 +851,13 @@ int V3PreProcImp::getStateToken() {
if (m_lexp->m_keepComments == KEEPCMT_SUB) { if (m_lexp->m_keepComments == KEEPCMT_SUB) {
string rtn; rtn.assign(yyourtext(),yyourleng()); string rtn; rtn.assign(yyourtext(),yyourleng());
comment(rtn); comment(rtn);
} else { // Need to insure "foo/**/bar" becomes two tokens
insertUnreadback (" ");
} else if (m_lexp->m_keepComments) {
return (tok); return (tok);
} else {
// Need to insure "foo/**/bar" becomes two tokens
insertUnreadback (" ");
} }
} }
// We're off or processed the comment specially. If there are newlines // We're off or processed the comment specially. If there are newlines
+6 -6
View File
@@ -208,12 +208,12 @@ private:
// Then over shifting gives the sign bit, not all zeros // Then over shifting gives the sign bit, not all zeros
// Note *NOT* clean output -- just like normal shift! // Note *NOT* clean output -- just like normal shift!
// Create equivalent of VL_SIGNONES_(node_width) // Create equivalent of VL_SIGNONES_(node_width)
constzerop = new AstUnaryMin (nodep->fileline(), constzerop = new AstNegate (nodep->fileline(),
new AstShiftR(nodep->fileline(), new AstShiftR(nodep->fileline(),
nodep->lhsp()->cloneTree(false), nodep->lhsp()->cloneTree(false),
new AstConst(nodep->fileline(), new AstConst(nodep->fileline(),
nodep->widthMin()-1), nodep->widthMin()-1),
nodep->width())); nodep->width()));
} else { } else {
V3Number zeronum (nodep->fileline(), nodep->width(), 0); V3Number zeronum (nodep->fileline(), nodep->width(), 0);
constzerop = new AstConst(nodep->fileline(), zeronum); constzerop = new AstConst(nodep->fileline(), zeronum);
-441
View File
@@ -1,441 +0,0 @@
//*************************************************************************
// DESCRIPTION: Verilator: Signed/unsigned resolution
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2005-2011 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
//
// Verilator is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//*************************************************************************
// Signedness depends on:
// Decimal numbers are signed
// Based numbers are unsigned unless 's' prefix
// Comparison results are unsigned
// Bit&Part selects are unsigned, even if whole
// Concatenates are unsigned
// Ignore signedness of self-determined:
// shift rhs, ** rhs, x?: lhs, concat and replicate members
// Else, if any operand unsigned, output unsigned
//*************************************************************************
#include "config_build.h"
#include "verilatedos.h"
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <map>
#include <iomanip>
#include "V3Global.h"
#include "V3Signed.h"
#include "V3Ast.h"
//######################################################################
// Signed class functions
class SignedVisitor : public AstNVisitor {
private:
// NODE STATE/TYPES
// STATE
int m_taskDepth; // Recursion check
bool m_paramsOnly; // Computing parameter value; limit operation
// METHODS - special type detection
bool backRequiresUnsigned(AstNode* nodep) {
// The spec doesn't state this, but if you have an array select where the selection
// index is NOT wide enough, you do not sign extend, but always zero extend.
return (nodep->castArraySel()
|| nodep->castSel());
}
// VISITORS
//========
// Signed: Output explicit by user, Lhs either
virtual void visit(AstSigned* nodep, AstNUser*) { signed_Os_Ix(nodep); }
virtual void visit(AstUnsigned* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
//========
// Signed: Output unsigned, Operands either
virtual void visit(AstSel* nodep, AstNUser*) { signed_Ou_Ix(nodep); } //See backRequiresUnsigned
virtual void visit(AstAttrOf* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstCountOnes* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstCLog2* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstPslBool* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstTime* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
//
virtual void visit(AstRedAnd* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstRedOr* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstRedXnor* nodep, AstNUser*){ signed_Ou_Ix(nodep); }
virtual void visit(AstRedXor* nodep,AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstIsUnknown* nodep,AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstOneHot* nodep,AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstOneHot0* nodep,AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstFEof* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstFGetC* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstFGetS* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstFScanF* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstSScanF* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstTestPlusArgs* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstValuePlusArgs* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
//
virtual void visit(AstConcat* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstReplicate* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstRange* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
// ... One presumes these are unsigned out, though the spec doesn't say
virtual void visit(AstLogNot* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstLogAnd* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstLogOr* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstLogIf* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstLogIff* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
// ... These shouldn't matter, just make unsigned
virtual void visit(AstScopeName* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstText* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstUCFunc* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
// ... These comparisons don't care about inbound types
// ... (Though they should match. We don't check.)
virtual void visit(AstEq* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstEqCase* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstEqWild* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstNeq* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstNeqCase* nodep, AstNUser*){ signed_Ou_Ix(nodep); }
virtual void visit(AstNeqWild* nodep, AstNUser*){ signed_Ou_Ix(nodep); }
// ... Opaque returns, so arbitrary
virtual void visit(AstCvtPackString* nodep, AstNUser*){ signed_Ou_Ix(nodep); }
//========
// Signed: Output signed
virtual void visit(AstRand* nodep, AstNUser*) { signed_Os_Ix(nodep); }
//=======
// Signed: Output signed iff LHS signed; unary operator
virtual void visit(AstNot* nodep, AstNUser*) { signed_Olhs(nodep); }
virtual void visit(AstUnaryMin* nodep, AstNUser*) { signed_Olhs(nodep); }
virtual void visit(AstShiftL* nodep, AstNUser*) { signed_Olhs(nodep); }
virtual void visit(AstShiftR* nodep, AstNUser*) { signed_Olhs(nodep); }
// Signed: Output signed iff LHS signed; binary operator
// Note by contrast, bit extract selects are unsigned
virtual void visit(AstArraySel* nodep, AstNUser*) { signed_Olhs(nodep); } //See backRequiresUnsigned
//=======
// Signed: Output signed iff LHS & RHS signed; binary operator
virtual void visit(AstAnd* nodep, AstNUser*) { signed_OlhsAndRhs(nodep); }
virtual void visit(AstOr* nodep, AstNUser*) { signed_OlhsAndRhs(nodep); }
virtual void visit(AstXnor* nodep, AstNUser*) { signed_OlhsAndRhs(nodep); }
virtual void visit(AstXor* nodep, AstNUser*) { signed_OlhsAndRhs(nodep); }
virtual void visit(AstSub* nodep, AstNUser*) { signed_OlhsAndRhs(nodep); }
virtual void visit(AstAdd* nodep, AstNUser*) { signed_OlhsAndRhs(nodep); }
//=======
// Signed: Output signed iff RHS & THS signed
virtual void visit(AstNodeCond* nodep, AstNUser*) { signed_OrhsAndThs(nodep); }
//=======
// These have proper signedness set when they were created.
virtual void visit(AstReturn* nodep, AstNUser*) { nodep->iterateChildren(*this); }
virtual void visit(AstNodeDType* nodep, AstNUser*) { nodep->iterateChildren(*this); }
// Inherit from others
virtual void visit(AstVar* nodep, AstNUser*) {
nodep->iterateChildren(*this);
nodep->signedFrom(nodep->dtypep());
}
virtual void visit(AstNodeVarRef* nodep, AstNUser*) {
nodep->varp()->iterate(*this);
nodep->signedFrom(nodep->varp());
}
virtual void visit(AstEnumItemRef* nodep, AstNUser*) {
nodep->itemp()->iterate(*this);
nodep->signedFrom(nodep->itemp());
}
virtual void visit(AstConst* nodep, AstNUser*) {
// The node got setup with the signed state of the node.
// However a later operation may have changed the node->signed w/o changing
// the number's sign. So we don't: nodep->isSigned(nodep->num().isSigned());
}
virtual void visit(AstNodeFTask* nodep, AstNUser*) {
// Avoid recursion; can't use user() as they're all full, and anyhow this is often called
if (nodep->didSigning()) return;
nodep->didSigning(true);
nodep->iterateChildren(*this);
if (nodep->fvarp()) {
nodep->signedFrom(nodep->fvarp()); // Which will get it from fvarp()->dtypep()
}
}
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (nodep->taskp()) nodep->taskp()->iterate(*this);
nodep->signedFrom(nodep->taskp());
}
virtual void visit(AstRefDType* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (nodep->defp()) nodep->defp()->iterate(*this);
nodep->signedFrom(nodep->skipRefp());
}
virtual void visit(AstNodeIf* nodep, AstNUser*) {
if (!nodep->castGenIf()) { // for m_paramsOnly
nodep->ifsp()->iterateAndNext(*this);
nodep->elsesp()->iterateAndNext(*this);
}
nodep->condp()->iterateAndNext(*this);
}
virtual void visit(AstPin* nodep, AstNUser*) {
// Same as above taskref argument.
nodep->iterateChildren(*this);
}
// VISITORS - Special
virtual void visit(AstSFormatF* nodep, AstNUser*) {
nodep->iterateChildren(*this);
//
UINFO(9," Display in "<<nodep->text()<<endl);
string dispout = "";
bool inPct = false;
AstNode* argp = nodep->exprsp();
for (const char* inp = nodep->text().c_str(); *inp; inp++) {
char ch = *inp; // Breaks with iterators...
if (!inPct && ch=='%') {
inPct = true;
} else if (inPct && isdigit(ch)) {
} else if (tolower(inPct)) {
inPct = false;
switch (tolower(ch)) {
case '%': break; // %% - just output a %
case 'm': break; // %m - auto insert "name"
case 'd': { // Convert decimal to either 'd' or 'u'
if (argp && argp->isSigned()) { // Convert it
ch = '~';
}
if (argp) argp=argp->nextp();
break;
}
default: // Most operators, just move to next argument
if (argp) argp=argp->nextp();
break;
} // switch
}
dispout += ch;
}
nodep->text(dispout);
UINFO(9," Display out "<<nodep->text()<<endl);
}
// VISITORS - These need to be changed to different op types
// Uniop
virtual void visit(AstExtend* nodep, AstNUser*) {
signed_Olhs(nodep);
if (nodep->isSigned() && !backRequiresUnsigned(nodep->backp())) {
replaceWithSignedVersion(nodep, new AstExtendS (nodep->fileline(), nodep->lhsp()->unlinkFrBack())); nodep=NULL;
}
}
virtual void visit(AstExtendS* nodep, AstNUser*) {
signed_Olhs(nodep);
if (!(nodep->isSigned() && !backRequiresUnsigned(nodep->backp()))) {
replaceWithSignedVersion(nodep, new AstExtend (nodep->fileline(), nodep->lhsp()->unlinkFrBack())); nodep=NULL;
}
}
// Biop
virtual void visit(AstPow* nodep, AstNUser*) {
// Pow is special, output sign only depends on LHS sign
signed_Olhs(nodep);
if (nodep->isSigned()) {
replaceWithSignedVersion(nodep, new AstPowS (nodep->fileline(), nodep->lhsp()->unlinkFrBack(), nodep->rhsp()->unlinkFrBack())); nodep=NULL;
}
}
virtual void visit(AstPowS* nodep, AstNUser*) {
// Pow is special, output sign only depends on LHS sign
signed_Olhs(nodep);
if (!nodep->isSigned()) {
replaceWithSignedVersion(nodep, new AstPow (nodep->fileline(), nodep->lhsp()->unlinkFrBack(), nodep->rhsp()->unlinkFrBack())); nodep=NULL;
}
}
// These have different node types, as they operate differently
// Must add to case statement below,
virtual void visit(AstGt* nodep, AstNUser*) { checkReplace_Ou_FlavLhsAndRhs(nodep); }
virtual void visit(AstGtS* nodep, AstNUser*) { checkReplace_Ou_FlavLhsAndRhs(nodep); }
virtual void visit(AstGte* nodep, AstNUser*) { checkReplace_Ou_FlavLhsAndRhs(nodep); }
virtual void visit(AstGteS* nodep, AstNUser*) { checkReplace_Ou_FlavLhsAndRhs(nodep); }
virtual void visit(AstLt* nodep, AstNUser*) { checkReplace_Ou_FlavLhsAndRhs(nodep); }
virtual void visit(AstLtS* nodep, AstNUser*) { checkReplace_Ou_FlavLhsAndRhs(nodep); }
virtual void visit(AstLte* nodep, AstNUser*) { checkReplace_Ou_FlavLhsAndRhs(nodep); }
virtual void visit(AstLteS* nodep, AstNUser*) { checkReplace_Ou_FlavLhsAndRhs(nodep); }
// Need replacements; output matches input sign
virtual void visit(AstDiv* nodep, AstNUser*) { checkReplace_OlhsAndRhs(nodep); }
virtual void visit(AstDivS* nodep, AstNUser*) { checkReplace_OlhsAndRhs(nodep); }
virtual void visit(AstModDiv* nodep, AstNUser*) { checkReplace_OlhsAndRhs(nodep); }
virtual void visit(AstModDivS* nodep, AstNUser*) { checkReplace_OlhsAndRhs(nodep); }
virtual void visit(AstMul* nodep, AstNUser*) { checkReplace_OlhsAndRhs(nodep); }
virtual void visit(AstMulS* nodep, AstNUser*) { checkReplace_OlhsAndRhs(nodep); }
// ShiftRS converts to ShiftR, but not vice-versa
virtual void visit(AstShiftRS* nodep, AstNUser*) { checkReplace_Olhs(nodep); }
void checkReplace_Ou_FlavLhsAndRhs(AstNodeBiop* nodep) {
// For compares, the output of the comparison is unsigned.
// However, we need the appropriate type of compare selected by RHS & LHS
signed_Ou_Ix(nodep);
checkReplace(nodep, nodep->lhsp()->isSigned() && nodep->rhsp()->isSigned());
}
void checkReplace_Olhs(AstNodeBiop* nodep) {
signed_Olhs(nodep);
checkReplace(nodep, nodep->isSigned());
}
void checkReplace_OlhsAndRhs(AstNodeBiop* nodep) {
signed_OlhsAndRhs(nodep);
checkReplace(nodep, nodep->isSigned());
}
void checkReplace(AstNodeBiop* nodep, bool signedFlavorNeeded) {
if (signedFlavorNeeded != nodep->signedFlavor()) {
AstNode* lhsp = nodep->lhsp()->unlinkFrBack();
AstNode* rhsp = nodep->rhsp()->unlinkFrBack();
AstNode* newp = NULL;
// Given a signed/unsigned node type, create the opposite type
switch (nodep->type()) {
case AstType::atGT: newp = new AstGtS (nodep->fileline(), lhsp, rhsp); break;
case AstType::atGTS: newp = new AstGt (nodep->fileline(), lhsp, rhsp); break;
case AstType::atGTE: newp = new AstGteS (nodep->fileline(), lhsp, rhsp); break;
case AstType::atGTES: newp = new AstGte (nodep->fileline(), lhsp, rhsp); break;
case AstType::atLT: newp = new AstLtS (nodep->fileline(), lhsp, rhsp); break;
case AstType::atLTS: newp = new AstLt (nodep->fileline(), lhsp, rhsp); break;
case AstType::atLTE: newp = new AstLteS (nodep->fileline(), lhsp, rhsp); break;
case AstType::atLTES: newp = new AstLte (nodep->fileline(), lhsp, rhsp); break;
case AstType::atDIV: newp = new AstDivS (nodep->fileline(), lhsp, rhsp); break;
case AstType::atDIVS: newp = new AstDiv (nodep->fileline(), lhsp, rhsp); break;
case AstType::atMODDIV: newp = new AstModDivS (nodep->fileline(), lhsp, rhsp); break;
case AstType::atMODDIVS: newp = new AstModDiv (nodep->fileline(), lhsp, rhsp); break;
case AstType::atMUL: newp = new AstMulS (nodep->fileline(), lhsp, rhsp); break;
case AstType::atMULS: newp = new AstMul (nodep->fileline(), lhsp, rhsp); break;
case AstType::atSHIFTRS: newp = new AstShiftR (nodep->fileline(), lhsp, rhsp); break;
default:
nodep->v3fatalSrc("Node needs sign change, but bad case: "<<nodep<<endl);
break;
}
replaceWithSignedVersion(nodep,newp);
}
}
// VISITORS - defaults
virtual void visit(AstNodeMath* nodep, AstNUser*) {
nodep->v3fatalSrc("Visit function missing? Signedness unknown for this node: "<<nodep);
nodep->iterateChildren(*this);
}
virtual void visit(AstNode* nodep, AstNUser*) {
nodep->iterateChildren(*this);
}
// COMMON SCHEMES
// Signed: Output signed, Lhs/Rhs/etc either
void signed_Os_Ix(AstNode* nodep) {
nodep->iterateChildren(*this);
nodep->isSigned(true);
}
// Signed: Output unsigned, Lhs/Rhs/etx either
void signed_Ou_Ix(AstNode* nodep) {
nodep->iterateChildren(*this);
nodep->isSigned(false);
}
// Signed: Output signed iff LHS signed; unary operator
void signed_Olhs(AstNodeUniop* nodep) {
nodep->iterateChildren(*this);
nodep->isSigned(nodep->lhsp()->isSigned());
}
// Signed: Output signed iff LHS signed; binary operator
void signed_Olhs(AstNodeBiop* nodep) {
nodep->iterateChildren(*this);
nodep->isSigned(nodep->lhsp()->isSigned());
}
// Signed: Output signed iff LHS signed; select operator
void signed_Olhs(AstSel* nodep) {
nodep->iterateChildren(*this);
nodep->isSigned(nodep->fromp()->isSigned());
}
// Signed: Output signed iff LHS & RHS signed; binary operator
void signed_OlhsAndRhs(AstNodeBiop* nodep) {
nodep->iterateChildren(*this);
nodep->isSigned(nodep->lhsp()->isSigned() && nodep->rhsp()->isSigned());
}
// Signed: Output signed iff RHS & THS signed
void signed_OrhsAndThs(AstNodeTriop* nodep) {
nodep->iterateChildren(*this);
nodep->isSigned(nodep->rhsp()->isSigned() && nodep->thsp()->isSigned());
}
void replaceWithSignedVersion(AstNode* nodep, AstNode* newp) {
UINFO(6," Replace "<<nodep<<" w/ "<<newp<<endl);
nodep->replaceWith(newp);
newp->widthSignedFrom(nodep);
pushDeletep(nodep); nodep=NULL;
}
public:
// CONSTRUCTORS
SignedVisitor(bool paramsOnly) {
m_paramsOnly = paramsOnly;
m_taskDepth = 0;
}
virtual ~SignedVisitor() {}
AstNode* mainAcceptEdit(AstNode* nodep) {
return nodep->acceptSubtreeReturnEdits(*this);
}
};
//######################################################################
// Signed class functions
/// Remove all $signed, $unsigned, we're done with them.
class SignedRemoveVisitor : public AstNVisitor {
private:
// VISITORS
virtual void visit(AstSigned* nodep, AstNUser*) {
replaceWithSignedVersion(nodep, nodep->lhsp()->unlinkFrBack()); nodep=NULL;
}
virtual void visit(AstUnsigned* nodep, AstNUser*) {
replaceWithSignedVersion(nodep, nodep->lhsp()->unlinkFrBack()); nodep=NULL;
}
virtual void visit(AstNode* nodep, AstNUser*) {
nodep->iterateChildren(*this);
}
void replaceWithSignedVersion(AstNode* nodep, AstNode* newp) {
UINFO(6," Replace "<<nodep<<" w/ "<<newp<<endl);
nodep->replaceWith(newp);
newp->widthSignedFrom(nodep);
pushDeletep(nodep); nodep=NULL;
}
public:
// CONSTRUCTORS
SignedRemoveVisitor() {}
virtual ~SignedRemoveVisitor() {}
AstNode* mainAcceptEdit(AstNode* nodep) {
return nodep->acceptSubtreeReturnEdits(*this);
}
};
//######################################################################
// Top Signed class
void V3Signed::signedAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
(void)signedParamsEdit(nodep);
}
AstNode* V3Signed::signedParamsEdit(AstNode* nodep) {
// Only called from V3Width::widthParamsEdit
UINFO(4,__FUNCTION__<<": "<<endl);
SignedVisitor visitor (true);
nodep = visitor.mainAcceptEdit(nodep);
SignedRemoveVisitor rvisitor;
nodep = rvisitor.mainAcceptEdit(nodep);
return nodep;
}
-40
View File
@@ -1,40 +0,0 @@
// -*- C++ -*-
//*************************************************************************
// DESCRIPTION: Verilator: Signed/unsigned resolution
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2005-2011 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
//
// Verilator is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//*************************************************************************
#ifndef _V3SIGNED_H_
#define _V3SIGNED_H_ 1
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
//============================================================================
class V3Signed {
public:
static void signedAll(AstNetlist* nodep);
protected:
friend class V3Width; // Use widthParamsEdit instead of signedParamsEdit
static AstNode* signedParamsEdit(AstNode* nodep); // May replace nodep
};
#endif // Guard
+8 -4
View File
@@ -53,6 +53,7 @@ class SliceCloneVisitor : public AstNVisitor {
// Inputs: // Inputs:
// AstArraySel::user1p() -> AstVarRef. The VarRef that the final ArraySel points to // AstArraySel::user1p() -> AstVarRef. The VarRef that the final ArraySel points to
// AstNodeAssign::user2() -> int. The number of clones needed for this assign // AstNodeAssign::user2() -> int. The number of clones needed for this assign
// AstArraySel::user3() -> bool. Error detected
// ENUMS // ENUMS
enum RedOp { // The type of unary operation to be expanded enum RedOp { // The type of unary operation to be expanded
@@ -221,6 +222,7 @@ class SliceVisitor : public AstNVisitor {
// AstNode::user2() -> int. The number of clones needed for this node // AstNode::user2() -> int. The number of clones needed for this node
AstUser1InUse m_inuser1; AstUser1InUse m_inuser1;
AstUser2InUse m_inuser2; AstUser2InUse m_inuser2;
AstUser3InUse m_inuser3;
// TYPEDEFS // TYPEDEFS
typedef pair<uint32_t, uint32_t> ArrayDimensions; // Array Dimensions (packed, unpacked) typedef pair<uint32_t, uint32_t> ArrayDimensions; // Array Dimensions (packed, unpacked)
@@ -328,11 +330,11 @@ class SliceVisitor : public AstNVisitor {
m_assignp->v3error("Unsupported: Assignment between a constant and an array slice"); m_assignp->v3error("Unsupported: Assignment between a constant and an array slice");
m_assignError = true; m_assignError = true;
} }
nodep->iterateChildren(*this);
} }
virtual void visit(AstArraySel* nodep, AstNUser*) { virtual void visit(AstArraySel* nodep, AstNUser*) {
if (!m_assignp) return; if (!m_assignp) return;
if (nodep->user3()) return; // Prevent recursion on just created nodes
unsigned dim = explicitDimensions(nodep); unsigned dim = explicitDimensions(nodep);
AstVarRef* refp = nodep->user1p()->castNode()->castVarRef(); AstVarRef* refp = nodep->user1p()->castNode()->castVarRef();
pair<uint32_t,uint32_t> arrDim = refp->varp()->dimensions(); pair<uint32_t,uint32_t> arrDim = refp->varp()->dimensions();
@@ -340,16 +342,18 @@ class SliceVisitor : public AstNVisitor {
if (implicit > 0) { if (implicit > 0) {
AstArraySel* newp = insertImplicit(nodep->cloneTree(false), dim+1, implicit); AstArraySel* newp = insertImplicit(nodep->cloneTree(false), dim+1, implicit);
nodep->replaceWith(newp); nodep = newp; nodep->replaceWith(newp); nodep = newp;
nodep->user3(true);
} }
int clones = countClones(nodep); int clones = countClones(nodep);
if (m_assignp->user2() > 0 && m_assignp->user2() != clones) { if (m_assignp->user2() > 0 && m_assignp->user2() != clones) {
m_assignp->v3error("Slices of arrays in assignments must have the same unpacked dimensions"); m_assignp->v3error("Slices of arrays in assignments must have the same unpacked dimensions");
} else if (m_assignp->user2() == 0 && !m_assignError) { } else if (!m_assignp->user2()) {
if (m_extend && clones > 1) { if (m_extend && clones > 1 && !m_assignError) {
m_assignp->v3error("Unsupported: Assignment between packed arrays of different dimensions"); m_assignp->v3error("Unsupported: Assignment between packed arrays of different dimensions");
m_assignError = true; m_assignError = true;
} }
if (clones > 1 && !refp->lvalue() && refp->varp() == m_lhsVarRefp->varp() && !m_assignp->castAssignDly()) { if (clones > 1 && !refp->lvalue() && refp->varp() == m_lhsVarRefp->varp()
&& !m_assignp->castAssignDly() && !m_assignError) {
// LHS Var != RHS Var for a non-delayed assignment // LHS Var != RHS Var for a non-delayed assignment
m_assignp->v3error("Unsupported: Slices in a non-delayed assignment with the same Var on both sides"); m_assignp->v3error("Unsupported: Slices in a non-delayed assignment with the same Var on both sides");
m_assignError = true; m_assignError = true;
+1 -1
View File
@@ -304,7 +304,7 @@ private:
if (debug()>5) nodep->dumpTree(cout," substw_old: "); if (debug()>5) nodep->dumpTree(cout," substw_old: ");
AstNode* newp = substp->cloneTree(true); AstNode* newp = substp->cloneTree(true);
if (!nodep->isQuad() && newp->isQuad()) { if (!nodep->isQuad() && newp->isQuad()) {
newp = new AstCast (newp->fileline(), newp, nodep); newp = new AstCCast (newp->fileline(), newp, nodep);
} }
if (debug()>5) newp->dumpTree(cout," w_new: "); if (debug()>5) newp->dumpTree(cout," w_new: ");
nodep->replaceWith(newp); nodep->replaceWith(newp);
+49 -50
View File
@@ -380,7 +380,10 @@ private:
UINFO(9, " pin "<<pinp<<endl); UINFO(9, " pin "<<pinp<<endl);
pinp->unlinkFrBack(); // Relinked to assignment below pinp->unlinkFrBack(); // Relinked to assignment below
// //
if (portp->isInout()) { if ((portp->isInout()||portp->isOutput()) && pinp->castConst()) {
pinp->v3error("Function/task output connected to constant instead of variable: "+portp->prettyName());
}
else if (portp->isInout()) {
if (AstVarRef* varrefp = pinp->castVarRef()) { if (AstVarRef* varrefp = pinp->castVarRef()) {
// Connect to this exact variable // Connect to this exact variable
AstVarScope* localVscp = varrefp->varScopep(); if (!localVscp) varrefp->v3fatalSrc("Null var scope"); AstVarScope* localVscp = varrefp->varScopep(); if (!localVscp) varrefp->v3fatalSrc("Null var scope");
@@ -390,9 +393,6 @@ private:
pinp->v3warn(E_TASKNSVAR,"Unsupported: Function/task input argument is not simple variable"); pinp->v3warn(E_TASKNSVAR,"Unsupported: Function/task input argument is not simple variable");
} }
} }
else if (portp->isOutput() && outvscp) {
refp->v3error("Outputs not allowed in function declarations");
}
else if (portp->isOutput()) { else if (portp->isOutput()) {
// Make output variables // Make output variables
// Correct lvalue; we didn't know when we linked // Correct lvalue; we didn't know when we linked
@@ -456,7 +456,7 @@ private:
tempp->stmtsp()->unlinkFrBackWithNext(); tempp->deleteTree(); tempp=NULL; tempp->stmtsp()->unlinkFrBackWithNext(); tempp->deleteTree(); tempp=NULL;
} }
// //
if (debug()>=9) { beginp->dumpTree(cout,"-iotask: "); } if (debug()>=9) { beginp->dumpTreeAndNext(cout,"-iotask: "); }
return beginp; return beginp;
} }
@@ -481,7 +481,10 @@ private:
} else { } else {
UINFO(9, " Port "<<portp<<endl); UINFO(9, " Port "<<portp<<endl);
UINFO(9, " pin "<<pinp<<endl); UINFO(9, " pin "<<pinp<<endl);
if (portp->isInout()) { if ((portp->isInout()||portp->isOutput()) && pinp->castConst()) {
pinp->v3error("Function/task output connected to constant instead of variable: "+portp->prettyName());
}
else if (portp->isInout()) {
if (pinp->castVarRef()) { if (pinp->castVarRef()) {
// Connect to this exact variable // Connect to this exact variable
} else { } else {
@@ -536,7 +539,7 @@ private:
ccallp->addArgsp(new AstVarRef(refp->fileline(), outvscp, true)); ccallp->addArgsp(new AstVarRef(refp->fileline(), outvscp, true));
} }
if (debug()>=9) { beginp->dumpTree(cout,"-nitask: "); } if (debug()>=9) { beginp->dumpTreeAndNext(cout,"-nitask: "); }
return beginp; return beginp;
} }
@@ -584,8 +587,12 @@ private:
// Someday we'll have better type support, and this can make variables and casts. // Someday we'll have better type support, and this can make variables and casts.
// But for now, we'll just text-bash it. // But for now, we'll just text-bash it.
if (bitvec) { if (bitvec) {
// We only support quads, so don't need to sweat longer stuff if (portp->isWide()) {
stmt += "VL_SET_WQ("+portp->name()+toSuffix+", "+portp->name()+frSuffix+")"; stmt += ("VL_SET_SVBV_W("+cvtToStr(portp->width())
+", "+portp->name()+toSuffix+", "+portp->name()+frSuffix+")");
} else {
stmt += "VL_SET_WQ("+portp->name()+toSuffix+", "+portp->name()+frSuffix+")";
}
} else { } else {
if (isPtr) stmt += "*"; // DPI outputs are pointers if (isPtr) stmt += "*"; // DPI outputs are pointers
stmt += portp->name()+toSuffix+" = "; stmt += portp->name()+toSuffix+" = ";
@@ -602,7 +609,7 @@ private:
return new AstCStmt(portp->fileline(), stmt); return new AstCStmt(portp->fileline(), stmt);
} }
AstNode* createAssignDpiToInternal(AstVarScope* portvscp, const string& frName) { AstNode* createAssignDpiToInternal(AstVarScope* portvscp, const string& frName, bool cvt) {
// Create assignment from DPI temporary into internal format // Create assignment from DPI temporary into internal format
AstVar* portp = portvscp->varp(); AstVar* portp = portvscp->varp();
string stmt; string stmt;
@@ -611,6 +618,9 @@ private:
stmt += "VL_CVT_VP_Q("; stmt += "VL_CVT_VP_Q(";
ket += ")"; ket += ")";
} }
if (!cvt
&& portp->basicp() && portp->basicp()->isBitLogic() && portp->widthMin() != 1 && !portp->isWide())
stmt += "*"; // it's a svBitVecVal, which other code won't think is arrayed (as WData aren't), but really is
stmt += frName; stmt += frName;
stmt += ket; stmt += ket;
// Use a AstCMath, as we want V3Clean to mask off bits that don't make sense. // Use a AstCMath, as we want V3Clean to mask off bits that don't make sense.
@@ -677,7 +687,7 @@ private:
argnodesp = argnodesp->addNextNull(refp); argnodesp = argnodesp->addNextNull(refp);
if (portp->isInput()) { if (portp->isInput()) {
dpip->addStmtsp(createAssignDpiToInternal(outvscp, portp->name())); dpip->addStmtsp(createAssignDpiToInternal(outvscp, portp->name(), false));
} }
} }
} }
@@ -792,7 +802,7 @@ private:
if (AstVar* portp = stmtp->castVar()) { if (AstVar* portp = stmtp->castVar()) {
if (portp->isIO() && (portp->isOutput() || portp->isFuncReturn())) { if (portp->isIO() && (portp->isOutput() || portp->isFuncReturn())) {
AstVarScope* portvscp = portp->user2p()->castNode()->castVarScope(); // Remembered when we created it earlier AstVarScope* portvscp = portp->user2p()->castNode()->castVarScope(); // Remembered when we created it earlier
cfuncp->addStmtsp(createAssignDpiToInternal(portvscp,portp->name()+"__Vcvt")); cfuncp->addStmtsp(createAssignDpiToInternal(portvscp,portp->name()+"__Vcvt",true));
} }
} }
} }
@@ -1011,40 +1021,22 @@ private:
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
m_scopep = NULL; m_scopep = NULL;
} }
virtual void visit(AstTaskRef* nodep, AstNUser*) { virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
iterateIntoFTask(nodep->taskp()); // First, do hierarchical funcs
UINFO(4," Task REF "<<nodep<<endl);
if (debug()>=9) { nodep->dumpTree(cout,"-inltask:"); }
// Create cloned statements
string namePrefix = "__Vtask_"+nodep->taskp()->shortName()+"__"+cvtToStr(m_modNCalls++);
AstNode* beginp;
if (m_statep->ftaskNoInline(nodep->taskp())) {
beginp = createNonInlinedFTask(nodep, namePrefix, NULL);
} else {
beginp = createInlinedFTask(nodep, namePrefix, NULL);
}
// Replace the ref
nodep->replaceWith(beginp);
nodep->deleteTree(); nodep=NULL;
}
virtual void visit(AstFuncRef* nodep, AstNUser*) {
UINFO(4," Func REF "<<nodep<<endl);
if (debug()>=9) { nodep->dumpTree(cout,"-preref:"); }
// First, do hierarchical funcs
AstNodeFTask* funcp = nodep->taskp();
if (!funcp) nodep->v3fatalSrc("unlinked");
if (!funcp->isFunction()) nodep->v3fatalSrc("func reference to non-function");
if (!m_scopep) nodep->v3fatalSrc("func ref not under scope");
// Inline func refs in the function
iterateIntoFTask(funcp);
// Create output variable
string namePrefix = "__Vfunc_"+nodep->taskp()->shortName()+"__"+cvtToStr(m_modNCalls++);
AstVarScope* outvscp = createVarScope (funcp->fvarp()->castVar(),
namePrefix+"__Vfuncout");
// Create cloned statements
if (debug()>=9) { nodep->taskp()->dumpTree(cout,"-oldfunc:"); }
if (!nodep->taskp()) nodep->v3fatalSrc("Unlinked?"); if (!nodep->taskp()) nodep->v3fatalSrc("Unlinked?");
iterateIntoFTask(nodep->taskp()); // First, do hierarchical funcs
UINFO(4," FTask REF "<<nodep<<endl);
if (debug()>=9) { nodep->dumpTree(cout,"-inlfunc:"); }
if (!m_scopep) nodep->v3fatalSrc("func ref not under scope");
string namePrefix = ((nodep->castFuncRef()?"__Vfunc_":"__Vtask_")
+nodep->taskp()->shortName()+"__"+cvtToStr(m_modNCalls++));
// Create output variable
AstVarScope* outvscp = NULL;
if (nodep->taskp()->isFunction()) {
// Not that it's a FUNCREF, but that we're calling a function (perhaps as a task)
outvscp = createVarScope (nodep->taskp()->fvarp()->castVar(),
namePrefix+"__Vfuncout");
}
// Create cloned statements
AstNode* beginp; AstNode* beginp;
if (m_statep->ftaskNoInline(nodep->taskp())) { if (m_statep->ftaskNoInline(nodep->taskp())) {
// This may share VarScope's with a public task, if any. Yuk. // This may share VarScope's with a public task, if any. Yuk.
@@ -1053,13 +1045,20 @@ private:
beginp = createInlinedFTask(nodep, namePrefix, outvscp); beginp = createInlinedFTask(nodep, namePrefix, outvscp);
} }
// Replace the ref // Replace the ref
AstVarRef* outrefp = new AstVarRef (nodep->fileline(), outvscp, false); if (nodep->castFuncRef()) {
nodep->replaceWith(outrefp); if (!nodep->taskp()->isFunction()) nodep->v3fatalSrc("func reference to non-function");
// Insert new statements AstVarRef* outrefp = new AstVarRef (nodep->fileline(), outvscp, false);
insertBeforeStmt(nodep, beginp); nodep->replaceWith(outrefp);
// Insert new statements
insertBeforeStmt(nodep, beginp);
} else {
// outvscp maybe non-NULL if calling a function in a taskref,
// but if so we want to simply ignore the function result
nodep->replaceWith(beginp);
}
// Cleanup // Cleanup
nodep->deleteTree(); nodep=NULL; nodep->deleteTree(); nodep=NULL;
UINFO(4," Func REF Done.\n"); UINFO(4," FTask REF Done.\n");
} }
virtual void visit(AstNodeFTask* nodep, AstNUser*) { virtual void visit(AstNodeFTask* nodep, AstNUser*) {
UINFO(4," Inline "<<nodep<<endl); UINFO(4," Inline "<<nodep<<endl);
+2 -2
View File
@@ -75,8 +75,8 @@ private:
if (prettyName.find("._") != string::npos) if (prettyName.find("._") != string::npos)
return "Inlined leading underscore"; return "Inlined leading underscore";
} }
if (nodep->width() > 256) return "Wide bus > 256 bits"; if ((int)nodep->width() > v3Global.opt.traceMaxWidth()) return "Wide bus > --trace-max-width bits";
if (nodep->arrayElements() > 32) return "Wide memory > 32 ents"; if ((int)nodep->arrayElements() > v3Global.opt.traceMaxArray()) return "Wide memory > --trace-max-array ents";
if (!(nodep->dtypeSkipRefp()->castBasicDType() if (!(nodep->dtypeSkipRefp()->castBasicDType()
|| (nodep->dtypeSkipRefp()->castArrayDType() || (nodep->dtypeSkipRefp()->castArrayDType()
&& nodep->dtypeSkipRefp()->castArrayDType()->dtypeSkipRefp()->castBasicDType()))) { && nodep->dtypeSkipRefp()->castArrayDType()->dtypeSkipRefp()->castBasicDType()))) {
+38 -7
View File
@@ -159,8 +159,8 @@ private:
// assign x = (OE) ? 'hz : y; // assign x = (OE) ? 'hz : y;
// see if this a COND and separate out the __en logic from the output logic if it is // see if this a COND and separate out the __en logic from the output logic if it is
if (nodep->rhsp()->castCond()) { if (AstCond* condp = nodep->rhsp()->castCond()) {
AstCond* condp = nodep->rhsp()->castCond(); //if (debug()>=9) nodep->dumpTree(cout,"- cond-in: ");
AstNode* oep = condp->condp(); AstNode* oep = condp->condp();
AstNode* expr1p = condp->expr1p(); AstNode* expr1p = condp->expr1p();
AstNode* expr2p = condp->expr2p(); AstNode* expr2p = condp->expr2p();
@@ -192,17 +192,44 @@ private:
// replace the old assign logic with the new one // replace the old assign logic with the new one
AstAssignW* newassp = new AstAssignW(nodep->fileline(), outp,outrhsp); AstAssignW* newassp = new AstAssignW(nodep->fileline(), outp,outrhsp);
//if (debug()>=9) newassp->dumpTreeAndNext(cout,"- cond-out: ");
nodep->replaceWith(newassp); nodep->replaceWith(newassp);
nodep->deleteTree(); nodep=NULL; nodep->deleteTree(); nodep=NULL;
newassp->iterateChildren(*this); newassp->iterateChildren(*this);
} else { }
// How about a tri gate?
else if (AstBufIf1* bufp = nodep->rhsp()->castBufIf1()) {
//if (debug()>=9) nodep->dumpTree(cout,"- tri-in : ");
AstNode* enrhsp = bufp->lhsp()->unlinkFrBack();
AstNode* outrhsp = bufp->rhsp()->unlinkFrBack();
AstNode* outp = nodep->lhsp()->unlinkFrBack();;
AstVarRef* outrefp = NULL;
if (outp->castVarRef()) {
outrefp = outp->castVarRef();
} else if (outp->castSel()) {
outrefp = outp->castSel()->fromp()->castVarRef();
} else {
nodep->v3error("Can't find LHS varref");
}
createEnableVar(outp, outrefp, enrhsp, outrhsp->width());
// replace the old assign logic with the new one
AstAssignW* newassp = new AstAssignW(nodep->fileline(), outp,outrhsp);
//if (debug()>=9) newassp->dumpTreeAndNext(cout,"- tri-out: ");
nodep->replaceWith(newassp);
nodep->deleteTree(); nodep=NULL;
newassp->iterateChildren(*this);
}
else {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
} }
AstVar* createEnableVar(AstNode* outp, AstVarRef* outrefp, AstNode* enrhsp, int width, string suffix="") { AstVar* createEnableVar(AstNode* outp, AstVarRef* outrefp, AstNode* enrhsp, int width, string suffix="") {
// this function creates an __en Var that cooresponds to // this function creates an __en Var that corresponds to
// the outp and outrefp and creates an assignw to enrhsp // the outp and outrefp and creates an assignw to enrhsp
AstVar* enp = new AstVar (outrefp->varp()->fileline(), AstVar* enp = new AstVar (outrefp->varp()->fileline(),
AstVarType::MODULETEMP, AstVarType::MODULETEMP,
@@ -218,10 +245,14 @@ private:
enrhsp->v3error("Don't know how to deal with selection logic wider than 1 bit"); enrhsp->v3error("Don't know how to deal with selection logic wider than 1 bit");
} }
} }
AstNode* newassp = new AstAssignW (enp->fileline(),
new AstVarRef (enp->fileline(), enp, true),
enrhsp);
if (debug()>=9) enp->dumpTreeAndNext(cout,"- cev-out: ");
if (debug()>=9) newassp->dumpTreeAndNext(cout,"- cev-out: ");
m_modp->addStmtp(enp); m_modp->addStmtp(enp);
m_modp->addStmtp(new AstAssignW (enp->fileline(), m_modp->addStmtp(newassp);
new AstVarRef (enp->fileline(), enp, true),
enrhsp));
outrefp->user1p(enp); // put __en signal into varref for later usage outrefp->user1p(enp); // put __en signal into varref for later usage
outrefp->varp()->user1p(enp); // put __en signal into var as well in the event this is a single lhs driver and this needs passed up one level outrefp->varp()->user1p(enp); // put __en signal into var as well in the event this is a single lhs driver and this needs passed up one level
+9
View File
@@ -170,27 +170,36 @@ public:
// thus undriven+unused bits get UNUSED warnings, as they're not as buggy. // thus undriven+unused bits get UNUSED warnings, as they're not as buggy.
if (!unusedMatch(nodep)) { if (!unusedMatch(nodep)) {
nodep->v3warn(UNUSED, "Signal is not driven, nor used: "<<nodep->prettyName()); nodep->v3warn(UNUSED, "Signal is not driven, nor used: "<<nodep->prettyName());
nodep->fileline()->modifyWarnOff(V3ErrorCode::UNUSED, true); // Warn only once
} }
} else if (allD && !anyU) { } else if (allD && !anyU) {
if (!unusedMatch(nodep)) { if (!unusedMatch(nodep)) {
nodep->v3warn(UNUSED, "Signal is not used: "<<nodep->prettyName()); nodep->v3warn(UNUSED, "Signal is not used: "<<nodep->prettyName());
nodep->fileline()->modifyWarnOff(V3ErrorCode::UNUSED, true); // Warn only once
} }
} else if (!anyD && allU) { } else if (!anyD && allU) {
nodep->v3warn(UNDRIVEN, "Signal is not driven: "<<nodep->prettyName()); nodep->v3warn(UNDRIVEN, "Signal is not driven: "<<nodep->prettyName());
nodep->fileline()->modifyWarnOff(V3ErrorCode::UNDRIVEN, true); // Warn only once
} else { } else {
// Bits have different dispositions // Bits have different dispositions
bool setU=false; bool setD=false;
if (anynotDU && !unusedMatch(nodep)) { if (anynotDU && !unusedMatch(nodep)) {
nodep->v3warn(UNUSED, "Bits of signal are not driven, nor used: "<<nodep->prettyName() nodep->v3warn(UNUSED, "Bits of signal are not driven, nor used: "<<nodep->prettyName()
<<bitNames(BN_BOTH)); <<bitNames(BN_BOTH));
setU=true;
} }
if (anyDnotU && !unusedMatch(nodep)) { if (anyDnotU && !unusedMatch(nodep)) {
nodep->v3warn(UNUSED, "Bits of signal are not used: "<<nodep->prettyName() nodep->v3warn(UNUSED, "Bits of signal are not used: "<<nodep->prettyName()
<<bitNames(BN_UNUSED)); <<bitNames(BN_UNUSED));
setU=true;
} }
if (anyUnotD) { if (anyUnotD) {
nodep->v3warn(UNDRIVEN, "Bits of signal are not driven: "<<nodep->prettyName() nodep->v3warn(UNDRIVEN, "Bits of signal are not driven: "<<nodep->prettyName()
<<bitNames(BN_UNDRIVEN)); <<bitNames(BN_UNDRIVEN));
setD=true;
} }
if (setU) nodep->fileline()->modifyWarnOff(V3ErrorCode::UNUSED, true); // Warn only once
if (setD) nodep->fileline()->modifyWarnOff(V3ErrorCode::UNDRIVEN, true); // Warn only once
} }
} }
} }
+2 -1
View File
@@ -187,8 +187,9 @@ private:
UINFO(8," In Numbers: for (v="<<valInit<<"; v<"<<valStop<<"; v=v+"<<valInc<<")\n"); UINFO(8," In Numbers: for (v="<<valInit<<"; v<"<<valStop<<"; v=v+"<<valInc<<")\n");
// //
if (!m_generate) { if (!m_generate) {
UINFO(8, " ~Iters: "<<((valStop - valInit)/valInc)<<" c="<<unrollCount()<<endl);
int loops = ((valStop - valInit)/valInc); int loops = ((valStop - valInit)/valInc);
if (loops < 0) { loops += (1ULL<<constStopp->width()); } // Will roll around
UINFO(8, " ~Iters: "<<loops<<" c="<<unrollCount()<<endl);
if (loops > unrollCount()) if (loops > unrollCount())
return cantUnroll(nodep, "too many iterations"); return cantUnroll(nodep, "too many iterations");
+1076 -540
View File
File diff suppressed because it is too large Load Diff
-1
View File
@@ -34,7 +34,6 @@ public:
static void width(AstNetlist* nodep); static void width(AstNetlist* nodep);
// Smaller step... Only do a single node for parameter propagation // Smaller step... Only do a single node for parameter propagation
static AstNode* widthParamsEdit(AstNode* nodep); static AstNode* widthParamsEdit(AstNode* nodep);
static AstNode* widthParamsEditIfNeed(AstNode* nodep);
// Final step... Mark all widths as equal // Final step... Mark all widths as equal
static void widthCommit(AstNetlist* nodep); static void widthCommit(AstNetlist* nodep);
+103
View File
@@ -0,0 +1,103 @@
// -*- C++ -*-
//*************************************************************************
// DESCRIPTION: Verilator: Cleanup stage in V3Width
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
//
// Verilator is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//*************************************************************************
#ifndef _V3WIDTHCOMMIT_H_
#define _V3WIDTHCOMMIT_H_ 1
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
#ifndef _V3WIDTH_CPP_
# error "V3WidthCommit for V3Width internal use only"
#endif
//######################################################################
/// Remove all $signed, $unsigned, we're done with them.
class WidthRemoveVisitor : public AstNVisitor {
private:
// VISITORS
virtual void visit(AstSigned* nodep, AstNUser*) {
replaceWithSignedVersion(nodep, nodep->lhsp()->unlinkFrBack()); nodep=NULL;
}
virtual void visit(AstUnsigned* nodep, AstNUser*) {
replaceWithSignedVersion(nodep, nodep->lhsp()->unlinkFrBack()); nodep=NULL;
}
virtual void visit(AstNode* nodep, AstNUser*) {
nodep->iterateChildren(*this);
}
void replaceWithSignedVersion(AstNode* nodep, AstNode* newp) {
UINFO(6," Replace "<<nodep<<" w/ "<<newp<<endl);
nodep->replaceWith(newp);
newp->widthSignedFrom(nodep);
pushDeletep(nodep); nodep=NULL;
}
public:
// CONSTRUCTORS
WidthRemoveVisitor() {}
virtual ~WidthRemoveVisitor() {}
AstNode* mainAcceptEdit(AstNode* nodep) {
return nodep->acceptSubtreeReturnEdits(*this);
}
};
//######################################################################
class WidthCommitVisitor : public AstNVisitor {
// Now that all widthing is complete,
// Copy all width() to widthMin(). V3Const expects this
private:
// VISITORS
virtual void visit(AstConst* nodep, AstNUser*) {
nodep->width(nodep->width(),nodep->width());
if ((nodep->width() != nodep->num().width()) || !nodep->num().sized()) {
V3Number num (nodep->fileline(), nodep->width());
num.opAssign(nodep->num());
num.isSigned(nodep->isSigned());
AstNode* newp = new AstConst(nodep->fileline(), num);
nodep->replaceWith(newp);
//if (debug()>4) nodep->dumpTree(cout," fixConstSize_old: ");
//if (debug()>4) newp->dumpTree(cout," _new: ");
pushDeletep(nodep); nodep=NULL;
}
}
virtual void visit(AstNode* nodep, AstNUser*) {
nodep->width(nodep->width(),nodep->width());
nodep->iterateChildren(*this);
}
virtual void visit(AstNodePreSel* nodep, AstNUser*) {
// This check could go anywhere after V3Param
nodep->v3fatalSrc("Presels should have been removed before this point");
}
public:
// CONSTUCTORS
WidthCommitVisitor(AstNetlist* nodep) {
nodep->accept(*this);
}
virtual ~WidthCommitVisitor() {}
};
//######################################################################
#endif // Guard
+3 -3
View File
@@ -111,12 +111,12 @@ private:
// We must make sure sub gets sign of original value // We must make sure sub gets sign of original value
AstNode* newp = new AstSub(lhsp->fileline(), lhsp, AstNode* newp = new AstSub(lhsp->fileline(), lhsp,
new AstConst(lhsp->fileline(), AstConst::Unsized32(), rhs)); new AstConst(lhsp->fileline(), AstConst::Unsized32(), rhs));
newp->signedFrom(lhsp); newp->numericFrom(lhsp);
return newp; return newp;
} else { // rhs < 0; } else { // rhs < 0;
AstNode* newp = new AstAdd(lhsp->fileline(), lhsp, AstNode* newp = new AstAdd(lhsp->fileline(), lhsp,
new AstConst(lhsp->fileline(), AstConst::Unsized32(), -rhs)); new AstConst(lhsp->fileline(), AstConst::Unsized32(), -rhs));
newp->signedFrom(lhsp); newp->numericFrom(lhsp);
return newp; return newp;
} }
} }
@@ -126,7 +126,7 @@ private:
AstNode* newp = new AstSub(rhsp->fileline(), AstNode* newp = new AstSub(rhsp->fileline(),
new AstConst(rhsp->fileline(), AstConst::Unsized32(), lhs), new AstConst(rhsp->fileline(), AstConst::Unsized32(), lhs),
rhsp); rhsp);
newp->signedFrom(rhsp); // Important as AstSub default is lhs's sign newp->numericFrom(rhsp); // Important as AstSub default is lhs's sign
return newp; return newp;
} }
+2 -7
View File
@@ -74,7 +74,6 @@
#include "V3PreShell.h" #include "V3PreShell.h"
#include "V3Premit.h" #include "V3Premit.h"
#include "V3Scope.h" #include "V3Scope.h"
#include "V3Signed.h"
#include "V3Slice.h" #include "V3Slice.h"
#include "V3Split.h" #include "V3Split.h"
#include "V3SplitAs.h" #include "V3SplitAs.h"
@@ -168,9 +167,6 @@ void process () {
V3Width::width(v3Global.rootp()); V3Width::width(v3Global.rootp());
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("width.tree")); v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("width.tree"));
// Compute signed/unsigned
V3Signed::signedAll(v3Global.rootp());
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("signed.tree"));
V3Error::abortIfErrors(); V3Error::abortIfErrors();
// Commit to the widths we've chosen; Make widthMin==width // Commit to the widths we've chosen; Make widthMin==width
@@ -571,9 +567,6 @@ int main(int argc, char** argv, char** env) {
v3Global.opt.bin(argv[0]); v3Global.opt.bin(argv[0]);
string argString = V3Options::argString(argc-1, argv+1); string argString = V3Options::argString(argc-1, argv+1);
v3Global.opt.parseOpts(new FileLine("COMMAND_LINE",0), argc-1, argv+1); v3Global.opt.parseOpts(new FileLine("COMMAND_LINE",0), argc-1, argv+1);
if (v3Global.opt.coverage() && !v3Global.opt.systemPerl() && !v3Global.opt.lintOnly()) {
v3fatal("Unsupported: Coverage analysis requires --sp output.");
}
if (!v3Global.opt.outFormatOk() if (!v3Global.opt.outFormatOk()
&& !v3Global.opt.preprocOnly() && !v3Global.opt.preprocOnly()
&& !v3Global.opt.lintOnly() && !v3Global.opt.lintOnly()
@@ -630,6 +623,8 @@ int main(int argc, char** argv, char** env) {
V3File::writeTimes(v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"__verFiles.dat", argString); V3File::writeTimes(v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"__verFiles.dat", argString);
} }
// Final writing shouldn't throw warnings, but...
V3Error::abortIfWarnings();
#ifdef VL_LEAK_CHECKS #ifdef VL_LEAK_CHECKS
// Cleanup memory for valgrind leak analysis // Cleanup memory for valgrind leak analysis
v3Global.clear(); v3Global.clear();
+95 -22
View File
@@ -9,7 +9,7 @@ use Pod::Usage;
use strict; use strict;
use vars qw ($Debug $VERSION); use vars qw ($Debug $VERSION);
$VERSION = '3.202'; $VERSION = '3.307';
our $Self; our $Self;
@@ -74,9 +74,10 @@ sub parameter {
sub process { sub process {
remove_outputs(); remove_outputs();
clean_input($Opt_Input, tmp_prefix().".y"); $Self->{bison_version} = bison_version_check();
my $supports_report = ($Self->{bison_version} >= 2.3);
my $supports_report = (bison_version_check() >= 2.3); clean_input($Opt_Input, tmp_prefix().".y");
# Run bison # Run bison
my $command = ($Opt_Yacc my $command = ($Opt_Yacc
@@ -100,11 +101,11 @@ sub process {
die "bisonpre: %Error: $Opt_Yacc version $v run failed due to errors\n"; die "bisonpre: %Error: $Opt_Yacc version $v run failed due to errors\n";
} }
clean_output(tmp_prefix().".output",output_prefix().".output", 1); clean_output(tmp_prefix().".output",output_prefix().".output", 1,0);
warning_check(output_prefix().".output"); warning_check(output_prefix().".output");
clean_output(tmp_prefix().".c", output_prefix().".c", 0); clean_output(tmp_prefix().".c", output_prefix().".c", 0,1);
clean_output(tmp_prefix().".h", output_prefix().".h", 0); clean_output(tmp_prefix().".h", output_prefix().".h", 0,1);
remove_tmp(); remove_tmp();
} }
@@ -150,15 +151,17 @@ sub clean_output {
my $filename = shift; my $filename = shift;
my $outname = shift || $filename; my $outname = shift || $filename;
my $is_output = shift; my $is_output = shift;
my $is_c = shift;
print " edit $filename $outname\n"; print " edit $filename $outname\n";
my $fh = IO::File->new("<$filename") or die "%Error: $! $filename\n"; my $fh = IO::File->new("<$filename") or die "%Error: $! $filename\n";
my @lines = $fh->getlines; my @lines = $fh->getlines;
$fh->close; $fh->close;
(my $basename = tmp_prefix().".y") =~ s!.*/!!; (my $basename = tmp_prefix().".") =~ s!.*/!!;
$basename = quotemeta($basename); $basename = quotemeta($basename);
(my $newbase = $Opt_Input) =~ s!.*/!!; (my $newbase = $Opt_Input) =~ s!.*/!!;
$newbase =~ s/\.y/./;
if ($is_output) { if ($is_output) {
my %state_line; my $l=0; my %state_line; my $l=0;
@@ -178,6 +181,28 @@ sub clean_output {
} }
@lines = @out; @out = (); @lines = @out; @out = ();
} }
if ($is_c) {
my %token_values;
my $in_en=0;
foreach my $line (@lines) {
$in_en=1 if $line =~ /enum\s+yytokentype/;
$in_en=0 if $line =~ /;/;
$token_values{$2} = $1 if $in_en && $line =~ /\b(\S+) = (\d+)/;
}
my @out;
foreach my $line (@lines) {
if ($line =~ /BISONPRE_TOKEN_NAMES/) {
push @out, $line;
foreach my $tv (sort keys %token_values) {
push @out, sprintf("\tcase %d: return \"%s\";\n",
$tv, $token_values{$tv});
}
next;
}
push @out, $line;
}
@lines = @out; @out = ();
}
$fh = IO::File->new(">$outname") or die "%Error: $! writing $outname\n"; $fh = IO::File->new(">$outname") or die "%Error: $! writing $outname\n";
foreach my $line (@lines) { foreach my $line (@lines) {
@@ -211,6 +236,7 @@ sub clean_input {
my $outname = shift || $filename; # Can == filename if desired my $outname = shift || $filename; # Can == filename if desired
print " edit $filename $outname\n"; print " edit $filename $outname\n";
$Self->{filename} = $filename;
my $fh = IO::File->new("<$filename") or die "%Error: $! $filename\n"; my $fh = IO::File->new("<$filename") or die "%Error: $! $filename\n";
my @lines = $fh->getlines; my @lines = $fh->getlines;
$fh->close; $fh->close;
@@ -232,7 +258,7 @@ sub clean_input {
$section++; $section++;
if ($section==2) { $last_rule = undef; } if ($section==2) { $last_rule = undef; }
} }
elsif ($line =~ s/^([a-zA-Z0-9_]+)<(\S+)>:/$1:/) { elsif ($line =~ s/^([a-zA-Z0-9_]+)<(\S*)>:/$1:/) {
!$rules{$1}{name} or die "%Error: $filename:$l: Redeclaring '$1': $line\n"; !$rules{$1}{name} or die "%Error: $filename:$l: Redeclaring '$1': $line\n";
$types{$2}{$1} = 1; $types{$2}{$1} = 1;
$rules{$1}{name} = $1; $rules{$1}{name} = $1;
@@ -272,6 +298,25 @@ sub clean_input {
#use Data::Dumper; print Dumper(\%rules); #use Data::Dumper; print Dumper(\%rules);
# Replace BISONPRE_VERSION(ver,,...) with expanded list
{
my @linesin = @lines; @lines=(); my $l=0;
foreach my $line (@linesin) {
$l++;
if ($line =~ /BISONPRE_VERSION/) {
($line =~ /BISONPRE_VERSION\((\S+)\s*,\s*([^\),]+)\)\s*$/)
or die "%Error: $filename:$l: Bad form of BISONPRE_VERSION: $line\n";
my $ver=$1; my $cmd=$2;
if ($Self->{bison_version} >= $1) {
$line = $cmd."\n";
} else {
$line = "//NOP: $line";
}
}
push @lines, $line;
}
}
# Replace BISONPRE_NOT(type,...) with expanded list # Replace BISONPRE_NOT(type,...) with expanded list
{ {
my @linesin = @lines; @lines=(); my $l=0; my @linesin = @lines; @lines=(); my $l=0;
@@ -308,20 +353,7 @@ sub clean_input {
foreach my $line (@linesin) { foreach my $line (@linesin) {
$l++; $l++;
if ($line =~ /BISONPRE_COPY/) { if ($line =~ /BISONPRE_COPY/) {
($line =~ s/BISONPRE_COPY\((\S+)\s*,\s*{([^}]*)}\s*\)/{HERE}/) $line = _bisonpre_copy($line,$l,0);
or die "%Error: $filename:$l: Bad form of BISONPRE_NOT: $line\n";
my $rule = $1; my $code = $2;
$rules{$rule} or die "%Error: $filename:$l: Can't find definition for rule: $rule\n";
# Push it all onto one line to avoid error messages changing
my $insert = $rules{$rule}{rules_and_productions};
$insert =~ s/^\S+://g; # Strip rule name
#print "COPY code $code\n";
#print "COPY in $insert\n";
$_=$insert; eval("$code; \$_;"); $insert = $_;
#print "COPY out $insert\n";
while ($insert =~ s/[ \t\n]+\n/\n/go) {}
while ($insert =~ s/\n/ /go) {} # Optional - preserve line numbering
$line =~ s/{HERE}/$insert/;
} }
push @lines, $line; push @lines, $line;
} }
@@ -346,6 +378,7 @@ sub clean_input {
if ($line =~ m!//BISONPRE_TYPES!) { if ($line =~ m!//BISONPRE_TYPES!) {
push @lines, $line; push @lines, $line;
foreach my $type (sort keys %types) { foreach my $type (sort keys %types) {
next if !$type;
my $line = "%type<$type>\t"; my $line = "%type<$type>\t";
foreach my $rule (sort keys %{$types{$type}}) { foreach my $rule (sort keys %{$types{$type}}) {
$line.=" ".$rule; $line.=" ".$rule;
@@ -372,6 +405,37 @@ sub clean_input {
$fh->close; $fh->close;
} }
sub _bisonpre_copy {
my $text = shift;
my $l = shift;
my $depth = shift;
while ($text =~ /BISONPRE_COPY/) {
($text =~ s/BISONPRE_COPY(_ONCE)?\((\S+)\s*,\s*{([^}]*)}\s*\)/{HERE}/)
or die "%Error: $Self->{filename}:$l: Bad form of BISONPRE_NOT: $text\n";
my $once = $1; my $rule = $2; my $code = $3;
$Self->{rules}{$rule} or die "%Error: $Self->{filename}:$l: Can't find definition for rule: $rule\n";
if ($depth > 0 && $once) {
# _ONCE means don't inherit
$text =~ s/\|[ \t]+{HERE}//; # Don't OR in nothing
$text =~ s/{HERE}//;
} else {
# Push it all onto one line to avoid error messages changing
my $insert = $Self->{rules}{$rule}{rules_and_productions};
$insert =~ s/^\S+://g; # Strip rule name
# Recurse so BISONPRE under B
#print "COPY $l code $code\n";
#print "COPY $l in $insert\n";
$_=$insert; eval("$code; \$_;"); $insert = $_;
#print "COPY $l out $insert\n";
while ($insert =~ s/[ \t\n]+\n/\n/go) {}
while ($insert =~ s/\n/ /go) {} # Optional - preserve line numbering
$text =~ s/{HERE}/$insert/;
}
$depth++;
}
return $text;
}
####################################################################### #######################################################################
__END__ __END__
@@ -416,10 +480,19 @@ rule. The type will be inserted where /*BISONPRE_TYPES*/ is encountered.
Copy the rules and productions from the specified rule, filter through the Copy the rules and productions from the specified rule, filter through the
Perl code provided in the {} and insert here into the output file. Perl code provided in the {} and insert here into the output file.
=item BISONPRE_COPY_ONCE(rule, {code})
As with BISONPRE_COPY, but if called from underneath another BISONPRE_COPY
rule, ignore it.
=item BISONPRE_NOT(token[, token...]) =item BISONPRE_NOT(token[, token...])
Create a rule that matches every token except for those specified. Create a rule that matches every token except for those specified.
=item BISONPRE_VERSION(ver, cmd)
If the bison version is >= the specified version, include the given command.
=back =back
=head1 ARGUMENTS =head1 ARGUMENTS
+1 -1
View File
@@ -25,7 +25,7 @@
//********************************************************************** //**********************************************************************
//**** Version and host name //**** Version and host name
#define DTVERSION "Verilator 3.810 2010/07/10" #define DTVERSION "Verilator 3.820 2011/07/28"
//********************************************************************** //**********************************************************************
//**** Functions //**** Functions
+32 -8
View File
@@ -174,6 +174,7 @@ word [a-zA-Z0-9_]+
/* Extensions to Verilog set, some specified by PSL */ /* Extensions to Verilog set, some specified by PSL */
"$c"[0-9]* { FL; return yD_C; } /*Verilator only*/ "$c"[0-9]* { FL; return yD_C; } /*Verilator only*/
/* System Tasks */ /* System Tasks */
"$bitstoreal" { FL; return yD_BITSTOREAL; }
"$display" { FL; return yD_DISPLAY; } "$display" { FL; return yD_DISPLAY; }
"$fclose" { FL; return yD_FCLOSE; } "$fclose" { FL; return yD_FCLOSE; }
"$fdisplay" { FL; return yD_FDISPLAY; } "$fdisplay" { FL; return yD_FDISPLAY; }
@@ -187,15 +188,18 @@ word [a-zA-Z0-9_]+
"$fullskew" { FL; return yaTIMINGSPEC; } "$fullskew" { FL; return yaTIMINGSPEC; }
"$fwrite" { FL; return yD_FWRITE; } "$fwrite" { FL; return yD_FWRITE; }
"$hold" { FL; return yaTIMINGSPEC; } "$hold" { FL; return yaTIMINGSPEC; }
"$itor" { FL; return yD_ITOR; }
"$nochange" { FL; return yaTIMINGSPEC; } "$nochange" { FL; return yaTIMINGSPEC; }
"$period" { FL; return yaTIMINGSPEC; } "$period" { FL; return yaTIMINGSPEC; }
"$random" { FL; return yD_RANDOM; } "$random" { FL; return yD_RANDOM; }
"$readmemb" { FL; return yD_READMEMB; } "$readmemb" { FL; return yD_READMEMB; }
"$readmemh" { FL; return yD_READMEMH; } "$readmemh" { FL; return yD_READMEMH; }
"$realtime" { FL; return yD_TIME; } "$realtime" { FL; return yD_REALTIME; }
"$realtobits" { FL; return yD_REALTOBITS; }
"$recovery" { FL; return yaTIMINGSPEC; } "$recovery" { FL; return yaTIMINGSPEC; }
"$recrem" { FL; return yaTIMINGSPEC; } "$recrem" { FL; return yaTIMINGSPEC; }
"$removal" { FL; return yaTIMINGSPEC; } "$removal" { FL; return yaTIMINGSPEC; }
"$rtoi" { FL; return yD_RTOI; }
"$setup" { FL; return yaTIMINGSPEC; } "$setup" { FL; return yaTIMINGSPEC; }
"$setuphold" { FL; return yaTIMINGSPEC; } "$setuphold" { FL; return yaTIMINGSPEC; }
"$sformat" { FL; return yD_SFORMAT; } "$sformat" { FL; return yD_SFORMAT; }
@@ -261,6 +265,8 @@ word [a-zA-Z0-9_]+
"pulldown" { FL; return yPULLDOWN; } "pulldown" { FL; return yPULLDOWN; }
"pullup" { FL; return yPULLUP; } "pullup" { FL; return yPULLUP; }
"rcmos" { FL; return yRCMOS; } "rcmos" { FL; return yRCMOS; }
"real" { FL; return yREAL; }
"realtime" { FL; return yREALTIME; }
"reg" { FL; return yREG; } "reg" { FL; return yREG; }
"repeat" { FL; return yREPEAT; } "repeat" { FL; return yREPEAT; }
"rnmos" { FL; return yRNMOS; } "rnmos" { FL; return yRNMOS; }
@@ -310,8 +316,6 @@ word [a-zA-Z0-9_]+
"medium" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); } "medium" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
"pull0" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); } "pull0" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
"pull1" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); } "pull1" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
"real" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
"realtime" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
"release" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); } "release" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
"small" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); } "small" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
"strong0" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); } "strong0" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
@@ -478,12 +482,12 @@ word [a-zA-Z0-9_]+
<S05,S09>{ <S05,S09>{
/* Keywords */ /* Keywords */
"assert" { FL; return yASSERT; } "assert" { FL; return yASSERT; }
"const" { FL; return yCONST__LEX; }
"cover" { FL; return yCOVER; } "cover" { FL; return yCOVER; }
"property" { FL; return yPROPERTY; } "property" { FL; return yPROPERTY; }
/* Generic unsupported warnings */ /* Generic unsupported warnings */
"assume" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); } "assume" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); }
"before" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); } "before" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); }
"const" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); }
"sequence" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); } "sequence" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); }
"union" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); } "union" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); }
"within" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); } "within" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); }
@@ -812,11 +816,11 @@ word [a-zA-Z0-9_]+
return yaINTNUM; return yaINTNUM;
} }
[0-9][_0-9]*(\.[_0-9]+)([eE][-+]?[_0-9]+)? { [0-9][_0-9]*(\.[_0-9]+)([eE][-+]?[_0-9]+)? {
FL; yylval.cdouble = 0; /* Only for delays, not used yet */ FL; yylval.cdouble = PARSEP->parseDouble(yytext, yyleng);
return yaFLOATNUM; return yaFLOATNUM;
} }
[0-9][_0-9]*(\.[_0-9]+)?([eE][-+]?[_0-9]+) { [0-9][_0-9]*(\.[_0-9]+)?([eE][-+]?[_0-9]+) {
FL; yylval.cdouble = 0; /* Only for delays, not used yet */ FL; yylval.cdouble = PARSEP->parseDouble(yytext, yyleng);
return yaFLOATNUM; return yaFLOATNUM;
} }
[0-9][_0-9]*(\.[_0-9]+)?(fs|ps|ns|us|ms|s|step) { [0-9][_0-9]*(\.[_0-9]+)?(fs|ps|ns|us|ms|s|step) {
@@ -949,6 +953,21 @@ word [a-zA-Z0-9_]+
%% %%
int V3ParseImp::stateVerilogRecent() { return STATE_VERILOG_RECENT; } int V3ParseImp::stateVerilogRecent() { return STATE_VERILOG_RECENT; }
double V3ParseImp::parseDouble(const char* textp, size_t length) {
char* strgp = new char[length+1];
char* dp=strgp;
for (const char* sp=textp; sp<(textp+length);) {
if (*sp != '_') *dp++ = *sp++;
else sp++;
}
*dp++ = '\0';
char* endp = strgp;
double d = strtod(strgp, &endp);
if ((endp-strgp) != length) { yyerrorf("Syntax error parsing real: %s",strgp); }
delete strgp;
return d;
}
int V3ParseImp::lexToken() { int V3ParseImp::lexToken() {
// called from lexToBison, has a "this" // called from lexToBison, has a "this"
// Fetch next token from prefetch or real lexer // Fetch next token from prefetch or real lexer
@@ -964,7 +983,8 @@ int V3ParseImp::lexToken() {
//yylval // Set by yylexThis() //yylval // Set by yylexThis()
} }
// If a paren, read another // If a paren, read another
if (token == yGLOBAL__LEX if (token == yCONST__LEX
|| token == yGLOBAL__LEX
// Never put yID_* here; below symbol table resolution would break // Never put yID_* here; below symbol table resolution would break
) { ) {
if (debugFlex()) { cout<<" lexToken: reading ahead to find possible strength"<<endl; } if (debugFlex()) { cout<<" lexToken: reading ahead to find possible strength"<<endl; }
@@ -975,7 +995,11 @@ int V3ParseImp::lexToken() {
m_aheadVal = yylval; m_aheadVal = yylval;
yylval = curValue; yylval = curValue;
// Now potentially munge the current token // Now potentially munge the current token
if (token == yGLOBAL__LEX) { if (token == yCONST__LEX) {
//UNSUP if (nexttok == yREF) token = yCONST__REF;
token = yCONST__ETC;
}
else if (token == yGLOBAL__LEX) {
if (nexttok == yCLOCKING) token = yGLOBAL__CLOCKING; if (nexttok == yCLOCKING) token = yGLOBAL__CLOCKING;
else { token = yaID__LEX; yylval.strp = PARSEP->newString("global"); } // Avoid 2009 "global" conflicting with old code when we can else { token = yaID__LEX; yylval.strp = PARSEP->newString("global"); } // Avoid 2009 "global" conflicting with old code when we can
} }
+136 -76
View File
@@ -151,7 +151,7 @@ const AstBasicDTypeKwd LOGIC_IMPLICIT = AstBasicDTypeKwd::LOGIC_IMPLICIT;
//====================================================================== //======================================================================
// Macro functions // Macro functions
#define CRELINE() (PARSEP->copyOrSameFileLine()) #define CRELINE() (PARSEP->copyOrSameFileLine()) // Only use in empty rules, so lines point at beginnings
#define VARRESET_LIST(decl) { GRAMMARP->m_pinNum=1; VARRESET(); VARDECL(decl); } // Start of pinlist #define VARRESET_LIST(decl) { GRAMMARP->m_pinNum=1; VARRESET(); VARDECL(decl); } // Start of pinlist
#define VARRESET_NONLIST(decl) { GRAMMARP->m_pinNum=0; VARRESET(); VARDECL(decl); } // Not in a pinlist #define VARRESET_NONLIST(decl) { GRAMMARP->m_pinNum=0; VARRESET(); VARDECL(decl); } // Not in a pinlist
@@ -160,7 +160,7 @@ const AstBasicDTypeKwd LOGIC_IMPLICIT = AstBasicDTypeKwd::LOGIC_IMPLICIT;
#define VARIO(type) { GRAMMARP->m_varIO = AstVarType::type; } #define VARIO(type) { GRAMMARP->m_varIO = AstVarType::type; }
#define VARDTYPE(dtypep) { GRAMMARP->setDType(dtypep); } #define VARDTYPE(dtypep) { GRAMMARP->setDType(dtypep); }
#define VARDONEA(name,array,attrs) GRAMMARP->createVariable(CRELINE(),(name),(array),(attrs)) #define VARDONEA(fl,name,array,attrs) GRAMMARP->createVariable((fl),(name),(array),(attrs))
#define VARDONEP(portp,array,attrs) GRAMMARP->createVariable((portp)->fileline(),(portp)->name(),(array),(attrs)) #define VARDONEP(portp,array,attrs) GRAMMARP->createVariable((portp)->fileline(),(portp)->name(),(array),(attrs))
#define PINNUMINC() (GRAMMARP->m_pinNum++) #define PINNUMINC() (GRAMMARP->m_pinNum++)
@@ -274,6 +274,8 @@ class AstSenTree;
%token<fl> yCASEZ "casez" %token<fl> yCASEZ "casez"
%token<fl> yCHANDLE "chandle" %token<fl> yCHANDLE "chandle"
%token<fl> yCLOCKING "clocking" %token<fl> yCLOCKING "clocking"
%token<fl> yCONST__ETC "const"
%token<fl> yCONST__LEX "const-in-lex"
%token<fl> yCMOS "cmos" %token<fl> yCMOS "cmos"
%token<fl> yCONTEXT "context" %token<fl> yCONTEXT "context"
%token<fl> yCONTINUE "continue" %token<fl> yCONTINUE "continue"
@@ -340,6 +342,8 @@ class AstSenTree;
%token<fl> yPULLUP "pullup" %token<fl> yPULLUP "pullup"
%token<fl> yPURE "pure" %token<fl> yPURE "pure"
%token<fl> yRCMOS "rcmos" %token<fl> yRCMOS "rcmos"
%token<fl> yREAL "real"
%token<fl> yREALTIME "realtime"
%token<fl> yREG "reg" %token<fl> yREG "reg"
%token<fl> yREPEAT "repeat" %token<fl> yREPEAT "repeat"
%token<fl> yRETURN "return" %token<fl> yRETURN "return"
@@ -380,6 +384,7 @@ class AstSenTree;
%token<fl> yXOR "xor" %token<fl> yXOR "xor"
%token<fl> yD_BITS "$bits" %token<fl> yD_BITS "$bits"
%token<fl> yD_BITSTOREAL "$bitstoreal"
%token<fl> yD_C "$c" %token<fl> yD_C "$c"
%token<fl> yD_CLOG2 "$clog2" %token<fl> yD_CLOG2 "$clog2"
%token<fl> yD_COUNTONES "$countones" %token<fl> yD_COUNTONES "$countones"
@@ -398,11 +403,15 @@ class AstSenTree;
%token<fl> yD_FWRITE "$fwrite" %token<fl> yD_FWRITE "$fwrite"
%token<fl> yD_INFO "$info" %token<fl> yD_INFO "$info"
%token<fl> yD_ISUNKNOWN "$isunknown" %token<fl> yD_ISUNKNOWN "$isunknown"
%token<fl> yD_ITOR "$itor"
%token<fl> yD_ONEHOT "$onehot" %token<fl> yD_ONEHOT "$onehot"
%token<fl> yD_ONEHOT0 "$onehot0" %token<fl> yD_ONEHOT0 "$onehot0"
%token<fl> yD_RANDOM "$random" %token<fl> yD_RANDOM "$random"
%token<fl> yD_READMEMB "$readmemb" %token<fl> yD_READMEMB "$readmemb"
%token<fl> yD_READMEMH "$readmemh" %token<fl> yD_READMEMH "$readmemh"
%token<fl> yD_REALTIME "$realtime"
%token<fl> yD_REALTOBITS "$realtobits"
%token<fl> yD_RTOI "$rtoi"
%token<fl> yD_SFORMAT "$sformat" %token<fl> yD_SFORMAT "$sformat"
%token<fl> yD_SIGNED "$signed" %token<fl> yD_SIGNED "$signed"
%token<fl> yD_SSCANF "$sscanf" %token<fl> yD_SSCANF "$sscanf"
@@ -777,10 +786,10 @@ port<nodep>: // ==IEEE: port
// // IEEE: interface_port_header port_identifier { unpacked_dimension } // // IEEE: interface_port_header port_identifier { unpacked_dimension }
// // Expanded interface_port_header // // Expanded interface_port_header
// // We use instantCb here because the non-port form looks just like a module instantiation // // We use instantCb here because the non-port form looks just like a module instantiation
//UNSUP portDirNetE id/*interface*/ idAny/*port*/ rangeListE sigAttrListE { VARDTYPE($2); VARDONEA($3, $4); PARSEP->instantCb(CRELINE(), $2, $3, $4); PINNUMINC(); } //UNSUP portDirNetE id/*interface*/ idAny/*port*/ rangeListE sigAttrListE { VARDTYPE($2); VARDONEA($<fl>3, $3, $4); PARSEP->instantCb($<fl>2, $2, $3, $4); PINNUMINC(); }
//UNSUP portDirNetE yINTERFACE idAny/*port*/ rangeListE sigAttrListE { VARDTYPE($2); VARDONEA($3, $4); PINNUMINC(); } //UNSUP portDirNetE yINTERFACE idAny/*port*/ rangeListE sigAttrListE { VARDTYPE($2); VARDONEA($<fl>3, $3, $4); PINNUMINC(); }
//UNSUP portDirNetE id/*interface*/ '.' idAny/*modport*/ idAny/*port*/ rangeListE sigAttrListE { VARDTYPE($2); VARDONEA($5, $6); PARSEP->instantCb(CRELINE(), $2, $5, $6); PINNUMINC(); } //UNSUP portDirNetE id/*interface*/ '.' idAny/*modport*/ idAny/*port*/ rangeListE sigAttrListE { VARDTYPE($2); VARDONEA($<fl>5, $5, $6); PARSEP->instantCb($<fl>2, $2, $5, $6); PINNUMINC(); }
//UNSUP portDirNetE yINTERFACE '.' idAny/*modport*/ idAny/*port*/ rangeListE sigAttrListE { VARDTYPE($2); VARDONEA($5, $6); PINNUMINC(); } //UNSUP portDirNetE yINTERFACE '.' idAny/*modport*/ idAny/*port*/ rangeListE sigAttrListE { VARDTYPE($2); VARDONEA($<fl>5, $5, $6); PINNUMINC(); }
// //
// // IEEE: ansi_port_declaration, with [port_direction] removed // // IEEE: ansi_port_declaration, with [port_direction] removed
// // IEEE: [ net_port_header | interface_port_header ] port_identifier { unpacked_dimension } // // IEEE: [ net_port_header | interface_port_header ] port_identifier { unpacked_dimension }
@@ -833,7 +842,7 @@ port<nodep>: // ==IEEE: port
| portDirNetE /*implicit*/ portSig variable_dimensionListE sigAttrListE '=' constExpr | portDirNetE /*implicit*/ portSig variable_dimensionListE sigAttrListE '=' constExpr
{ $$=$2; /*VARDTYPE-same*/ AstVar* vp=VARDONEP($$,$3,$4); $$->addNextNull(vp); vp->valuep($6); } { $$=$2; /*VARDTYPE-same*/ AstVar* vp=VARDONEP($$,$3,$4); $$->addNextNull(vp); vp->valuep($6); }
; ;
portDirNetE: // IEEE: part of port, optional net type and/or direction portDirNetE: // IEEE: part of port, optional net type and/or direction
/* empty */ { } /* empty */ { }
// // Per spec, if direction given default the nettype. // // Per spec, if direction given default the nettype.
@@ -842,15 +851,15 @@ portDirNetE: // IEEE: part of port, optional net type and/or direction
| port_direction net_type { VARDECL(PORT); VARDTYPE(NULL/*default_nettype*/); } // net_type calls VARNET | port_direction net_type { VARDECL(PORT); VARDTYPE(NULL/*default_nettype*/); } // net_type calls VARNET
| net_type { } // net_type calls VARNET | net_type { } // net_type calls VARNET
; ;
port_declNetE: // IEEE: part of port_declaration, optional net type port_declNetE: // IEEE: part of port_declaration, optional net type
/* empty */ { } /* empty */ { }
| net_type { } // net_type calls VARNET | net_type { } // net_type calls VARNET
; ;
portSig<nodep>: portSig<nodep>:
id/*port*/ { $$ = new AstPort(CRELINE(),PINNUMINC(),*$1); } id/*port*/ { $$ = new AstPort($<fl>1,PINNUMINC(),*$1); }
| idSVKwd { $$ = new AstPort(CRELINE(),PINNUMINC(),*$1); } | idSVKwd { $$ = new AstPort($<fl>1,PINNUMINC(),*$1); }
; ;
//********************************************************************** //**********************************************************************
@@ -926,7 +935,7 @@ list_of_genvar_identifiers<nodep>: // IEEE: list_of_genvar_identifiers (for decl
genvar_identifierDecl<nodep>: // IEEE: genvar_identifier (for declaration) genvar_identifierDecl<nodep>: // IEEE: genvar_identifier (for declaration)
id/*new-genvar_identifier*/ sigAttrListE id/*new-genvar_identifier*/ sigAttrListE
{ VARRESET_NONLIST(GENVAR); VARDTYPE(new AstBasicDType($<fl>1,AstBasicDTypeKwd::INTEGER)); { VARRESET_NONLIST(GENVAR); VARDTYPE(new AstBasicDType($<fl>1,AstBasicDTypeKwd::INTEGER));
$$ = VARDONEA(*$1, NULL, $2); } $$ = VARDONEA($<fl>1, *$1, NULL, $2); }
; ;
local_parameter_declaration<nodep>: // IEEE: local_parameter_declaration local_parameter_declaration<nodep>: // IEEE: local_parameter_declaration
@@ -1065,6 +1074,12 @@ integer_vector_type<bdtypep>: // ==IEEE: integer_atom_type
| yREG { $$ = new AstBasicDType($1,AstBasicDTypeKwd::LOGIC); } // logic==reg | yREG { $$ = new AstBasicDType($1,AstBasicDTypeKwd::LOGIC); } // logic==reg
; ;
non_integer_type<bdtypep>: // ==IEEE: non_integer_type
yREAL { $$ = new AstBasicDType($1,AstBasicDTypeKwd::DOUBLE); }
| yREALTIME { $$ = new AstBasicDType($1,AstBasicDTypeKwd::DOUBLE); }
//UNSUP ySHORTREAL { $$ = new AstBasicDType($1,AstBasicDTypeKwd::FLOAT); }
;
signingE<signstate>: // IEEE: signing - plus empty signingE<signstate>: // IEEE: signing - plus empty
/*empty*/ { $$ = signedst_NOP; } /*empty*/ { $$ = signedst_NOP; }
| signing { $$ = $1; } | signing { $$ = $1; }
@@ -1078,6 +1093,31 @@ signing<signstate>: // ==IEEE: signing
//************************************************ //************************************************
// Data Types // Data Types
casting_type<dtypep>: // IEEE: casting_type
simple_type { $$ = $1; }
// // IEEE: constant_primary
// // In expr:cast this is expanded to just "expr"
//
// // IEEE: signing
//See where casting_type used
//^^ ySIGNED { $$ = new AstSigned($1,$3); }
//^^ yUNSIGNED { $$ = new AstUnsigned($1,$3); }
//UNSUP ySTRING { $$ = $1; }
//UNSUP yCONST__ETC/*then `*/ { $$ = $1; }
;
simple_type<dtypep>: // ==IEEE: simple_type
// // IEEE: integer_type
integer_atom_type { $$ = $1; }
| integer_vector_type { $$ = $1; }
| non_integer_type { $$ = $1; }
// // IEEE: ps_type_identifier
// // IEEE: ps_parameter_identifier (presumably a PARAMETER TYPE)
| ps_type { $$ = $1; }
// // { generate_block_identifer ... } '.'
// // Need to determine if generate_block_identifier can be lex-detected
;
data_type<dtypep>: // ==IEEE: data_type data_type<dtypep>: // ==IEEE: data_type
// // This expansion also replicated elsewhere, IE data_type__AndID // // This expansion also replicated elsewhere, IE data_type__AndID
data_typeNoRef { $$ = $1; } data_typeNoRef { $$ = $1; }
@@ -1093,7 +1133,7 @@ data_type<dtypep>: // ==IEEE: data_type
data_typeBasic<dtypep>: // IEEE: part of data_type data_typeBasic<dtypep>: // IEEE: part of data_type
integer_vector_type signingE rangeListE { $1->setSignedState($2); $$ = GRAMMARP->addRange($1,$3,true); } integer_vector_type signingE rangeListE { $1->setSignedState($2); $$ = GRAMMARP->addRange($1,$3,true); }
| integer_atom_type signingE { $1->setSignedState($2); $$ = $1; } | integer_atom_type signingE { $1->setSignedState($2); $$ = $1; }
//UNSUP non_integer_type { UNSUP } | non_integer_type { $$ = $1; }
; ;
data_typeNoRef<dtypep>: // ==IEEE: data_type, excluding class_type etc references data_typeNoRef<dtypep>: // ==IEEE: data_type, excluding class_type etc references
@@ -1121,9 +1161,9 @@ list_of_variable_decl_assignments<nodep>: // ==IEEE: list_of_variable_decl_assig
variable_decl_assignment<varp>: // ==IEEE: variable_decl_assignment variable_decl_assignment<varp>: // ==IEEE: variable_decl_assignment
id variable_dimensionListE sigAttrListE id variable_dimensionListE sigAttrListE
{ $$ = VARDONEA(*$1,$2,$3); } { $$ = VARDONEA($<fl>1,*$1,$2,$3); }
| id variable_dimensionListE sigAttrListE '=' variable_declExpr | id variable_dimensionListE sigAttrListE '=' variable_declExpr
{ $$ = VARDONEA(*$1,$2,$3); $$->valuep($5); } { $$ = VARDONEA($<fl>1,*$1,$2,$3); $$->valuep($5); }
| idSVKwd { $$ = NULL; } | idSVKwd { $$ = NULL; }
// //
// // IEEE: "dynamic_array_variable_identifier '[' ']' [ '=' dynamic_array_new ]" // // IEEE: "dynamic_array_variable_identifier '[' ']' [ '=' dynamic_array_new ]"
@@ -1144,9 +1184,9 @@ list_of_tf_variable_identifiers<nodep>: // ==IEEE: list_of_tf_variable_identifie
tf_variable_identifier<varp>: // IEEE: part of list_of_tf_variable_identifiers tf_variable_identifier<varp>: // IEEE: part of list_of_tf_variable_identifiers
id variable_dimensionListE sigAttrListE id variable_dimensionListE sigAttrListE
{ $$ = VARDONEA(*$1, $2, $3); } { $$ = VARDONEA($<fl>1,*$1, $2, $3); }
| id variable_dimensionListE sigAttrListE '=' expr | id variable_dimensionListE sigAttrListE '=' expr
{ $$ = VARDONEA(*$1, $2, $3); { $$ = VARDONEA($<fl>1,*$1, $2, $3);
$$->addNext(new AstAssign($4, new AstVarRef($4, *$1, true), $5)); } $$->addNext(new AstAssign($4, new AstVarRef($4, *$1, true), $5)); }
; ;
@@ -1244,23 +1284,24 @@ data_declarationVar<nodep>: // IEEE: part of data_declaration
; ;
data_declarationVarFront: // IEEE: part of data_declaration data_declarationVarFront: // IEEE: part of data_declaration
// // Expanded: "constE yVAR lifetimeE data_type"
// // implicit_type expanded into /*empty*/ or "signingE rangeList" // // implicit_type expanded into /*empty*/ or "signingE rangeList"
constE yVAR lifetimeE data_type { /*VARRESET-in-ddVar*/ VARDTYPE($4); } /**/ yVAR lifetimeE data_type { /*VARRESET-in-ddVar*/ VARDTYPE($3); }
| constE yVAR lifetimeE { /*VARRESET-in-ddVar*/ VARDTYPE(new AstBasicDType($<fl>2, LOGIC_IMPLICIT)); } | /**/ yVAR lifetimeE { /*VARRESET-in-ddVar*/ VARDTYPE(new AstBasicDType($<fl>1, LOGIC_IMPLICIT)); }
| constE yVAR lifetimeE signingE rangeList { /*VARRESET-in-ddVar*/ VARDTYPE(GRAMMARP->addRange(new AstBasicDType($<fl>2, LOGIC_IMPLICIT, $4),$5,false)); } | /**/ yVAR lifetimeE signingE rangeList { /*VARRESET-in-ddVar*/ VARDTYPE(GRAMMARP->addRange(new AstBasicDType($<fl>1, LOGIC_IMPLICIT, $3), $4,false)); }
//
// // implicit_type expanded into /*empty*/ or "signingE rangeList"
| yCONST__ETC yVAR lifetimeE data_type { /*VARRESET-in-ddVar*/ VARDTYPE(new AstConstDType($<fl>1, $4)); }
| yCONST__ETC yVAR lifetimeE { /*VARRESET-in-ddVar*/ VARDTYPE(new AstConstDType($<fl>1, new AstBasicDType($<fl>2, LOGIC_IMPLICIT))); }
| yCONST__ETC yVAR lifetimeE signingE rangeList { /*VARRESET-in-ddVar*/ VARDTYPE(new AstConstDType($<fl>1, GRAMMARP->addRange(new AstBasicDType($<fl>2, LOGIC_IMPLICIT, $4), $5,false))); }
// //
// // Expanded: "constE lifetimeE data_type" // // Expanded: "constE lifetimeE data_type"
| /**/ data_type { /*VARRESET-in-ddVar*/ VARDTYPE($1); } | /**/ data_type { /*VARRESET-in-ddVar*/ VARDTYPE($1); }
| /**/ lifetime data_type { /*VARRESET-in-ddVar*/ VARDTYPE($2); } | /**/ lifetime data_type { /*VARRESET-in-ddVar*/ VARDTYPE($2); }
//UNSUP yCONST__ETC lifetimeE data_type { /*VARRESET-in-ddVar*/ VARDTYPE($3); } | yCONST__ETC lifetimeE data_type { /*VARRESET-in-ddVar*/ VARDTYPE(new AstConstDType($<fl>1, $3)); }
// // = class_new is in variable_decl_assignment // // = class_new is in variable_decl_assignment
; ;
constE: // IEEE: part of data_declaration
/* empty */ { }
//UNSUP yCONST__ETC { UNSUP }
;
implicit_typeE<dtypep>: // IEEE: part of *data_type_or_implicit implicit_typeE<dtypep>: // IEEE: part of *data_type_or_implicit
// // Also expanded in data_declaration // // Also expanded in data_declaration
/* empty */ { $$ = NULL; } /* empty */ { $$ = NULL; }
@@ -1384,7 +1425,7 @@ module_or_generate_item_declaration<nodep>: // ==IEEE: module_or_generate_item_d
generate_block_or_null<nodep>: // IEEE: generate_block_or_null generate_block_or_null<nodep>: // IEEE: generate_block_or_null
// ';' // is included in // ';' // is included in
// // IEEE: generate_block // // IEEE: generate_block
genItem { $$ = new AstBegin(CRELINE(),"genblk",$1); } genItem { $$ = $1 ? (new AstBegin($1->fileline(),"genblk",$1)) : NULL; }
| genItemBegin { $$ = $1; } | genItemBegin { $$ = $1; }
; ;
@@ -1499,8 +1540,7 @@ delay_value: // ==IEEE:delay_value
delayExpr: delayExpr:
expr { } expr { }
// // Verilator doesn't support yaFLOATNUM/yaTIMENUM, so not in expr // // Verilator doesn't support yaTIMENUM, so not in expr
| yaFLOATNUM { }
| yaTIMENUM { } | yaTIMENUM { }
; ;
@@ -1515,18 +1555,18 @@ netSigList<varp>: // IEEE: list_of_port_identifiers
; ;
netSig<varp>: // IEEE: net_decl_assignment - one element from list_of_port_identifiers netSig<varp>: // IEEE: net_decl_assignment - one element from list_of_port_identifiers
netId sigAttrListE { $$ = VARDONEA(*$1, NULL, $2); } netId sigAttrListE { $$ = VARDONEA($<fl>1,*$1, NULL, $2); }
| netId sigAttrListE '=' expr { $$ = VARDONEA(*$1, NULL, $2); $$->addNext(new AstAssignW($3,new AstVarRef($3,$$->name(),true),$4)); } | netId sigAttrListE '=' expr { $$ = VARDONEA($<fl>1,*$1, NULL, $2); $$->addNext(new AstAssignW($3,new AstVarRef($3,$$->name(),true),$4)); }
| netId rangeList sigAttrListE { $$ = VARDONEA(*$1, $2, $3); } | netId rangeList sigAttrListE { $$ = VARDONEA($<fl>1,*$1, $2, $3); }
; ;
netId<strp>: netId<strp>:
id/*new-net*/ { $$ = $1; } id/*new-net*/ { $$ = $1; $<fl>$=$<fl>1; }
| idSVKwd { $$ = $1; } | idSVKwd { $$ = $1; $<fl>$=$<fl>1; }
; ;
sigId<varp>: sigId<varp>:
id { $$ = VARDONEA(*$1, NULL, NULL); } id { $$ = VARDONEA($<fl>1,*$1, NULL, NULL); }
; ;
sigAttrListE<nodep>: sigAttrListE<nodep>:
@@ -1564,7 +1604,7 @@ rangeList<rangep>: // IEEE: {packed_dimension}
wirerangeE<dtypep>: wirerangeE<dtypep>:
/* empty */ { $$ = new AstBasicDType(CRELINE(), LOGIC); } // not implicit /* empty */ { $$ = new AstBasicDType(CRELINE(), LOGIC); } // not implicit
| rangeList { $$ = GRAMMARP->addRange(new AstBasicDType(CRELINE(), LOGIC),$1,false); } // not implicit | rangeList { $$ = GRAMMARP->addRange(new AstBasicDType($1->fileline(), LOGIC),$1,false); } // not implicit
; ;
// IEEE: select // IEEE: select
@@ -1646,8 +1686,8 @@ instnameList<nodep>:
; ;
instnameParen<nodep>: instnameParen<nodep>:
id instRangeE '(' cellpinList ')' { $$ = new AstCell($3, *$1,GRAMMARP->m_instModule,$4, GRAMMARP->m_instParamp,$2); } id instRangeE '(' cellpinList ')' { $$ = new AstCell($<fl>1,*$1,GRAMMARP->m_instModule,$4, GRAMMARP->m_instParamp,$2); }
| id instRangeE { $$ = new AstCell(CRELINE(),*$1,GRAMMARP->m_instModule,NULL,GRAMMARP->m_instParamp,$2); } | id instRangeE { $$ = new AstCell($<fl>1,*$1,GRAMMARP->m_instModule,NULL,GRAMMARP->m_instParamp,$2); }
//UNSUP instRangeE '(' cellpinList ')' { UNSUP } // UDP //UNSUP instRangeE '(' cellpinList ')' { UNSUP } // UDP
; ;
@@ -1667,11 +1707,12 @@ cellpinItList<pinp>: // IEEE: list_of_port_connections + list_of_parameter_assi
; ;
cellpinItemE<pinp>: // IEEE: named_port_connection + named_parameter_assignment + empty cellpinItemE<pinp>: // IEEE: named_port_connection + named_parameter_assignment + empty
/* empty: ',,' is legal */ { $$ = NULL; PINNUMINC(); } // Note empty can match either () or (,); V3LinkCells cleans up ()
/* empty: ',,' is legal */ { $$ = new AstPin(CRELINE(),PINNUMINC(),"",NULL); }
| yP_DOTSTAR { $$ = new AstPin($1,PINNUMINC(),".*",NULL); } | yP_DOTSTAR { $$ = new AstPin($1,PINNUMINC(),".*",NULL); }
| '.' idSVKwd { $$ = NULL; PINNUMINC(); } | '.' idSVKwd { $$ = new AstPin($1,PINNUMINC(),*$2,new AstVarRef($1,*$2,false)); $$->svImplicit(true);}
| '.' idAny { $$ = new AstPin($1,PINNUMINC(),*$2,new AstVarRef($1,*$2,false)); $$->svImplicit(true);} | '.' idAny { $$ = new AstPin($1,PINNUMINC(),*$2,new AstVarRef($1,*$2,false)); $$->svImplicit(true);}
| '.' idAny '(' ')' { $$ = NULL; PINNUMINC(); } | '.' idAny '(' ')' { $$ = new AstPin($1,PINNUMINC(),*$2,NULL); }
// // mintypmax is expanded here, as it might be a UDP or gate primitive // // mintypmax is expanded here, as it might be a UDP or gate primitive
| '.' idAny '(' expr ')' { $$ = new AstPin($1,PINNUMINC(),*$2,$4); } | '.' idAny '(' expr ')' { $$ = new AstPin($1,PINNUMINC(),*$2,$4); }
//UNSUP '.' idAny '(' expr ':' expr ')' { } //UNSUP '.' idAny '(' expr ':' expr ')' { }
@@ -1684,8 +1725,6 @@ cellpinItemE<pinp>: // IEEE: named_port_connection + named_parameter_assignment
| expr { $$ = new AstPin($1->fileline(),PINNUMINC(),"",$1); } | expr { $$ = new AstPin($1->fileline(),PINNUMINC(),"",$1); }
//UNSUP expr ':' expr { } //UNSUP expr ':' expr { }
//UNSUP expr ':' expr ':' expr { } //UNSUP expr ':' expr ':' expr { }
// // Floatnum should only occur with UDPs, but since ports aren't floats, it's legal to round always
| yaFLOATNUM { $$ = new AstPin($<fl>1,PINNUMINC(),"",new AstConst($<fl>1,AstConst::Unsized32(),(int)(($1<0)?($1-0.5):($1+0.5)))); }
; ;
//************************************************ //************************************************
@@ -1733,7 +1772,7 @@ senitem<senitemp>: // IEEE: part of event_expression, non-'OR' ',' terms
; ;
senitemVar<senitemp>: senitemVar<senitemp>:
idClassSel { $$ = new AstSenItem(CRELINE(),AstEdgeType::ET_ANYEDGE,$1); } idClassSel { $$ = new AstSenItem($1->fileline(),AstEdgeType::ET_ANYEDGE,$1); }
; ;
senitemEdge<senitemp>: // IEEE: part of event_expression senitemEdge<senitemp>: // IEEE: part of event_expression
@@ -1860,7 +1899,7 @@ statement_item<nodep>: // IEEE: statement_item
| statementVerilatorPragmas { $$ = $1; } | statementVerilatorPragmas { $$ = $1; }
// //
// // IEEE: disable_statement // // IEEE: disable_statement
//UNSUP yDISABLE idAny/*hierarchical_identifier-task_or_block*/ ';' { UNSUP } | yDISABLE idAny/*hierarchical_identifier-task_or_block*/ ';' { $$ = new AstDisable($1,*$2); }
//UNSUP yDISABLE yFORK ';' { UNSUP } //UNSUP yDISABLE yFORK ';' { UNSUP }
// // IEEE: event_trigger // // IEEE: event_trigger
//UNSUP yP_MINUSGT hierarchical_identifier/*event*/ ';' { UNSUP } //UNSUP yP_MINUSGT hierarchical_identifier/*event*/ ';' { UNSUP }
@@ -2008,7 +2047,7 @@ for_initialization<nodep>: // ==IEEE: for_initialization + for_variable_declarat
// // IEEE: for_variable_declaration // // IEEE: for_variable_declaration
varRESET data_type idAny/*new*/ '=' expr ';' varRESET data_type idAny/*new*/ '=' expr ';'
{ VARDTYPE($2); { VARDTYPE($2);
$$ = VARDONEA(*$3,NULL,NULL); $$ = VARDONEA($<fl>3,*$3,NULL,NULL);
$$->addNext(new AstAssign($4,new AstVarRef($4,*$3,true),$5));} $$->addNext(new AstAssign($4,new AstVarRef($4,*$3,true),$5));}
| varRefBase '=' expr ';' { $$ = new AstAssign($2,$1,$3); } | varRefBase '=' expr ';' { $$ = new AstAssign($2,$1,$3); }
//UNSUP: List of initializations //UNSUP: List of initializations
@@ -2032,10 +2071,10 @@ for_step<nodep>: // IEEE: for_step
// Functions/tasks // Functions/tasks
taskRef<ftaskrefp>: // IEEE: part of tf_call taskRef<ftaskrefp>: // IEEE: part of tf_call
idDotted { $$ = new AstTaskRef(CRELINE(),new AstParseRef($1->fileline(), AstParseRefExp::PX_TASK, $1),NULL);} idDotted { $$ = new AstTaskRef($1->fileline(),new AstParseRef($1->fileline(), AstParseRefExp::PX_TASK, $1),NULL);}
| idDotted '(' list_of_argumentsE ')' { $$ = new AstTaskRef(CRELINE(),new AstParseRef($1->fileline(), AstParseRefExp::PX_TASK, $1),$3);} | idDotted '(' list_of_argumentsE ')' { $$ = new AstTaskRef($1->fileline(),new AstParseRef($1->fileline(), AstParseRefExp::PX_TASK, $1),$3);}
//UNSUP: package_scopeIdFollows idDotted { $$ = new AstTaskRef(CRELINE(),new AstParseRef($2->fileline(), AstParseRefExp::PX_TASK, $2),NULL);} //UNSUP: package_scopeIdFollows idDotted { $$ = new AstTaskRef($1->fileline(),new AstParseRef($2->fileline(), AstParseRefExp::PX_TASK, $2),NULL);}
//UNSUP: package_scopeIdFollows idDotted '(' list_of_argumentsE ')' { $$ = new AstTaskRef(CRELINE(),new AstParseRef($2->fileline(), AstParseRefExp::PX_TASK, $2),$4);} //UNSUP: package_scopeIdFollows idDotted '(' list_of_argumentsE ')' { $$ = new AstTaskRef($1->fileline(),new AstParseRef($2->fileline(), AstParseRefExp::PX_TASK, $2),$4);}
//UNSUP: idDotted is really just id to allow dotted method calls //UNSUP: idDotted is really just id to allow dotted method calls
; ;
@@ -2114,6 +2153,8 @@ system_f_call<nodep>: // IEEE: system_tf_call (as func)
| yaD_DPI '(' exprList ')' { $$ = new AstFuncRef($2,*$1,$3); } | yaD_DPI '(' exprList ')' { $$ = new AstFuncRef($2,*$1,$3); }
// //
| yD_BITS '(' expr ')' { $$ = new AstAttrOf($1,AstAttrType::EXPR_BITS,$3); } | yD_BITS '(' expr ')' { $$ = new AstAttrOf($1,AstAttrType::EXPR_BITS,$3); }
| yD_BITS '(' data_type ')' { $$ = new AstAttrOf($1,AstAttrType::EXPR_BITS,$3); }
| yD_BITSTOREAL '(' expr ')' { $$ = new AstBitsToRealD($1,$3); }
| yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCFunc($1,$3)); } | yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCFunc($1,$3)); }
| yD_CLOG2 '(' expr ')' { $$ = new AstCLog2($1,$3); } | yD_CLOG2 '(' expr ')' { $$ = new AstCLog2($1,$3); }
| yD_COUNTONES '(' expr ')' { $$ = new AstCountOnes($1,$3); } | yD_COUNTONES '(' expr ')' { $$ = new AstCountOnes($1,$3); }
@@ -2123,10 +2164,14 @@ system_f_call<nodep>: // IEEE: system_tf_call (as func)
| yD_FSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstFScanF($1,*$5,$3,$6); } | yD_FSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstFScanF($1,*$5,$3,$6); }
| yD_SSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstSScanF($1,*$5,$3,$6); } | yD_SSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstSScanF($1,*$5,$3,$6); }
| yD_ISUNKNOWN '(' expr ')' { $$ = new AstIsUnknown($1,$3); } | yD_ISUNKNOWN '(' expr ')' { $$ = new AstIsUnknown($1,$3); }
| yD_ITOR '(' expr ')' { $$ = new AstIToRD($1,$3); }
| yD_ONEHOT '(' expr ')' { $$ = new AstOneHot($1,$3); } | yD_ONEHOT '(' expr ')' { $$ = new AstOneHot($1,$3); }
| yD_ONEHOT0 '(' expr ')' { $$ = new AstOneHot0($1,$3); } | yD_ONEHOT0 '(' expr ')' { $$ = new AstOneHot0($1,$3); }
| yD_RANDOM '(' expr ')' { $1->v3error("Unsupported: Seeding $random doesn't map to C++, use $c(\"srand\")"); } | yD_RANDOM '(' expr ')' { $1->v3error("Unsupported: Seeding $random doesn't map to C++, use $c(\"srand\")"); }
| yD_RANDOM parenE { $$ = new AstRand($1); } | yD_RANDOM parenE { $$ = new AstRand($1); }
| yD_REALTIME parenE { $$ = new AstTimeD($1); }
| yD_REALTOBITS '(' expr ')' { $$ = new AstRealToBits($1,$3); }
| yD_RTOI '(' expr ')' { $$ = new AstRToIS($1,$3); }
//| yD_SFORMATF '(' str commaEListE ')' { $$ = new AstSFormatF($1,*$3,false,$4); } // Have AST, just need testing and debug //| yD_SFORMATF '(' str commaEListE ')' { $$ = new AstSFormatF($1,*$3,false,$4); } // Have AST, just need testing and debug
| yD_SIGNED '(' expr ')' { $$ = new AstSigned($1,$3); } | yD_SIGNED '(' expr ')' { $$ = new AstSigned($1,$3); }
| yD_STIME parenE { $$ = new AstSel($1,new AstTime($1),0,32); } | yD_STIME parenE { $$ = new AstSel($1,new AstTime($1),0,32); }
@@ -2281,9 +2326,9 @@ tf_port_itemDir: // IEEE: part of tf_port_item, direction
tf_port_itemAssignment<varp>: // IEEE: part of tf_port_item, which has assignment tf_port_itemAssignment<varp>: // IEEE: part of tf_port_item, which has assignment
id variable_dimensionListE sigAttrListE id variable_dimensionListE sigAttrListE
{ $$ = VARDONEA(*$1, $2, $3); } { $$ = VARDONEA($<fl>1, *$1, $2, $3); }
| id variable_dimensionListE sigAttrListE '=' expr | id variable_dimensionListE sigAttrListE '=' expr
{ $$ = VARDONEA(*$1, $2, $3); $$->valuep($5); } { $$ = VARDONEA($<fl>1, *$1, $2, $3); $$->valuep($5); }
; ;
parenE: parenE:
@@ -2347,7 +2392,7 @@ expr<nodep>: // IEEE: part of expression/constant_expression/primary
// //
// // IEEE: unary_operator primary // // IEEE: unary_operator primary
'+' ~r~expr %prec prUNARYARITH { $$ = $2; } '+' ~r~expr %prec prUNARYARITH { $$ = $2; }
| '-' ~r~expr %prec prUNARYARITH { $$ = new AstUnaryMin ($1,$2); } | '-' ~r~expr %prec prUNARYARITH { $$ = new AstNegate ($1,$2); }
| '!' ~r~expr %prec prNEGATION { $$ = new AstLogNot ($1,$2); } | '!' ~r~expr %prec prNEGATION { $$ = new AstLogNot ($1,$2); }
| '&' ~r~expr %prec prREDUCTION { $$ = new AstRedAnd ($1,$2); } | '&' ~r~expr %prec prREDUCTION { $$ = new AstRedAnd ($1,$2); }
| '~' ~r~expr %prec prNEGATION { $$ = new AstNot ($1,$2); } | '~' ~r~expr %prec prNEGATION { $$ = new AstNot ($1,$2); }
@@ -2425,7 +2470,7 @@ expr<nodep>: // IEEE: part of expression/constant_expression/primary
// //
// // IEEE: primary_literal (minus string, which is handled specially) // // IEEE: primary_literal (minus string, which is handled specially)
| yaINTNUM { $$ = new AstConst($<fl>1,*$1); } | yaINTNUM { $$ = new AstConst($<fl>1,*$1); }
//UNSUP yaFLOATNUM { UNSUP } | yaFLOATNUM { $$ = new AstConst($<fl>1,AstConst::RealDouble(),$1); }
//UNSUP yaTIMENUM { UNSUP } //UNSUP yaTIMENUM { UNSUP }
| strAsInt~noStr__IGNORE~ { $$ = $1; } | strAsInt~noStr__IGNORE~ { $$ = $1; }
// //
@@ -2453,7 +2498,10 @@ expr<nodep>: // IEEE: part of expression/constant_expression/primary
| '_' '(' statePushVlg expr statePop ')' { $$ = $4; } // Arbitrary Verilog inside PSL | '_' '(' statePushVlg expr statePop ')' { $$ = $4; } // Arbitrary Verilog inside PSL
// //
// // IEEE: cast/constant_cast // // IEEE: cast/constant_cast
//UNSUP casting_type yP_TICK '(' expr ')' { UNSUP } | casting_type yP_TICK '(' expr ')' { $$ = new AstCast($2,$4,$1); }
// // expanded from casting_type
| ySIGNED yP_TICK '(' expr ')' { $$ = new AstSigned($1,$4); }
| yUNSIGNED yP_TICK '(' expr ')' { $$ = new AstUnsigned($1,$4); }
// // Spec only allows primary with addition of a type reference // // Spec only allows primary with addition of a type reference
// // We'll be more general, and later assert LHS was a type. // // We'll be more general, and later assert LHS was a type.
//UNSUP ~l~expr yP_TICK '(' expr ')' { UNSUP } //UNSUP ~l~expr yP_TICK '(' expr ')' { UNSUP }
@@ -2680,46 +2728,58 @@ gateUnsupList<nodep>:
; ;
gateBuf<nodep>: gateBuf<nodep>:
gateIdE instRangeE '(' idClassSel ',' expr ')' { $$ = new AstAssignW ($3,$4,$6); } gateIdE instRangeE '(' variable_lvalue ',' expr ')'
{ $$ = new AstAssignW ($3,$4,$6); }
; ;
gateBufif0<nodep>: gateBufif0<nodep>:
gateIdE instRangeE '(' idClassSel ',' expr ',' expr ')' { $$ = new AstAssignW ($3,$4,new AstCond($3,$8, new AstConst($3,V3Number($3,"1'bz")), $6)); } gateIdE instRangeE '(' variable_lvalue ',' expr ',' expr ')'
{ $$ = new AstAssignW ($3,$4,new AstBufIf1($3,new AstNot($3,$8),$6)); }
; ;
gateBufif1<nodep>: gateBufif1<nodep>:
gateIdE instRangeE '(' idClassSel ',' expr ',' expr ')' { $$ = new AstAssignW ($3,$4,new AstCond($3,$8, $6, new AstConst($3,V3Number($3,"1'bz")))); } gateIdE instRangeE '(' variable_lvalue ',' expr ',' expr ')'
{ $$ = new AstAssignW ($3,$4,new AstBufIf1($3,$8,$6)); }
; ;
gateNot<nodep>: gateNot<nodep>:
gateIdE instRangeE '(' idClassSel ',' expr ')' { $$ = new AstAssignW ($3,$4,new AstNot($5,$6)); } gateIdE instRangeE '(' variable_lvalue ',' expr ')'
{ $$ = new AstAssignW ($3,$4,new AstNot($5,$6)); }
; ;
gateNotif0<nodep>: gateNotif0<nodep>:
gateIdE instRangeE '(' idClassSel ',' expr ',' expr ')' { $$ = new AstAssignW ($3,$4,new AstCond($3,$8, new AstConst($3,V3Number($3,"1'bz")), new AstNot($3, $6))); } gateIdE instRangeE '(' variable_lvalue ',' expr ',' expr ')'
{ $$ = new AstAssignW ($3,$4,new AstBufIf1($3,new AstNot($3,$8), new AstNot($3, $6))); }
; ;
gateNotif1<nodep>: gateNotif1<nodep>:
gateIdE instRangeE '(' idClassSel ',' expr ',' expr ')' { $$ = new AstAssignW ($3,$4,new AstCond($3,$8, new AstNot($3,$6), new AstConst($3,V3Number($3,"1'bz")))); } gateIdE instRangeE '(' variable_lvalue ',' expr ',' expr ')'
{ $$ = new AstAssignW ($3,$4,new AstBufIf1($3,$8, new AstNot($3,$6))); }
; ;
gateAnd<nodep>: gateAnd<nodep>:
gateIdE instRangeE '(' idClassSel ',' gateAndPinList ')' { $$ = new AstAssignW ($3,$4,$6); } gateIdE instRangeE '(' variable_lvalue ',' gateAndPinList ')'
{ $$ = new AstAssignW ($3,$4,$6); }
; ;
gateNand<nodep>: gateNand<nodep>:
gateIdE instRangeE '(' idClassSel ',' gateAndPinList ')' { $$ = new AstAssignW ($3,$4,new AstNot($5,$6)); } gateIdE instRangeE '(' variable_lvalue ',' gateAndPinList ')'
{ $$ = new AstAssignW ($3,$4,new AstNot($5,$6)); }
; ;
gateOr<nodep>: gateOr<nodep>:
gateIdE instRangeE '(' idClassSel ',' gateOrPinList ')' { $$ = new AstAssignW ($3,$4,$6); } gateIdE instRangeE '(' variable_lvalue ',' gateOrPinList ')'
{ $$ = new AstAssignW ($3,$4,$6); }
; ;
gateNor<nodep>: gateNor<nodep>:
gateIdE instRangeE '(' idClassSel ',' gateOrPinList ')' { $$ = new AstAssignW ($3,$4,new AstNot($5,$6)); } gateIdE instRangeE '(' variable_lvalue ',' gateOrPinList ')'
{ $$ = new AstAssignW ($3,$4,new AstNot($5,$6)); }
; ;
gateXor<nodep>: gateXor<nodep>:
gateIdE instRangeE '(' idClassSel ',' gateXorPinList ')' { $$ = new AstAssignW ($3,$4,$6); } gateIdE instRangeE '(' variable_lvalue ',' gateXorPinList ')'
{ $$ = new AstAssignW ($3,$4,$6); }
; ;
gateXnor<nodep>: gateXnor<nodep>:
gateIdE instRangeE '(' idClassSel ',' gateXorPinList ')' { $$ = new AstAssignW ($3,$4,new AstNot($5,$6)); } gateIdE instRangeE '(' variable_lvalue ',' gateXorPinList ')'
{ $$ = new AstAssignW ($3,$4,new AstNot($5,$6)); }
; ;
gatePullup<nodep>: gatePullup<nodep>:
gateIdE instRangeE '(' idClassSel ')' { $$ = new AstPull ($3, $4, true); } gateIdE instRangeE '(' variable_lvalue ')' { $$ = new AstPull ($3, $4, true); }
; ;
gatePulldown<nodep>: gatePulldown<nodep>:
gateIdE instRangeE '(' idClassSel ')' { $$ = new AstPull ($3, $4, false); } gateIdE instRangeE '(' variable_lvalue ')' { $$ = new AstPull ($3, $4, false); }
; ;
gateUnsup<nodep>: gateUnsup<nodep>:
gateIdE instRangeE '(' gateUnsupPinList ')' { $$ = new AstImplicit ($3,$4); } gateIdE instRangeE '(' gateUnsupPinList ')' { $$ = new AstImplicit ($3,$4); }
@@ -2796,7 +2856,7 @@ junkToSemiList:
junkToSemi { } /* ignored */ junkToSemi { } /* ignored */
| junkToSemiList junkToSemi { } /* ignored */ | junkToSemiList junkToSemi { } /* ignored */
; ;
junkToSemi: junkToSemi:
BISONPRE_NOT(';',yENDSPECIFY,yENDMODULE) { } BISONPRE_NOT(';',yENDSPECIFY,yENDMODULE) { }
| error {} | error {}
@@ -2819,8 +2879,8 @@ idAny<strp>: // Any kind of identifier
idSVKwd<strp>: // Warn about non-forward compatible Verilog 2001 code idSVKwd<strp>: // Warn about non-forward compatible Verilog 2001 code
// // yBIT, yBYTE won't work here as causes conflicts // // yBIT, yBYTE won't work here as causes conflicts
yDO { static string s = "do" ; $$ = &s; ERRSVKWD($1,*$$); } yDO { static string s = "do" ; $$ = &s; ERRSVKWD($1,*$$); $<fl>$=$<fl>1; }
| yFINAL { static string s = "final"; $$ = &s; ERRSVKWD($1,*$$); } | yFINAL { static string s = "final"; $$ = &s; ERRSVKWD($1,*$$); $<fl>$=$<fl>1; }
; ;
variable_lvalue<nodep>: // IEEE: variable_lvalue or net_lvalue variable_lvalue<nodep>: // IEEE: variable_lvalue or net_lvalue
@@ -2872,7 +2932,7 @@ idDottedMore<nodep>:
// id below includes: // id below includes:
// enum_identifier // enum_identifier
idArrayed<nodep>: // IEEE: id + select idArrayed<nodep>: // IEEE: id + select
id { $$ = new AstText(CRELINE(),*$1); } id { $$ = new AstText($<fl>1,*$1); }
// // IEEE: id + part_select_range/constant_part_select_range // // IEEE: id + part_select_range/constant_part_select_range
| idArrayed '[' expr ']' { $$ = new AstSelBit($2,$1,$3); } // Or AstArraySel, don't know yet. | idArrayed '[' expr ']' { $$ = new AstSelBit($2,$1,$3); } // Or AstArraySel, don't know yet.
| idArrayed '[' constExpr ':' constExpr ']' { $$ = new AstSelExtract($2,$1,$3,$5); } | idArrayed '[' constExpr ':' constExpr ']' { $$ = new AstSelExtract($2,$1,$3,$5); }
@@ -2883,7 +2943,7 @@ idArrayed<nodep>: // IEEE: id + select
// VarRef without any dots or vectorizaion // VarRef without any dots or vectorizaion
varRefBase<varrefp>: varRefBase<varrefp>:
id { $$ = new AstVarRef(CRELINE(),*$1,false);} id { $$ = new AstVarRef($<fl>1,*$1,false);}
; ;
// yaSTRING shouldn't be used directly, instead via an abstraction below // yaSTRING shouldn't be used directly, instead via an abstraction below
@@ -3067,7 +3127,7 @@ vltOffFront<errcodeen>:
int V3ParseImp::bisonParse() { int V3ParseImp::bisonParse() {
if (PARSEP->debugBison()>=9) yydebug = 1; if (PARSEP->debugBison()>=9) yydebug = 1;
return yyparse(); return yyparse();
} }
const char* V3ParseImp::tokenName(int token) { const char* V3ParseImp::tokenName(int token) {
@@ -3091,7 +3151,7 @@ void V3ParseImp::parserClear() {
AstNode* V3ParseGrammar::createSupplyExpr(FileLine* fileline, string name, int value) { AstNode* V3ParseGrammar::createSupplyExpr(FileLine* fileline, string name, int value) {
FileLine* newfl = new FileLine (fileline); FileLine* newfl = new FileLine (fileline);
newfl->warnOff(V3ErrorCode::WIDTH, true); newfl->warnOff(V3ErrorCode::WIDTH, true);
AstNode* nodep = new AstConst(newfl, V3Number(fileline)); AstNode* nodep = new AstConst(newfl, V3Number(newfl));
// Adding a NOT is less work than figuring out how wide to make it // Adding a NOT is less work than figuring out how wide to make it
if (value) nodep = new AstNot(newfl, nodep); if (value) nodep = new AstNot(newfl, nodep);
nodep = new AstAssignW(newfl, new AstVarRef(fileline, name, true), nodep = new AstAssignW(newfl, new AstVarRef(fileline, name, true),
+64 -42
View File
@@ -110,8 +110,8 @@ if ($#opt_tests<0) {
} }
mkdir "obj_dir"; mkdir "obj_dir";
mkdir "logs";
our $Log_Filename = "obj_dir/driver_".strftime("%Y%m%d_%H%M%S.log", localtime);
my $leftcnt=0; my $okcnt=0; my $failcnt=0; my $skcnt=0; my $leftcnt=0; my $okcnt=0; my $failcnt=0; my $skcnt=0;
my @fails; my @fails;
@@ -161,16 +161,17 @@ sub one_test {
push @fails, "\t\tmake$j && test_regress/" push @fails, "\t\tmake$j && test_regress/"
.$test->{pl_filename}." ".join(' ',@Orig_ARGV_Sw)."\n"; .$test->{pl_filename}." ".join(' ',@Orig_ARGV_Sw)."\n";
$failcnt++; $failcnt++;
report(\@fails, $Log_Filename);
if ($opt_stop) { die "%Error: --stop and errors found\n"; } if ($opt_stop) { die "%Error: --stop and errors found\n"; }
} }
$leftcnt--; $leftcnt--;
print "==SUMMARY: Left $leftcnt Passed $okcnt Skipped $skcnt Failed $failcnt\n"; print STDERR "==SUMMARY: Left $leftcnt Passed $okcnt Skipped $skcnt Failed $failcnt\n";
}, },
)->ready(); )->ready();
} }
report(\@fails, undef); report(\@fails, undef);
report(\@fails, "obj_dir/driver_".strftime("%Y%m%d_%H%M%S.log", localtime)); report(\@fails, $Log_Filename);
exit(10) if $failcnt; exit(10) if $failcnt;
@@ -303,8 +304,9 @@ sub new {
ivrun_flags => [], ivrun_flags => [],
# VCS # VCS
vcs => 0, vcs => 0,
vcs_flags => [split(/\s+/,"+cli -I +define+VCS+1 -q -sverilog -CFLAGS '-DVCS' ")], vcs_flags => [split(/\s+/,"+vcs+lic+wait +cli -I +define+VCS+1 -q -sverilog -CFLAGS '-DVCS' ")],
vcs_flags2 => [], # Overridden in some sim files vcs_flags2 => [], # Overridden in some sim files
vcsrun_flags => [split(/\s+/,"+vcs+lic_wait")],
# NC # NC
nc => 0, nc => 0,
nc_flags => [split(/\s+/,"+licqueue +nowarn+LIBNOU +define+NC=1 -q +assert +sv -c ")], nc_flags => [split(/\s+/,"+licqueue +nowarn+LIBNOU +define+NC=1 -q +assert +sv -c ")],
@@ -334,6 +336,7 @@ sub new {
$self->{run_log_filename} ||= "$self->{obj_dir}/vlt_sim.log"; $self->{run_log_filename} ||= "$self->{obj_dir}/vlt_sim.log";
$self->{coverage_filename} ||= "$self->{obj_dir}/vlt_coverage.pl"; $self->{coverage_filename} ||= "$self->{obj_dir}/vlt_coverage.pl";
$self->{vcd_filename} ||= "$self->{obj_dir}/sim.vcd"; $self->{vcd_filename} ||= "$self->{obj_dir}/sim.vcd";
$self->{main_filename} ||= "$self->{obj_dir}/$self->{VM_PREFIX}__main.cpp";
($self->{top_filename} = $self->{pl_filename}) =~ s/\.pl$/\.v/; ($self->{top_filename} = $self->{pl_filename}) =~ s/\.pl$/\.v/;
if (!$self->{make_top_shell}) { if (!$self->{make_top_shell}) {
$self->{top_shell_filename} = $self->{top_filename}; $self->{top_shell_filename} = $self->{top_filename};
@@ -408,11 +411,10 @@ sub read_status {
#---------------------------------------------------------------------- #----------------------------------------------------------------------
# Methods invoked by tests # Methods invoked by tests
sub compile { sub compile_vlt_flags {
my $self = (ref $_[0]? shift : $Self); my $self = (ref $_[0]? shift : $Self);
my %param = (%{$self}, @_); # Default arguments are from $self my %param = (%{$self}, @_); # Default arguments are from $self
return 1 if $self->errors || $self->skips; return 1 if $self->errors || $self->skips;
$self->oprint("Compile\n");
my $checkflags = join(' ',@{$param{v_flags}}, my $checkflags = join(' ',@{$param{v_flags}},
@{$param{v_flags2}}, @{$param{v_flags2}},
@@ -423,6 +425,48 @@ sub compile {
$self->{trace} = 1 if ($opt_trace || $checkflags =~ /-trace\b/); $self->{trace} = 1 if ($opt_trace || $checkflags =~ /-trace\b/);
$self->{coverage} = 1 if ($checkflags =~ /-coverage\b/); $self->{coverage} = 1 if ($checkflags =~ /-coverage\b/);
$opt_gdb="gdbrun" if defined $opt_gdb;
my @verilator_flags = @{$param{verilator_flags}};
unshift @verilator_flags, "--gdb $opt_gdb" if $opt_gdb;
unshift @verilator_flags, "--gdbbt" if $opt_gdbbt;
unshift @verilator_flags, @Opt_Driver_Verilator_Flags;
unshift @verilator_flags, "--x-assign unique"; # More likely to be buggy
unshift @verilator_flags, "--trace" if $opt_trace;
if (defined $opt_optimize) {
my $letters = "";
if ($opt_optimize =~ /[a-zA-Z]/) {
$letters = $opt_optimize;
} else { # Randomly turn on/off different optimizations
foreach my $l ('a'..'z') {
$letters .= ((rand() > 0.5) ? $l : uc $l);
}
unshift @verilator_flags, "--trace" if rand() > 0.5;
unshift @verilator_flags, "--coverage" if rand() > 0.5;
}
unshift @verilator_flags, "--O".$letters;
}
my @cmdargs = ("perl","../bin/verilator",
"--prefix ".$param{VM_PREFIX},
@verilator_flags,
@{$param{verilator_flags2}},
@{$param{v_flags}},
@{$param{v_flags2}},
$param{top_filename},
@{$param{v_other_filenames}},
($param{stdout_filename}?"> ".$param{stdout_filename}:""),
);
return @cmdargs;
}
sub compile {
my $self = (ref $_[0]? shift : $Self);
my %param = (%{$self}, @_); # Default arguments are from $self
return 1 if $self->errors || $self->skips;
$self->oprint("Compile\n");
compile_vlt_flags(%param);
if ($param{atsim}) { if ($param{atsim}) {
$self->_make_top(); $self->_make_top();
$self->_run(logfile=>"$self->{obj_dir}/atsim_compile.log", $self->_run(logfile=>"$self->{obj_dir}/atsim_compile.log",
@@ -482,37 +526,8 @@ sub compile {
cmd=>\@cmd); cmd=>\@cmd);
} }
if ($param{vlt}) { if ($param{vlt}) {
$opt_gdb="gdbrun" if defined $opt_gdb; my @cmdargs = $self->compile_vlt_flags(%param);
my @verilator_flags = @{$param{verilator_flags}};
unshift @verilator_flags, "--gdb $opt_gdb" if $opt_gdb;
unshift @verilator_flags, "--gdbbt" if $opt_gdbbt;
unshift @verilator_flags, @Opt_Driver_Verilator_Flags;
unshift @verilator_flags, "--x-assign unique"; # More likely to be buggy
unshift @verilator_flags, "--trace" if $opt_trace;
if (defined $opt_optimize) {
my $letters = "";
if ($opt_optimize =~ /[a-zA-Z]/) {
$letters = $opt_optimize;
} else { # Randomly turn on/off different optimizations
foreach my $l ('a'..'z') {
$letters .= ((rand() > 0.5) ? $l : uc $l);
}
unshift @verilator_flags, "--trace" if rand() > 0.5;
unshift @verilator_flags, "--coverage" if rand() > 0.5;
}
unshift @verilator_flags, "--O".$letters;
}
my @vlargs = ("perl","../bin/verilator",
"--prefix ".$self->{VM_PREFIX},
@verilator_flags,
@{$param{verilator_flags2}},
@{$param{v_flags}},
@{$param{v_flags2}},
$param{top_filename},
@{$param{v_other_filenames}},
($param{stdout_filename}?"> ".$param{stdout_filename}:""),
);
if ($self->sc_or_sp && !defined $ENV{SYSTEMC}) { if ($self->sc_or_sp && !defined $ENV{SYSTEMC}) {
$self->skip("Test requires SystemC; ignore error since not installed\n"); $self->skip("Test requires SystemC; ignore error since not installed\n");
return 1; return 1;
@@ -522,16 +537,18 @@ sub compile {
return 1; return 1;
} }
if (!$param{fails} && $param{verilator_make_gcc}
&& $param{make_main}) {
$self->_make_main();
}
$self->_run(logfile=>"$self->{obj_dir}/vlt_compile.log", $self->_run(logfile=>"$self->{obj_dir}/vlt_compile.log",
fails=>$param{fails}, fails=>$param{fails},
expect=>$param{expect}, expect=>$param{expect},
cmd=>\@vlargs); cmd=>\@cmdargs);
return 1 if $self->errors || $self->skips; return 1 if $self->errors || $self->skips;
if (!$param{fails} && $param{verilator_make_gcc}) { if (!$param{fails} && $param{verilator_make_gcc}) {
if ($param{make_main}) {
$self->_make_main();
}
if ($self->sp) { if ($self->sp) {
$self->_sp_preproc(%param); $self->_sp_preproc(%param);
} }
@@ -590,6 +607,7 @@ sub execute {
#$fh->print("quit\n"); $fh->close; #$fh->print("quit\n"); $fh->close;
$self->_run(logfile=>"$self->{obj_dir}/vcs_sim.log", $self->_run(logfile=>"$self->{obj_dir}/vcs_sim.log",
cmd=>["echo q | ".$run_env."./simv", cmd=>["echo q | ".$run_env."./simv",
@{$param{vcsrun_flags}},
@{$param{all_run_flags}}, @{$param{all_run_flags}},
], ],
%param, %param,
@@ -791,7 +809,7 @@ sub _make_main {
$self->_read_inputs(); $self->_read_inputs();
my $filename = "$self->{obj_dir}/$self->{VM_PREFIX}__main.cpp"; my $filename = $self->{main_filename};
my $fh = IO::File->new(">$filename") or die "%Error: $! $filename,"; my $fh = IO::File->new(">$filename") or die "%Error: $! $filename,";
print $fh "// Test defines\n"; print $fh "// Test defines\n";
@@ -879,8 +897,12 @@ sub _make_main {
print $fh ' vl_fatal(__FILE__,__LINE__,"main", "%Error: Timeout; never got a $finish");',"\n"; print $fh ' vl_fatal(__FILE__,__LINE__,"main", "%Error: Timeout; never got a $finish");',"\n";
print $fh " }\n"; print $fh " }\n";
print $fh " topp->final();\n"; print $fh " topp->final();\n";
print $fh " SpCoverage::write(\"",$self->{coverage_filename},"\");\n" if $self->{coverage};
if ($self->{coverage}) {
$fh->print("#if VM_COVERAGE\n");
$fh->print(" SpCoverage::write(\"",$self->{coverage_filename},"\");\n");
$fh->print("#endif //VM_COVERAGE\n");
}
if ($self->{trace}) { if ($self->{trace}) {
$fh->print("#if VM_TRACE\n"); $fh->print("#if VM_TRACE\n");
$fh->print(" if (tfp) tfp->close();\n"); $fh->print(" if (tfp) tfp->close();\n");
+1 -1
View File
@@ -13,7 +13,7 @@
// please note it here, otherwise:** // please note it here, otherwise:**
// //
// This file ONLY is placed into the Public Domain, for any use, // This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2010 by Wilson Snyder. // without warranty, 2011 by Wilson Snyder.
module t (/*AUTOARG*/ module t (/*AUTOARG*/
// Inputs // Inputs
+1 -1
View File
@@ -47,7 +47,7 @@ module t (/*AUTOARG*/
endcase endcase
end end
`ifdef NOT_YET_verilator `ifdef NOT_YET_VERILATOR // Unsupported
// ambit synthesis one_hot "a, b_oh" // ambit synthesis one_hot "a, b_oh"
// cadence one_cold "a_l, b_oc_l" // cadence one_cold "a_l, b_oc_l"
`endif `endif
+1 -1
View File
@@ -25,7 +25,7 @@ module t_case_huge_sub2 (/*AUTOARG*/
always @(/*AS*/index) begin always @(/*AS*/index) begin
case (index[7:0]) case (index[7:0])
`ifdef verilator `ifdef VERILATOR // Harder test
8'h00: begin outa = $c("0"); end // Makes whole table non-optimizable 8'h00: begin outa = $c("0"); end // Makes whole table non-optimizable
`else `else
8'h00: begin outa = 10'h0; end 8'h00: begin outa = 10'h0; end
-4
View File
@@ -2497,11 +2497,7 @@ module t_case_write1_tasks ();
endtask endtask
task big_case; task big_case;
`ifdef verilator
input [ 63:0] fd;
`else
input [ 31:0] fd; input [ 31:0] fd;
`endif
input [ 31:0] foo; input [ 31:0] foo;
reg [STRLEN*8: 1] foobar; reg [STRLEN*8: 1] foobar;
// verilator no_inline_task // verilator no_inline_task
-4
View File
@@ -10,11 +10,7 @@ module t_case_write2_tasks ();
// verilator lint_off WIDTH // verilator lint_off WIDTH
// verilator lint_off CASEINCOMPLETE // verilator lint_off CASEINCOMPLETE
`ifdef verilator
`define FD_BITS 63:0
`else
`define FD_BITS 31:0 `define FD_BITS 31:0
`endif
parameter STRLEN = 78; parameter STRLEN = 78;
task ozonerab; task ozonerab;
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
compile (
);
execute (
check_finished=>1,
);
ok(1);
1;
+26
View File
@@ -0,0 +1,26 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2011 by Wilson Snyder.
module t;
typedef logic [3:0] mc_t;
typedef mc_t tocast_t;
mc_t o;
initial begin
if (4'shf > 4'sh0) $stop;
if (signed'(4'hf) > 4'sh0) $stop;
if (4'hf < 4'h0) $stop;
if (unsigned'(4'shf) < 4'h0) $stop;
o = tocast_t'(4'b1);
if (o != 4'b1) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule
+4 -3
View File
@@ -12,11 +12,12 @@ compile (
verilator_make_gcc => 0, verilator_make_gcc => 0,
fails => 1, fails => 1,
expect=> expect=>
'%Warning-CDCRSTLOGIC: t/t_cdc_async_bad.v:\d+: Logic in path that feeds async reset, via signal: TOP->v.rst2_bad_n '%Warning-CDCRSTLOGIC: t/t_cdc_async_bad.v:\d+: Logic in path that feeds async reset, via signal: v.rst2_bad_n
%Warning-CDCRSTLOGIC: Use "/\* verilator lint_off CDCRSTLOGIC \*/" and lint_on around source to disable this message. %Warning-CDCRSTLOGIC: Use "/\* verilator lint_off CDCRSTLOGIC \*/" and lint_on around source to disable this message.
%Warning-CDCRSTLOGIC: See details in obj_dir/t_cdc_async_bad/Vt_cdc_async_bad__cdc.txt %Warning-CDCRSTLOGIC: See details in obj_dir/t_cdc_async_bad/Vt_cdc_async_bad__cdc.txt
%Warning-CDCRSTLOGIC: t/t_cdc_async_bad.v:\d+: Logic in path that feeds async reset, via signal: TOP->v.rst6a_bad_n %Warning-CDCRSTLOGIC: t/t_cdc_async_bad.v:\d+: Logic in path that feeds async reset, via signal: v.rst6a_bad_n
%Warning-CDCRSTLOGIC: t/t_cdc_async_bad.v:\d+: Logic in path that feeds async reset, via signal: TOP->v.rst3_bad_n %Warning-CDCRSTLOGIC: t/t_cdc_async_bad.v:\d+: Logic in path that feeds async reset, via signal: v.rst6b_bad_n
%Warning-CDCRSTLOGIC: t/t_cdc_async_bad.v:\d+: Logic in path that feeds async reset, via signal: v.rst3_bad_n
%Error: Exiting due to.*', %Error: Exiting due to.*',
); );
+1 -1
View File
@@ -86,7 +86,7 @@ module Test (/*AUTOARG*/
end end
reg displayit; reg displayit;
`ifdef verilator `ifdef VERILATOR // Harder test
initial displayit = $c1("0"); // Something that won't optimize away initial displayit = $c1("0"); // Something that won't optimize away
`else `else
initial displayit = '0; initial displayit = '0;
+2
View File
@@ -59,7 +59,9 @@ module t (/*AUTOARG*/
reg [7:0] cyc; initial cyc=0; reg [7:0] cyc; initial cyc=0;
always @ (posedge clk) begin always @ (posedge clk) begin
`ifdef TEST_VERBOSE
$write("[%0t] rs %x cyc %d cg1f %x cnt %x cg %x\n",$time,reset_l,cyc,clkgate_e1f,count,countgated); $write("[%0t] rs %x cyc %d cg1f %x cnt %x cg %x\n",$time,reset_l,cyc,clkgate_e1f,count,countgated);
`endif
cyc <= cyc + 8'd1; cyc <= cyc + 8'd1;
case (cyc) case (cyc)
8'd00: begin 8'd00: begin
+24
View File
@@ -0,0 +1,24 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
top_filename("t/t_cover_line.v");
compile (
verilator_flags2 => ['--cc --coverage-line'],
);
execute (
check_finished=>1,
);
# Read the input .v file and do any CHECK_COVER requests
inline_checks();
ok(1);
1;
+24
View File
@@ -0,0 +1,24 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
top_filename("t/t_cover_line.v");
compile (
verilator_flags2 => ['--sc --coverage-line'],
);
execute (
check_finished=>1,
);
# Read the input .v file and do any CHECK_COVER requests
inline_checks();
ok(1);
1;
@@ -7,6 +7,8 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
# Lesser General Public License Version 3 or the Perl Artistic License # Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0. # Version 2.0.
top_filename("t/t_cover_line.v");
compile ( compile (
verilator_flags2 => ['--sp --coverage-line'], verilator_flags2 => ['--sp --coverage-line'],
); );
+4 -2
View File
@@ -19,10 +19,12 @@ execute (
[0] In top.v.sub2 [0] In top.v.sub2
[0] In top.v.sub2.subblock2 [0] In top.v.sub2.subblock2
[0] Back \ Quote " [0] Back \ Quote "
[0] %X=0c %D=12 %0X=c %0O=14 %B=001100 [0] %X=00c %0X=c %0O=14 %B=000001100
[0] %x=0c %d=12 %0x=c %0o=14 %b=001100 [0] %x=00c %0x=c %0o=14 %b=000001100
[0] %D= 12 %d= 12 %01d=12 %06d=000012 %6d= 12
[0] %x=00abbbbcccc %0x=abbbbcccc %o=00527356746314 %b=00000101010111011101110111100110011001100 [0] %x=00abbbbcccc %0x=abbbbcccc %o=00527356746314 %b=00000101010111011101110111100110011001100
[0] %x=00abc1234567812345678 %0x=abc1234567812345678 %o=012570110642547402215053170 %b=000001010101111000001001000110100010101100111100000010010001101000101011001111000 [0] %x=00abc1234567812345678 %0x=abc1234567812345678 %o=012570110642547402215053170 %b=000001010101111000001001000110100010101100111100000010010001101000101011001111000
[0] %t= 0 %03t= 0 %0t=0
[0] %s=! %s= what! %s= hmmm!1234 [0] %s=! %s= what! %s= hmmm!1234
[0] hello, from a very long string. Percent %s are literally substituted in. [0] hello, from a very long string. Percent %s are literally substituted in.
+10 -4
View File
@@ -9,6 +9,7 @@ module t;
reg [31:0] str; initial str = "\000\277\021\n"; reg [31:0] str; initial str = "\000\277\021\n";
reg [47:0] str2; initial str2 = "\000what!"; reg [47:0] str2; initial str2 = "\000what!";
reg [79:0] str3; initial str3 = "\000hmmm!1234"; reg [79:0] str3; initial str3 = "\000hmmm!1234";
reg [8:0] nine;
sub sub (); sub sub ();
sub2 sub2 (); sub2 sub2 ();
@@ -22,14 +23,19 @@ module t;
$display("[%0t] Back \\ Quote \"", $time); // Old bug when \" last on the line. $display("[%0t] Back \\ Quote \"", $time); // Old bug when \" last on the line.
// Display formatting // Display formatting
$display("[%0t] %%X=%X %%D=%D %%0X=%0X %%0O=%0O %%B=%B", $time, nine = {3'd0,quad[5:0]};
quad[5:0], quad[5:0], quad[5:0], quad[5:0], quad[5:0]); $display("[%0t] %%X=%X %%0X=%0X %%0O=%0O %%B=%B", $time,
$display("[%0t] %%x=%x %%d=%d %%0x=%0x %%0o=%0o %%b=%b", $time, nine, nine, nine, nine);
quad[5:0], quad[5:0], quad[5:0], quad[5:0], quad[5:0]); $display("[%0t] %%x=%x %%0x=%0x %%0o=%0o %%b=%b", $time,
nine, nine, nine, nine);
$display("[%0t] %%D=%D %%d=%d %%01d=%01d %%06d=%06d %%6d=%6d", $time,
nine, nine, nine, nine, nine);
$display("[%0t] %%x=%x %%0x=%0x %%o=%o %%b=%b", $time, $display("[%0t] %%x=%x %%0x=%0x %%o=%o %%b=%b", $time,
quad, quad, quad, quad); quad, quad, quad, quad);
$display("[%0t] %%x=%x %%0x=%0x %%o=%o %%b=%b", $time, $display("[%0t] %%x=%x %%0x=%0x %%o=%o %%b=%b", $time,
wide, wide, wide, wide); wide, wide, wide, wide);
$display("[%0t] %%t=%t %%03t=%03t %%0t=%0t", $time,
$time, $time, $time);
$display; $display;
// Not testing %0s, it does different things in different simulators // Not testing %0s, it does different things in different simulators
$display("[%0t] %%s=%s %%s=%s %%s=%s", $time, $display("[%0t] %%s=%s %%s=%s %%s=%s", $time,
+4 -2
View File
@@ -22,10 +22,12 @@ execute (
[0] In top.v.sub2 [0] In top.v.sub2
[0] In top.v.sub2.subblock2 [0] In top.v.sub2.subblock2
[0] Back \ Quote " [0] Back \ Quote "
[0] %X=0c %D=12 %0X=c %0O=14 %B=001100 [0] %X=00c %0X=c %0O=14 %B=000001100
[0] %x=0c %d=12 %0x=c %0o=14 %b=001100 [0] %x=00c %0x=c %0o=14 %b=000001100
[0] %D= 12 %d= 12 %01d=12 %06d=000012 %6d= 12
[0] %x=00abbbbcccc %0x=abbbbcccc %o=00527356746314 %b=00000101010111011101110111100110011001100 [0] %x=00abbbbcccc %0x=abbbbcccc %o=00527356746314 %b=00000101010111011101110111100110011001100
[0] %x=00abc1234567812345678 %0x=abc1234567812345678 %o=012570110642547402215053170 %b=000001010101111000001001000110100010101100111100000010010001101000101011001111000 [0] %x=00abc1234567812345678 %0x=abc1234567812345678 %o=012570110642547402215053170 %b=000001010101111000001001000110100010101100111100000010010001101000101011001111000
[0] %t= 0 %03t= 0 %0t=0
[0] %s=! %s= what! %s= hmmm!1234 [0] %s=! %s= what! %s= hmmm!1234
[0] hello, from a very long string. Percent %s are literally substituted in. [0] hello, from a very long string. Percent %s are literally substituted in.
+39
View File
@@ -0,0 +1,39 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
compile (
);
execute (
check_finished=>1,
expect=> quotemeta(
'[0] e=0.000000e+00 e1=0.000000e+00 e30=0e+00 e32=0.00e+00
[0] f=0.000000 f1=0.000000e+00 f30=0e+00 f32=0.00e+00
[0] g=0 g1=0.000000e+00 g30=0e+00 g32=0.00e+00
[0] e=1.000000e+00 e1=1.000000e+00 e30=1e+00 e32=1.00e+00
[0] f=1.000000 f1=1.000000e+00 f30=1e+00 f32=1.00e+00
[0] g=1 g1=1.000000e+00 g30=1e+00 g32=1.00e+00
[0] e=1.000000e-01 e1=1.000000e-01 e30=1e-01 e32=1.00e-01
[0] f=0.100000 f1=1.000000e-01 f30=1e-01 f32=1.00e-01
[0] g=0.1 g1=1.000000e-01 g30=1e-01 g32=1.00e-01
[0] e=1.234500e-15 e1=1.234500e-15 e30=1e-15 e32=1.23e-15
[0] f=0.000000 f1=1.234500e-15 f30=1e-15 f32=1.23e-15
[0] g=1.2345e-15 g1=1.234500e-15 g30=1e-15 g32=1.23e-15
[0] e=2.579000e+15 e1=2.579000e+15 e30=3e+15 e32=2.58e+15
[0] f=2579000000000000.000000 f1=2.579000e+15 f30=3e+15 f32=2.58e+15
[0] g=2.579e+15 g1=2.579000e+15 g30=3e+15 g32=2.58e+15
'),
);
ok(1);
1;
+37
View File
@@ -0,0 +1,37 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2003 by Wilson Snyder.
module t;
real n0; initial n0 = 0.0;
real n1; initial n1 = 1.0;
real n2; initial n2 = 0.1;
real n3; initial n3 = 1.2345e-15;
real n4; initial n4 = 2.579e+15;
initial begin
// Display formatting
$display("[%0t] e=%e e1=%1e e30=%3.0e e32=%3.2e", $time, n0,n0,n0,n0);
$display("[%0t] f=%f f1=%1e f30=%3.0e f32=%3.2e", $time, n0,n0,n0,n0);
$display("[%0t] g=%g g1=%1e g30=%3.0e g32=%3.2e", $time, n0,n0,n0,n0);
$display;
$display("[%0t] e=%e e1=%1e e30=%3.0e e32=%3.2e", $time, n1,n1,n1,n1);
$display("[%0t] f=%f f1=%1e f30=%3.0e f32=%3.2e", $time, n1,n1,n1,n1);
$display("[%0t] g=%g g1=%1e g30=%3.0e g32=%3.2e", $time, n1,n1,n1,n1);
$display;
$display("[%0t] e=%e e1=%1e e30=%3.0e e32=%3.2e", $time, n2,n2,n2,n2);
$display("[%0t] f=%f f1=%1e f30=%3.0e f32=%3.2e", $time, n2,n2,n2,n2);
$display("[%0t] g=%g g1=%1e g30=%3.0e g32=%3.2e", $time, n2,n2,n2,n2);
$display;
$display("[%0t] e=%e e1=%1e e30=%3.0e e32=%3.2e", $time, n3,n3,n3,n3);
$display("[%0t] f=%f f1=%1e f30=%3.0e f32=%3.2e", $time, n3,n3,n3,n3);
$display("[%0t] g=%g g1=%1e g30=%3.0e g32=%3.2e", $time, n3,n3,n3,n3);
$display;
$display("[%0t] e=%e e1=%1e e30=%3.0e e32=%3.2e", $time, n4,n4,n4,n4);
$display("[%0t] f=%f f1=%1e f30=%3.0e f32=%3.2e", $time, n4,n4,n4,n4);
$display("[%0t] g=%g g1=%1e g30=%3.0e g32=%3.2e", $time, n4,n4,n4,n4);
$write("*-* All Finished *-*\n");
$finish;
end
endmodule
+42
View File
@@ -0,0 +1,42 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
top_filename("t/t_display_real.v");
compile (
v_flags2 => [$Self->{v3}?"-O0":""],
);
execute (
check_finished=>1,
expect=> quotemeta(
'[0] e=0.000000e+00 e1=0.000000e+00 e30=0e+00 e32=0.00e+00
[0] f=0.000000 f1=0.000000e+00 f30=0e+00 f32=0.00e+00
[0] g=0 g1=0.000000e+00 g30=0e+00 g32=0.00e+00
[0] e=1.000000e+00 e1=1.000000e+00 e30=1e+00 e32=1.00e+00
[0] f=1.000000 f1=1.000000e+00 f30=1e+00 f32=1.00e+00
[0] g=1 g1=1.000000e+00 g30=1e+00 g32=1.00e+00
[0] e=1.000000e-01 e1=1.000000e-01 e30=1e-01 e32=1.00e-01
[0] f=0.100000 f1=1.000000e-01 f30=1e-01 f32=1.00e-01
[0] g=0.1 g1=1.000000e-01 g30=1e-01 g32=1.00e-01
[0] e=1.234500e-15 e1=1.234500e-15 e30=1e-15 e32=1.23e-15
[0] f=0.000000 f1=1.234500e-15 f30=1e-15 f32=1.23e-15
[0] g=1.2345e-15 g1=1.234500e-15 g30=1e-15 g32=1.23e-15
[0] e=2.579000e+15 e1=2.579000e+15 e30=3e+15 e32=2.58e+15
[0] f=2579000000000000.000000 f1=2.579000e+15 f30=3e+15 f32=2.58e+15
[0] g=2.579e+15 g1=2.579000e+15 g30=3e+15 g32=2.58e+15
'),
);
ok(1);
1;
+24
View File
@@ -0,0 +1,24 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
$Self->{vl_time_multiplier} = 1000;
compile (
);
execute (
check_finished=>1,
expect=> quotemeta(
'[1000.000] cyc==99 crc=2961926edde3e5c6018be970cdbf327b72b5f3c5eab42995891005eec8767e5fdf03051edbe9d222ee756ee34d8d6c83ee877aad65c487140ac87d26c636a66214b4a69acad924c568cc8e8c79f97d07a6eedf91011919d0e3cdda5215ee58c942f6c4dea48b3f38abc77bf47e4f6d6a859fcc5b5d46ec9d2f6a5bf7b978b1ba7ca15d0713a2eb06ade1570c4e3a12db687625eef8dfebcb4095ab4bdffe79c1298f609307a5ef773a6432b855e3e54deb88ca342bf5a7fecc5f2f3e165a59cdb9179718a2d11c9d55f14d69f40b01e41fcb7335a8872a6ba7876ec684d6a3af0b82aa31cca6e26340a2589cf7bf886faa8d23844596dc71233c7025c5250a968b770ab72db90b03d8c045fb8848159df544a3a3bf063269be0aa11d5507f5c8b328b760a6df9e3fbe276faad8eadee126443ad3f99d595b12d0ae514b20693298a58642a07718f9ab7ea8c66575f7f8d0e3ba77d992235b3d5a4e015a7ff9b97a8c4f48ebdbfc2365e6bca4dd3ba6bfc7e850f7c8e2842c717a1d85a977a033f564fc
[1000.000] cyc==99 crc=001010010110000110010010011011101101110111100011111001011100011000000001100010111110100101110000110011011011111100110010011110110111001010110101111100111100010111101010101101000010100110010101100010010001000000000101111011101100100001110110011111100101111111011111000000110000010100011110110110111110100111010010001000101110111001110101011011101110001101001101100011010110110010000011111011101000011101111010101011010110010111000100100001110001010000001010110010000111110100100110110001100011011010100110011000100001010010110100101001101001101011001010110110010010010011000101011010001100110010001110100011000111100111111001011111010000011110100110111011101101111110010001000000010001100100011001110100001110001111001101110110100101001000010101111011100101100011001001010000101111011011000100110111101010010010001011001111110011100010101011110001110111101111110100011111100100111101101101011010101000010110011111110011000101101101011101010001101110110010011101001011110110101001011011111101111011100101111000101100011011101001111100101000010101110100000111000100111010001011101011000001101010110111100001010101110000110001001110001110100001001011011011011010000111011000100101111011101111100011011111111010111100101101000000100101011010101101001011110111111111111001111001110000010010100110001111011000001001001100000111101001011110111101110111001110100110010000110010101110000101010111100011111001010100110111101011100010001100101000110100001010111111010110100111111111101100110001011111001011110011111000010110010110100101100111001101101110010001011110010111000110001010001011010001000111001001110101010101111100010100110101101001111101000000101100000001111001000001111111001011011100110011010110101000100001110010101001101011101001111000011101101110110001101000010011010110101000111010111100001011100000101010101000110001110011001010011011100010011000110100000010100010010110001001110011110111101111111000100001101111101010101000110100100011100001000100010110010110110111000111000100100011001111000111000000100101110001010010010100001010100101101000101101110111000010101011011100101101101110010000101100000011110110001100000001000101111110111000100001001000000101011001110111110101010001001010001110100011101111110000011000110010011010011011111000001010101000010001110101010101000001111111010111001000101100110010100010110111011000001010011011011111100111100011111110111110001001110110111110101010110110001110101011011110111000010010011001000100001110101101001111111001100111010101100101011011000100101101000010101110010100010100101100100000011010010011001010011000101001011000011001000010101000000111011100011000111110011010101101111110101010001100011001100101011101011111011111111000110100001110001110111010011101111101100110010010001000110101101100111101010110100100111000000001010110100111111111111001101110010111101010001100010011110100100011101011110110111111110000100011011001011110011010111100101001001101110100111011101001101011111111000111111010000101000011110111110010001110001010000100001011000111000101111010000111011000010110101001011101111010000000110011111101010110010011111100'
),
);
ok(1);
1;
+33
View File
@@ -0,0 +1,33 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2011 by Wilson Snyder.
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
integer cyc=0;
reg [4095:0] crc;
// Test loop
always @ (posedge clk) begin
cyc <= cyc + 1;
crc <= {crc[4094:0], crc[63]^crc[2]^crc[0]}; // not a good crc :)
if (cyc==0) begin
// Setup
crc <= 4096'h9f51804b5275c7b6ab9907144a58649bb778f9718062fa5c336fcc9edcad7cf17aad0a656244017bb21d9f97f7c0c147b6fa7488bb9d5bb8d3635b20fba1deab597121c502b21f49b18da998852d29a6b2b649315a3323a31e7e5f41e9bbb7e44046467438f37694857b963250bdb137a922cfce2af1defd1f93db5aa167f316d751bb274bda96fdee5e2c6eb21886633246b165341f0594c27697b06b62b1ad05ebe3c08909a54272de651296dcdd3d1774fc432d22210d8f6afa50b02cf23336f8cc3a0a2ebfd1a3a60366a1b66ef346e0379116d68caa01279ac2772d1f3cd76d2cbbc68ada6f83ec2441b2679b405486df8aa734ea1729b40c3f82210e8e42823eb3fd6ca77ee19f285741c4e8bac1ab7855c3138e84b6da1d897bbe37faf2d0256ad2f7ff9e704a63d824c1e97bddce990cae1578f9537ae2328d0afd69ffb317cbcf859696736e45e5c628b44727557c535a7d02c07907f2dccd6a21ca9ae9e1dbb1a135a8ebc2e0aa8c7329b898d02896273defe21beaa348e11165b71c48cf1c09714942a5a2ddc2adcb6e42c0f630117ee21205677d5128e8efc18c9a6f82a8475541fd722cca2dd829b7e78fef89dbeab63ab7b849910eb4fe675656c4b42b9452c81a4ca6296190a81dc63e6adfaa31995d7dfe3438ee9df66488d6cf569380569ffe6e5ea313d23af6ff08d979af29374ee9aff1fa143df238a1;
end
else if (cyc==99) begin
$write("[%0t] cyc==%0d crc=%x%x%x%x\n",$time, cyc, crc[4095:3072], crc[2071:2048], crc[2047:1024], crc[1023:0]);
$write("[%0t] cyc==%0d crc=%b%b%b%b\n",$time, cyc, crc[4095:3072], crc[2071:2048], crc[2047:1024], crc[1023:0]);
//Unsupported: $write("[%0t] cyc==%0d crc=%x\n",$time, cyc, crc);
if (crc != 4096'h2961926edde3e5c6018be970cdbf327b72b5f3c5eab42995891005eec8767e5fdf03051edbe9d222ee756ee34d8d6c83ee877aad65c487140ac87d26c636a66214b4a69acad924c568cc8e8c79f97d07a6eedf91011919d0e3cdda5215ee58c942f6c4dea48b3f38abc77bf47e4f6d6a859fcc5b5d46ec9d2f6a5bf7b978b1bac862198cc91ac594d07c165309da5ec1ad8ac6b417af8f0224269509cb79944a5b7374f45dd3f10cb48884363dabe942c0b3c8ccdbe330e828baff468e980d9a86d9bbcd1b80de445b5a32a8049e6b09dcb47cf35db4b2ef1a2b69be0fb09106c99e6d01521b7e2a9cd3a85ca6d030fe08843a390a08facff5b29dfb867ca15d0713a2eb06ade1570c4e3a12db687625eef8dfebcb4095ab4bdffe79c1298f609307a5ef773a6432b855e3e54deb88ca342bf5a7fecc5f2f3e165a59cdb9179718a2d11c9d55f14d69f40b01e41fcb7335a8872a6ba7876ec684d6a3af0b82aa31cca6e26340a2589cf7bf886faa8d23844596dc71233c7025c5250a968b770ab72db90b03d8c045fb8848159df544a3a3bf063269be0aa11d5507f5c8b328b760a6df9e3fbe276faad8eadee126443ad3f99d595b12d0ae514b20693298a58642a07718f9ab7ea8c66575f7f8d0e3ba77d992235b3d5a4e015a7ff9b97a8c4f48ebdbfc2365e6bca4dd3ba6bfc7e850f7c8e2842c717a1d85a977a033f564fc
) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule
+7
View File
@@ -23,6 +23,7 @@ module t;
function int dpix_int123(); dpix_int123 = 32'h123; endfunction function int dpix_int123(); dpix_int123 = 32'h123; endfunction
export "DPI-C" function dpix_f_bit; export "DPI-C" function dpix_f_bit;
export "DPI-C" function dpix_f_bit15;
export "DPI-C" function dpix_f_int; export "DPI-C" function dpix_f_int;
export "DPI-C" function dpix_f_byte; export "DPI-C" function dpix_f_byte;
export "DPI-C" function dpix_f_shortint; export "DPI-C" function dpix_f_shortint;
@@ -30,12 +31,18 @@ module t;
export "DPI-C" function dpix_f_chandle; export "DPI-C" function dpix_f_chandle;
function bit dpix_f_bit (bit i); dpix_f_bit = ~i; endfunction function bit dpix_f_bit (bit i); dpix_f_bit = ~i; endfunction
function bit [14:0] dpix_f_bit15 (bit [14:0] i); dpix_f_bit15 = ~i; endfunction
function int dpix_f_int (int i); dpix_f_int = ~i; endfunction function int dpix_f_int (int i); dpix_f_int = ~i; endfunction
function byte dpix_f_byte (byte i); dpix_f_byte = ~i; endfunction function byte dpix_f_byte (byte i); dpix_f_byte = ~i; endfunction
function shortint dpix_f_shortint(shortint i); dpix_f_shortint = ~i; endfunction function shortint dpix_f_shortint(shortint i); dpix_f_shortint = ~i; endfunction
function longint dpix_f_longint (longint i); dpix_f_longint = ~i; endfunction function longint dpix_f_longint (longint i); dpix_f_longint = ~i; endfunction
function chandle dpix_f_chandle (chandle i); dpix_f_chandle = i; endfunction function chandle dpix_f_chandle (chandle i); dpix_f_chandle = i; endfunction
export "DPI-C" task dpix_t_bit95;
task dpix_t_bit95(input bit [94:0] i, output bit [94:0] o); o = ~i; endtask
export "DPI-C" task dpix_t_bit96;
task dpix_t_bit96(input bit [95:0] i, output bit [95:0] o); o = ~i; endtask
int lineno; int lineno;
initial begin initial begin
+20
View File
@@ -123,8 +123,11 @@ int dpix_run_tests() {
CHECK_RESULT (int, o, 0x458UL); CHECK_RESULT (int, o, 0x458UL);
#endif #endif
svBitVecVal vec10[1] = {0x10};
CHECK_RESULT (int, dpix_f_bit(1), 0x0); CHECK_RESULT (int, dpix_f_bit(1), 0x0);
CHECK_RESULT (int, dpix_f_bit(0), 0x1); CHECK_RESULT (int, dpix_f_bit(0), 0x1);
CHECK_RESULT (int, dpix_f_bit15(vec10) & 0x7fUL, 0x6f);
// Simulators disagree over the next three's sign extension unless we mask the upper bits // Simulators disagree over the next three's sign extension unless we mask the upper bits
CHECK_RESULT (int, dpix_f_int(1) & 0xffffffffUL, 0xfffffffeUL); CHECK_RESULT (int, dpix_f_int(1) & 0xffffffffUL, 0xfffffffeUL);
CHECK_RESULT (int, dpix_f_byte(1) & 0xffUL, 0xfe); CHECK_RESULT (int, dpix_f_byte(1) & 0xffUL, 0xfe);
@@ -133,6 +136,23 @@ int dpix_run_tests() {
CHECK_RESULT (unsigned long long, dpix_f_longint(1), 0xfffffffffffffffeULL); CHECK_RESULT (unsigned long long, dpix_f_longint(1), 0xfffffffffffffffeULL);
CHECK_RESULT (void*, dpix_f_chandle((void*)(12345)), (void*)(12345)); CHECK_RESULT (void*, dpix_f_chandle((void*)(12345)), (void*)(12345));
{
svBitVecVal i_vec95[3] = {0x72912312,0xab782a12,0x8a413bd9};
svBitVecVal o_vec95[3] = {0,0,0};
dpix_t_bit95(i_vec95, o_vec95);
CHECK_RESULT(int, o_vec95[0], ~i_vec95[0]);
CHECK_RESULT(int, o_vec95[1], ~i_vec95[1]);
CHECK_RESULT(int, o_vec95[2], (~i_vec95[2])&0x7fffffffUL);
}
{
svBitVecVal i_vec96[3] = {0xf2912312,0xab782a12,0x8a413bd9};
svBitVecVal o_vec96[3] = {0,0,0};
dpix_t_bit96(i_vec96, o_vec96);
CHECK_RESULT(int, o_vec96[0], ~i_vec96[0]);
CHECK_RESULT(int, o_vec96[1], ~i_vec96[1]);
CHECK_RESULT(int, o_vec96[2], ~i_vec96[2]);
}
if (int bad=check_sub("top.t.a",1)) return bad; if (int bad=check_sub("top.t.a",1)) return bad;
if (int bad=check_sub("top.t.b",2)) return bad; if (int bad=check_sub("top.t.b",2)) return bad;
+13 -11
View File
@@ -11,7 +11,7 @@
`ifdef NC `ifdef NC
`define NO_SHORTREAL `define NO_SHORTREAL
`endif `endif
`ifdef VERILATOR `ifdef VERILATOR // Unsupported
`define NO_SHORTREAL `define NO_SHORTREAL
`endif `endif
@@ -39,9 +39,7 @@ module t ();
import "DPI-C" pure function longint dpii_f_longint (input longint i); import "DPI-C" pure function longint dpii_f_longint (input longint i);
import "DPI-C" pure function chandle dpii_f_chandle (input chandle i); import "DPI-C" pure function chandle dpii_f_chandle (input chandle i);
import "DPI-C" pure function string dpii_f_string (input string i); import "DPI-C" pure function string dpii_f_string (input string i);
`ifndef VERILATOR
import "DPI-C" pure function real dpii_f_real (input real i); import "DPI-C" pure function real dpii_f_real (input real i);
`endif
`ifndef NO_SHORTREAL `ifndef NO_SHORTREAL
import "DPI-C" pure function shortreal dpii_f_shortreal(input shortreal i); import "DPI-C" pure function shortreal dpii_f_shortreal(input shortreal i);
`endif `endif
@@ -53,12 +51,12 @@ module t ();
import "DPI-C" pure function void dpii_v_longint (input longint i, output longint o); import "DPI-C" pure function void dpii_v_longint (input longint i, output longint o);
import "DPI-C" pure function void dpii_v_chandle (input chandle i, output chandle o); import "DPI-C" pure function void dpii_v_chandle (input chandle i, output chandle o);
import "DPI-C" pure function void dpii_v_string (input string i, output string o); import "DPI-C" pure function void dpii_v_string (input string i, output string o);
`ifndef VERILATOR
import "DPI-C" pure function void dpii_v_real (input real i, output real o); import "DPI-C" pure function void dpii_v_real (input real i, output real o);
`endif
`ifndef NO_SHORTREAL `ifndef NO_SHORTREAL
import "DPI-C" pure function void dpii_v_shortreal(input shortreal i, output shortreal o); import "DPI-C" pure function void dpii_v_shortreal(input shortreal i, output shortreal o);
`endif `endif
import "DPI-C" pure function void dpii_v_bit95 (input bit [95-1:0] i, output bit [95-1:0] o);
import "DPI-C" pure function void dpii_v_bit96 (input bit [96-1:0] i, output bit [96-1:0] o);
import "DPI-C" pure function int dpii_f_strlen (input string i); import "DPI-C" pure function int dpii_f_strlen (input string i);
@@ -82,6 +80,8 @@ module t ();
bit [31:0] i_b32, o_b32; bit [31:0] i_b32, o_b32;
bit [32:0] i_b33, o_b33; bit [32:0] i_b33, o_b33;
bit [63:0] i_b64, o_b64; bit [63:0] i_b64, o_b64;
bit [94:0] i_b95, o_b95;
bit [95:0] i_b96, o_b96;
int i_i, o_i; int i_i, o_i;
byte i_y, o_y; byte i_y, o_y;
@@ -89,9 +89,7 @@ module t ();
longint i_l, o_l; longint i_l, o_l;
chandle i_c, o_c; chandle i_c, o_c;
string i_n, o_n; string i_n, o_n;
`ifndef VERILATOR
real i_d, o_d; real i_d, o_d;
`endif
`ifndef NO_SHORTREAL `ifndef NO_SHORTREAL
shortreal i_f, o_f; shortreal i_f, o_f;
`endif `endif
@@ -111,11 +109,17 @@ module t ();
i_b32 = {1'b1,wide[32-2:0]}; i_b32 = {1'b1,wide[32-2:0]};
i_b33 = {1'b1,wide[33-2:0]}; i_b33 = {1'b1,wide[33-2:0]};
i_b64 = {1'b1,wide[64-2:0]}; i_b64 = {1'b1,wide[64-2:0]};
i_b95 = {1'b1,wide[95-2:0]};
i_b96 = {1'b1,wide[96-2:0]};
i_i = {1'b1,wide[32-2:0]}; i_i = {1'b1,wide[32-2:0]};
i_y = {1'b1,wide[8-2:0]}; i_y = {1'b1,wide[8-2:0]};
i_s = {1'b1,wide[16-2:0]}; i_s = {1'b1,wide[16-2:0]};
i_l = {1'b1,wide[64-2:0]}; i_l = {1'b1,wide[64-2:0]};
i_d = 32.1;
`ifndef NO_SHORTREAL
i_f = 30.2;
`endif
if (dpii_f_bit (i_b) !== ~i_b) $stop; if (dpii_f_bit (i_b) !== ~i_b) $stop;
if (dpii_f_bit8 (i_b8) !== ~i_b8) $stop; if (dpii_f_bit8 (i_b8) !== ~i_b8) $stop;
@@ -139,9 +143,7 @@ module t ();
if (dpii_f_longint (i_l) !== ~i_l) $stop; if (dpii_f_longint (i_l) !== ~i_l) $stop;
if (dpii_f_chandle (i_c) !== i_c) $stop; if (dpii_f_chandle (i_c) !== i_c) $stop;
if (dpii_f_string (i_n) != i_n) $stop; if (dpii_f_string (i_n) != i_n) $stop;
`ifndef VERILATOR
if (dpii_f_real (i_d) != i_d+1.5) $stop; if (dpii_f_real (i_d) != i_d+1.5) $stop;
`endif
`ifndef NO_SHORTREAL `ifndef NO_SHORTREAL
if (dpii_f_shortreal(i_f) != i_f+1.5) $stop; if (dpii_f_shortreal(i_f) != i_f+1.5) $stop;
`endif `endif
@@ -153,12 +155,12 @@ module t ();
dpii_v_longint (i_l,o_l); if (o_l !== ~i_l) $stop; dpii_v_longint (i_l,o_l); if (o_l !== ~i_l) $stop;
dpii_v_chandle (i_c,o_c); if (o_c !== i_c) $stop; dpii_v_chandle (i_c,o_c); if (o_c !== i_c) $stop;
dpii_v_string (i_n,o_n); if (o_n != i_n) $stop; dpii_v_string (i_n,o_n); if (o_n != i_n) $stop;
`ifndef VERILATOR
dpii_v_real (i_d,o_d); if (o_d != i_d+1.5) $stop; dpii_v_real (i_d,o_d); if (o_d != i_d+1.5) $stop;
`endif
`ifndef NO_SHORTREAL `ifndef NO_SHORTREAL
dpii_v_shortreal(i_f,o_f); if (o_f != i_f+1.5) $stop; dpii_v_shortreal(i_f,o_f); if (o_f != i_f+1.5) $stop;
`endif `endif
dpii_v_bit95 (i_b95,o_b95); if (o_b95 !== ~i_b95) $stop;
dpii_v_bit96 (i_b96,o_b96); if (o_b96 !== ~i_b96) $stop;
if (dpii_f_strlen ("")!=0) $stop; if (dpii_f_strlen ("")!=0) $stop;
if (dpii_f_strlen ("s")!=1) $stop; if (dpii_f_strlen ("s")!=1) $stop;
+20 -8
View File
@@ -33,13 +33,14 @@
extern "C" { extern "C" {
extern unsigned char dpii_f_bit (unsigned char i); extern unsigned char dpii_f_bit (unsigned char i);
extern svBitVecVal dpii_f_bit8 (const svBitVecVal *i); extern svBitVecVal dpii_f_bit8 (const svBitVecVal* i);
extern svBitVecVal dpii_f_bit9 (const svBitVecVal *i); extern svBitVecVal dpii_f_bit9 (const svBitVecVal* i);
extern svBitVecVal dpii_f_bit16 (const svBitVecVal *i); extern svBitVecVal dpii_f_bit16 (const svBitVecVal* i);
extern svBitVecVal dpii_f_bit17 (const svBitVecVal *i); extern svBitVecVal dpii_f_bit17 (const svBitVecVal* i);
extern svBitVecVal dpii_f_bit32 (const svBitVecVal *i); extern svBitVecVal dpii_f_bit32 (const svBitVecVal* i);
extern long long dpii_f_bit33 (const svBitVecVal *i); extern long long dpii_f_bit33 (const svBitVecVal* i);
extern long long dpii_f_bit64 (const svBitVecVal *i); extern long long dpii_f_bit64 (const svBitVecVal* i);
extern long long dpii_f_bit95 (const svBitVecVal* i, svBitVecVal* o);
extern int dpii_f_int (int i); extern int dpii_f_int (int i);
extern char dpii_f_byte (char i); extern char dpii_f_byte (char i);
extern short int dpii_f_shortint(short int i); extern short int dpii_f_shortint(short int i);
@@ -49,7 +50,7 @@ extern "C" {
extern double dpii_f_real (double i); extern double dpii_f_real (double i);
extern float dpii_f_shortreal(float i); extern float dpii_f_shortreal(float i);
extern void dpii_v_bit (unsigned char i, unsigned char *o); extern void dpii_v_bit (unsigned char i, unsigned char* o);
extern void dpii_v_int (int i, int *o); extern void dpii_v_int (int i, int *o);
extern void dpii_v_byte (char i, char *o); extern void dpii_v_byte (char i, char *o);
extern void dpii_v_shortint (short int i, short int *o); extern void dpii_v_shortint (short int i, short int *o);
@@ -100,6 +101,17 @@ void dpii_v_string (const char* i, const char** o) { *o = i; }
void dpii_v_real (double i, double* o) { *o = i + 1.5; } void dpii_v_real (double i, double* o) { *o = i + 1.5; }
void dpii_v_shortreal(float i, float* o) { *o = i + 1.5; } void dpii_v_shortreal(float i, float* o) { *o = i + 1.5; }
void dpii_v_bit95(const svBitVecVal* i, svBitVecVal* o) {
o[0] = ~i[0];
o[1] = ~i[1];
o[2] = SV_MASK(95-64) & ~i[2];
}
void dpii_v_bit96(const svBitVecVal* i, svBitVecVal* o) {
o[0] = ~i[0];
o[1] = ~i[1];
o[2] = ~i[2];
}
int dpii_f_strlen (const char* i) { return strlen(i); } int dpii_f_strlen (const char* i) { return strlen(i); }
//====================================================================== //======================================================================
+51
View File
@@ -0,0 +1,51 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
use File::Spec;
my $self = $Self;
my $child_dir = "$Self->{obj_dir}_child";
mkdir $child_dir;
# Compile the child
{
my @cmdargs = $Self->compile_vlt_flags
(VM_PREFIX => "$Self->{VM_PREFIX}_child",
top_filename => "$Self->{name}_child.v",
verilator_flags => ["-cc", "-Mdir", "${child_dir}", "--debug-check"],
);
$Self->_run(logfile=>"${child_dir}/vlt_compile.log",
cmd=>\@cmdargs);
$Self->_run(logfile=>"${child_dir}/vlt_gcc.log",
cmd=>["cd ${child_dir} && ",
"make", "-f".getcwd()."/Makefile_obj",
"CPPFLAGS_DRIVER=-D".uc($self->{name}),
($opt_verbose ? "CPPFLAGS_DRIVER2=-DTEST_VERBOSE=1":""),
"MAKE_MAIN=0",
"VM_PREFIX=$self->{VM_PREFIX}_child",
"V$self->{name}_child__ALL.a", # bypass default rule, make archive
($param{make_flags}||""),
]);
}
# Compile the parent (might be with other than verilator)
compile (
v_flags2 => [File::Spec->rel2abs("${child_dir}/V$self->{name}_child__ALL.a"),
# TODO would be nice to have this in embedded archive
"t/t_embed1_c.cpp"],
);
execute (
check_finished=>1,
);
ok(1);
1;
+109
View File
@@ -0,0 +1,109 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2011 by Wilson Snyder.
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
integer cyc=0;
reg [63:0] crc;
reg [63:0] sum;
// Take CRC data and apply to testblock inputs
wire bit_in = crc[0];
wire [30:0] vec_in = crc[31:1];
wire [123:0] wide_in = {crc[59:0],~crc[63:0]};
/*AUTOWIRE*/
// Beginning of automatic wires (for undeclared instantiated-module outputs)
wire exp_bit_out; // From reference of t_embed1_child.v
wire exp_did_init_out; // From reference of t_embed1_child.v
wire [30:0] exp_vec_out; // From reference of t_embed1_child.v
wire [123:0] exp_wide_out; // From reference of t_embed1_child.v
wire got_bit_out; // From test of t_embed1_wrap.v
wire got_did_init_out; // From test of t_embed1_wrap.v
wire [30:0] got_vec_out; // From test of t_embed1_wrap.v
wire [123:0] got_wide_out; // From test of t_embed1_wrap.v
// End of automatics
// A non-embedded master
/* t_embed1_child AUTO_TEMPLATE(
.\(.*_out\) (exp_\1[]),
.is_ref (1'b1));
*/
t_embed1_child reference
(/*AUTOINST*/
// Outputs
.bit_out (exp_bit_out), // Templated
.vec_out (exp_vec_out[30:0]), // Templated
.wide_out (exp_wide_out[123:0]), // Templated
.did_init_out (exp_did_init_out), // Templated
// Inputs
.clk (clk),
.bit_in (bit_in),
.vec_in (vec_in[30:0]),
.wide_in (wide_in[123:0]),
.is_ref (1'b1)); // Templated
// The embeded comparison
/* t_embed1_wrap AUTO_TEMPLATE(
.\(.*_out\) (got_\1[]),
.is_ref (1'b0));
*/
t_embed1_wrap test
(/*AUTOINST*/
// Outputs
.bit_out (got_bit_out), // Templated
.vec_out (got_vec_out[30:0]), // Templated
.wide_out (got_wide_out[123:0]), // Templated
.did_init_out (got_did_init_out), // Templated
// Inputs
.clk (clk),
.bit_in (bit_in),
.vec_in (vec_in[30:0]),
.wide_in (wide_in[123:0]),
.is_ref (1'b0)); // Templated
// Aggregate outputs into a single result vector
wire [63:0] result = {60'h0,
got_wide_out !== exp_wide_out,
got_vec_out !== exp_vec_out,
got_bit_out !== exp_bit_out,
got_did_init_out !== exp_did_init_out};
// Test loop
always @ (posedge clk) begin
`ifdef TEST_VERBOSE
$write("[%0t] cyc==%0d crc=%x result=%x gv=%x ev=%x\n",$time, cyc, crc, result,
got_vec_out, exp_vec_out);
`endif
cyc <= cyc + 1;
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
if (cyc==0) begin
// Setup
crc <= 64'h5aef0c8d_d70a4497;
end
else if (cyc<10) begin
end
else if (cyc<90) begin
if (result != 64'h0) begin
$display("Bit mismatch, result=%x\n", result);
$stop;
end
end
else if (cyc==99) begin
$write("[%0t] cyc==%0d crc=%x sum=%x\n",$time, cyc, crc, sum);
if (crc !== 64'hc77bb9b3784ea091) $stop;
//Child prints this: $write("*-* All Finished *-*\n");
$finish;
end
end
endmodule
+123
View File
@@ -0,0 +1,123 @@
// -*- C++ -*-
//*************************************************************************
//
// Copyright 2011-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.
//
//*************************************************************************
#include <cstdio>
#include "svdpi.h"
#include "../t_embed1_child/Vt_embed1_child.h"
//======================================================================
#if defined(VERILATOR)
# include "Vt_embed1__Dpi.h"
#elif defined(VCS)
# include "../vc_hdrs.h"
#elif defined(CADENCE)
# define NEED_EXTERNS
#else
# error "Unknown simulator for DPI test"
#endif
#include "verilated.h"
#ifdef NEED_EXTERNS
extern "C" {
extern void t_embed_child_initial();
extern void t_embed_child_final();
extern void t_embed_child_eval();
extern void t_embed_child_io_eval(); // TODO real function params here
}
#endif
//======================================================================
extern int T_Embed_Child_Unique;
int T_Embed_Child_Unique = 0; // Address used for uniqueness
Vt_embed1_child* __get_modelp() {
svScope scope = svGetScope();
if (!scope) {
vl_fatal(__FILE__,__LINE__,__FILE__,"svGetScope failed");
return NULL;
}
void* __modelp = svGetUserData(scope, &T_Embed_Child_Unique);
if (!__modelp) {
// Create the model
const char* scopenamep = svGetNameFromScope(scope);
if (!scopenamep) vl_fatal(__FILE__,__LINE__,__FILE__,"svGetNameFromScope failed");
__modelp = new Vt_embed1_child(scopenamep);
if (svPutUserData(scope, &T_Embed_Child_Unique, __modelp)) {
vl_fatal(__FILE__,__LINE__,__FILE__,"svPutUserData failed");
}
}
return (Vt_embed1_child*)(__modelp);
}
void t_embed_child_initial() {
VL_DEBUG_IF(VL_PRINTF(" t_embed1_child_initial\n"); );
Vt_embed1_child* __modelp = __get_modelp();
__modelp->eval();
}
void t_embed_child_final() {
VL_DEBUG_IF(VL_PRINTF(" t_embed1_child_final\n"); );
Vt_embed1_child* __modelp = __get_modelp();
__modelp->final();
}
void t_embed_child_eval() {
VL_DEBUG_IF(VL_PRINTF(" t_embed1_child_eval\n"); );
Vt_embed1_child* __modelp = __get_modelp();
__modelp->eval();
}
void t_embed_child_io_eval (unsigned char clk,
unsigned char bit_in,
const svBitVecVal* vec_in,
const svBitVecVal* wide_in,
unsigned char is_ref,
unsigned char* bit_out,
svBitVecVal* vec_out,
svBitVecVal* wide_out,
unsigned char* did_init_out) {
VL_DEBUG_IF(VL_PRINTF(" t_embed1_child_io_eval\n"); );
Vt_embed1_child* __modelp = __get_modelp();
VL_DEBUG_IF(VL_PRINTF("[%0ld] in clk=%x b=%x V=%x R=%x\n",
VL_TIME_Q(), clk, bit_in, vec_in[0], is_ref););
__modelp->clk = clk;
__modelp->bit_in = bit_in;
__modelp->vec_in = vec_in[0];
__modelp->wide_in[0] = wide_in[0];
__modelp->wide_in[1] = wide_in[1];
__modelp->wide_in[2] = wide_in[2];
__modelp->wide_in[3] = wide_in[3];
__modelp->is_ref = is_ref;
//
__modelp->eval();
// TODO maybe we should look at a "change detect" to know if we need to copy
// out the variables; can return this value to the caller verilog code too
//
*bit_out = __modelp->bit_out;
vec_out[0] = __modelp->vec_out;
wide_out[0] = __modelp->wide_out[0];
wide_out[1] = __modelp->wide_out[1];
wide_out[2] = __modelp->wide_out[2];
wide_out[3] = __modelp->wide_out[3];
*did_init_out = __modelp->did_init_out;
VL_DEBUG_IF(VL_PRINTF("[%0ld] out b=%x V=%x DI=%x\n",
VL_TIME_Q(), *bit_out, *vec_out, *did_init_out););
}
+45
View File
@@ -0,0 +1,45 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2011 by Wilson Snyder.
module t_embed1_child (/*AUTOARG*/
// Outputs
bit_out, vec_out, wide_out, did_init_out,
// Inputs
clk, bit_in, vec_in, wide_in, is_ref
);
input clk;
input bit_in;
output bit_out;
input [30:0] vec_in;
output [30:0] vec_out;
input [123:0] wide_in;
output [123:0] wide_out;
output did_init_out;
input is_ref;
reg did_init; initial did_init = 0;
initial begin
did_init = 1;
end
reg did_final; initial did_final = 0;
final begin
did_final = 1;
if (!is_ref) $write("*-* All Finished *-*\n");
//$finish is in parent
end
// Note async use!
wire bit_out = bit_in;
wire did_init_out = did_init;
always @ (posedge clk) begin
vec_out <= vec_in;
wide_out <= wide_in;
end
endmodule

Some files were not shown because too many files have changed in this diff Show More