mirror of
https://github.com/verilator/verilator.git
synced 2026-10-03 16:44:11 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ad53833040 | ||
|
|
bc8c85668a | ||
|
|
d12a3dde45 | ||
|
|
301c878c0f | ||
|
|
bd55bfa071 | ||
|
|
6d2f09b579 | ||
|
|
4bfea7f54d | ||
|
|
55906486d8 | ||
|
|
d5478e6e08 | ||
|
|
d88d85c172 | ||
|
|
59c3c536c7 | ||
|
|
a007458cb8 | ||
|
|
d051912f21 | ||
|
|
a547158a50 | ||
|
|
95f2351aa0 | ||
|
|
698aaffb0b | ||
|
|
73eccecbf8 | ||
|
|
ae4a261463 | ||
|
|
c9f0d0cec2 | ||
|
|
4fa1e45d45 | ||
|
|
1b3d252bfe | ||
|
|
a9ba4a9fcd | ||
|
|
7f49619875 | ||
|
|
696660639a | ||
|
|
da4323062d | ||
|
|
a901e171b2 | ||
|
|
6e41d532fe | ||
|
|
4fc78ffb58 | ||
|
|
8137f41fc3 | ||
|
|
2e9471797d | ||
|
|
344248cea0 | ||
|
|
2789e3dba5 | ||
|
|
cca759a41e | ||
|
|
4f7b3d8882 | ||
|
|
2b330b78b7 | ||
|
|
d47ca1912b | ||
|
|
3fd2108b10 | ||
|
|
96e2a407f4 | ||
|
|
cdf18c96f4 | ||
|
|
53acaa05b8 | ||
|
|
fb85679068 | ||
|
|
9558e14479 | ||
|
|
4af0af93bf | ||
|
|
df4bc950fe | ||
|
|
250394f72b | ||
|
|
ca83fd6dc1 | ||
|
|
d5e9e7cd2b | ||
|
|
9a96f621ef | ||
|
|
5d7ce096c6 | ||
|
|
c9f8109c06 | ||
|
|
a20b4f2864 | ||
|
|
44a19d2a0a | ||
|
|
02f3beb8db | ||
|
|
3269cc3d90 | ||
|
|
fb70a1f4ab | ||
|
|
df0aa483ce | ||
|
|
c83f12a55c | ||
|
|
9704f59566 | ||
|
|
2923893d34 | ||
|
|
890dab0742 | ||
|
|
607e26b041 | ||
|
|
ea75290f65 | ||
|
|
a176054118 | ||
|
|
9a697dc5f5 | ||
|
|
cfdb852843 | ||
|
|
2e67a91982 | ||
|
|
074ca9330d | ||
|
|
f0d7cdcb20 |
@@ -3,6 +3,61 @@ Revision history for Verilator
|
||||
The contributors that suggested a given feature are shown in []. [by ...]
|
||||
indicates the contributor was also the author of the fix; Thanks!
|
||||
|
||||
* Verilator 3.820 2011/07/28
|
||||
|
||||
** Support 'real' numbers and related functions.
|
||||
|
||||
*** Support 'const' variables in limited cases; similar to enums. [Alex Solomatnikov]
|
||||
|
||||
*** Support disable for loop escapes.
|
||||
|
||||
*** Support $fopen and I/O with integer instead of `verilator_file_descriptor.
|
||||
|
||||
*** Support coverage in -cc and -sc output modes. [John Li]
|
||||
Note this requires SystemPerl 1.338 or newer.
|
||||
|
||||
**** Fix vpi_register_cb using bad s_cb_data, bug370. [by Thomas Watts]
|
||||
|
||||
**** Fix $display missing leading zeros in %0d, bug367. [Alex Solomatnikov]
|
||||
|
||||
**** Use 'vluint64_t' for SystemC instead of (same sized) 'uint64' for MSVC++.
|
||||
|
||||
* Verilator 3.813 2011/06/28
|
||||
|
||||
*** Support bit vectors > 64 bits wide in DPI import and exports.
|
||||
|
||||
*** Fix out of memory on slice syntax error, bug354. [Alex Solomatnikov]
|
||||
|
||||
**** Fix error on enum references to other packages, bug339. [Alex Solomatnikov]
|
||||
|
||||
**** Fix DPI undeclared svBitVecVal compile error, bug346. [Chandan Egbert]
|
||||
|
||||
**** Fix DPI bit vector compile errors, bug347, bug359. [Chandan Egbert]
|
||||
|
||||
**** Fix CDCRSTLOGIC report showing endpoint flops without resets.
|
||||
|
||||
**** Fix compiler warnings on SPARC, bug288. [Ahmed El-Mahmoudy]
|
||||
|
||||
* Verilator 3.812 2011/04/06
|
||||
|
||||
*** Add --trace-max-width and --trace-max-array, bug319. [Alex Solomatnikov]
|
||||
|
||||
*** Add --Wno-fatal to turn off abort on warnings. [by Stefan Wallentowitz]
|
||||
|
||||
**** Support ${...} and $(...) env vars in .vc files. [by Stefan Wallentowitz]
|
||||
|
||||
**** Support $bits(data_type), bug327. [Alex Solomatnikov]
|
||||
|
||||
**** Support loop unrolling on width mismatches, bug333. [Joe Eiler]
|
||||
|
||||
**** Support simple cast operators, bug335. [Alex Solomatnikov]
|
||||
|
||||
**** Accelerate bit-selected inversions.
|
||||
|
||||
**** Add error on circular parameter definitions, bug329. [Alex Solomatnikov]
|
||||
|
||||
**** Fix concatenates and vectored bufif1, bug326. [Iztok Jeras]
|
||||
|
||||
* Verilator 3.811 2011/02/14
|
||||
|
||||
**** Report errors on duplicated or empty pins, bug321. [Christian Leber]
|
||||
|
||||
+126
-54
@@ -252,7 +252,7 @@ descriptions in the next sections for more information.
|
||||
--exe Link to create executable
|
||||
-F <file> Parse options from a file, relatively
|
||||
-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
|
||||
-I<dir> Directory to search for includes
|
||||
--if-depth <value> Tune IFDEPTH warning
|
||||
@@ -268,7 +268,7 @@ descriptions in the next sections for more information.
|
||||
--MP Create phony dependency targets
|
||||
--Mdir <directory> Name of output object directory
|
||||
--mod-prefix <topname> Name to prepend to lower classes
|
||||
--no-pins64 Don't use uint64_t's for 33-64 bit sigs
|
||||
--no-pins64 Don't use vluint64_t's for 33-64 bit sigs
|
||||
--no-skip-identical Disable skipping identical output
|
||||
+notimingchecks Ignored
|
||||
-O0 Disable optimizations
|
||||
@@ -292,6 +292,8 @@ descriptions in the next sections for more information.
|
||||
--top-module <topname> Name of top level input module
|
||||
--trace Enable waveform creation
|
||||
--trace-depth <levels> Depth of tracing
|
||||
--trace-max-array <bits> Maximum bit width for tracing
|
||||
--trace-max-width <depth> Maximum array depth for tracing
|
||||
--trace-underscore Enable tracing of _signals
|
||||
-U<var> Undefine preprocessor define
|
||||
--unroll-count <loops> Tune maximum loop iterations
|
||||
@@ -304,6 +306,7 @@ descriptions in the next sections for more information.
|
||||
-Wno-<message> Disable warning
|
||||
-Wno-lint Disable all lint warnings
|
||||
-Wno-style Disable all style warnings
|
||||
-Wno-fatal Disable fatal exit on warnings
|
||||
-x-assign <mode> Initially assign Xs to this value
|
||||
-y <dir> Directory to search for modules
|
||||
|
||||
@@ -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
|
||||
command line parameters. Any relative paths are relative to the directory
|
||||
containing the specified file. Note -F is fairly standard across Verilog
|
||||
tools.
|
||||
containing the specified file. See also -f. Note -F is fairly standard
|
||||
across Verilog tools.
|
||||
|
||||
=item -f I<file>
|
||||
|
||||
Read the specified file, and act as if all text inside it was specified as
|
||||
command line parameters. 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
|
||||
|
||||
@@ -610,7 +617,7 @@ appropriate `begin_keywords.
|
||||
|
||||
Specify the extensions that should be used for finding modules. If for
|
||||
example module I<x> is referenced, look in I<x>.I<ext>. Note +libext+ is
|
||||
fairly standard across Verilog tools.
|
||||
fairly standard across Verilog tools. Defaults to .v and .sv.
|
||||
|
||||
=item --lint-only
|
||||
|
||||
@@ -706,7 +713,7 @@ Backward compatible alias for "--pins-bv 65". Note that's a 65, not a 64.
|
||||
=item --pins-bv I<width>
|
||||
|
||||
Specifies SystemC inputs/outputs of greater than or equal to I<width> bits
|
||||
wide should use sc_bv's instead of uint32/uint64_t's. The default is
|
||||
wide should use sc_bv's instead of uint32/vluint64_t's. The default is
|
||||
"--pins-bv 65". Versions before Verilator 3.671 defaulted to "--pins-bv
|
||||
33". The more sc_bv is used, the worse for performance.
|
||||
|
||||
@@ -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
|
||||
improve runtime and trace file size.
|
||||
|
||||
=item --trace-max-array I<bits>
|
||||
|
||||
Rarely needed. Specify the maximum array depth of a signal that may be
|
||||
traced. Defaults to 32, as tracing large arrays may greatly slow traced
|
||||
simulations.
|
||||
|
||||
=item --trace-max-width I<depth>
|
||||
|
||||
Rarely needed. Specify the maximum bit width of a signal that may be
|
||||
traced. Defaults to 256, as tracing large vectors may greatly slow traced
|
||||
simulations.
|
||||
|
||||
=item --trace-underscore
|
||||
|
||||
Enable tracing of signals that start with an underscore. Normally, these
|
||||
@@ -865,11 +884,11 @@ example C<-Werror-NOUNOPTFLAT>.
|
||||
|
||||
=item -Wfuture-I<message>
|
||||
|
||||
Suppress unknown Verilator comments or warning messages with the given
|
||||
message code. This is used to allow code written with pragmas for a later
|
||||
version of Verilator to run under a older version; add -Wfuture- arguments
|
||||
for each message code or comment that the new version supports which the
|
||||
older version does not support.
|
||||
Rarely needed. Suppress unknown Verilator comments or warning messages
|
||||
with the given message code. This is used to allow code written with
|
||||
pragmas for a later version of Verilator to run under a older version; add
|
||||
-Wfuture- arguments for each message code or comment that the new version
|
||||
supports which the older version does not support.
|
||||
|
||||
=item -Wno-I<message>
|
||||
|
||||
@@ -894,6 +913,14 @@ already disabled). This is equivalent to "-Wno-DECLFILENAME -Wno-DEFPARAM
|
||||
-Wno-INCABSPATH -Wno-SYNCASYNCNET -Wno-UNDRIVEN -Wno-UNUSED
|
||||
-Wno-VARHIDDEN".
|
||||
|
||||
=item -Wno-fatal
|
||||
|
||||
When warnings are detected, print them, but do not exit the simulator.
|
||||
|
||||
Having warning messages in builds is sloppy. It is strongly recommended
|
||||
you cleanup your code, use inline lint_off, or use -Wno-... flags rather
|
||||
than using this option.
|
||||
|
||||
=item -Wwarn-I<message>
|
||||
|
||||
Enables the specified warning message.
|
||||
@@ -903,8 +930,8 @@ Enables the specified warning message.
|
||||
Enable all lint related warning messages (note by default they are already
|
||||
enabled), but do not affect style messages. This is equivalent to
|
||||
"-Wwarn-CASEINCOMPLETE -Wwarn-CASEOVERLAP -Wwarn-CASEX -Wwarn-CASEWITHX
|
||||
-Wwarn-CMPCONST -Wwarn-IMPLICIT -Wwarn-LITENDIAN -Wwarn-UNSIGNED
|
||||
-Wwarn-WIDTH".
|
||||
-Wwarn-CMPCONST -Wwarn-IMPLICIT -Wwarn-LITENDIAN -Wwarn-REALCVT
|
||||
-Wwarn-UNSIGNED -Wwarn-WIDTH".
|
||||
|
||||
=item -Wwarn-style
|
||||
|
||||
@@ -954,7 +981,7 @@ We'll compile this example into C++.
|
||||
|
||||
cat <<EOF >our.v
|
||||
module our;
|
||||
initial begin \$display("Hello World"); \$finish; end
|
||||
initial begin $display("Hello World"); $finish; end
|
||||
endmodule
|
||||
EOF
|
||||
|
||||
@@ -976,7 +1003,7 @@ your operating system (as an RPM), first you need to point to the kit:
|
||||
export PATH=$VERILATOR_ROOT/bin:$PATH
|
||||
|
||||
Now we run Verilator on our little example.
|
||||
|
||||
|
||||
verilator -Wall --cc our.v --exe sim_main.cpp
|
||||
|
||||
We can see the source code under the "obj_dir" directory. See the FILES
|
||||
@@ -1019,7 +1046,7 @@ This is an example similar to the above, but using SystemPerl.
|
||||
module our (clk);
|
||||
input clk; // Clock is required to get initial activation
|
||||
always @ (posedge clk)
|
||||
begin \$display("Hello World"); \$finish; end
|
||||
begin $display("Hello World"); $finish; end
|
||||
endmodule
|
||||
EOF
|
||||
|
||||
@@ -1325,7 +1352,7 @@ will plug directly into a SystemC netlist.
|
||||
The SC_MODULE gets the same pinout as the Verilog module, with the
|
||||
following type conversions: Pins of a single bit become bool. Pins 2-32
|
||||
bits wide become uint32_t's. Pins 33-64 bits wide become sc_bv's or
|
||||
uint64_t's depending on the --no-pins64 switch. Wider pins become sc_bv's.
|
||||
vluint64_t's depending on the --no-pins64 switch. Wider pins become sc_bv's.
|
||||
(Uints simulate the fastest so are used where possible.)
|
||||
|
||||
Lower modules are not pure SystemC code. This is a feature, as using the
|
||||
@@ -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
|
||||
format.
|
||||
|
||||
=head2 DPI Context Functions
|
||||
|
||||
Verilator supports IEEE DPI Context Functions. Context imports pass the
|
||||
simulator context, including calling scope name, and filename and line
|
||||
number to the C code. For example, in Verilog:
|
||||
|
||||
import "DPI-C" context function int dpic_line();
|
||||
initial $display("This is line %d, again, line %d\n", `line, dpic_line());
|
||||
|
||||
This will call C++ code which may then use the svGet* functions to read
|
||||
information, in this case the line number of the Verilog statement that
|
||||
invoked the dpic_line function:
|
||||
|
||||
int dpic_line() {
|
||||
// Get a scope: svScope scope = svGetScope();
|
||||
|
||||
const char* scopenamep = svGetNameFromScope(scope);
|
||||
assert(scopenamep);
|
||||
|
||||
const char* filenamep = "";
|
||||
int lineno = 0;
|
||||
if (svGetCallerInfo(&filenamep, &lineno)) {
|
||||
printf("dpic_line called from scope %s on line %d\n",
|
||||
scopenamep, lineno);
|
||||
return lineno;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
See the IEEE Standard for more information.
|
||||
|
||||
=head2 DPI Header Isolation
|
||||
|
||||
Verilator places the IEEE standard header files such as svdpi.h into a
|
||||
@@ -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
|
||||
definitions.
|
||||
|
||||
=head2 Public Functions
|
||||
=head2 Public Functions
|
||||
|
||||
Instead of DPI exporting, there's also Verilator public functions, which
|
||||
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,
|
||||
$bits, $countones, $error, $fatal, $info, $isunknown, $onehot, $onehot0,
|
||||
$unit, $warning, always_comb, always_ff, always_latch, bit, byte, chandle,
|
||||
do-while, enum, export, final, import, int, logic, longint, package,
|
||||
const, do-while, enum, export, final, import, int, logic, longint, package,
|
||||
program, shortint, time, typedef, var, void, priority case/if, and unique
|
||||
case/if.
|
||||
|
||||
@@ -1652,8 +1711,8 @@ assertion clocks.
|
||||
=head2 Synthesis Directive Assertion Support
|
||||
|
||||
With the --assert switch, Verilator reads any "//synopsys full_case" or "//
|
||||
synopsys parallel_case" directives. The same applies to any "//cadence" or
|
||||
"// ambit synthesis" directives of the same form.
|
||||
synopsys parallel_case" directives. The same applies to any "// ambit
|
||||
synthesis", "//cadence" or "//pragma" directives of the same form.
|
||||
|
||||
When these synthesis directives are discovered, Verilator will either
|
||||
formally prove the directive to be true, or failing that, will insert the
|
||||
@@ -2037,7 +2096,7 @@ that Verilator will print a list of known scopes to help your debugging.
|
||||
|
||||
=head2 Floating Point
|
||||
|
||||
Floating Point numbers are not synthesizable, and so not supported.
|
||||
Floating Point (real) numbers are supported.
|
||||
|
||||
=head2 Latches
|
||||
|
||||
@@ -2080,7 +2139,7 @@ of the form:
|
||||
|
||||
inout driver;
|
||||
wire driver = (enable) ? output_value : 1'bz;
|
||||
|
||||
|
||||
Will be converted to
|
||||
|
||||
input driver__in; // Value being driven in from "external" drivers
|
||||
@@ -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
|
||||
expressions ("a = b++;").
|
||||
|
||||
=item cast operator
|
||||
|
||||
Casting is supported only between simple scalar types, signed and unsigned,
|
||||
not arrays nor structs.
|
||||
|
||||
=item chandle
|
||||
|
||||
Treated as a "longint"; does not yet warn about operations that are
|
||||
specified as illegal on chandles.
|
||||
|
||||
=item disable
|
||||
|
||||
Disable statements may be used only if the block being disabled is a block
|
||||
the disable statement itself is inside. This was commonly used to provide
|
||||
loop break and continue functionality before SystemVerilog added the break
|
||||
and continue keywords.
|
||||
|
||||
=item priority if, unique if
|
||||
|
||||
Priority and unique if's are treated as normal ifs and not asserted to be
|
||||
@@ -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
|
||||
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
|
||||
|
||||
@@ -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
|
||||
arrays.
|
||||
|
||||
=item $realtime
|
||||
|
||||
Treated as $time.
|
||||
|
||||
=item $test$plusargs, $value$plusargs
|
||||
|
||||
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
|
||||
read in as libraries with -v, instead of automatically with -y.
|
||||
|
||||
=item REALCVT
|
||||
|
||||
Warns that a real number is being implicitly rounded to an integer, with
|
||||
possible loss of precision.
|
||||
|
||||
=item REDEFMACRO
|
||||
|
||||
Warns that you have redefined the same macro with a different value, for
|
||||
@@ -2987,8 +3054,8 @@ network disk. Network disks are generally far slower.
|
||||
=item How do I do coverage analysis?
|
||||
|
||||
Verilator supports both block (line) coverage and user inserted functional
|
||||
coverage. Both currently require SystemPerl output mode and the SystemPerl
|
||||
package.
|
||||
coverage. Both require the SystemPerl package to be installed but do not
|
||||
require use of the SystemPerl output mode.
|
||||
|
||||
First, run verilator with the --coverage option. If you're using your own
|
||||
makefile, compile the model with the GCC flag -DSP_COVERAGE_ENABLE (if
|
||||
@@ -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
|
||||
bit long longs that fits the width of the signal. Generally, you can use
|
||||
just uint32_t's for 1 to 32 bits, or uint64_t for 1 to 64 bits, and the
|
||||
just uint32_t's for 1 to 32 bits, or vluint64_t for 1 to 64 bits, and the
|
||||
compiler will properly up-convert smaller entities.
|
||||
|
||||
Signals wider than 64 bits are stored as an array of 32-bit uint32_t's.
|
||||
@@ -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.
|
||||
|
||||
Some of the people who have provided ideas and feedback for Verilator
|
||||
include David Addison, Hans Van Antwerpen, Vasu Arasanipalai, Jens Arm, J
|
||||
include: David Addison, Hans Van Antwerpen, Vasu Arasanipalai, Jens Arm, J
|
||||
Baxter, Jeremy Bennett, David Black, Gregg Bouchard, Christopher Boumenot,
|
||||
Byron Bradley, Bryan Brady, Lane Brooks, John Brownlee, Lawrence Butcher,
|
||||
Chris Candler, Lauren Carlson, Donal Casey, Robert A. Clark, Allan
|
||||
Cochrane, Gunter Dannoritzer, Bernard Deadman, John Deroo, John Dickol,
|
||||
Danny Ding, Alex Duller, Jeff Dutton, Robert Farrell, Eugen Fekete, Andrea
|
||||
Foletto, Bob Fredieu, Shankar Giri, Sam Gladstone, Chitlesh Goorah, Thomas
|
||||
Hawkins, David Hewson, Jae Hossell, Ben Jackson, Mike Kagen, Guy-Armand
|
||||
Kamendje, Vasu Kandadi, Patricio Kaplan, Ralf Karge, Dan Katz, Sol Katzman,
|
||||
Jonathan Kimmitt, Gernot Koch, Soon Koh, Steve Kolecki, Steve Lang,
|
||||
Stephane Laurent, Charlie Lind, Dan Lussier, Fred Ma, Duraid Madina, Mark
|
||||
Marshall, Wim Michiels, Dennis Muhlestein, John Murphy, Richard Myers,
|
||||
Dimitris Nalbantis, Paul Nitza, Pete Nixon, Lisa Noack, Mark Nodine,
|
||||
Andreas Olofsson, Niranjan Prabhu, Oleg Rodionov, John Sanguinetti, Mike
|
||||
Shinkarovsky, Rafael Shirakawa, Rodney Sinclair, Brian Small, Art Stamness,
|
||||
John Stroebel, Emerson Suguimoto, Renga Sundararajan, Stefan Thiede, Gary
|
||||
Thomas, Steve Tong, Holger Waechtler, Shawn Wang, Greg Waters, Eugene
|
||||
Weber, Leon Wildman, Gerald Williams, Jeff Winston, Johan Wouters, and Ding
|
||||
Xiaoliang.
|
||||
Nick Bowler, Byron Bradley, Bryan Brady, Lane Brooks, John Brownlee,
|
||||
Lawrence Butcher, Chris Candler, Lauren Carlson, Donal Casey, Terry Chen,
|
||||
Robert A. Clark, Allan Cochrane, Gunter Dannoritzer, Ashutosh Das, Bernard
|
||||
Deadman, John Deroo, John Dickol, Danny Ding, Ivan Djordjevic, Alex Duller,
|
||||
Jeff Dutton, Chandan Egbert, Joe Eiler, Ahmed El-Mahmoudy, Robert Farrell,
|
||||
Eugen Fekete, Andrea Foletto, Bob Fredieu, Shankar Giri, Sam Gladstone,
|
||||
Amir Gonnen, Chitlesh Goorah, Neil Hamilton, Thomas Hawkins, David Hewson,
|
||||
Jae Hossell, Ben Jackson, Iztok Jeras, Mike Kagen, Guy-Armand Kamendje,
|
||||
Vasu Kandadi, Patricio Kaplan, Ralf Karge, Dan Katz, Sol Katzman, Jonathan
|
||||
Kimmitt, Gernot Koch, Soon Koh, Steve Kolecki, Steve Lang, Stephane
|
||||
Laurent, Christian Leber, Charlie Lind, Paul Liu, Dan Lussier, Fred Ma,
|
||||
Duraid Madina, Mark Marshall, Jason McMullan, Wim Michiels, Dennis
|
||||
Muhlestein, John Murphy, Richard Myers, Dimitris Nalbantis, Paul Nitza,
|
||||
Pete Nixon, Lisa Noack, Mark Nodine, Andreas Olofsson, Brad Parker, Dominic
|
||||
Plunkett, Niranjan Prabhu, Usha Priyadharshini, Oleg Rodionov, John
|
||||
Sanguinetti, Salman Sheikh, Mike Shinkarovsky, Rafael Shirakawa, Jeffrey
|
||||
Short, Rodney Sinclair, Brian Small, Alex Solomatnikov, Art Stamness, John
|
||||
Stroebel, Emerson Suguimoto, Gene Sullivan, Renga Sundararajan, Stefan
|
||||
Thiede, Gary Thomas, Steve Tong, Holger Waechtler, Stefan Wallentowitz,
|
||||
Shawn Wang, Greg Waters, Eugene Weber, David Welch, Leon Wildman, Gerald
|
||||
Williams, Trevor Williams, Jeff Winston, Joshua Wise, Johan Wouters, and
|
||||
Ding Xiaoliang.
|
||||
|
||||
Thanks all.
|
||||
|
||||
|
||||
+53
-12
@@ -26,7 +26,6 @@
|
||||
#define _VERILATED_CPP_
|
||||
#include "verilated_imp.h"
|
||||
#include <cctype>
|
||||
#include <vector>
|
||||
|
||||
#define VL_VALUE_STRING_MAX_WIDTH 1024 ///< Max static char array for VL_VALUE_STRING
|
||||
|
||||
@@ -285,12 +284,15 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
||||
// Note also assumes variables < 64 are not wide, this assumption is
|
||||
// sometimes not true in low-level routines written here in verilated.cpp
|
||||
static VL_THREAD char tmp[VL_VALUE_STRING_MAX_WIDTH];
|
||||
static VL_THREAD char tmpf[VL_VALUE_STRING_MAX_WIDTH];
|
||||
const char* pctp = NULL; // Most recent %##.##g format
|
||||
bool inPct = false;
|
||||
bool widthSet = false;
|
||||
int width = 0;
|
||||
const char* pos = formatp;
|
||||
for (; *pos; ++pos) {
|
||||
if (!inPct && pos[0]=='%') {
|
||||
pctp = pos;
|
||||
inPct = true;
|
||||
widthSet = false;
|
||||
width = 0;
|
||||
@@ -312,6 +314,9 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
||||
widthSet = true;
|
||||
width = width*10 + (fmt - '0');
|
||||
break;
|
||||
case '.':
|
||||
inPct = true; // Get more digits
|
||||
break;
|
||||
case '%':
|
||||
output += '%';
|
||||
break;
|
||||
@@ -325,6 +330,16 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
||||
output += cstrp;
|
||||
break;
|
||||
}
|
||||
case 'e':
|
||||
case 'f':
|
||||
case 'g': {
|
||||
double d = va_arg(ap, double);
|
||||
strncpy(tmpf, pctp, pos-pctp+1);
|
||||
tmpf[pos-pctp+1] = '\0';
|
||||
sprintf(tmp, tmpf, d);
|
||||
output += tmp;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// Deal with all read-and-print somethings
|
||||
const int lbits = va_arg(ap, int);
|
||||
@@ -358,14 +373,26 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
||||
case 'd': { // Signed decimal
|
||||
int digits=sprintf(tmp,"%" VL_PRI64 "d",(vlsint64_t)(VL_EXTENDS_QQ(lbits,lbits,ld)));
|
||||
int needmore = width-digits;
|
||||
if (needmore>0) output.append(needmore,' '); // Pre-pad spaces
|
||||
if (needmore>0) {
|
||||
if (pctp && pctp[0] && pctp[1]=='0') { //%0
|
||||
output.append(needmore,'0'); // Pre-pad zero
|
||||
} else {
|
||||
output.append(needmore,' '); // Pre-pad spaces
|
||||
}
|
||||
}
|
||||
output += tmp;
|
||||
break;
|
||||
}
|
||||
case 'u': { // Unsigned decimal
|
||||
int digits=sprintf(tmp,"%" VL_PRI64 "u",ld);
|
||||
int needmore = width-digits;
|
||||
if (needmore>0) output.append(needmore,' '); // Pre-pad spaces
|
||||
if (needmore>0) {
|
||||
if (pctp && pctp[0] && pctp[1]=='0') { //%0
|
||||
output.append(needmore,'0'); // Pre-pad zero
|
||||
} else {
|
||||
output.append(needmore,' '); // Pre-pad spaces
|
||||
}
|
||||
}
|
||||
output += tmp;
|
||||
break;
|
||||
}
|
||||
@@ -628,6 +655,10 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
||||
//===========================================================================
|
||||
// File I/O
|
||||
|
||||
FILE* VL_CVT_I_FP(IData lhs) {
|
||||
return VerilatedImp::fdToFp(lhs);
|
||||
}
|
||||
|
||||
void _VL_VINT_TO_STRING(int obits, char* destoutp, WDataInP sourcep) {
|
||||
// See also VL_DATA_TO_STRING_NW
|
||||
int lsb=obits-1;
|
||||
@@ -655,8 +686,8 @@ void _VL_STRING_TO_VINT(int obits, void* destp, int srclen, const char* srcp) {
|
||||
for (; i<bytes; i++) { *op++ = 0; }
|
||||
}
|
||||
|
||||
IData VL_FGETS_IXQ(int obits, void* destp, QData fpq) {
|
||||
FILE* fp = VL_CVT_Q_FP(fpq);
|
||||
IData VL_FGETS_IXI(int obits, void* destp, IData fpi) {
|
||||
FILE* fp = VL_CVT_I_FP(fpi);
|
||||
if (VL_UNLIKELY(!fp)) return 0;
|
||||
|
||||
// The string needs to be padded with 0's in unused spaces in front of
|
||||
@@ -683,16 +714,26 @@ IData VL_FGETS_IXQ(int obits, void* destp, QData fpq) {
|
||||
return got;
|
||||
}
|
||||
|
||||
QData VL_FOPEN_QI(QData filename, IData mode) {
|
||||
IData VL_FOPEN_QI(QData filename, IData mode) {
|
||||
IData fnw[2]; VL_SET_WQ(fnw, filename);
|
||||
return VL_FOPEN_WI(2, fnw, mode);
|
||||
}
|
||||
QData VL_FOPEN_WI(int fnwords, WDataInP filenamep, IData mode) {
|
||||
IData VL_FOPEN_WI(int fnwords, WDataInP filenamep, IData mode) {
|
||||
char filenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1];
|
||||
_VL_VINT_TO_STRING(fnwords*VL_WORDSIZE, filenamez, filenamep);
|
||||
char modez[5];
|
||||
_VL_VINT_TO_STRING(VL_WORDSIZE, modez, &mode);
|
||||
return VL_CVT_FP_Q(fopen(filenamez,modez));
|
||||
return VL_FOPEN_S(filenamez,modez);
|
||||
}
|
||||
IData VL_FOPEN_S(const char* filenamep, const char* modep) {
|
||||
return VerilatedImp::fdNew(fopen(filenamep,modep));
|
||||
}
|
||||
|
||||
void VL_FCLOSE_I(IData fdi) {
|
||||
FILE* fp = VL_CVT_I_FP(fdi);
|
||||
if (VL_UNLIKELY(!fp)) return;
|
||||
fclose(fp);
|
||||
VerilatedImp::fdDelete(fdi);
|
||||
}
|
||||
|
||||
void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...) {
|
||||
@@ -726,8 +767,8 @@ void VL_WRITEF(const char* formatp, ...) {
|
||||
VL_PRINTF("%s", output.c_str());
|
||||
}
|
||||
|
||||
void VL_FWRITEF(QData fpq, const char* formatp, ...) {
|
||||
FILE* fp = VL_CVT_Q_FP(fpq);
|
||||
void VL_FWRITEF(IData fpi, const char* formatp, ...) {
|
||||
FILE* fp = VL_CVT_I_FP(fpi);
|
||||
if (VL_UNLIKELY(!fp)) return;
|
||||
|
||||
va_list ap;
|
||||
@@ -739,8 +780,8 @@ void VL_FWRITEF(QData fpq, const char* formatp, ...) {
|
||||
fputs(output.c_str(), fp);
|
||||
}
|
||||
|
||||
IData VL_FSCANF_IX(QData fpq, const char* formatp, ...) {
|
||||
FILE* fp = VL_CVT_Q_FP(fpq);
|
||||
IData VL_FSCANF_IX(IData fpi, const char* formatp, ...) {
|
||||
FILE* fp = VL_CVT_I_FP(fpi);
|
||||
if (VL_UNLIKELY(!fp)) return 0;
|
||||
|
||||
va_list ap;
|
||||
|
||||
+39
-24
@@ -35,6 +35,7 @@
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
// <iostream> avoided to reduce compile time
|
||||
// <string> avoided and instead in verilated_heavy.h to reduce compile time
|
||||
using namespace std;
|
||||
@@ -321,11 +322,14 @@ extern WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp); ///< Zero reset a
|
||||
extern WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, bool is_modulus);
|
||||
|
||||
/// File I/O
|
||||
extern IData VL_FGETS_IXQ(int obits, void* destp, QData fpq);
|
||||
extern IData VL_FGETS_IXI(int obits, void* destp, IData fpi);
|
||||
|
||||
extern QData VL_FOPEN_WI(int fnwords, WDataInP ofilename, IData mode);
|
||||
extern QData VL_FOPEN_QI(QData ofilename, IData mode);
|
||||
inline QData VL_FOPEN_II(IData ofilename, IData mode) { return VL_FOPEN_QI(ofilename,mode); }
|
||||
extern IData VL_FOPEN_S(const char* filenamep, const char* mode);
|
||||
extern IData VL_FOPEN_WI(int fnwords, WDataInP ofilename, IData mode);
|
||||
extern IData VL_FOPEN_QI(QData ofilename, IData mode);
|
||||
inline IData VL_FOPEN_II(IData ofilename, IData mode) { return VL_FOPEN_QI(ofilename,mode); }
|
||||
|
||||
extern void VL_FCLOSE_I(IData fdi);
|
||||
|
||||
extern void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||
WDataInP ofilename, void* memp, IData start, IData end);
|
||||
@@ -336,9 +340,9 @@ inline void VL_READMEM_I(bool hex, int width, int depth, int array_lsb, int fnwo
|
||||
VL_READMEM_Q(hex, width,depth,array_lsb,fnwords, ofilename,memp,start,end); }
|
||||
|
||||
extern void VL_WRITEF(const char* formatp, ...);
|
||||
extern void VL_FWRITEF(QData fpq, const char* formatp, ...);
|
||||
extern void VL_FWRITEF(IData fpi, const char* formatp, ...);
|
||||
|
||||
extern IData VL_FSCANF_IX(QData fpq, const char* formatp, ...);
|
||||
extern IData VL_FSCANF_IX(IData fpi, const char* formatp, ...);
|
||||
extern IData VL_SSCANF_IIX(int lbits, IData ld, const char* formatp, ...);
|
||||
extern IData VL_SSCANF_IQX(int lbits, QData ld, const char* formatp, ...);
|
||||
extern IData VL_SSCANF_IWX(int lbits, WDataInP lwp, const char* formatp, ...);
|
||||
@@ -364,15 +368,24 @@ extern const char* vl_mc_scan_plusargs(const char* prefixp); // PLIish
|
||||
#define VL_SET_QW(lwp) ( ((QData)(lwp[0])) | ((QData)(lwp[1])<<((QData)(VL_WORDSIZE)) ))
|
||||
#define _VL_SET_QII(ld,rd) ( ((QData)(ld)<<VL_ULL(32)) | (QData)(rd) )
|
||||
|
||||
/// Return FILE* from IData
|
||||
extern FILE* VL_CVT_I_FP(IData lhs);
|
||||
|
||||
// Use a union to avoid cast-to-different-size warnings
|
||||
/// Return FILE* from QData
|
||||
static inline FILE* VL_CVT_Q_FP(QData lhs) { union { FILE* fp; QData q; } u; u.q=lhs; return u.fp; }
|
||||
/// Return void* from QData
|
||||
static inline void* VL_CVT_Q_VP(QData lhs) { union { void* fp; QData q; } u; u.q=lhs; return u.fp; }
|
||||
/// Return QData from FILE*
|
||||
static inline QData VL_CVT_FP_Q(FILE* fp) { union { FILE* fp; QData q; } u; u.q=0; u.fp=fp; return u.q; }
|
||||
/// Return QData from void*
|
||||
static inline QData VL_CVT_VP_Q(void* fp) { union { void* fp; QData q; } u; u.q=0; u.fp=fp; return u.q; }
|
||||
/// Return double from QData (bits, not numerically)
|
||||
static inline double VL_CVT_D_Q(QData lhs) { union { double d; QData q; } u; u.q=lhs; return u.d; }
|
||||
/// Return QData from double (bits, not numerically)
|
||||
static inline QData VL_CVT_Q_D(double lhs) { union { double d; QData q; } u; u.d=lhs; return u.q; }
|
||||
/// Return double from QData (numeric)
|
||||
static inline double VL_ITOR_D_I(IData lhs) { return ((double)((vlsint32_t)(lhs))); }
|
||||
/// Return QData from double (numeric)
|
||||
static inline IData VL_RTOI_I_D(double lhs) { return ((vlsint32_t)(trunc(lhs))); }
|
||||
/// Return QData from double (numeric)
|
||||
static inline IData VL_RTOIROUND_I_D(double lhs) { return ((vlsint32_t)(round(lhs))); }
|
||||
|
||||
// Sign extend such that if MSB set, we get ffff_ffff, else 0s
|
||||
// (Requires clean input)
|
||||
@@ -402,9 +415,11 @@ void _VL_DEBUG_PRINT_W(int lbits, WDataInP iwp);
|
||||
#if defined(SYSTEMC_VERSION) && (SYSTEMC_VERSION>20011000)
|
||||
# define VL_TIME_I() ((IData)(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
|
||||
# define VL_TIME_Q() ((QData)(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
|
||||
# define VL_TIME_D() ((double)(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
|
||||
#else
|
||||
# define VL_TIME_I() ((IData)(sc_time_stamp()*VL_TIME_MULTIPLIER))
|
||||
# define VL_TIME_Q() ((QData)(sc_time_stamp()*VL_TIME_MULTIPLIER))
|
||||
# define VL_TIME_D() ((double)(sc_time_stamp()*VL_TIME_MULTIPLIER))
|
||||
extern double sc_time_stamp();
|
||||
#endif
|
||||
|
||||
@@ -947,11 +962,11 @@ static inline WDataOutP VL_SUB_W(int words, WDataOutP owp,WDataInP lwp,WDataInP
|
||||
|
||||
// Optimization bug in GCC 2.96 and presumably all-pre GCC 3 versions need this workaround,
|
||||
// we can't just
|
||||
//# define VL_UNARYMIN_I(data) (-(data))
|
||||
static inline IData VL_UNARYMIN_I(IData data) { return -data; }
|
||||
static inline QData VL_UNARYMIN_Q(QData data) { return -data; }
|
||||
//# define VL_NEGATE_I(data) (-(data))
|
||||
static inline IData VL_NEGATE_I(IData data) { return -data; }
|
||||
static inline QData VL_NEGATE_Q(QData data) { return -data; }
|
||||
|
||||
static inline WDataOutP VL_UNARYMIN_W(int words, WDataOutP owp,WDataInP lwp){
|
||||
static inline WDataOutP VL_NEGATE_W(int words, WDataOutP owp,WDataInP lwp){
|
||||
QData carry = 0;
|
||||
for (int i=0; i<words; i++) {
|
||||
carry = carry + (QData)(IData)(~lwp[i]);
|
||||
@@ -998,18 +1013,18 @@ static inline WDataOutP VL_MULS_WWW(int,int lbits,int, WDataOutP owp,WDataInP lw
|
||||
IData lneg = VL_SIGN_I(lbits,lwp[words-1]);
|
||||
if (lneg) { // Negate lhs
|
||||
lwusp = lwstore;
|
||||
VL_UNARYMIN_W(words, lwstore, lwp);
|
||||
VL_NEGATE_W(words, lwstore, lwp);
|
||||
lwstore[words-1] &= VL_MASK_I(lbits); // Clean it
|
||||
}
|
||||
IData rneg = VL_SIGN_I(lbits,rwp[words-1]);
|
||||
if (rneg) { // Negate rhs
|
||||
rwusp = rwstore;
|
||||
VL_UNARYMIN_W(words, rwstore, rwp);
|
||||
VL_NEGATE_W(words, rwstore, rwp);
|
||||
rwstore[words-1] &= VL_MASK_I(lbits); // Clean it
|
||||
}
|
||||
VL_MUL_W(words,owp,lwusp,rwusp);
|
||||
owp[words-1] &= VL_MASK_I(lbits); // Clean. Note it's ok for the multiply to overflow into the sign bit
|
||||
if ((lneg ^ rneg) & 1) { // Negate output (not using UNARYMIN, as owp==lwp)
|
||||
if ((lneg ^ rneg) & 1) { // Negate output (not using NEGATE, as owp==lwp)
|
||||
QData carry = 0;
|
||||
for (int i=0; i<words; i++) {
|
||||
carry = carry + (QData)(IData)(~owp[i]);
|
||||
@@ -1056,12 +1071,12 @@ static inline WDataOutP VL_DIVS_WWW(int lbits, WDataOutP owp,WDataInP lwp,WDataI
|
||||
IData rwstore[VL_MULS_MAX_WORDS];
|
||||
WDataInP ltup = lwp;
|
||||
WDataInP rtup = rwp;
|
||||
if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), lwstore, lwp)); }
|
||||
if (rsign) { rtup = _VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), rwstore, rwp)); }
|
||||
if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), lwstore, lwp)); }
|
||||
if (rsign) { rtup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), rwstore, rwp)); }
|
||||
if ((lsign && !rsign) || (!lsign && rsign)) {
|
||||
IData qNoSign[VL_MULS_MAX_WORDS];
|
||||
VL_DIV_WWW(lbits,qNoSign,ltup,rtup);
|
||||
_VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), owp, qNoSign));
|
||||
_VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), owp, qNoSign));
|
||||
return owp;
|
||||
} else {
|
||||
return VL_DIV_WWW(lbits,owp,ltup,rtup);
|
||||
@@ -1075,12 +1090,12 @@ static inline WDataOutP VL_MODDIVS_WWW(int lbits, WDataOutP owp,WDataInP lwp,WDa
|
||||
IData rwstore[VL_MULS_MAX_WORDS];
|
||||
WDataInP ltup = lwp;
|
||||
WDataInP rtup = rwp;
|
||||
if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), lwstore, lwp)); }
|
||||
if (rsign) { rtup = _VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), rwstore, rwp)); }
|
||||
if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), lwstore, lwp)); }
|
||||
if (rsign) { rtup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), rwstore, rwp)); }
|
||||
if (lsign) { // Only dividend sign matters for modulus
|
||||
IData qNoSign[VL_MULS_MAX_WORDS];
|
||||
VL_MODDIV_WWW(lbits,qNoSign,ltup,rtup);
|
||||
_VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), owp, qNoSign));
|
||||
_VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), owp, qNoSign));
|
||||
return owp;
|
||||
} else {
|
||||
return VL_MODDIV_WWW(lbits,owp,ltup,rtup);
|
||||
@@ -1633,6 +1648,6 @@ static inline WDataOutP VL_CONST_W_9X(int obits, WDataOutP o,
|
||||
|
||||
#undef _END
|
||||
|
||||
// Debugging
|
||||
//======================================================================
|
||||
|
||||
#endif /*_VERILATED_H_*/
|
||||
|
||||
@@ -116,6 +116,10 @@ ifeq ($(VM_SP),1)
|
||||
$(SP_PREPROC) -M sp_preproc.d --tree $(VM_PREFIX).sp_tree \
|
||||
--preproc $(VK_CLASSES_SP)
|
||||
else
|
||||
ifeq ($(VM_COVERAGE),1)
|
||||
CPPFLAGS += -I$(SYSTEMPERL_INCLUDE)
|
||||
VPATH += $(SYSTEMPERL_INCLUDE)
|
||||
endif
|
||||
preproc:
|
||||
endif
|
||||
|
||||
|
||||
+2
-6
@@ -27,11 +27,7 @@
|
||||
`define coverage_block_off
|
||||
`endif
|
||||
|
||||
// Hide file descriptor difference
|
||||
`ifdef verilator
|
||||
`define verilator_file_descriptor reg [63:0]
|
||||
`else
|
||||
`define verilator_file_descriptor integer
|
||||
`endif
|
||||
// Hide file descriptor difference - deprecated - for older versions
|
||||
`define verilator_file_descriptor integer
|
||||
|
||||
`endif // guard
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#define _VERILATED_DPI_CPP_
|
||||
#include "verilatedos.h"
|
||||
#include "verilated_dpi.h"
|
||||
#include "verilated_imp.h"
|
||||
|
||||
// On MSVC++ we need svdpi.h to declare exports, not imports
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
// -*- C++ -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||
// Version 2.0.
|
||||
//
|
||||
// Verilator is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
//*************************************************************************
|
||||
///
|
||||
/// \file
|
||||
/// \brief Verilator: Common include for all Verilated C files that use DPI
|
||||
///
|
||||
/// This file is included automatically by Verilator at the top of
|
||||
/// all C++ files it generates where DPI is used. It contains
|
||||
/// DPI interface functions required by the Verilated code.
|
||||
///
|
||||
/// Code available from: http://www.veripool.org/verilator
|
||||
///
|
||||
//*************************************************************************
|
||||
|
||||
|
||||
#ifndef _VERILATED_DPI_H_
|
||||
#define _VERILATED_DPI_H_ 1 ///< Header Guard
|
||||
|
||||
#include "verilated.h" // Presumed done by caller
|
||||
#include "svdpi.h"
|
||||
|
||||
//===================================================================
|
||||
// SETTING OPERATORS
|
||||
|
||||
/// Return svBitVecVal from WData
|
||||
static inline void VL_SET_W_SVBV(int obits, WDataOutP owp, svBitVecVal* lwp) {
|
||||
int words = VL_WORDS_I(obits);
|
||||
for (int i=0; i<words-1; i++) owp[i]=lwp[i];
|
||||
owp[words-1] = lwp[words-1] & VL_MASK_I(obits);
|
||||
}
|
||||
static inline void VL_SET_SVBV_W(int obits, svBitVecVal* owp, WDataInP lwp) {
|
||||
int words = VL_WORDS_I(obits);
|
||||
for (int i=0; i<words-1; i++) owp[i]=lwp[i];
|
||||
owp[words-1] = lwp[words-1] & VL_MASK_I(obits);
|
||||
}
|
||||
static inline void VL_SET_W_SVLV(int obits, WDataOutP owp, svLogicVecVal* lwp) {
|
||||
// Note we ignore X/Z in svLogicVecVal
|
||||
int words = VL_WORDS_I(obits);
|
||||
for (int i=0; i<words-1; i++) owp[i]=lwp[i].aval;
|
||||
owp[words-1] = lwp[words-1].aval & VL_MASK_I(obits);
|
||||
}
|
||||
static inline void VL_SET_SVLV_W(int obits, svLogicVecVal* owp, WDataInP lwp) {
|
||||
// Note we don't create X/Z in svLogicVecVal
|
||||
int words = VL_WORDS_I(obits);
|
||||
for (int i=0; i<words; i++) owp[i].bval=0;
|
||||
for (int i=0; i<words-1; i++) owp[i].aval=lwp[i];
|
||||
owp[words-1].aval = lwp[words-1] & VL_MASK_I(obits);
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
|
||||
#endif // _VERILATED_DPI_H_
|
||||
+39
-1
@@ -35,6 +35,7 @@
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <string>
|
||||
|
||||
class VerilatedScope;
|
||||
@@ -62,9 +63,18 @@ class VerilatedImp {
|
||||
ExportNameMap m_exportMap; ///< Map of <export_func_proto, func number>
|
||||
int m_exportNext; ///< Next export funcnum
|
||||
|
||||
// File I/O
|
||||
vector<FILE*> m_fdps; ///< File descriptors
|
||||
deque<IData> m_fdFree; ///< List of free descriptors (SLOW - FOPEN/CLOSE only)
|
||||
|
||||
public: // But only for verilated*.cpp
|
||||
// CONSTRUCTORS
|
||||
VerilatedImp() : m_argVecLoaded(false), m_exportNext(0) {}
|
||||
VerilatedImp() : m_argVecLoaded(false), m_exportNext(0) {
|
||||
m_fdps.resize(3);
|
||||
m_fdps[0] = stdin;
|
||||
m_fdps[1] = stdout;
|
||||
m_fdps[2] = stderr;
|
||||
}
|
||||
~VerilatedImp() {}
|
||||
|
||||
// METHODS - arguments
|
||||
@@ -184,6 +194,34 @@ public: // But only for verilated*.cpp
|
||||
}
|
||||
// We don't free up m_exportMap until the end, because we can't be sure
|
||||
// what other models are using the assigned funcnum's.
|
||||
|
||||
public: // But only for verilated*.cpp
|
||||
// METHODS - file IO
|
||||
static IData fdNew(FILE* fp) {
|
||||
if (VL_UNLIKELY(!fp)) return 0;
|
||||
// Bit 31 indicates it's a descriptor not a MCD
|
||||
if (s_s.m_fdFree.empty()) {
|
||||
// Need to create more space in m_fdps and m_fdFree
|
||||
size_t start = s_s.m_fdps.size();
|
||||
s_s.m_fdps.resize(start*2);
|
||||
for (size_t i=start; i<start*2; i++) s_s.m_fdFree.push_back((IData)i);
|
||||
}
|
||||
IData idx = s_s.m_fdFree.back(); s_s.m_fdFree.pop_back();
|
||||
s_s.m_fdps[idx] = fp;
|
||||
return (idx | (1UL<<31)); // bit 31 indicates not MCD
|
||||
}
|
||||
static void fdDelete(IData fdi) {
|
||||
IData idx = VL_MASK_I(31) & fdi;
|
||||
if (VL_UNLIKELY(!(fdi & (1ULL<<31)) || idx >= s_s.m_fdps.size())) return;
|
||||
if (VL_UNLIKELY(!s_s.m_fdps[idx])) return; // Already free
|
||||
s_s.m_fdps[idx] = NULL;
|
||||
s_s.m_fdFree.push_back(idx);
|
||||
}
|
||||
static inline FILE* fdToFp(IData fdi) {
|
||||
IData idx = VL_MASK_I(31) & fdi;
|
||||
if (VL_UNLIKELY(!(fdi & (1ULL<<31)) || idx >= s_s.m_fdps.size())) return NULL;
|
||||
return s_s.m_fdps[idx];
|
||||
}
|
||||
};
|
||||
|
||||
#endif // Guard
|
||||
|
||||
+40
-20
@@ -95,9 +95,12 @@ typedef PLI_INT32 (*VerilatedPliCb)(struct t_cb_data *);
|
||||
|
||||
class VerilatedVpioCb : public VerilatedVpio {
|
||||
t_cb_data m_cbData;
|
||||
s_vpi_value m_value;
|
||||
QData m_time;
|
||||
public:
|
||||
VerilatedVpioCb(const t_cb_data* cbDatap, QData time) : m_cbData(*cbDatap), m_time(time) {}
|
||||
VerilatedVpioCb(const t_cb_data* cbDatap, QData time) : m_cbData(*cbDatap), m_time(time) {
|
||||
m_cbData.value = &m_value;
|
||||
}
|
||||
virtual ~VerilatedVpioCb() {}
|
||||
static inline VerilatedVpioCb* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioCb*>((VerilatedVpio*)h); }
|
||||
vluint32_t reason() const { return m_cbData.reason; }
|
||||
@@ -326,6 +329,7 @@ public:
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: value_callback %p %s v[0]=%d\n",
|
||||
vop,varop->fullname(), *((CData*)newDatap)););
|
||||
memcpy(prevDatap, newDatap, varop->entSize());
|
||||
vpi_get_value(vop->cb_datap()->obj, vop->cb_datap()->value);
|
||||
(vop->cb_rtnp()) (vop->cb_datap());
|
||||
}
|
||||
}
|
||||
@@ -735,19 +739,26 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
|
||||
|
||||
// I/O routines
|
||||
|
||||
//-PLI_UINT32 vpi_mcd_open(PLI_BYTE8 *fileName) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
//-PLI_UINT32 vpi_mcd_close(PLI_UINT32 mcd) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
//-PLI_BYTE8 *vpi_mcd_name(PLI_UINT32 cd) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
//-PLI_INT32 vpi_mcd_printf(PLI_UINT32 mcd, PLI_BYTE8 *format, ...) {
|
||||
PLI_UINT32 vpi_mcd_open(PLI_BYTE8 *filenamep) {
|
||||
return VL_FOPEN_S(filenamep,"wb");
|
||||
}
|
||||
|
||||
PLI_UINT32 vpi_mcd_close(PLI_UINT32 mcd) {
|
||||
VL_FCLOSE_I(mcd); return 0;
|
||||
}
|
||||
|
||||
//-PLI_BYTE8 *vpi_mcd_name(PLI_UINT32 mcd) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
|
||||
PLI_INT32 vpi_mcd_printf(PLI_UINT32 mcd, PLI_BYTE8 *formatp, ...) {
|
||||
va_list ap;
|
||||
va_start(ap,formatp);
|
||||
int chars = vpi_mcd_vprintf(mcd, formatp, ap);
|
||||
va_end(ap);
|
||||
return chars;
|
||||
}
|
||||
|
||||
PLI_INT32 vpi_printf(PLI_BYTE8 *formatp, ...) {
|
||||
va_list ap;
|
||||
va_start(ap,formatp);
|
||||
@@ -760,15 +771,24 @@ PLI_INT32 vpi_vprintf(PLI_BYTE8* formatp, va_list ap) {
|
||||
return VL_VPRINTF(formatp, ap);
|
||||
}
|
||||
|
||||
//-PLI_INT32 vpi_mcd_vprintf(PLI_UINT32 mcd, PLI_BYTE8 *format, va_list ap) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
//-PLI_INT32 vpi_flush(void) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
//-PLI_INT32 vpi_mcd_flush(PLI_UINT32 mcd) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
PLI_INT32 vpi_mcd_vprintf(PLI_UINT32 mcd, PLI_BYTE8 *format, va_list ap) {
|
||||
FILE* fp = VL_CVT_I_FP(mcd);
|
||||
if (VL_UNLIKELY(!fp)) return 0;
|
||||
int chars = vfprintf(fp, format, ap);
|
||||
return chars;
|
||||
}
|
||||
|
||||
PLI_INT32 vpi_flush(void) {
|
||||
Verilated::flushCall();
|
||||
return 0;
|
||||
}
|
||||
|
||||
PLI_INT32 vpi_mcd_flush(PLI_UINT32 mcd) {
|
||||
FILE* fp = VL_CVT_I_FP(mcd);
|
||||
if (VL_UNLIKELY(!fp)) return 1;
|
||||
fflush(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// utility routines
|
||||
|
||||
|
||||
+1
-13
@@ -8,21 +8,9 @@ use strict;
|
||||
#======================================================================
|
||||
# main
|
||||
|
||||
delete $ENV{MODULE_VERSION};
|
||||
_setup_modules();
|
||||
module('add','axiom-athdl');
|
||||
eval `modulecmd perl add axiom-athdl`;
|
||||
exec('atsim',@ARGV);
|
||||
|
||||
#######################################################################
|
||||
# Modules package
|
||||
|
||||
sub _setup_modules {
|
||||
# Load the 'module' command into the environment
|
||||
my $init = "$ENV{MODULESHOME}/init/perl";
|
||||
(-f $init) or die "%Error: Script not found: $init,";
|
||||
require $init;
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
__END__
|
||||
|
||||
|
||||
+1
-13
@@ -8,21 +8,9 @@ use strict;
|
||||
#======================================================================
|
||||
# main
|
||||
|
||||
delete $ENV{MODULE_VERSION};
|
||||
_setup_modules();
|
||||
module('add','cadence-ius');
|
||||
eval `modulecmd perl add cds-ius`;
|
||||
exec('iccr',@ARGV);
|
||||
|
||||
#######################################################################
|
||||
# Modules package
|
||||
|
||||
sub _setup_modules {
|
||||
# Load the 'module' command into the environment
|
||||
my $init = "$ENV{MODULESHOME}/init/perl";
|
||||
(-f $init) or die "%Error: Script not found: $init,";
|
||||
require $init;
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
__END__
|
||||
|
||||
|
||||
+1
-13
@@ -8,21 +8,9 @@ use strict;
|
||||
#======================================================================
|
||||
# main
|
||||
|
||||
delete $ENV{MODULE_VERSION};
|
||||
_setup_modules();
|
||||
module('add','cadence-ius');
|
||||
eval `modulecmd perl add cds-ius`;
|
||||
exec('ncverilog',@ARGV);
|
||||
|
||||
#######################################################################
|
||||
# Modules package
|
||||
|
||||
sub _setup_modules {
|
||||
# Load the 'module' command into the environment
|
||||
my $init = "$ENV{MODULESHOME}/init/perl";
|
||||
(-f $init) or die "%Error: Script not found: $init,";
|
||||
require $init;
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
__END__
|
||||
|
||||
|
||||
+1
-13
@@ -8,21 +8,9 @@ use strict;
|
||||
#======================================================================
|
||||
# main
|
||||
|
||||
delete $ENV{MODULE_VERSION};
|
||||
_setup_modules();
|
||||
module('add','synopsys-vcs');
|
||||
eval `modulecmd perl add synopsys-vcs`;
|
||||
exec('vcs',@ARGV);
|
||||
|
||||
#######################################################################
|
||||
# Modules package
|
||||
|
||||
sub _setup_modules {
|
||||
# Load the 'module' command into the environment
|
||||
my $init = "$ENV{MODULESHOME}/init/perl";
|
||||
(-f $init) or die "%Error: Script not found: $init,";
|
||||
require $init;
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
__END__
|
||||
|
||||
|
||||
@@ -256,7 +256,7 @@ sub gentree {
|
||||
'TRACE' => sub { p "TRACE what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
||||
'UCFUNC' => sub { p '$c(';p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p ")"; },
|
||||
'UCSTMT' => sub { p '$c(';p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p ");";nl; },
|
||||
'UNARYMIN' => sub { p " -";p1; },
|
||||
'NEGATE' => sub { p " -";p1; },
|
||||
'VAR' => sub { p_var(); },
|
||||
'VARPIN' => sub { p "VARPIN what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
||||
'VARREF' => sub { a1; },
|
||||
|
||||
@@ -209,7 +209,6 @@ RAW_OBJS = \
|
||||
V3PreShell.o \
|
||||
V3Premit.o \
|
||||
V3Scope.o \
|
||||
V3Signed.o \
|
||||
V3Slice.o \
|
||||
V3Split.o \
|
||||
V3SplitAs.o \
|
||||
|
||||
+4
-2
@@ -74,7 +74,9 @@ void AstNode::init() {
|
||||
m_clonep = NULL;
|
||||
m_cloneCnt = 0;
|
||||
// Attributes
|
||||
m_signed = false;
|
||||
m_numeric = (int)AstNumeric::UNSIGNED;
|
||||
m_didWidth = false;
|
||||
m_doingWidth = false;
|
||||
m_width = 0;
|
||||
m_widthMin = 0;
|
||||
m_user1p = NULL;
|
||||
@@ -873,7 +875,7 @@ bool AstNode::sameTreeIter(AstNode* node2p, bool ignNext) {
|
||||
if (this==NULL || node2p==NULL) return false;
|
||||
if (this->type() != node2p->type()
|
||||
|| this->width() != node2p->width()
|
||||
|| this->isSigned() != node2p->isSigned()
|
||||
|| this->numeric() != node2p->numeric()
|
||||
|| !this->same(node2p)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
+63
-15
@@ -56,6 +56,36 @@ public:
|
||||
|
||||
//######################################################################
|
||||
|
||||
class AstNumeric {
|
||||
public:
|
||||
enum en {
|
||||
UNSIGNED,
|
||||
SIGNED,
|
||||
DOUBLE
|
||||
// Limited to 2 bits, unless change V3Ast's packing function
|
||||
};
|
||||
enum en m_e;
|
||||
const char* ascii() const {
|
||||
static const char* names[] = {
|
||||
"UNSIGNED","SIGNED","DOUBLE"
|
||||
};
|
||||
return names[m_e];
|
||||
};
|
||||
inline AstNumeric () {}
|
||||
inline AstNumeric (en _e) : m_e(_e) {}
|
||||
explicit inline AstNumeric (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
inline bool isDouble() const { return m_e==DOUBLE; }
|
||||
inline bool isSigned() const { return m_e==SIGNED; }
|
||||
inline bool isUnsigned() const { return m_e==UNSIGNED; }
|
||||
};
|
||||
inline bool operator== (AstNumeric lhs, AstNumeric rhs) { return (lhs.m_e == rhs.m_e); }
|
||||
inline bool operator== (AstNumeric lhs, AstNumeric::en rhs) { return (lhs.m_e == rhs); }
|
||||
inline bool operator== (AstNumeric::en lhs, AstNumeric rhs) { return (lhs == rhs.m_e); }
|
||||
inline ostream& operator<<(ostream& os, AstNumeric rhs) { return os<<rhs.ascii(); }
|
||||
|
||||
//######################################################################
|
||||
|
||||
class AstPragmaType {
|
||||
public:
|
||||
enum en {
|
||||
@@ -209,7 +239,7 @@ class AstBasicDTypeKwd {
|
||||
public:
|
||||
enum en {
|
||||
BIT, BYTE, CHANDLE, INT, INTEGER, LOGIC, LONGINT,
|
||||
REAL, REALTIME, SHORTINT, SHORTREAL, TIME,
|
||||
DOUBLE, SHORTINT, FLOAT, TIME,
|
||||
// Closer to a class type, but limited usage
|
||||
STRING,
|
||||
// Internal types for mid-steps
|
||||
@@ -221,7 +251,7 @@ public:
|
||||
const char* ascii() const {
|
||||
static const char* names[] = {
|
||||
"bit", "byte", "chandle", "int", "integer", "logic", "longint",
|
||||
"real", "realtime", "shortint", "shortreal", "time",
|
||||
"real", "shortint", "shortreal", "time",
|
||||
"string",
|
||||
"VerilatedScope*", "char*",
|
||||
"LOGIC_IMPLICIT"
|
||||
@@ -231,7 +261,7 @@ public:
|
||||
const char* dpiType() const {
|
||||
static const char* names[] = {
|
||||
"unsigned char", "char", "void*", "int", "int", "svLogic", "long long",
|
||||
"double", "double", "short int", "float", "long long",
|
||||
"double", "short int", "float", "long long",
|
||||
"const char*",
|
||||
"dpiScope", "const char*",
|
||||
""
|
||||
@@ -251,6 +281,8 @@ public:
|
||||
case INTEGER: return 32;
|
||||
case LOGIC: return 1;
|
||||
case LONGINT: return 64;
|
||||
case DOUBLE: return 64;
|
||||
case FLOAT: return 32;
|
||||
case SHORTINT: return 16;
|
||||
case TIME: return 64;
|
||||
case STRING: return 64; // Just the pointer, for today
|
||||
@@ -265,7 +297,7 @@ public:
|
||||
}
|
||||
bool isZeroInit() const { // Otherwise initializes to X
|
||||
return (m_e==BIT || m_e==BYTE || m_e==CHANDLE || m_e==INT || m_e==LONGINT || m_e==SHORTINT
|
||||
|| m_e==STRING);
|
||||
|| m_e==STRING || m_e==DOUBLE || m_e==FLOAT);
|
||||
}
|
||||
bool isSloppy() const { // Don't be as anal about width warnings
|
||||
return !(m_e==LOGIC || m_e==BIT);
|
||||
@@ -274,10 +306,13 @@ public:
|
||||
return (m_e==LOGIC || m_e==BIT);
|
||||
}
|
||||
bool isDpiUnsupported() const {
|
||||
return (m_e==LOGIC || m_e==TIME || m_e==REALTIME);
|
||||
return (m_e==LOGIC || m_e==TIME);
|
||||
}
|
||||
bool isOpaque() const { // IE not a simple number we can bit optimize
|
||||
return (m_e==STRING || m_e==SCOPEPTR || m_e==CHARPTR);
|
||||
return (m_e==STRING || m_e==SCOPEPTR || m_e==CHARPTR || m_e==DOUBLE || m_e==FLOAT);
|
||||
}
|
||||
bool isDouble() const {
|
||||
return (m_e==DOUBLE);
|
||||
}
|
||||
};
|
||||
inline bool operator== (AstBasicDTypeKwd lhs, AstBasicDTypeKwd rhs) { return (lhs.m_e == rhs.m_e); }
|
||||
@@ -684,7 +719,9 @@ class AstNode {
|
||||
static int s_cloneCntGbl; // Count of which userp is set
|
||||
|
||||
// Attributes
|
||||
bool m_signed:1; // Node is signed
|
||||
uint32_t m_numeric:2; // Node is real/signed - important that bitfields remain unsigned
|
||||
bool m_didWidth:1; // Did V3Width computation
|
||||
bool m_doingWidth:1; // Inside V3Width
|
||||
// // Space for more bools here
|
||||
|
||||
int m_width; // Bit width of operation
|
||||
@@ -780,6 +817,8 @@ public:
|
||||
static int instrCountLd() { return 2; } ///< Instruction cycles to load memory
|
||||
static int instrCountMul() { return 3; } ///< Instruction cycles to multiply integers
|
||||
static int instrCountPli() { return 20; } ///< Instruction cycles to call pli routines
|
||||
static int instrCountDouble() { return 8; } ///< Instruction cycles to convert or do floats
|
||||
static int instrCountDoubleDiv() { return 40; } ///< Instruction cycles to divide floats
|
||||
static int instrCountCall() { return instrCountBranch()+10; } ///< Instruction cycles to call subroutine
|
||||
static int instrCountTime() { return instrCountCall()+5; } ///< Instruction cycles to determine simulation time
|
||||
|
||||
@@ -807,10 +846,18 @@ public:
|
||||
bool widthSized() const { return !m_widthMin || m_widthMin==m_width; }
|
||||
void width(int width, int sized) { m_width=width; m_widthMin=sized; }
|
||||
void widthFrom(AstNode* fromp) { if (fromp) { m_width=fromp->m_width; m_widthMin=fromp->m_widthMin; }}
|
||||
void widthSignedFrom(AstNode* fromp) { widthFrom(fromp); signedFrom(fromp); }
|
||||
void signedFrom(AstNode* fromp) { if (fromp) { m_signed=fromp->m_signed; }}
|
||||
void isSigned(bool flag) { m_signed=flag; }
|
||||
bool isSigned() const { return m_signed; }
|
||||
void widthSignedFrom(AstNode* fromp) { widthFrom(fromp); numericFrom(fromp); }
|
||||
void numericFrom(AstNode* fromp) { numeric(fromp->numeric()); }
|
||||
void numeric(AstNumeric flag) { m_numeric = (int)flag; if (flag.isDouble()) width(64,64); }
|
||||
AstNumeric numeric() const { return AstNumeric(m_numeric); }
|
||||
bool isDouble() const { return numeric().isDouble(); }
|
||||
bool isSigned() const { return numeric().isSigned(); }
|
||||
void isSigned(bool flag) { numeric(flag ? AstNumeric::SIGNED : AstNumeric::UNSIGNED); }
|
||||
bool isUnsigned() const { return numeric().isUnsigned(); }
|
||||
void didWidth(bool flag) { m_didWidth=flag; }
|
||||
bool didWidth() const { return m_didWidth; }
|
||||
void doingWidth(bool flag) { m_doingWidth=flag; }
|
||||
bool doingWidth() const { return m_doingWidth; }
|
||||
bool isQuad() const { return (width()>VL_WORDSIZE && width()<=VL_QUADSIZE); }
|
||||
bool isWide() const { return (width()>VL_QUADSIZE); }
|
||||
|
||||
@@ -976,10 +1023,13 @@ struct AstNodeUniop : public AstNodeMath {
|
||||
setOp1p(lhsp); }
|
||||
ASTNODE_BASE_FUNCS(NodeUniop)
|
||||
AstNode* lhsp() const { return op1p()->castNode(); }
|
||||
void lhsp(AstNode* nodep) { return setOp1p(nodep); }
|
||||
// METHODS
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) = 0; // Set out to evaluation of a AstConst'ed lhs
|
||||
virtual bool cleanLhs() = 0;
|
||||
virtual bool sizeMattersLhs() = 0; // True if output result depends on lhs size
|
||||
virtual bool signedFlavor() const { return false; } // Signed flavor of nodes with both flavors?
|
||||
virtual bool doubleFlavor() const { return false; } // D flavor of nodes with both flavors?
|
||||
virtual int instrCount() const { return widthInstrs(); }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(AstNode*) const { return true; }
|
||||
@@ -1002,6 +1052,7 @@ struct AstNodeBiop : public AstNodeMath {
|
||||
virtual bool sizeMattersLhs() = 0; // True if output result depends on lhs size
|
||||
virtual bool sizeMattersRhs() = 0; // True if output result depends on rhs size
|
||||
virtual bool signedFlavor() const { return false; } // Signed flavor of nodes with both flavors?
|
||||
virtual bool doubleFlavor() const { return false; } // D flavor of nodes with both flavors?
|
||||
virtual int instrCount() const { return widthInstrs(); }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(AstNode*) const { return true; }
|
||||
@@ -1274,7 +1325,6 @@ private:
|
||||
string m_name; // Name of task
|
||||
string m_cname; // Name of task if DPI import
|
||||
bool m_taskPublic:1; // Public task
|
||||
bool m_didSigning:1; // V3Signed completed; can skip iteration
|
||||
bool m_attrIsolateAssign:1;// User isolate_assignments attribute
|
||||
bool m_prototype:1; // Just a prototype
|
||||
bool m_dpiExport:1; // DPI exported
|
||||
@@ -1285,7 +1335,7 @@ private:
|
||||
public:
|
||||
AstNodeFTask(FileLine* fileline, const string& name, AstNode* stmtsp)
|
||||
: AstNode(fileline)
|
||||
, m_name(name), m_taskPublic(false), m_didSigning(false)
|
||||
, m_name(name), m_taskPublic(false)
|
||||
, m_attrIsolateAssign(false), m_prototype(false)
|
||||
, m_dpiExport(false), m_dpiImport(false), m_dpiContext(false)
|
||||
, m_dpiTask(false), m_pure(false) {
|
||||
@@ -1312,8 +1362,6 @@ public:
|
||||
void scopeNamep(AstNode* nodep) { setNOp4p(nodep); }
|
||||
void taskPublic(bool flag) { m_taskPublic=flag; }
|
||||
bool taskPublic() const { return m_taskPublic; }
|
||||
void didSigning(bool flag) { m_didSigning=flag; }
|
||||
bool didSigning() const { return m_didSigning; }
|
||||
void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; }
|
||||
bool attrIsolateAssign() const { return m_attrIsolateAssign; }
|
||||
void prototype(bool flag) { m_prototype = flag; }
|
||||
|
||||
+10
-5
@@ -113,6 +113,10 @@ string AstVar::vlArgType(bool named, bool forReturn) const {
|
||||
arg += "const char*";
|
||||
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::SCOPEPTR) {
|
||||
arg += "const VerilatedScope*";
|
||||
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::DOUBLE) {
|
||||
arg += "double";
|
||||
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::FLOAT) {
|
||||
arg += "float";
|
||||
} else if (strtype) {
|
||||
if (isInOnly()) arg += "const ";
|
||||
arg += "string";
|
||||
@@ -185,7 +189,7 @@ string AstVar::cPubArgType(bool named, bool forReturn) const {
|
||||
} else if (isWide()) {
|
||||
arg += "uint32_t"; // []'s added later
|
||||
} else {
|
||||
arg += "uint64_t";
|
||||
arg += "vluint64_t";
|
||||
}
|
||||
if (isWide()) {
|
||||
if (forReturn) v3error("Unsupported: Public functions with >64 bit outputs; make an output of a public task instead");
|
||||
@@ -202,7 +206,6 @@ string AstVar::dpiArgType(bool named, bool forReturn) const {
|
||||
if (forReturn) named=false;
|
||||
string arg;
|
||||
if (!basicp()) arg = "UNKNOWN";
|
||||
if (isWide()) v3error("Unsupported: DPI functions with vectored outputs > 32-bits");
|
||||
if (basicp()->isBitLogic()) {
|
||||
if (widthMin() == 1) {
|
||||
arg = "unsigned char";
|
||||
@@ -238,7 +241,7 @@ string AstVar::scType() const {
|
||||
return "uint32_t";
|
||||
}
|
||||
} else {
|
||||
return "uint64_t";
|
||||
return "vluint64_t";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -500,6 +503,7 @@ void AstNode::dump(ostream& os) {
|
||||
<<((editCount()>=editCountLast())?"#>":">")
|
||||
<<" {"<<dec<<fileline()->lineno()<<"}"
|
||||
<<" "<<(isSigned()?"s":"")
|
||||
<<(isDouble()?"d":"")
|
||||
<<"w"<<(widthSized()?"":"u")<<width();
|
||||
if (!widthSized()) os<<"/"<<widthMin();
|
||||
if (name()!="") os<<" "<<AstNode::quoteName(name());
|
||||
@@ -522,7 +526,7 @@ void AstBasicDType::dump(ostream& str) {
|
||||
str<<" ["<<keyword().ascii()<<"]";
|
||||
if (implicit()) str<<" [IMPLICIT]";
|
||||
}
|
||||
void AstCast::dump(ostream& str) {
|
||||
void AstCCast::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
str<<" sz"<<size();
|
||||
}
|
||||
@@ -609,7 +613,8 @@ void AstVar::dump(ostream& str) {
|
||||
else if (isInput()) str<<" [I]";
|
||||
else if (isOutput()) str<<" [O]";
|
||||
}
|
||||
if (isUsedClock()) str<<" [C]";
|
||||
if (isConst()) str<<" [CONST]";
|
||||
if (isUsedClock()) str<<" [CLK]";
|
||||
if (isSigPublic()) str<<" [P]";
|
||||
if (isUsedLoopIdx()) str<<" [LOOP]";
|
||||
if (attrClockEn()) str<<" [aCLKEN]";
|
||||
|
||||
+345
-27
@@ -46,19 +46,25 @@ struct AstConst : public AstNodeMath {
|
||||
private:
|
||||
V3Number m_num; // Constant value
|
||||
public:
|
||||
class Unsized32 {}; // for creator type-overload selection
|
||||
AstConst(FileLine* fl, const V3Number& num)
|
||||
:AstNodeMath(fl)
|
||||
,m_num(num) {
|
||||
width(m_num.width(), m_num.sized()?0:m_num.minWidth());
|
||||
isSigned(m_num.isSigned());
|
||||
numeric(m_num.isDouble() ? AstNumeric::DOUBLE
|
||||
: m_num.isSigned() ? AstNumeric::SIGNED
|
||||
: AstNumeric::UNSIGNED);
|
||||
}
|
||||
AstConst(FileLine* fl, uint32_t num)
|
||||
:AstNodeMath(fl)
|
||||
,m_num(V3Number(fl,32,num)) { width(m_num.width(), m_num.sized()?0:m_num.minWidth()); }
|
||||
class Unsized32 {}; // for creator type-overload selection
|
||||
AstConst(FileLine* fl, Unsized32, uint32_t num) // Unsized 32-bit integer of specified value
|
||||
:AstNodeMath(fl)
|
||||
,m_num(V3Number(fl,32,num)) { m_num.width(32,false); width(32,m_num.minWidth()); }
|
||||
class RealDouble {}; // for creator type-overload selection
|
||||
AstConst(FileLine* fl, RealDouble, double num)
|
||||
:AstNodeMath(fl)
|
||||
,m_num(V3Number(fl,64)) { m_num.setDouble(num); numeric(AstNumeric::DOUBLE); }
|
||||
class LogicFalse {};
|
||||
AstConst(FileLine* fl, LogicFalse) // Shorthand const 0, know the dtype should be a logic of size 1
|
||||
:AstNodeMath(fl)
|
||||
@@ -258,7 +264,8 @@ private:
|
||||
m_keyword = AstBasicDTypeKwd::LOGIC;
|
||||
}
|
||||
if (signst == signedst_NOP && keyword().isSigned()) signst = signedst_SIGNED;
|
||||
setSignedState(signst);
|
||||
if (keyword().isDouble()) numeric(AstNumeric::DOUBLE);
|
||||
else setSignedState(signst);
|
||||
if (!rangep) { // Set based on keyword properties
|
||||
// V3Width will pull from this width
|
||||
if (keyword().width() > 1 && !isOpaque()) rangep = new AstRange(fileline(), keyword().width()-1, 0);
|
||||
@@ -278,7 +285,8 @@ public:
|
||||
AstRange* rangep() const { return op1p()->castRange(); } // op1 = Range of variable
|
||||
void rangep(AstRange* nodep) { setNOp1p(nodep); }
|
||||
void setSignedState(AstSignedState signst) {
|
||||
if (signst!=signedst_NOP) isSigned(signst==signedst_SIGNED);
|
||||
if (signst==signedst_UNSIGNED) numeric(AstNumeric::UNSIGNED);
|
||||
else if (signst==signedst_SIGNED) numeric(AstNumeric::SIGNED);
|
||||
}
|
||||
// METHODS
|
||||
virtual AstBasicDType* basicp() const { return (AstBasicDType*)this; } // (Slow) recurse down to find basic data type
|
||||
@@ -300,6 +308,25 @@ public:
|
||||
void implicit(bool flag) { m_implicit = flag; }
|
||||
};
|
||||
|
||||
struct AstConstDType : public AstNodeDType {
|
||||
// const data type, ie "const some_dtype var_name [2:0]"
|
||||
// ConstDType are removed in V3LinkLValue and become AstVar::isConst.
|
||||
// When more generic types are supported AstConstDType will be propagated further.
|
||||
AstConstDType(FileLine* fl, AstNodeDType* dtypep)
|
||||
: AstNodeDType(fl) {
|
||||
setOp1p(dtypep);
|
||||
widthSignedFrom(dtypep);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(ConstDType, CONSTDTYPE)
|
||||
AstNodeDType* dtypep() const { return op1p()->castNodeDType(); } // op1 = Range of variable
|
||||
void dtypep(AstNodeDType* nodep) { setOp1p(nodep); }
|
||||
// METHODS
|
||||
virtual AstBasicDType* basicp() const { return dtypep()->basicp(); } // (Slow) recurse down to find basic data type
|
||||
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
|
||||
virtual int widthAlignBytes() const { return dtypep()->widthAlignBytes(); }
|
||||
virtual int widthTotalBytes() const { return dtypep()->widthTotalBytes(); }
|
||||
};
|
||||
|
||||
struct AstRefDType : public AstNodeDType {
|
||||
private:
|
||||
AstTypedef* m_defp;
|
||||
@@ -364,9 +391,10 @@ public:
|
||||
struct AstEnumItemRef : public AstNodeMath {
|
||||
private:
|
||||
AstEnumItem* m_itemp; // [AfterLink] Pointer to item
|
||||
AstPackage* m_packagep; // Package hierarchy
|
||||
public:
|
||||
AstEnumItemRef(FileLine* fl, AstEnumItem* itemp)
|
||||
: AstNodeMath(fl), m_itemp(itemp) {
|
||||
AstEnumItemRef(FileLine* fl, AstEnumItem* itemp, AstPackage* packagep)
|
||||
: AstNodeMath(fl), m_itemp(itemp), m_packagep(packagep) {
|
||||
if (m_itemp) widthSignedFrom(m_itemp);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(EnumItemRef, ENUMITEMREF)
|
||||
@@ -381,6 +409,8 @@ public:
|
||||
virtual string emitVerilog() { V3ERROR_NA; return ""; } // Implemented specially
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual bool cleanOut() { return true; }
|
||||
AstPackage* packagep() const { return m_packagep; }
|
||||
void packagep(AstPackage* nodep) { m_packagep=nodep; }
|
||||
};
|
||||
|
||||
struct AstEnumDType : public AstNodeDType {
|
||||
@@ -582,6 +612,7 @@ public:
|
||||
init();
|
||||
combineType(type); setOp1p(dtypep);
|
||||
if (dtypep && dtypep->basicp()) {
|
||||
numericFrom(dtypep);
|
||||
width(dtypep->basicp()->width(), 0);
|
||||
} else width(1, 0);
|
||||
}
|
||||
@@ -601,6 +632,7 @@ public:
|
||||
if (examplep->dtypep()) {
|
||||
setOp1p(examplep->dtypep()->cloneTree(true));
|
||||
}
|
||||
numericFrom(examplep);
|
||||
width(examplep->width(), examplep->widthMin());
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(Var, VAR)
|
||||
@@ -667,7 +699,7 @@ public:
|
||||
bool isToggleCoverable() const { return ((isIO() || isSignal())
|
||||
&& (isIO() || isBitLogic())
|
||||
// Wrapper would otherwise duplicate wrapped module's coverage
|
||||
&& !isSc() && !isPrimaryIO()); }
|
||||
&& !isSc() && !isPrimaryIO() && !isConst()); }
|
||||
bool isStatementTemp() const { return (varType()==AstVarType::STMTTEMP); }
|
||||
bool isMovableToBlock() const { return (varType()==AstVarType::BLOCKTEMP || isFuncLocal()); }
|
||||
bool isPure() const { return (varType()==AstVarType::XTEMP); }
|
||||
@@ -1425,6 +1457,15 @@ struct AstCondBound : public AstNodeCond {
|
||||
ASTNODE_NODE_FUNCS(CondBound, CONDBOUND)
|
||||
};
|
||||
|
||||
struct AstCondD : public AstNodeCond {
|
||||
// Conditional ?: statement, double rhs/lhs/out
|
||||
// Parents: MATH
|
||||
// Children: MATH
|
||||
AstCondD(FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p)
|
||||
: AstNodeCond(fl, condp, expr1p, expr2p) { numeric(AstNumeric::DOUBLE); }
|
||||
ASTNODE_NODE_FUNCS(CondD, CONDD)
|
||||
};
|
||||
|
||||
struct AstCoverDecl : public AstNodeStmt {
|
||||
// Coverage analysis point declaration
|
||||
// Parents: {statement list}
|
||||
@@ -1595,7 +1636,7 @@ public:
|
||||
void ignoreOverlap(bool flag) { m_ignoreOverlap = flag; }
|
||||
};
|
||||
|
||||
class AstSFormatF : public AstNode {
|
||||
struct AstSFormatF : public AstNode {
|
||||
// Convert format to string, generally under a AstDisplay or AstSFormat
|
||||
// Also used as "real" function for /*verilator sformat*/ functions
|
||||
string m_text;
|
||||
@@ -1963,6 +2004,18 @@ struct AstContinue : public AstNodeStmt {
|
||||
virtual bool isSplittable() const { return false; } // SPECIAL: We don't process code after breaks
|
||||
};
|
||||
|
||||
struct AstDisable : public AstNodeStmt {
|
||||
private:
|
||||
string m_name; // Name of block
|
||||
public:
|
||||
AstDisable(FileLine* fileline, const string& name)
|
||||
: AstNodeStmt(fileline), m_name(name) {}
|
||||
ASTNODE_NODE_FUNCS(Disable, DISABLE)
|
||||
virtual string name() const { return m_name; } // * = Block name
|
||||
void name(const string& flag) { m_name=flag; }
|
||||
virtual bool isSplittable() const { return false; } // SPECIAL: We don't process code after breaks
|
||||
};
|
||||
|
||||
struct AstReturn : public AstNodeStmt {
|
||||
AstReturn(FileLine* fileline, AstNode* lhsp=NULL)
|
||||
: AstNodeStmt (fileline) {
|
||||
@@ -2406,6 +2459,20 @@ struct AstTime : public AstNodeTermop {
|
||||
virtual bool same(AstNode* samep) const { return true; }
|
||||
};
|
||||
|
||||
struct AstTimeD : public AstNodeTermop {
|
||||
AstTimeD(FileLine* fl) : AstNodeTermop(fl) {
|
||||
numeric(AstNumeric::DOUBLE); }
|
||||
ASTNODE_NODE_FUNCS(TimeD, TIMED)
|
||||
virtual string emitVerilog() { return "%f$realtime"; }
|
||||
virtual string emitC() { return "VL_TIME_D()"; }
|
||||
virtual bool cleanOut() { return true; }
|
||||
virtual bool isGateOptimizable() const { return false; }
|
||||
virtual bool isPredictOptimizable() const { return false; }
|
||||
virtual int instrCount() const { return instrCountTime(); }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(AstNode* samep) const { return true; }
|
||||
};
|
||||
|
||||
struct AstUCFunc : public AstNodeMath {
|
||||
// User's $c function
|
||||
// Perhaps this should be a AstNodeListop; but there's only one list math right now
|
||||
@@ -2431,19 +2498,32 @@ struct AstUCFunc : public AstNodeMath {
|
||||
//======================================================================
|
||||
// Unary ops
|
||||
|
||||
struct AstUnaryMin : public AstNodeUniop {
|
||||
AstUnaryMin(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
struct AstNegate : public AstNodeUniop {
|
||||
AstNegate(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
if (lhsp) widthSignedFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(UnaryMin, UNARYMIN)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opUnaryMin(lhs); }
|
||||
ASTNODE_NODE_FUNCS(Negate, NEGATE)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opNegate(lhs); }
|
||||
virtual string emitVerilog() { return "%f(- %l)"; }
|
||||
virtual string emitC() { return "VL_UNARYMIN_%lq(%lW, %P, %li)"; }
|
||||
virtual string emitC() { return "VL_NEGATE_%lq(%lW, %P, %li)"; }
|
||||
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return true;}
|
||||
};
|
||||
struct AstNegateD : public AstNodeUniop {
|
||||
AstNegateD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
numeric(AstNumeric::DOUBLE); }
|
||||
ASTNODE_NODE_FUNCS(NegateD, NEGATED)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opNegateD(lhs); }
|
||||
virtual string emitVerilog() { return "%f(- %l)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual string emitSimpleOperator() { return "-"; }
|
||||
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return false;}
|
||||
virtual int instrCount() const { return instrCountDouble(); }
|
||||
virtual bool doubleFlavor() const { return true; }
|
||||
};
|
||||
struct AstRedAnd : public AstNodeUniop {
|
||||
AstRedAnd(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
width(1,1); }
|
||||
width(1,1); numeric(AstNumeric::UNSIGNED); }
|
||||
ASTNODE_NODE_FUNCS(RedAnd, REDAND)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedAnd(lhs); }
|
||||
virtual string emitVerilog() { return "%f(& %l)"; }
|
||||
@@ -2453,7 +2533,7 @@ struct AstRedAnd : public AstNodeUniop {
|
||||
};
|
||||
struct AstRedOr : public AstNodeUniop {
|
||||
AstRedOr(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
width(1,1); }
|
||||
width(1,1); numeric(AstNumeric::UNSIGNED); }
|
||||
ASTNODE_NODE_FUNCS(RedOr, REDOR)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedOr(lhs); }
|
||||
virtual string emitVerilog() { return "%f(| %l)"; }
|
||||
@@ -2463,7 +2543,7 @@ struct AstRedOr : public AstNodeUniop {
|
||||
};
|
||||
struct AstRedXor : public AstNodeUniop {
|
||||
AstRedXor(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
width(1,1); }
|
||||
width(1,1); numeric(AstNumeric::UNSIGNED); }
|
||||
ASTNODE_NODE_FUNCS(RedXor, REDXOR)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedXor(lhs); }
|
||||
virtual string emitVerilog() { return "%f(^ %l)"; }
|
||||
@@ -2477,7 +2557,7 @@ struct AstRedXor : public AstNodeUniop {
|
||||
struct AstRedXnor : public AstNodeUniop {
|
||||
// AstRedXnors are replaced with AstRedXors in V3Const.
|
||||
AstRedXnor(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
width(1,1); }
|
||||
width(1,1); numeric(AstNumeric::UNSIGNED); }
|
||||
ASTNODE_NODE_FUNCS(RedXnor, REDXNOR)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedXnor(lhs); }
|
||||
virtual string emitVerilog() { return "%f(~^ %l)"; }
|
||||
@@ -2535,7 +2615,7 @@ struct AstExtendS : public AstNodeUniop {
|
||||
struct AstSigned : public AstNodeUniop {
|
||||
// $signed(lhs)
|
||||
AstSigned(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
isSigned(true);
|
||||
numeric(AstNumeric::SIGNED);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(Signed, SIGNED)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); out.isSigned(false); }
|
||||
@@ -2548,7 +2628,7 @@ struct AstSigned : public AstNodeUniop {
|
||||
struct AstUnsigned : public AstNodeUniop {
|
||||
// $unsigned(lhs)
|
||||
AstUnsigned(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
isSigned(false);
|
||||
numeric(AstNumeric::UNSIGNED);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(Unsigned, UNSIGNED)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); out.isSigned(false); }
|
||||
@@ -2558,6 +2638,63 @@ struct AstUnsigned : public AstNodeUniop {
|
||||
virtual bool sizeMattersLhs() {return true;} // Eliminated before matters
|
||||
virtual int instrCount() const { return 0; }
|
||||
};
|
||||
struct AstRToIS : public AstNodeUniop {
|
||||
// $rtoi(lhs)
|
||||
AstRToIS(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
width(32,32); }
|
||||
ASTNODE_NODE_FUNCS(RToIS, RTOIS)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRToIS(lhs); }
|
||||
virtual string emitVerilog() { return "%f$rtoi(%l)"; }
|
||||
virtual string emitC() { return "VL_RTOI_I_D(%li)"; }
|
||||
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;} // Eliminated before matters
|
||||
virtual bool sizeMattersLhs() {return false;} // Eliminated before matters
|
||||
virtual int instrCount() const { return instrCountDouble(); }
|
||||
};
|
||||
struct AstRToIRoundS : public AstNodeUniop {
|
||||
AstRToIRoundS(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
width(32,32); }
|
||||
ASTNODE_NODE_FUNCS(RToIRoundS, RTOIROUNDS)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRToIRoundS(lhs); }
|
||||
virtual string emitVerilog() { return "%f$rtoi_rounded(%l)"; }
|
||||
virtual string emitC() { return "VL_RTOIROUND_I_D(%li)"; }
|
||||
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;} // Eliminated before matters
|
||||
virtual bool sizeMattersLhs() {return false;} // Eliminated before matters
|
||||
virtual int instrCount() const { return instrCountDouble(); }
|
||||
};
|
||||
struct AstIToRD : public AstNodeUniop {
|
||||
AstIToRD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
numeric(AstNumeric::DOUBLE); }
|
||||
ASTNODE_NODE_FUNCS(IToRD, ITORD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opIToRD(lhs); }
|
||||
virtual string emitVerilog() { return "%f$itor(%l)"; }
|
||||
virtual string emitC() { return "VL_ITOR_D_I(%li)"; }
|
||||
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;} // Eliminated before matters
|
||||
virtual bool sizeMattersLhs() {return false;} // Eliminated before matters
|
||||
virtual int instrCount() const { return instrCountDouble(); }
|
||||
};
|
||||
struct AstRealToBits : public AstNodeUniop {
|
||||
AstRealToBits(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
width(64,64); }
|
||||
ASTNODE_NODE_FUNCS(RealToBits, REALTOBITS)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRealToBits(lhs); }
|
||||
virtual string emitVerilog() { return "%f$realtobits(%l)"; }
|
||||
virtual string emitC() { return "VL_CVT_Q_D(%li)"; }
|
||||
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;} // Eliminated before matters
|
||||
virtual bool sizeMattersLhs() {return false;} // Eliminated before matters
|
||||
virtual int instrCount() const { return instrCountDouble(); }
|
||||
};
|
||||
struct AstBitsToRealD : public AstNodeUniop {
|
||||
AstBitsToRealD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
numeric(AstNumeric::DOUBLE); }
|
||||
ASTNODE_NODE_FUNCS(BitsToRealD, BITSTOREALD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opBitsToRealD(lhs); }
|
||||
virtual string emitVerilog() { return "%f$bitstoreal(%l)"; }
|
||||
virtual string emitC() { return "VL_CVT_D_Q(%li)"; }
|
||||
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;} // Eliminated before matters
|
||||
virtual bool sizeMattersLhs() {return false;} // Eliminated before matters
|
||||
virtual int instrCount() const { return instrCountDouble(); }
|
||||
};
|
||||
|
||||
struct AstCLog2 : public AstNodeUniop {
|
||||
AstCLog2(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {}
|
||||
ASTNODE_NODE_FUNCS(CLog2, CLOG2)
|
||||
@@ -2615,27 +2752,42 @@ struct AstOneHot0 : public AstNodeUniop {
|
||||
virtual int instrCount() const { return widthInstrs()*3; }
|
||||
};
|
||||
|
||||
struct AstCast : public AstNodeUniop {
|
||||
// Cast to appropriate data type
|
||||
struct AstCast : public AstNode {
|
||||
// Cast to appropriate data type - note lhsp is value, to match AstTypedef, AstCCast, etc
|
||||
AstCast(FileLine* fl, AstNode* lhsp, AstNodeDType* dtypep) : AstNode(fl) {
|
||||
setOp1p(lhsp); setOp2p(dtypep);
|
||||
if (dtypep) { widthSignedFrom(dtypep); }
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(Cast, CAST)
|
||||
virtual string emitVerilog() { return "((%r)'(%l))"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual bool cleanOut() { V3ERROR_NA; return true;} virtual bool cleanLhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;}
|
||||
AstNode* lhsp() const { return op1p(); }
|
||||
AstNodeDType* dtypep() const { return op2p()->castNodeDType(); }
|
||||
};
|
||||
|
||||
struct AstCCast : public AstNodeUniop {
|
||||
// Cast to C-based data type
|
||||
private:
|
||||
int m_size;
|
||||
public:
|
||||
AstCast(FileLine* fl, AstNode* lhsp, int setwidth) : AstNodeUniop(fl, lhsp) {
|
||||
AstCCast(FileLine* fl, AstNode* lhsp, int setwidth) : AstNodeUniop(fl, lhsp) {
|
||||
m_size=setwidth;
|
||||
if (setwidth) { width(setwidth,setwidth); }
|
||||
}
|
||||
AstCast(FileLine* fl, AstNode* lhsp, AstNode* widthFromp) : AstNodeUniop(fl, lhsp) {
|
||||
AstCCast(FileLine* fl, AstNode* lhsp, AstNode* widthFromp) : AstNodeUniop(fl, lhsp) {
|
||||
if (widthFromp) { widthSignedFrom(widthFromp); }
|
||||
m_size=width();
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(Cast, CAST)
|
||||
ASTNODE_NODE_FUNCS(CCast, CCAST)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); }
|
||||
virtual string emitVerilog() { return "%f$_CAST(%l)"; }
|
||||
virtual string emitC() { return "VL_CAST_%nq%lq(%nw,%lw, %P, %li)"; }
|
||||
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} // Special cased in V3Cast
|
||||
virtual V3Hash sameHash() const { return V3Hash(size()); }
|
||||
virtual bool same(AstNode* samep) const { return size()==samep->castCast()->size(); }
|
||||
virtual bool same(AstNode* samep) const { return size()==samep->castCCast()->size(); }
|
||||
virtual void dump(ostream& str=cout);
|
||||
//
|
||||
int size() const { return m_size; }
|
||||
@@ -2660,7 +2812,7 @@ struct AstFEof : public AstNodeUniop {
|
||||
ASTNODE_NODE_FUNCS(FEof, FEOF)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { V3ERROR_NA; }
|
||||
virtual string emitVerilog() { return "%f$feof(%l)"; }
|
||||
virtual string emitC() { return "(%li ? feof(VL_CVT_Q_FP(%li)) : true)"; }
|
||||
virtual string emitC() { return "(%li ? feof(VL_CVT_I_FP(%li)) : true)"; }
|
||||
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;}
|
||||
virtual int instrCount() const { return widthInstrs()*16; }
|
||||
@@ -2673,7 +2825,7 @@ struct AstFGetC : public AstNodeUniop {
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { V3ERROR_NA; }
|
||||
virtual string emitVerilog() { return "%f$fgetc(%l)"; }
|
||||
// Non-existent filehandle returns EOF
|
||||
virtual string emitC() { return "(%li ? fgetc(VL_CVT_Q_FP(%li)) : -1)"; }
|
||||
virtual string emitC() { return "(%li ? fgetc(VL_CVT_I_FP(%li)) : -1)"; }
|
||||
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;}
|
||||
virtual int instrCount() const { return widthInstrs()*64; }
|
||||
@@ -2795,6 +2947,20 @@ struct AstEq : public AstNodeBiCom {
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
};
|
||||
struct AstEqD : public AstNodeBiCom {
|
||||
AstEqD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
|
||||
width(1,1); }
|
||||
ASTNODE_NODE_FUNCS(EqD, EQD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opEqD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f== %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual string emitSimpleOperator() { return "=="; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
virtual int instrCount() const { return instrCountDouble(); }
|
||||
virtual bool doubleFlavor() const { return true; }
|
||||
};
|
||||
struct AstNeq : public AstNodeBiCom {
|
||||
AstNeq(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
|
||||
width(1,1); }
|
||||
@@ -2807,6 +2973,20 @@ struct AstNeq : public AstNodeBiCom {
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
};
|
||||
struct AstNeqD : public AstNodeBiCom {
|
||||
AstNeqD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
|
||||
width(1,1); }
|
||||
ASTNODE_NODE_FUNCS(NeqD, NEQD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opNeqD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f!= %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual string emitSimpleOperator() { return "!="; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
virtual int instrCount() const { return instrCountDouble(); }
|
||||
virtual bool doubleFlavor() const { return true; }
|
||||
};
|
||||
struct AstLt : public AstNodeBiop {
|
||||
AstLt(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
width(1,1); }
|
||||
@@ -2819,6 +2999,20 @@ struct AstLt : public AstNodeBiop {
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
};
|
||||
struct AstLtD : public AstNodeBiop {
|
||||
AstLtD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
width(1,1); }
|
||||
ASTNODE_NODE_FUNCS(LtD, LTD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLtD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f< %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual string emitSimpleOperator() { return "<"; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
virtual int instrCount() const { return instrCountDouble(); }
|
||||
virtual bool doubleFlavor() const { return true; }
|
||||
};
|
||||
struct AstLtS : public AstNodeBiop {
|
||||
AstLtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
width(1,1); }
|
||||
@@ -2844,6 +3038,20 @@ struct AstGt : public AstNodeBiop {
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
};
|
||||
struct AstGtD : public AstNodeBiop {
|
||||
AstGtD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
width(1,1); }
|
||||
ASTNODE_NODE_FUNCS(GtD, GTD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGtD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f> %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual string emitSimpleOperator() { return ">"; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
virtual int instrCount() const { return instrCountDouble(); }
|
||||
virtual bool doubleFlavor() const { return true; }
|
||||
};
|
||||
struct AstGtS : public AstNodeBiop {
|
||||
AstGtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
width(1,1); }
|
||||
@@ -2869,6 +3077,20 @@ struct AstGte : public AstNodeBiop {
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
};
|
||||
struct AstGteD : public AstNodeBiop {
|
||||
AstGteD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
width(1,1); }
|
||||
ASTNODE_NODE_FUNCS(GteD, GTED)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGteD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f>= %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual string emitSimpleOperator() { return ">="; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
virtual int instrCount() const { return instrCountDouble(); }
|
||||
virtual bool doubleFlavor() const { return true; }
|
||||
};
|
||||
struct AstGteS : public AstNodeBiop {
|
||||
AstGteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
width(1,1); }
|
||||
@@ -2894,6 +3116,20 @@ struct AstLte : public AstNodeBiop {
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
};
|
||||
struct AstLteD : public AstNodeBiop {
|
||||
AstLteD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
width(1,1); }
|
||||
ASTNODE_NODE_FUNCS(LteD, LTED)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLteD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f<= %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual string emitSimpleOperator() { return "<="; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
virtual int instrCount() const { return instrCountDouble(); }
|
||||
virtual bool doubleFlavor() const { return true; }
|
||||
};
|
||||
struct AstLteS : public AstNodeBiop {
|
||||
AstLteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
width(1,1); }
|
||||
@@ -2962,6 +3198,20 @@ struct AstAdd : public AstNodeBiComAsv {
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
|
||||
};
|
||||
struct AstAddD : public AstNodeBiComAsv {
|
||||
AstAddD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
|
||||
numeric(AstNumeric::DOUBLE); }
|
||||
ASTNODE_NODE_FUNCS(AddD, ADDD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opAddD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f+ %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual string emitSimpleOperator() { return "+"; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
virtual int instrCount() const { return instrCountDouble(); }
|
||||
virtual bool doubleFlavor() const { return true; }
|
||||
};
|
||||
struct AstSub : public AstNodeBiop {
|
||||
AstSub(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
if (lhsp) widthSignedFrom(lhsp); }
|
||||
@@ -2974,6 +3224,20 @@ struct AstSub : public AstNodeBiop {
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
|
||||
};
|
||||
struct AstSubD : public AstNodeBiop {
|
||||
AstSubD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
numeric(AstNumeric::DOUBLE); }
|
||||
ASTNODE_NODE_FUNCS(SubD, SUBD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opSubD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f- %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual string emitSimpleOperator() { return "-"; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
virtual int instrCount() const { return instrCountDouble(); }
|
||||
virtual bool doubleFlavor() const { return true; }
|
||||
};
|
||||
struct AstMul : public AstNodeBiComAsv {
|
||||
AstMul(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
|
||||
if (lhsp) widthSignedFrom(lhsp); }
|
||||
@@ -2987,6 +3251,20 @@ struct AstMul : public AstNodeBiComAsv {
|
||||
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
|
||||
virtual int instrCount() const { return widthInstrs()*instrCountMul(); }
|
||||
};
|
||||
struct AstMulD : public AstNodeBiComAsv {
|
||||
AstMulD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
|
||||
numeric(AstNumeric::DOUBLE); }
|
||||
ASTNODE_NODE_FUNCS(MulD, MULD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opMulD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f* %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual string emitSimpleOperator() { return "*"; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
|
||||
virtual int instrCount() const { return instrCountDouble(); }
|
||||
virtual bool doubleFlavor() const { return true; }
|
||||
};
|
||||
struct AstMulS : public AstNodeBiComAsv {
|
||||
AstMulS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
|
||||
if (lhsp) widthSignedFrom(lhsp); }
|
||||
@@ -3013,6 +3291,20 @@ struct AstDiv : public AstNodeBiop {
|
||||
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
|
||||
virtual int instrCount() const { return widthInstrs()*instrCountDiv(); }
|
||||
};
|
||||
struct AstDivD : public AstNodeBiop {
|
||||
AstDivD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
numeric(AstNumeric::DOUBLE); }
|
||||
ASTNODE_NODE_FUNCS(DivD, DIVD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opDivD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f/ %r)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual string emitSimpleOperator() { return "/"; }
|
||||
virtual bool cleanOut() {return true;}
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
virtual int instrCount() const { return instrCountDoubleDiv(); }
|
||||
virtual bool doubleFlavor() const { return true; }
|
||||
};
|
||||
struct AstDivS : public AstNodeBiop {
|
||||
AstDivS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
if (lhsp) widthSignedFrom(lhsp); }
|
||||
@@ -3063,6 +3355,19 @@ struct AstPow : public AstNodeBiop {
|
||||
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return false;}
|
||||
virtual int instrCount() const { return widthInstrs()*instrCountMul(); }
|
||||
};
|
||||
struct AstPowD : public AstNodeBiop {
|
||||
AstPowD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
numeric(AstNumeric::DOUBLE); }
|
||||
ASTNODE_NODE_FUNCS(PowD, POWD)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opPowD(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "%k(%l %f** %r)"; }
|
||||
virtual string emitC() { return "pow(%li,%ri)"; }
|
||||
virtual bool cleanOut() {return false;}
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
virtual int instrCount() const { return instrCountDoubleDiv(); }
|
||||
virtual bool doubleFlavor() const { return true; }
|
||||
};
|
||||
struct AstPowS : public AstNodeBiop {
|
||||
AstPowS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
if (lhsp) widthSignedFrom(lhsp); }
|
||||
@@ -3152,6 +3457,19 @@ struct AstReplicate : public AstNodeBiop {
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
virtual int instrCount() const { return widthInstrs()*2; }
|
||||
};
|
||||
struct AstBufIf1 : public AstNodeBiop {
|
||||
// lhs is enable, rhs is data to drive
|
||||
AstBufIf1(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
if (lhsp) widthSignedFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(BufIf1, BUFIF1)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opBufIf1(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "bufif(%r,%l)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return "";} // Lclean || Rclean
|
||||
virtual string emitSimpleOperator() { V3ERROR_NA; return false;} // Lclean || Rclean
|
||||
virtual bool cleanOut() {V3ERROR_NA; return "";} // Lclean || Rclean
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
};
|
||||
struct AstFGetS : public AstNodeBiop {
|
||||
AstFGetS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {}
|
||||
ASTNODE_NODE_FUNCS(FGetS, FGETS)
|
||||
|
||||
+6
-2
@@ -148,17 +148,19 @@ private:
|
||||
|
||||
bool isCaseTreeFast(AstCase* nodep) {
|
||||
int width = 0;
|
||||
bool opaque = false;
|
||||
m_caseItems = 0;
|
||||
m_caseNoOverlapsAllCovered = true;
|
||||
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
|
||||
for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) {
|
||||
if (icondp->width() > width) width = icondp->width();
|
||||
if (icondp->isDouble()) opaque = true;
|
||||
if (!icondp->castConst()) width = CASE_BARF; // Can't parse; not a constant
|
||||
m_caseItems++;
|
||||
}
|
||||
}
|
||||
m_caseWidth = width;
|
||||
if (width==0 || width > CASE_OVERLAP_WIDTH) {
|
||||
if (width==0 || width > CASE_OVERLAP_WIDTH || opaque) {
|
||||
m_caseNoOverlapsAllCovered = false;
|
||||
return false; // Too wide for analysis
|
||||
}
|
||||
@@ -348,7 +350,9 @@ private:
|
||||
and1p = cexprp->cloneTree(false);
|
||||
and2p = icondp;
|
||||
}
|
||||
AstEq* condp = new AstEq(itemp->fileline(), and1p, and2p);
|
||||
AstNodeBiop* condp = (and1p->isDouble()
|
||||
? (new AstEqD(itemp->fileline(), and1p, and2p))->castNodeBiop()
|
||||
: (new AstEq(itemp->fileline(), and1p, and2p))->castNodeBiop());
|
||||
if (!ifexprp) {
|
||||
ifexprp = condp;
|
||||
} else {
|
||||
|
||||
+6
-6
@@ -77,7 +77,7 @@ private:
|
||||
AstNRelinker relinkHandle;
|
||||
nodep->unlinkFrBack(&relinkHandle);
|
||||
//
|
||||
AstCast* castp = new AstCast (nodep->fileline(), nodep, needsize);
|
||||
AstCCast* castp = new AstCCast (nodep->fileline(), nodep, needsize);
|
||||
castp->width(needsize, nodep->widthMin());
|
||||
relinkHandle.relink(castp);
|
||||
//if (debug()>8) castp->dumpTree(cout,"-castins: ");
|
||||
@@ -97,13 +97,13 @@ private:
|
||||
insertCast(nodep, castSize(nodep->backp()));
|
||||
}
|
||||
}
|
||||
void insureLower32Cast(AstCast* nodep) {
|
||||
void insureLower32Cast(AstCCast* nodep) {
|
||||
// If we have uint64 = CAST(uint64(x)) then the upcasting
|
||||
// really needs to be CAST(uint64(CAST(uint32(x))).
|
||||
// Otherwise a (uint64)(a>b) would return wrong value, as
|
||||
// less than has undeterministic signedness.
|
||||
if (nodep->isQuad() && !nodep->lhsp()->isQuad()
|
||||
&& !nodep->lhsp()->castCast()) {
|
||||
&& !nodep->lhsp()->castCCast()) {
|
||||
insertCast(nodep->lhsp(), VL_WORDSIZE);
|
||||
}
|
||||
}
|
||||
@@ -130,12 +130,12 @@ private:
|
||||
if (nodep->sizeMattersRhs()) insureCast(nodep->rhsp());
|
||||
if (nodep->sizeMattersThs()) insureCast(nodep->thsp());
|
||||
}
|
||||
virtual void visit(AstCast* nodep, AstNUser*) {
|
||||
virtual void visit(AstCCast* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
insureLower32Cast(nodep);
|
||||
nodep->user1(1);
|
||||
}
|
||||
virtual void visit(AstUnaryMin* nodep, AstNUser*) {
|
||||
virtual void visit(AstNegate* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
nodep->user1(nodep->lhsp()->user1());
|
||||
if (nodep->lhsp()->widthMin()==1) {
|
||||
@@ -149,7 +149,7 @@ private:
|
||||
}
|
||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||
if (!nodep->lvalue()
|
||||
&& !nodep->backp()->castCast()
|
||||
&& !nodep->backp()->castCCast()
|
||||
&& nodep->backp()->castNodeMath()
|
||||
&& nodep->backp()->width()
|
||||
&& castSize(nodep) != castSize(nodep->varp())) {
|
||||
|
||||
+30
-6
@@ -46,6 +46,8 @@
|
||||
#include "V3EmitV.h"
|
||||
#include "V3File.h"
|
||||
|
||||
#define CDC_WEIGHT_ASYNC 0x1000 // Weight for edges that feed async logic
|
||||
|
||||
//######################################################################
|
||||
|
||||
class CdcBaseVisitor : public AstNVisitor {
|
||||
@@ -314,7 +316,9 @@ private:
|
||||
UINFO(3,__FUNCTION__<<": "<<endl);
|
||||
//if (debug()>6) m_graph.dump();
|
||||
if (debug()>6) m_graph.dumpDotFilePrefixed("cdc_pre");
|
||||
m_graph.removeRedundantEdgesSum(&V3GraphEdge::followAlwaysTrue);
|
||||
//
|
||||
m_graph.removeRedundantEdges(&V3GraphEdge::followAlwaysTrue); // This will MAX across edge weights
|
||||
//
|
||||
m_graph.dumpDotFilePrefixed("cdc_simp");
|
||||
//
|
||||
analyzeReset();
|
||||
@@ -411,12 +415,15 @@ private:
|
||||
CdcEitherVertex* eToVertexp = (CdcEitherVertex*)edgep->top();
|
||||
if (!eToVertexp) targetp = eToVertexp;
|
||||
if (CdcLogicVertex* vvertexp = dynamic_cast<CdcLogicVertex*>(eToVertexp)) {
|
||||
if (vvertexp->isFlop()) {
|
||||
if (vvertexp->isFlop() // IE the target flop that is upsetting us
|
||||
&& edgep->weight() >= CDC_WEIGHT_ASYNC) { // And this signal feeds an async reset line
|
||||
targetp = eToVertexp;
|
||||
//UINFO(9," targetasync "<<targetp->name()<<" "<<" from "<<vertexp->name()<<endl);
|
||||
break;
|
||||
}
|
||||
} // else it might be random logic that's not relevant
|
||||
}
|
||||
//UINFO(9," finalflop "<<targetp->name()<<" "<<targetp->nodep()->fileline()<<endl);
|
||||
warnAndFile(markp->nodep(),V3ErrorCode::CDCRSTLOGIC,"Logic in path that feeds async reset, via signal: "+nodep->prettyName());
|
||||
dumpAsyncRecurse(targetp, "", " ",0);
|
||||
}
|
||||
@@ -469,6 +476,12 @@ private:
|
||||
|
||||
void edgeReport() {
|
||||
// Make report of all signal names and what clock edges they have
|
||||
//
|
||||
// Due to flattening, many interesting direct-connect signals are
|
||||
// lost, so we can't make a report showing I/Os for a low level
|
||||
// module. Disabling flattening though makes us consider each
|
||||
// signal in it's own unique clock domain.
|
||||
|
||||
UINFO(3,__FUNCTION__<<": "<<endl);
|
||||
|
||||
// Trace all sources and sinks
|
||||
@@ -498,6 +511,10 @@ private:
|
||||
|
||||
ostringstream os;
|
||||
os.setf(ios::left);
|
||||
// Module name - doesn't work due to flattening having lost the original
|
||||
// so we assume the modulename matches the filebasename
|
||||
string fname = vvertexp->varScp()->fileline()->filebasename() + ":";
|
||||
os<<" "<<setw(20)<<fname;
|
||||
os<<" "<<setw(8)<<whatp;
|
||||
os<<" "<<setw(40)<<vvertexp->varScp()->prettyName();
|
||||
os<<" SRC=";
|
||||
@@ -618,8 +635,9 @@ private:
|
||||
if (!varscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp\n");
|
||||
CdcVarVertex* varvertexp = makeVarVertex(varscp);
|
||||
UINFO(5," VARREF to "<<varscp<<endl);
|
||||
// We use weight of one; if we ref the var more than once, when we simplify,
|
||||
// the weight will increase
|
||||
// We use weight of one for normal edges,
|
||||
// Weight of CDC_WEIGHT_ASYNC to indicate feeds async (for reporting)
|
||||
// When simplify we'll take the MAX weight
|
||||
if (nodep->lvalue()) {
|
||||
new V3GraphEdge(&m_graph, m_logicVertexp, varvertexp, 1);
|
||||
if (m_inDly) {
|
||||
@@ -628,7 +646,13 @@ private:
|
||||
varvertexp->srcDomainSet(true);
|
||||
}
|
||||
} else {
|
||||
new V3GraphEdge(&m_graph, varvertexp, m_logicVertexp, 1);
|
||||
if (varvertexp->cntAsyncRst()) {
|
||||
//UINFO(9," edgeasync "<<varvertexp->name()<<" to "<<m_logicVertexp<<endl);
|
||||
new V3GraphEdge(&m_graph, varvertexp, m_logicVertexp, CDC_WEIGHT_ASYNC);
|
||||
} else {
|
||||
//UINFO(9," edgena "<<varvertexp->name()<<" to "<<m_logicVertexp<<endl);
|
||||
new V3GraphEdge(&m_graph, varvertexp, m_logicVertexp, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -725,7 +749,7 @@ public:
|
||||
|
||||
nodep->accept(*this);
|
||||
analyze();
|
||||
//edgeReport(); // Not useful at the moment
|
||||
if (debug()>=1) edgeReport(); // Not useful to users at the moment
|
||||
|
||||
if (0) { *m_ofp<<"\nDBG-test-dumper\n"; V3EmitV::verilogPrefixedTree(nodep, *m_ofp, "DBG ",40,NULL,true); *m_ofp<<endl; }
|
||||
}
|
||||
|
||||
+118
-11
@@ -37,7 +37,6 @@
|
||||
#include "V3Const.h"
|
||||
#include "V3Ast.h"
|
||||
#include "V3Width.h"
|
||||
#include "V3Signed.h"
|
||||
#include "V3Simulate.h"
|
||||
|
||||
//######################################################################
|
||||
@@ -290,13 +289,61 @@ private:
|
||||
// SEL(EXTEND(any,width,...),(width-1),0) -> ...
|
||||
// Since select's return unsigned, this is always an extend
|
||||
AstExtend* extendp = nodep->fromp()->castExtend();
|
||||
return (m_doV
|
||||
&& extendp
|
||||
&& nodep->lsbp()->castConst()
|
||||
&& nodep->widthp()->castConst()
|
||||
&& nodep->lsbConst()==0
|
||||
&& (int)nodep->widthConst()==extendp->lhsp()->width()
|
||||
);
|
||||
if (!(m_doV
|
||||
&& extendp
|
||||
&& nodep->lsbp()->castConst()
|
||||
&& nodep->widthp()->castConst()
|
||||
&& nodep->lsbConst()==0
|
||||
&& (int)nodep->widthConst()==extendp->lhsp()->width()
|
||||
)) return false;
|
||||
replaceWChild(nodep, extendp->lhsp()); nodep=NULL;
|
||||
return true;
|
||||
}
|
||||
bool operandSelBiLower(AstSel* nodep) {
|
||||
// SEL(ADD(a,b),(width-1),0) -> ADD(SEL(a),SEL(b))
|
||||
// Add or any operation which doesn't care if we discard top bits
|
||||
AstNodeBiop* bip = nodep->fromp()->castNodeBiop();
|
||||
if (!(m_doV
|
||||
&& bip
|
||||
&& nodep->lsbp()->castConst()
|
||||
&& nodep->widthp()->castConst()
|
||||
&& nodep->lsbConst()==0
|
||||
)) return false;
|
||||
if (debug()>=9) nodep->dumpTree(cout,"SEL(BI)-in:");
|
||||
AstNode* bilhsp = bip->lhsp()->unlinkFrBack();
|
||||
AstNode* birhsp = bip->rhsp()->unlinkFrBack();
|
||||
bip->lhsp(new AstSel(nodep->fileline(), bilhsp, 0, nodep->widthConst()));
|
||||
bip->rhsp(new AstSel(nodep->fileline(), birhsp, 0, nodep->widthConst()));
|
||||
if (debug()>=9) bip->dumpTree(cout,"SEL(BI)-ou:");
|
||||
replaceWChild(nodep, bip); nodep=NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operandBiExtendConst(AstNodeBiop* nodep) {
|
||||
// Loop unrolling likes standalone compares
|
||||
// EQ(EXTEND(xx{width3}), const{width32}) -> EQ(xx{3},const{3})
|
||||
// Beware that the constant must have zero bits (+ 1 if signed) or compare
|
||||
// would be incorrect
|
||||
AstExtend* extendp = nodep->lhsp()->castExtend();
|
||||
if (!extendp) return false;
|
||||
AstNode* smallerp = extendp->lhsp();
|
||||
int subsize = smallerp->width();
|
||||
AstConst* constp = nodep->rhsp()->castConst();
|
||||
if (!constp) return false;
|
||||
if (!constp->num().isBitsZero(constp->width()-1, subsize)) return false;
|
||||
//
|
||||
if (debug()>=9) nodep->dumpTree(cout,"BI(EXTEND)-in:");
|
||||
smallerp->unlinkFrBack();
|
||||
extendp->unlinkFrBack()->deleteTree(); // aka nodep->lhsp.
|
||||
nodep->lhsp(smallerp);
|
||||
|
||||
constp->unlinkFrBack();
|
||||
V3Number num (constp->fileline(), subsize);
|
||||
num.opAssign(constp->num());
|
||||
nodep->rhsp(new AstConst(constp->fileline(), num));
|
||||
constp->deleteTree(); constp=NULL;
|
||||
if (debug()>=9) nodep->dumpTree(cout,"BI(EXTEND)-ou:");
|
||||
return true;
|
||||
}
|
||||
|
||||
AstNode* afterComment(AstNode* nodep) {
|
||||
@@ -1061,6 +1108,38 @@ private:
|
||||
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
|
||||
void replaceSelIntoBiop(AstSel* nodep) {
|
||||
// SEL(BUFIF1(a,b),1,bit) => BUFIF1(SEL(a,1,bit),SEL(b,1,bit))
|
||||
AstNodeBiop* fromp = nodep->fromp()->unlinkFrBack()->castNodeBiop();
|
||||
if (!fromp) nodep->v3fatalSrc("Called on non biop");
|
||||
AstNode* lsbp = nodep->lsbp()->unlinkFrBack();
|
||||
AstNode* widthp = nodep->widthp()->unlinkFrBack();
|
||||
//
|
||||
AstNode* bilhsp = fromp->lhsp()->unlinkFrBack();
|
||||
AstNode* birhsp = fromp->rhsp()->unlinkFrBack();
|
||||
//
|
||||
fromp->lhsp(new AstSel(nodep->fileline(),
|
||||
bilhsp, lsbp->cloneTree(true), widthp->cloneTree(true)));
|
||||
fromp->rhsp(new AstSel(nodep->fileline(),
|
||||
birhsp, lsbp, widthp));
|
||||
fromp->widthSignedFrom(nodep);
|
||||
nodep->replaceWith(fromp); nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
void replaceSelIntoUniop(AstSel* nodep) {
|
||||
// SEL(NOT(a),1,bit) => NOT(SEL(a,bit))
|
||||
AstNodeUniop* fromp = nodep->fromp()->unlinkFrBack()->castNodeUniop();
|
||||
if (!fromp) nodep->v3fatalSrc("Called on non biop");
|
||||
AstNode* lsbp = nodep->lsbp()->unlinkFrBack();
|
||||
AstNode* widthp = nodep->widthp()->unlinkFrBack();
|
||||
//
|
||||
AstNode* bilhsp = fromp->lhsp()->unlinkFrBack();
|
||||
//
|
||||
fromp->lhsp(new AstSel(nodep->fileline(),
|
||||
bilhsp, lsbp->cloneTree(true), widthp->cloneTree(true)));
|
||||
fromp->widthSignedFrom(nodep);
|
||||
nodep->replaceWith(fromp); nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
|
||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (!nodep->varp()) nodep->v3fatalSrc("Not linked");
|
||||
@@ -1439,7 +1518,7 @@ private:
|
||||
if (!inPct && ch=='%') {
|
||||
inPct = true;
|
||||
fmt = ch;
|
||||
} else if (inPct && isdigit(ch)) {
|
||||
} else if (inPct && (isdigit(ch) || ch=='.')) {
|
||||
fmt += ch;
|
||||
} else if (inPct) {
|
||||
inPct = false;
|
||||
@@ -1584,7 +1663,7 @@ private:
|
||||
TREEOP ("AstShiftRS{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP ("AstXor {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP ("AstXnor {$lhsp.isZero, $rhsp}", "AstNot{$rhsp}");
|
||||
TREEOP ("AstSub {$lhsp.isZero, $rhsp}", "AstUnaryMin{$rhsp}");
|
||||
TREEOP ("AstSub {$lhsp.isZero, $rhsp}", "AstNegate{$rhsp}");
|
||||
TREEOP ("AstAdd {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||
TREEOP ("AstAnd {$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
|
||||
TREEOP ("AstLogAnd{$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
|
||||
@@ -1684,6 +1763,13 @@ private:
|
||||
TREEOP ("AstShiftL{operandShiftShift(nodep)}", "replaceShiftShift(nodep)");
|
||||
TREEOP ("AstShiftR{operandShiftShift(nodep)}", "replaceShiftShift(nodep)");
|
||||
TREEOP ("AstWordSel{operandWordOOB(nodep)}", "replaceZero(nodep)");
|
||||
// Compress out EXTENDs to appease loop unroller
|
||||
TREEOPV("AstEq {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
|
||||
TREEOPV("AstNeq {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
|
||||
TREEOPV("AstGt {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
|
||||
TREEOPV("AstGte {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
|
||||
TREEOPV("AstLt {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
|
||||
TREEOPV("AstLte {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
|
||||
// Identical operands on both sides
|
||||
// AstLogAnd/AstLogOr already converted to AstAnd/AstOr for these rules
|
||||
// AstAdd->ShiftL(#,1) but uncommon
|
||||
@@ -1696,17 +1782,23 @@ private:
|
||||
TREEOP ("AstXnor {operandsSame($lhsp,,$rhsp)}", "replaceAllOnes(nodep)");
|
||||
TREEOP ("AstXor {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstEq {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); // We let X==X -> 1, although in a true 4-state sim it's X.
|
||||
TREEOP ("AstEqD {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); // We let X==X -> 1, although in a true 4-state sim it's X.
|
||||
TREEOP ("AstEqCase {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstEqWild {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstGt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstGtD {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstGtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstGte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstGteD {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstGteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstLt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstLtD {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstLtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstLte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstLteD {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstLteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstNeq {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstNeqD {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstNeqCase{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstNeqWild{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstLogAnd {operandsSame($lhsp,,$rhsp), $lhsp.width1}", "replaceWLhs(nodep)");
|
||||
@@ -1761,12 +1853,27 @@ private:
|
||||
TREEOPV("AstReplicate{$lhsp, $rhsp.isOne, $lhsp->width()==nodep->width()}", "replaceWLhs(nodep)"); // {1{lhs}}->lhs
|
||||
// Next rule because AUTOINST puts the width of bits in
|
||||
// to pins, even when the widths are exactly the same across the hierarchy.
|
||||
TREEOPV("AstSel{operandSelExtend(nodep)}", "replaceWChild(nodep, nodep->fromp()->castExtend()->lhsp())");
|
||||
TREEOPV("AstSel{operandSelExtend(nodep)}", "DONE");
|
||||
TREEOPV("AstSel{operandSelFull(nodep)}", "replaceWChild(nodep, nodep->fromp())");
|
||||
TREEOPV("AstSel{$fromp.castSel}", "replaceSelSel(nodep)");
|
||||
TREEOPV("AstSel{$fromp.castAdd, operandSelBiLower(nodep)}", "DONE");
|
||||
TREEOPV("AstSel{$fromp.castAnd, operandSelBiLower(nodep)}", "DONE");
|
||||
TREEOPV("AstSel{$fromp.castOr, operandSelBiLower(nodep)}", "DONE");
|
||||
TREEOPV("AstSel{$fromp.castSub, operandSelBiLower(nodep)}", "DONE");
|
||||
TREEOPV("AstSel{$fromp.castXnor,operandSelBiLower(nodep)}", "DONE");
|
||||
TREEOPV("AstSel{$fromp.castXor, operandSelBiLower(nodep)}", "DONE");
|
||||
TREEOPC("AstSel{$fromp.castConst, $lsbp.castConst, $widthp.castConst, }", "replaceConst(nodep)");
|
||||
TREEOPV("AstSel{$fromp.castConcat, $lsbp.castConst, $widthp.castConst, }", "replaceSelConcat(nodep)");
|
||||
TREEOPV("AstSel{$fromp.castReplicate, $lsbp.castConst, $widthp.isOne, }", "replaceSelReplicate(nodep)");
|
||||
// V3Tristate requires selects below BufIf1.
|
||||
// Also do additional operators that are bit-independent, but only definite
|
||||
// win if bit select is a constant (otherwise we may need to compute bit index several times)
|
||||
TREEOPV("AstSel{$fromp.castBufIf1}", "replaceSelIntoBiop(nodep)");
|
||||
TREEOPV("AstSel{$fromp.castNot}", "replaceSelIntoUniop(nodep)");
|
||||
TREEOPV("AstSel{$fromp.castAnd,$lhsp.castConst}", "replaceSelIntoUniop(nodep)");
|
||||
TREEOPV("AstSel{$fromp.castOr,$lhsp.castConst}", "replaceSelIntoUniop(nodep)");
|
||||
TREEOPV("AstSel{$fromp.castXor,$lhsp.castConst}", "replaceSelIntoUniop(nodep)");
|
||||
TREEOPV("AstSel{$fromp.castXnor,$lhsp.castConst}", "replaceSelIntoUniop(nodep)");
|
||||
// Conversions
|
||||
TREEOPV("AstRedXnor{$lhsp}", "AstNot{AstRedXor{$lhsp}}"); // Just eliminate XNOR's
|
||||
TREEOPV("AstLogIf {$lhsp, $rhsp}", "AstLogOr{AstLogNot{$lhsp},$rhsp}");
|
||||
|
||||
@@ -122,6 +122,12 @@ private:
|
||||
nodep->packagep()->user1Inc();
|
||||
}
|
||||
}
|
||||
virtual void visit(AstEnumItemRef* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (nodep->packagep()) {
|
||||
nodep->packagep()->user1Inc();
|
||||
}
|
||||
}
|
||||
virtual void visit(AstVarScope* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
m_vscsp.push_back(nodep);
|
||||
|
||||
+27
-11
@@ -127,6 +127,7 @@ public:
|
||||
nodep->lhsp()->iterateAndNext(*this); puts(", ");
|
||||
} else if (nodep->isWide()
|
||||
&& nodep->lhsp()->castVarRef()
|
||||
&& !nodep->rhsp()->castCMath()
|
||||
&& !nodep->rhsp()->castVarRef()
|
||||
&& !nodep->rhsp()->castArraySel()) {
|
||||
// Wide functions assign into the array directly, don't need separate assign statement
|
||||
@@ -343,13 +344,11 @@ public:
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstFClose* nodep, AstNUser*) {
|
||||
puts("if (");
|
||||
puts("VL_FCLOSE_I(");
|
||||
nodep->filep()->iterateAndNext(*this);
|
||||
puts(") { fclose (VL_CVT_Q_FP(");
|
||||
nodep->filep()->iterateAndNext(*this);
|
||||
puts(")); ");
|
||||
puts("); ");
|
||||
nodep->filep()->iterateAndNext(*this); // For saftey, so user doesn't later WRITE with it.
|
||||
puts("=0; }\n");
|
||||
puts("=0;\n");
|
||||
}
|
||||
virtual void visit(AstFFlush* nodep, AstNUser*) {
|
||||
if (!nodep->filep()) {
|
||||
@@ -357,7 +356,7 @@ public:
|
||||
} else {
|
||||
puts("if (");
|
||||
nodep->filep()->iterateAndNext(*this);
|
||||
puts(") { fflush (VL_CVT_Q_FP(");
|
||||
puts(") { fflush (VL_CVT_I_FP(");
|
||||
nodep->filep()->iterateAndNext(*this);
|
||||
puts(")); }\n");
|
||||
}
|
||||
@@ -475,7 +474,7 @@ public:
|
||||
}
|
||||
visit(nodep->castNodeBiop(), vup);
|
||||
}
|
||||
virtual void visit(AstCast* nodep, AstNUser*) {
|
||||
virtual void visit(AstCCast* nodep, AstNUser*) {
|
||||
// Extending a value of the same word width is just a NOP.
|
||||
if (nodep->size()>VL_WORDSIZE) {
|
||||
puts("(QData)(");
|
||||
@@ -546,6 +545,8 @@ public:
|
||||
ofp()->printf(",0x%08" VL_PRI64 "x", (vluint64_t)(nodep->num().dataWord(word)));
|
||||
}
|
||||
ofp()->printf(",0x%08" VL_PRI64 "x)", (vluint64_t)(nodep->num().dataWord(0)));
|
||||
} else if (nodep->isDouble()) {
|
||||
ofp()->printf("%g", nodep->num().toDouble());
|
||||
} else if (nodep->isQuad()) {
|
||||
vluint64_t num = nodep->toUQuad();
|
||||
if (num<10) ofp()->printf("VL_ULL(%" VL_PRI64 "d)", num);
|
||||
@@ -1211,6 +1212,7 @@ void EmitCStmts::displayNode(AstNode* nodep, AstScopeName* scopenamep,
|
||||
switch (tolower(pos[0])) {
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
case '.':
|
||||
// Digits, like %5d, etc.
|
||||
vfmt += pos[0];
|
||||
inPct = true; // Get more digits
|
||||
@@ -1229,6 +1231,9 @@ void EmitCStmts::displayNode(AstNode* nodep, AstScopeName* scopenamep,
|
||||
case 'h':
|
||||
case 'x': displayArg(nodep,&elistp,isScan, vfmt,'x'); break;
|
||||
case 's': displayArg(nodep,&elistp,isScan, vfmt,'s'); break;
|
||||
case 'e': displayArg(nodep,&elistp,isScan, vfmt,'e'); break;
|
||||
case 'f': displayArg(nodep,&elistp,isScan, vfmt,'f'); break;
|
||||
case 'g': displayArg(nodep,&elistp,isScan, vfmt,'g'); break;
|
||||
case 'm': {
|
||||
if (!scopenamep) nodep->v3fatalSrc("Display with %m but no AstScopeName");
|
||||
string suffix = scopenamep->scopePrettyName();
|
||||
@@ -1619,7 +1624,12 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
|
||||
if (v3Global.needHInlines()) { // Set by V3EmitCInlines; should have been called before us
|
||||
puts("#include \""+topClassName()+"__Inlines.h\"\n");
|
||||
}
|
||||
// No __Dpi.h needed, we've shimmed it all into the interface
|
||||
if (v3Global.dpi()) {
|
||||
// do this before including our main .h file so that any references to
|
||||
// types defined in svdpi.h are available
|
||||
puts("#include \""+ topClassName() +"__Dpi.h\"\n");
|
||||
puts("\n");
|
||||
}
|
||||
|
||||
// Declare foreign instances up front to make C++ happy
|
||||
puts("class "+symClassName()+";\n");
|
||||
@@ -1797,8 +1807,10 @@ void EmitCImp::emitImp(AstNodeModule* modp) {
|
||||
|
||||
// Us
|
||||
puts("#include \""+ symClassName() +".h\"\n");
|
||||
|
||||
if (v3Global.dpi()) {
|
||||
puts("#include \""+ topClassName() +"__Dpi.h\"\n");
|
||||
puts("\n");
|
||||
puts("#include \"verilated_dpi.h\"\n");
|
||||
}
|
||||
|
||||
if (optSystemPerl() && (splitFilenum() || !m_fast)) {
|
||||
@@ -2003,7 +2015,9 @@ class EmitCTrace : EmitCStmts {
|
||||
return varp->isSc() && varp->isScBv();
|
||||
}
|
||||
void emitTraceInitOne(AstTraceDecl* nodep) {
|
||||
if (nodep->isWide()) {
|
||||
if (nodep->isDouble()) {
|
||||
puts("vcdp->declDouble");
|
||||
} else if (nodep->isWide()) {
|
||||
puts("vcdp->declArray");
|
||||
} else if (nodep->isQuad()) {
|
||||
puts("vcdp->declQuad ");
|
||||
@@ -2032,7 +2046,9 @@ class EmitCTrace : EmitCStmts {
|
||||
string full = ((m_funcp->funcType() == AstCFuncType::TRACE_FULL
|
||||
|| m_funcp->funcType() == AstCFuncType::TRACE_FULL_SUB)
|
||||
? "full":"chg");
|
||||
if (nodep->isWide() || emitTraceIsScBv(nodep)) {
|
||||
if (nodep->isDouble()) {
|
||||
puts("vcdp->"+full+"Double");
|
||||
} else if (nodep->isWide() || emitTraceIsScBv(nodep)) {
|
||||
puts("vcdp->"+full+"Array");
|
||||
} else if (nodep->isQuad()) {
|
||||
puts("vcdp->"+full+"Quad ");
|
||||
|
||||
@@ -519,6 +519,8 @@ void EmitCSyms::emitDpiHdr() {
|
||||
puts("// Manually include this file where DPI .c import functions are declared to insure\n");
|
||||
puts("// the C functions match the expectations of the DPI imports.\n");
|
||||
puts("\n");
|
||||
puts("#include \"svdpi.h\"\n");
|
||||
puts("\n");
|
||||
puts("#ifdef __cplusplus\n");
|
||||
puts("extern \"C\" {\n");
|
||||
puts("#endif\n");
|
||||
|
||||
+9
-4
@@ -84,10 +84,15 @@ public:
|
||||
if (v3Global.opt.systemPerl()) {
|
||||
putMakeClassEntry(of, "Sp.cpp"); // Note Sp.cpp includes SpTraceVcdC
|
||||
}
|
||||
else if (v3Global.opt.trace()) {
|
||||
putMakeClassEntry(of, "verilated_vcd_c.cpp");
|
||||
if (v3Global.opt.systemC()) {
|
||||
putMakeClassEntry(of, "verilated_vcd_sc.cpp");
|
||||
else {
|
||||
if (v3Global.opt.coverage()) {
|
||||
putMakeClassEntry(of, "SpCoverage.cpp");
|
||||
}
|
||||
if (v3Global.opt.trace()) {
|
||||
putMakeClassEntry(of, "verilated_vcd_c.cpp");
|
||||
if (v3Global.opt.systemC()) {
|
||||
putMakeClassEntry(of, "verilated_vcd_sc.cpp");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,6 +217,9 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
||||
}
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstDisable* nodep, AstNUser*) {
|
||||
putbs("disable "+nodep->name()+";\n");
|
||||
}
|
||||
virtual void visit(AstDisplay* nodep, AstNUser*) {
|
||||
visitNodeDisplay(nodep, nodep->filep(), nodep->fmtp()->text(), nodep->fmtp()->exprsp());
|
||||
}
|
||||
@@ -480,6 +483,10 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
||||
putfs(nodep,nodep->prettyName());
|
||||
if (nodep->rangep()) { puts(" "); nodep->rangep()->iterateAndNext(*this); puts(" "); }
|
||||
}
|
||||
virtual void visit(AstConstDType* nodep, AstNUser*) {
|
||||
putfs(nodep,"const ");
|
||||
nodep->dtypep()->iterateAndNext(*this);
|
||||
}
|
||||
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
|
||||
if (nodep->dotted()!="") { putfs(nodep,nodep->dotted()); puts("."); puts(nodep->prettyName()); }
|
||||
else { putfs(nodep,nodep->prettyName()); }
|
||||
|
||||
+1
-1
@@ -309,7 +309,7 @@ void V3Error::abortIfErrors() {
|
||||
}
|
||||
|
||||
void V3Error::abortIfWarnings() {
|
||||
if (errorOrWarnCount()) {
|
||||
if (v3Global.opt.warnFatal() ? errorOrWarnCount() : errorCount()) {
|
||||
v3fatal ("Exiting due to "<<dec<<errorOrWarnCount()<<" warning(s)\n");
|
||||
}
|
||||
}
|
||||
|
||||
+3
-1
@@ -73,6 +73,7 @@ public:
|
||||
LITENDIAN, // Little bit endian vector
|
||||
MODDUP, // Duplicate module
|
||||
MULTIDRIVEN, // Driven from multiple blocks
|
||||
REALCVT, // Real conversion
|
||||
REDEFMACRO, // Redefining existing define macro
|
||||
STMTDLY, // Delayed statement
|
||||
SYMRSVDWORD, // Symbol is Reserved Word
|
||||
@@ -111,7 +112,7 @@ public:
|
||||
"IFDEPTH", "IMPERFECTSCH", "IMPLICIT", "IMPURE", "INCABSPATH",
|
||||
"LITENDIAN", "MODDUP",
|
||||
"MULTIDRIVEN",
|
||||
"REDEFMACRO",
|
||||
"REALCVT", "REDEFMACRO",
|
||||
"STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET",
|
||||
"UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNSIGNED", "UNUSED",
|
||||
"VARHIDDEN", "WIDTH", "WIDTHCONCAT",
|
||||
@@ -135,6 +136,7 @@ public:
|
||||
|| m_e==CMPCONST
|
||||
|| m_e==IMPLICIT
|
||||
|| m_e==LITENDIAN
|
||||
|| m_e==REALCVT
|
||||
|| m_e==UNSIGNED
|
||||
|| m_e==WIDTH); }
|
||||
// Warnings that are style only
|
||||
|
||||
+22
-23
@@ -127,18 +127,18 @@ private:
|
||||
} else if (nodep->isQuad() && word==0) {
|
||||
AstNode* quadfromp = nodep->cloneTree(true);
|
||||
quadfromp->width(VL_QUADSIZE,quadfromp->widthMin());
|
||||
return new AstCast (nodep->fileline(),
|
||||
quadfromp,
|
||||
VL_WORDSIZE);
|
||||
return new AstCCast (nodep->fileline(),
|
||||
quadfromp,
|
||||
VL_WORDSIZE);
|
||||
} else if (nodep->isQuad() && word==1) {
|
||||
AstNode* quadfromp = nodep->cloneTree(true);
|
||||
quadfromp->width(VL_QUADSIZE,quadfromp->widthMin());
|
||||
return new AstCast (nodep->fileline(),
|
||||
new AstShiftR (nodep->fileline(),
|
||||
quadfromp,
|
||||
new AstConst (nodep->fileline(), VL_WORDSIZE),
|
||||
VL_WORDSIZE),
|
||||
VL_WORDSIZE);
|
||||
return new AstCCast (nodep->fileline(),
|
||||
new AstShiftR (nodep->fileline(),
|
||||
quadfromp,
|
||||
new AstConst (nodep->fileline(), VL_WORDSIZE),
|
||||
VL_WORDSIZE),
|
||||
VL_WORDSIZE);
|
||||
} else if (!nodep->isWide() && !nodep->isQuad() && word==0) {
|
||||
return nodep->cloneTree(true);
|
||||
} else { // Out of bounds
|
||||
@@ -324,7 +324,7 @@ private:
|
||||
nodep->v3fatalSrc("extending larger thing into smaller?");
|
||||
} else {
|
||||
UINFO(8," EXTEND(q<-l) "<<nodep<<endl);
|
||||
newp = new AstCast (nodep->fileline(), lhsp, nodep);
|
||||
newp = new AstCCast (nodep->fileline(), lhsp, nodep);
|
||||
}
|
||||
} else { // Long
|
||||
if (lhsp->isQuad() || lhsp->isWide()) {
|
||||
@@ -366,7 +366,7 @@ private:
|
||||
AstNode* lowwordp = new AstWordSel (nodep->fromp()->fileline(),
|
||||
nodep->fromp()->cloneTree(true),
|
||||
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(),
|
||||
lowwordp,
|
||||
newSelBitBit(nodep->lsbp()),
|
||||
@@ -379,7 +379,7 @@ private:
|
||||
new AstWordSel (nodep->fromp()->fileline(),
|
||||
nodep->fromp()->cloneTree(true),
|
||||
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
|
||||
// else we need to form the lower word, so we << by 31 or less
|
||||
// nbitsfromlow <= (lsb==0) ? 64-bitbit(lsb) : 32-bitbit(lsb)
|
||||
@@ -417,7 +417,7 @@ private:
|
||||
new AstWordSel (nodep->fromp()->fileline(),
|
||||
nodep->fromp()->cloneTree(true),
|
||||
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 =
|
||||
new AstShiftL (nodep->fileline(),
|
||||
hiwordp,
|
||||
@@ -445,14 +445,14 @@ private:
|
||||
UINFO(8," SEL->SHIFT "<<nodep<<endl);
|
||||
AstNode* fromp = nodep->fromp()->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(),
|
||||
fromp,
|
||||
dropCondBound(lsbp),
|
||||
nodep->width());
|
||||
newp->widthSignedFrom(nodep);
|
||||
if (!nodep->isQuad() && fromp->isQuad()) {
|
||||
newp = new AstCast (newp->fileline(), newp, nodep);
|
||||
newp = new AstCCast (newp->fileline(), newp, nodep);
|
||||
}
|
||||
newp->widthSignedFrom(nodep);
|
||||
replaceWithDelete(nodep,newp); nodep=NULL;
|
||||
@@ -546,7 +546,7 @@ private:
|
||||
destp->deleteTree(); destp=NULL;
|
||||
} else {
|
||||
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);
|
||||
fixCloneLvalue(oldvalp);
|
||||
if (!ones) oldvalp = new AstAnd (lhsp->fileline(),
|
||||
@@ -620,7 +620,7 @@ private:
|
||||
V3Number maskwidth (nodep->fileline(), destp->widthMin());
|
||||
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)
|
||||
oldvalp = new AstAnd (lhsp->fileline(),
|
||||
new AstNot (lhsp->fileline(),
|
||||
@@ -655,8 +655,8 @@ private:
|
||||
AstNode* lhsp = nodep->lhsp()->unlinkFrBack();
|
||||
AstNode* rhsp = nodep->rhsp()->unlinkFrBack();
|
||||
int rhsshift = rhsp->widthMin();
|
||||
if (nodep->isQuad() && !lhsp->isQuad()) lhsp = new AstCast(nodep->fileline(), lhsp, nodep);
|
||||
if (nodep->isQuad() && !rhsp->isQuad()) rhsp = new AstCast(nodep->fileline(), rhsp, nodep);
|
||||
if (nodep->isQuad() && !lhsp->isQuad()) lhsp = new AstCCast(nodep->fileline(), lhsp, nodep);
|
||||
if (nodep->isQuad() && !rhsp->isQuad()) rhsp = new AstCCast(nodep->fileline(), rhsp, nodep);
|
||||
AstNode* newp = new AstOr (nodep->fileline(),
|
||||
new AstShiftL (nodep->fileline(),
|
||||
lhsp,
|
||||
@@ -696,14 +696,13 @@ private:
|
||||
int lhswidth = lhsp->widthMin();
|
||||
if (lhswidth==1) {
|
||||
UINFO(8," REPLICATE(w1) "<<nodep<<endl);
|
||||
newp = new AstUnaryMin (nodep->fileline(),
|
||||
lhsp);
|
||||
newp = new AstNegate (nodep->fileline(), lhsp);
|
||||
} else {
|
||||
UINFO(8," REPLICATE "<<nodep<<endl);
|
||||
AstConst* constp = nodep->rhsp()->castConst();
|
||||
if (!constp) nodep->v3fatalSrc("Replication value isn't a constant. Checked earlier!");
|
||||
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);
|
||||
for (unsigned repnum=1; repnum<times; repnum++) {
|
||||
int rhsshift = repnum*lhswidth;
|
||||
@@ -731,7 +730,7 @@ private:
|
||||
for (int w=0; w<rhsp->widthWords(); w++) {
|
||||
AstNode* newp;
|
||||
if (lhswidth==1) {
|
||||
newp = new AstUnaryMin (nodep->fileline(), lhsp->cloneTree(true));
|
||||
newp = new AstNegate (nodep->fileline(), lhsp->cloneTree(true));
|
||||
newp->width(VL_WORDSIZE,VL_WORDSIZE);
|
||||
} else {
|
||||
newp = newAstWordSelClone (lhsp, w);
|
||||
|
||||
+1
-1
@@ -184,7 +184,7 @@ private:
|
||||
// user2p is either a const or a var.
|
||||
AstConst* exprconstp = nodep->user2p()->castNode()->castConst();
|
||||
AstVarRef* exprvarrefp = nodep->user2p()->castNode()->castVarRef();
|
||||
UINFO(1,"connectto: "<<nodep->user2p()->castNode()<<endl);
|
||||
UINFO(8,"connectto: "<<nodep->user2p()->castNode()<<endl);
|
||||
if (!exprconstp && !exprvarrefp) {
|
||||
nodep->v3fatalSrc("Unknown interconnect type; pinReconnectSimple should have cleared up\n");
|
||||
}
|
||||
|
||||
+2
-2
@@ -134,7 +134,7 @@ private:
|
||||
nodep->packagep(packageFor(varp));
|
||||
}
|
||||
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->deleteTree(); nodep=NULL;
|
||||
return true; // Edited
|
||||
@@ -428,7 +428,7 @@ private:
|
||||
if (dtypep) dtypep->unlinkFrBack();
|
||||
else dtypep = new AstBasicDType(nodep->fileline(), AstBasicDTypeKwd::LOGIC);
|
||||
AstVar* newvarp = new AstVar(nodep->fileline(), AstVarType::OUTPUT, nodep->name(), dtypep);
|
||||
newvarp->isSigned(nodep->isSigned());
|
||||
if (nodep->isSigned()) newvarp->numeric(AstNumeric::SIGNED);
|
||||
newvarp->funcReturn(true);
|
||||
newvarp->trace(false); // Not user visible
|
||||
newvarp->attrIsolateAssign(nodep->attrIsolateAssign());
|
||||
|
||||
+24
-3
@@ -135,8 +135,8 @@ private:
|
||||
// Spec says value is integral, if negative is ignored
|
||||
AstVar* varp = new AstVar(nodep->fileline(), AstVarType::BLOCKTEMP, name,
|
||||
AstLogicPacked(), 32);
|
||||
varp->isSigned(true);
|
||||
varp->dtypep()->isSigned(true);
|
||||
varp->numeric(AstNumeric::SIGNED);
|
||||
varp->dtypep()->numeric(AstNumeric::SIGNED);
|
||||
varp->usedLoopIdx(true);
|
||||
m_modp->addStmtp(varp);
|
||||
AstNode* initsp = new AstAssign(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, true),
|
||||
@@ -144,7 +144,7 @@ private:
|
||||
AstNode* decp = new AstAssign(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, true),
|
||||
new AstSub(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false),
|
||||
new AstConst(nodep->fileline(), 1)));
|
||||
AstNode* zerosp = new AstConst(nodep->fileline(), 0); zerosp->isSigned(true);
|
||||
AstNode* zerosp = new AstConst(nodep->fileline(), 0); zerosp->numeric(AstNumeric::SIGNED);
|
||||
AstNode* condp = new AstGtS(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false),
|
||||
zerosp);
|
||||
AstNode* bodysp = nodep->bodysp(); if (bodysp) bodysp->unlinkFrBackWithNext();
|
||||
@@ -211,6 +211,27 @@ private:
|
||||
}
|
||||
nodep->unlinkFrBack(); pushDeletep(nodep); nodep=NULL;
|
||||
}
|
||||
virtual void visit(AstDisable* nodep, AstNUser*) {
|
||||
UINFO(8," DISABLE "<<nodep<<endl);
|
||||
nodep->iterateChildren(*this);
|
||||
AstBegin* beginp = NULL;
|
||||
for (BeginStack::reverse_iterator it = m_beginStack.rbegin(); it != m_beginStack.rend(); ++it) {
|
||||
UINFO(9," UNDERBLK "<<*it<<endl);
|
||||
if ((*it)->name() == nodep->name()) {
|
||||
beginp = *it;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//if (debug()>=9) { UINFO(0,"\n"); beginp->dumpTree(cout," labeli: "); }
|
||||
if (!beginp) { nodep->v3error("disable isn't underneath a begin with name: "<<nodep->name()); }
|
||||
else {
|
||||
// Jump to the end of the named begin
|
||||
AstJumpLabel* labelp = findAddLabel(beginp, false);
|
||||
nodep->addNextHere(new AstJumpGo(nodep->fileline(), labelp));
|
||||
}
|
||||
nodep->unlinkFrBack(); pushDeletep(nodep); nodep=NULL;
|
||||
//if (debug()>=9) { UINFO(0,"\n"); beginp->dumpTree(cout," labelo: "); }
|
||||
}
|
||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||
if (m_loopInc && nodep->varp()) nodep->varp()->usedLoopIdx(true);
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ private:
|
||||
|
||||
// STATE
|
||||
bool m_setRefLvalue; // Set VarRefs to lvalues for pin assignments
|
||||
AstInitial* m_initialp; // In an initial block
|
||||
AstNodeFTask* m_ftaskp; // Function or task we're inside
|
||||
|
||||
// METHODS
|
||||
@@ -67,6 +68,10 @@ private:
|
||||
nodep->v3error("Assigning to input variable: "<<nodep->prettyName());
|
||||
}
|
||||
}
|
||||
if (nodep->lvalue() && nodep->varp()->isConst()
|
||||
&& !m_initialp) { // Too loose, but need to allow our generated first assignment
|
||||
nodep->v3error("Assigning to const variable: "<<nodep->prettyName());
|
||||
}
|
||||
}
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
@@ -222,6 +227,11 @@ private:
|
||||
}
|
||||
m_setRefLvalue = last_setRefLvalue;
|
||||
}
|
||||
virtual void visit(AstInitial* nodep, AstNUser*) {
|
||||
m_initialp = nodep;
|
||||
nodep->iterateChildren(*this);
|
||||
m_initialp = NULL;
|
||||
}
|
||||
virtual void visit(AstNodeFTask* nodep, AstNUser*) {
|
||||
m_ftaskp = nodep;
|
||||
nodep->iterateChildren(*this);
|
||||
@@ -259,6 +269,7 @@ public:
|
||||
LinkLValueVisitor(AstNode* nodep, bool start) {
|
||||
m_setRefLvalue = start;
|
||||
m_ftaskp = NULL;
|
||||
m_initialp = NULL;
|
||||
nodep->accept(*this);
|
||||
}
|
||||
virtual ~LinkLValueVisitor() {}
|
||||
|
||||
@@ -95,6 +95,9 @@ private:
|
||||
nodep->dtypeSkipRefp()->castArrayDType())) {
|
||||
nodep->v3error("Unsupported: Inputs and outputs must be simple data types");
|
||||
}
|
||||
if (nodep->dtypeSkipRefp()->castConstDType()) {
|
||||
nodep->isConst(true);
|
||||
}
|
||||
if (m_ftaskp) nodep->funcLocal(true);
|
||||
if (nodep->isSigModPublic()) {
|
||||
nodep->sigModPublic(false); // We're done with this attribute
|
||||
@@ -254,6 +257,7 @@ private:
|
||||
switch (tolower(ch)) {
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
case '.':
|
||||
inPct = true;
|
||||
break;
|
||||
case '%': break; // %% - just output a %
|
||||
|
||||
+189
-19
@@ -27,6 +27,8 @@
|
||||
#include <algorithm>
|
||||
#include "V3Number.h"
|
||||
|
||||
#define MAX_SPRINTF_DOUBLE_SIZE 100 // Maximum characters with a sprintf %e/%f/%g (probably < 30)
|
||||
|
||||
//######################################################################
|
||||
// Read class functions
|
||||
// CREATION
|
||||
@@ -44,6 +46,7 @@ void V3Number::width(int width, bool sized) {
|
||||
void V3Number::init (FileLine* fileline, int swidth) {
|
||||
m_fileline = fileline;
|
||||
m_signed = false;
|
||||
m_double = false;
|
||||
m_autoExtend = false;
|
||||
m_fromString = false;
|
||||
width(swidth);
|
||||
@@ -298,6 +301,24 @@ V3Number& V3Number::setLong(uint32_t value) {
|
||||
m_value[0] = value;
|
||||
return *this;
|
||||
}
|
||||
V3Number& V3Number::setLongS(vlsint32_t value) {
|
||||
for (int i=0; i<words(); i++) m_value[i]=m_valueX[i] = 0;
|
||||
union { uint32_t u; vlsint32_t s; } u;
|
||||
u.s = value;
|
||||
m_value[0] = u.u;
|
||||
return *this;
|
||||
}
|
||||
V3Number& V3Number::setDouble(double value) {
|
||||
if (VL_UNLIKELY(width()!=64)) {
|
||||
m_fileline->v3fatalSrc("Real operation on wrong sized number");
|
||||
}
|
||||
m_double = true;
|
||||
union { double d; uint32_t u[2]; } u;
|
||||
u.d = value;
|
||||
for (int i=2; i<words(); i++) m_value[i]=m_valueX[i] = 0;
|
||||
m_value[0] = u.u[0]; m_value[1] = u.u[1];
|
||||
return *this;
|
||||
}
|
||||
V3Number& V3Number::setSingleBits(char value) {
|
||||
for (int i=1/*upper*/; i<words(); i++) m_value[i]=m_valueX[i] = 0;
|
||||
m_value[0] = (value=='1'||value=='x'||value==1||value==3);
|
||||
@@ -306,12 +327,12 @@ V3Number& V3Number::setSingleBits(char value) {
|
||||
}
|
||||
|
||||
V3Number& V3Number::setAllBits0() {
|
||||
for (int i=0; i<words(); i++) { m_value[i] = m_valueX[i]=0; }
|
||||
return *this;
|
||||
for (int i=0; i<words(); i++) { m_value[i] = m_valueX[i]=0; }
|
||||
return *this;
|
||||
}
|
||||
V3Number& V3Number::setAllBits1() {
|
||||
for (int i=0; i<words(); i++) { m_value[i]= ~0; m_valueX[i] = 0; }
|
||||
return *this;
|
||||
for (int i=0; i<words(); i++) { m_value[i]= ~0; m_valueX[i] = 0; }
|
||||
return *this;
|
||||
}
|
||||
V3Number& V3Number::setAllBitsX() {
|
||||
for (int i=0; i<words(); i++) { m_value[i]=m_valueX[i] = ~0; }
|
||||
@@ -333,6 +354,10 @@ V3Number& V3Number::setMask(int nbits) {
|
||||
string V3Number::ascii(bool prefixed, bool cleanVerilog) const {
|
||||
ostringstream out;
|
||||
|
||||
if (isDouble()) {
|
||||
out<<toDouble();
|
||||
return out.str();
|
||||
}
|
||||
if (prefixed) {
|
||||
if (sized()) {
|
||||
out<<width()<<"'";
|
||||
@@ -375,6 +400,9 @@ bool V3Number::displayedFmtLegal(char format) {
|
||||
case 'b': return true;
|
||||
case 'c': return true;
|
||||
case 'd': return true; // Unsigned decimal
|
||||
case 'e': return true;
|
||||
case 'f': return true;
|
||||
case 'g': return true;
|
||||
case 'h': return true;
|
||||
case 'o': return true;
|
||||
case 's': return true;
|
||||
@@ -390,7 +418,7 @@ string V3Number::displayed(const string& vformat) const {
|
||||
UASSERT(pos != vformat.end() && pos[0]=='%', "display with non format argument "<<*this);
|
||||
pos++;
|
||||
string fmtsize;
|
||||
for (; pos != vformat.end() && isdigit(pos[0]); pos++) {
|
||||
for (; pos != vformat.end() && (isdigit(pos[0]) || pos[0]=='.'); pos++) {
|
||||
fmtsize += pos[0];
|
||||
}
|
||||
string str;
|
||||
@@ -472,9 +500,20 @@ string V3Number::displayed(const string& vformat) const {
|
||||
str = cvtToStr(toUQuad());
|
||||
}
|
||||
int intfmtsize = atoi(fmtsize.c_str());
|
||||
while ((int)(str.length()) < intfmtsize) str = " "+str;
|
||||
bool zeropad = fmtsize.length()>0 && fmtsize[0]=='0';
|
||||
while ((int)(str.length()) < intfmtsize) {
|
||||
if (zeropad) str = "0"+str;
|
||||
else str = " "+str;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
case 'e':
|
||||
case 'f':
|
||||
case 'g': {
|
||||
char tmp[MAX_SPRINTF_DOUBLE_SIZE];
|
||||
sprintf(tmp, vformat.c_str(), toDouble());
|
||||
return tmp;
|
||||
}
|
||||
default:
|
||||
m_fileline->v3fatalSrc("Unknown $display format code for number: %"<<pos[0]);
|
||||
return "ERR";
|
||||
@@ -490,6 +529,18 @@ uint32_t V3Number::toUInt() const {
|
||||
return m_value[0];
|
||||
}
|
||||
|
||||
double V3Number::toDouble() const {
|
||||
if (VL_UNLIKELY(!isDouble())) {
|
||||
m_fileline->v3fatalSrc("Real conversion on non real number");
|
||||
}
|
||||
if (VL_UNLIKELY(width()!=64)) {
|
||||
m_fileline->v3fatalSrc("Real operation on wrong sized number");
|
||||
}
|
||||
union { double d; uint32_t u[2]; } u;
|
||||
u.u[0] = m_value[0]; u.u[1] = m_value[1];
|
||||
return u.d;
|
||||
}
|
||||
|
||||
vlsint32_t V3Number::toSInt() const {
|
||||
if (isSigned()) {
|
||||
uint32_t v = toUInt();
|
||||
@@ -555,6 +606,12 @@ bool V3Number::isNeqZero() const {
|
||||
}
|
||||
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 {
|
||||
if (m_value[0]!=1 || m_valueX[0]) return false;
|
||||
for (int i=1; i<words(); i++) {
|
||||
@@ -1005,6 +1062,30 @@ V3Number& V3Number::opLteS (const V3Number& lhs, const V3Number& rhs) {
|
||||
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) {
|
||||
// L(lhs) bit return
|
||||
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) {
|
||||
// L(lhs) bit return
|
||||
// The spec says a unsigned >>> still acts as a normal >>.
|
||||
// We presume it is signed; as that's V3Signed's job to convert to opShiftR
|
||||
// We presume it is signed; as that's V3Width's job to convert to opShiftR
|
||||
if (rhs.isFourState()) return setAllBitsX();
|
||||
setZero();
|
||||
uint32_t rhsval = rhs.toUInt();
|
||||
@@ -1032,8 +1113,8 @@ V3Number& V3Number::opShiftRS (const V3Number& lhs, const V3Number& rhs) {
|
||||
V3Number& V3Number::opShiftL (const V3Number& lhs, const V3Number& rhs) {
|
||||
// L(lhs) bit return
|
||||
if (rhs.isFourState()) return setAllBitsX();
|
||||
uint32_t rhsval = rhs.toUInt();
|
||||
setZero();
|
||||
uint32_t rhsval = rhs.toUInt();
|
||||
for (int bit=0; bit<this->width(); bit++) {
|
||||
if (bit >= (int)rhsval) {
|
||||
setBit(bit,lhs.bitIs(bit - rhsval));
|
||||
@@ -1045,7 +1126,16 @@ V3Number& V3Number::opShiftL (const V3Number& lhs, const V3Number& rhs) {
|
||||
//======================================================================
|
||||
// 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
|
||||
if (lhs.isFourState()) return setAllBitsX();
|
||||
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
|
||||
if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX();
|
||||
V3Number negrhs (rhs.m_fileline, rhs.width());
|
||||
negrhs.opUnaryMin(rhs);
|
||||
negrhs.opNegate(rhs);
|
||||
return opAdd(lhs, negrhs);
|
||||
}
|
||||
V3Number& V3Number::opMul (const V3Number& lhs, const V3Number& rhs) {
|
||||
@@ -1101,12 +1191,12 @@ V3Number& V3Number::opMul (const V3Number& lhs, const V3Number& rhs) {
|
||||
V3Number& V3Number::opMulS (const V3Number& lhs, const V3Number& rhs) {
|
||||
// Signed multiply
|
||||
if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX();
|
||||
V3Number lhsNoSign = lhs; if (lhs.isNegative()) lhsNoSign.opUnaryMin(lhs);
|
||||
V3Number rhsNoSign = rhs; if (rhs.isNegative()) rhsNoSign.opUnaryMin(rhs);
|
||||
V3Number lhsNoSign = lhs; if (lhs.isNegative()) lhsNoSign.opNegate(lhs);
|
||||
V3Number rhsNoSign = rhs; if (rhs.isNegative()) rhsNoSign.opNegate(rhs);
|
||||
V3Number qNoSign = opMul(lhsNoSign,rhsNoSign);
|
||||
if ((lhs.isNegative() && !rhs.isNegative())
|
||||
|| (!lhs.isNegative() && rhs.isNegative())) {
|
||||
opUnaryMin(qNoSign);
|
||||
opNegate(qNoSign);
|
||||
} else {
|
||||
opAssign(qNoSign);
|
||||
}
|
||||
@@ -1130,13 +1220,13 @@ V3Number& V3Number::opDivS (const V3Number& lhs, const V3Number& rhs) {
|
||||
//UINFO(9, ">>divs-start "<<lhs<<" "<<rhs<<endl);
|
||||
if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX();
|
||||
if (rhs.isEqZero()) return setAllBitsX();
|
||||
V3Number lhsNoSign = lhs; if (lhs.isNegative()) lhsNoSign.opUnaryMin(lhs);
|
||||
V3Number rhsNoSign = rhs; if (rhs.isNegative()) rhsNoSign.opUnaryMin(rhs);
|
||||
V3Number lhsNoSign = lhs; if (lhs.isNegative()) lhsNoSign.opNegate(lhs);
|
||||
V3Number rhsNoSign = rhs; if (rhs.isNegative()) rhsNoSign.opNegate(rhs);
|
||||
V3Number qNoSign = opDiv(lhsNoSign,rhsNoSign);
|
||||
//UINFO(9, " >divs-mid "<<lhs<<" "<<rhs<<" "<<qNoSign<<endl);
|
||||
if ((lhs.isNegative() && !rhs.isNegative())
|
||||
|| (!lhs.isNegative() && rhs.isNegative())) {
|
||||
opUnaryMin(qNoSign);
|
||||
opNegate(qNoSign);
|
||||
} else {
|
||||
opAssign(qNoSign);
|
||||
}
|
||||
@@ -1159,11 +1249,11 @@ V3Number& V3Number::opModDivS (const V3Number& lhs, const V3Number& rhs) {
|
||||
// Signed moddiv
|
||||
if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX();
|
||||
if (rhs.isEqZero()) return setAllBitsX();
|
||||
V3Number lhsNoSign = lhs; if (lhs.isNegative()) lhsNoSign.opUnaryMin(lhs);
|
||||
V3Number rhsNoSign = rhs; if (rhs.isNegative()) rhsNoSign.opUnaryMin(rhs);
|
||||
V3Number lhsNoSign = lhs; if (lhs.isNegative()) lhsNoSign.opNegate(lhs);
|
||||
V3Number rhsNoSign = rhs; if (rhs.isNegative()) rhsNoSign.opNegate(rhs);
|
||||
V3Number qNoSign = opModDiv(lhsNoSign,rhsNoSign);
|
||||
if (lhs.isNegative()) { // Just lhs' sign (*DIFFERENT FROM PERL, which uses rhs sign*)
|
||||
opUnaryMin(qNoSign);
|
||||
opNegate(qNoSign);
|
||||
} else {
|
||||
opAssign(qNoSign);
|
||||
}
|
||||
@@ -1318,6 +1408,15 @@ V3Number& V3Number::opPowS (const V3Number& lhs, const V3Number& rhs) {
|
||||
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) {
|
||||
// Note may be a width change during the assign
|
||||
setZero();
|
||||
@@ -1386,3 +1485,74 @@ V3Number& V3Number::opCond (const V3Number& lhs, const V3Number& if1s, const V3
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// Ops - Floating point
|
||||
|
||||
V3Number& V3Number::opIToRD (const V3Number& lhs) {
|
||||
return setDouble(lhs.toSInt());
|
||||
}
|
||||
V3Number& V3Number::opRToIS (const V3Number& lhs) {
|
||||
double v = trunc(lhs.toDouble());
|
||||
vlsint32_t i = (vlsint32_t)v; // C converts from double to vlsint32
|
||||
return setLongS(i);
|
||||
}
|
||||
V3Number& V3Number::opRToIRoundS (const V3Number& lhs) {
|
||||
double v = round(lhs.toDouble());
|
||||
vlsint32_t i = (vlsint32_t)v; // C converts from double to vlsint32
|
||||
return setLongS(i);
|
||||
}
|
||||
V3Number& V3Number::opRealToBits (const V3Number& lhs) {
|
||||
// Conveniently our internal format is identical so we can copy bits...
|
||||
if (lhs.width()!=64 || this->width()!=64) {
|
||||
m_fileline->v3fatalSrc("Real operation on wrong sized number");
|
||||
}
|
||||
return opAssign(lhs);
|
||||
}
|
||||
V3Number& V3Number::opBitsToRealD (const V3Number& lhs) {
|
||||
// Conveniently our internal format is identical so we can copy bits...
|
||||
if (lhs.width()!=64 || this->width()!=64) {
|
||||
m_fileline->v3fatalSrc("Real operation on wrong sized number");
|
||||
}
|
||||
return opAssign(lhs);
|
||||
}
|
||||
V3Number& V3Number::opNegateD (const V3Number& lhs) {
|
||||
return setDouble(- lhs.toDouble());
|
||||
}
|
||||
V3Number& V3Number::opAddD (const V3Number& lhs, const V3Number& rhs) {
|
||||
return setDouble(lhs.toDouble() + rhs.toDouble());
|
||||
}
|
||||
V3Number& V3Number::opSubD (const V3Number& lhs, const V3Number& rhs) {
|
||||
return setDouble(lhs.toDouble() - rhs.toDouble());
|
||||
}
|
||||
V3Number& V3Number::opMulD (const V3Number& lhs, const V3Number& rhs) {
|
||||
return setDouble(lhs.toDouble() * rhs.toDouble());
|
||||
}
|
||||
V3Number& V3Number::opDivD (const V3Number& lhs, const V3Number& rhs) {
|
||||
// On exceptions, we just generate 'inf' through floating point
|
||||
// IEEE says it's implementation defined what happens
|
||||
return setDouble(lhs.toDouble() / rhs.toDouble());
|
||||
}
|
||||
V3Number& V3Number::opPowD (const V3Number& lhs, const V3Number& rhs) {
|
||||
// On exceptions, we just generate 'inf' through floating point
|
||||
// IEEE says it's implementation defined what happens
|
||||
return setDouble(pow(lhs.toDouble(), rhs.toDouble()));
|
||||
}
|
||||
V3Number& V3Number::opEqD (const V3Number& lhs, const V3Number& rhs) {
|
||||
return setSingleBits(lhs.toDouble() == rhs.toDouble());
|
||||
}
|
||||
V3Number& V3Number::opNeqD (const V3Number& lhs, const V3Number& rhs) {
|
||||
return setSingleBits(lhs.toDouble() != rhs.toDouble());
|
||||
}
|
||||
V3Number& V3Number::opGtD (const V3Number& lhs, const V3Number& rhs) {
|
||||
return setSingleBits(lhs.toDouble() > rhs.toDouble());
|
||||
}
|
||||
V3Number& V3Number::opGteD (const V3Number& lhs, const V3Number& rhs) {
|
||||
return setSingleBits(lhs.toDouble() >= rhs.toDouble());
|
||||
}
|
||||
V3Number& V3Number::opLtD (const V3Number& lhs, const V3Number& rhs) {
|
||||
return setSingleBits(lhs.toDouble() < rhs.toDouble());
|
||||
}
|
||||
V3Number& V3Number::opLteD (const V3Number& lhs, const V3Number& rhs) {
|
||||
return setSingleBits(lhs.toDouble() <= rhs.toDouble());
|
||||
}
|
||||
|
||||
+30
-1
@@ -35,6 +35,7 @@ class V3Number {
|
||||
int m_width; // Width as specified/calculated.
|
||||
bool m_sized:1; // True if the user specified the width, else we track it.
|
||||
bool m_signed:1; // True if signed value
|
||||
bool m_double:1; // True if double real value
|
||||
bool m_fromString:1; // True if from string
|
||||
bool m_autoExtend:1; // True if SystemVerilog extend-to-any-width
|
||||
FileLine* m_fileline;
|
||||
@@ -50,6 +51,8 @@ public:
|
||||
V3Number& setZero();
|
||||
V3Number& setQuad(vluint64_t value);
|
||||
V3Number& setLong(uint32_t value);
|
||||
V3Number& setLongS(vlsint32_t value);
|
||||
V3Number& setDouble(double value);
|
||||
void setBit (int bit, char value) { // Note must be pre-zeroed!
|
||||
if (bit>=m_width) return;
|
||||
if (value=='0'||value==0) m_value [bit/32] &= ~(1UL<<(bit&31));
|
||||
@@ -132,12 +135,14 @@ public:
|
||||
bool autoExtend() const { return m_autoExtend; }
|
||||
bool isFromString() const { return m_fromString; }
|
||||
bool isSigned() const { return m_signed; } // Only correct for parsing of numbers from strings, otherwise not used (use AstConst::isSigned())
|
||||
bool isDouble() const { return m_double; } // Only correct for parsing of numbers from strings, otherwise not used (use AstConst::isSigned())
|
||||
bool isNegative() const { return bitIs1(width()-1); }
|
||||
bool isFourState() const { for (int i=0;i<words();i++) {if (m_valueX[i]) return true;} return false; }
|
||||
bool hasZ() const { for(int i=0;i<words();i++) {if((~m_value[i]) & m_valueX[i]) return true;} return false;}
|
||||
bool isAllZ() const { for(int i=0;i<width();i++) { if(!bitIsZ(i)){return false;} } return true; }
|
||||
bool isEqZero() const;
|
||||
bool isNeqZero() const;
|
||||
bool isBitsZero(int msb, int lsb) const;
|
||||
bool isEqOne() const;
|
||||
bool isEqAllOnes(int optwidth=0) const;
|
||||
bool isCaseEq(const V3Number& rhsp) const; // operator==
|
||||
@@ -150,6 +155,7 @@ public:
|
||||
vluint64_t toUQuad() const;
|
||||
vlsint64_t toSQuad() const;
|
||||
string toString() const;
|
||||
double toDouble() const;
|
||||
uint32_t toHash() const;
|
||||
uint32_t dataWord(int word) const;
|
||||
uint32_t countOnes() const;
|
||||
@@ -195,12 +201,14 @@ public:
|
||||
V3Number& opCaseNeq (const V3Number& lhs, const V3Number& rhs);
|
||||
V3Number& opWildEq (const V3Number& lhs, const V3Number& rhs);
|
||||
V3Number& opWildNeq (const V3Number& lhs, const V3Number& rhs);
|
||||
V3Number& opBufIf1 (const V3Number& lhs, const V3Number& rhs);
|
||||
// "standard" math
|
||||
V3Number& opNot (const V3Number& lhs);
|
||||
V3Number& opLogNot (const V3Number& lhs);
|
||||
V3Number& opLogAnd (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& opSub (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& opXnor (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& opShiftRS (const V3Number& lhs, const V3Number& rhs); // Arithmetic w/carry
|
||||
V3Number& opShiftL (const V3Number& lhs, const V3Number& rhs);
|
||||
@@ -231,6 +241,25 @@ public:
|
||||
V3Number& opLte (const V3Number& lhs, const V3Number& rhs);
|
||||
V3Number& opLteS (const V3Number& lhs, const V3Number& rhs); // Signed
|
||||
|
||||
// "D" - double (aka real) math
|
||||
V3Number& opIToRD (const V3Number& lhs);
|
||||
V3Number& opRToIS (const V3Number& lhs);
|
||||
V3Number& opRToIRoundS (const V3Number& lhs);
|
||||
V3Number& opRealToBits (const V3Number& lhs);
|
||||
V3Number& opBitsToRealD(const V3Number& lhs);
|
||||
V3Number& opNegateD (const V3Number& lhs);
|
||||
V3Number& opAddD (const V3Number& lhs, const V3Number& rhs);
|
||||
V3Number& opSubD (const V3Number& lhs, const V3Number& rhs);
|
||||
V3Number& opMulD (const V3Number& lhs, const V3Number& rhs);
|
||||
V3Number& opDivD (const V3Number& lhs, const V3Number& rhs);
|
||||
V3Number& opPowD (const V3Number& lhs, const V3Number& rhs);
|
||||
// Comparisons
|
||||
V3Number& opEqD (const V3Number& lhs, const V3Number& rhs);
|
||||
V3Number& opNeqD (const V3Number& lhs, const V3Number& rhs);
|
||||
V3Number& opGtD (const V3Number& lhs, const V3Number& rhs);
|
||||
V3Number& opGteD (const V3Number& lhs, const V3Number& rhs);
|
||||
V3Number& opLtD (const V3Number& lhs, const V3Number& rhs);
|
||||
V3Number& opLteD (const V3Number& lhs, const V3Number& rhs);
|
||||
};
|
||||
inline ostream& operator<<(ostream& os, V3Number rhs) { return os<<rhs.ascii(); }
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ void test(string lhss, string op, string rhss, string exps) {
|
||||
else if (op=="repl") gotnum.opRepl (lhnum,rhnum);
|
||||
else if (op=="~") gotnum.opNot (lhnum);
|
||||
else if (op=="!") gotnum.opLogNot (lhnum);
|
||||
else if (op=="unaryMin") gotnum.opUnaryMin (lhnum);
|
||||
else if (op=="negate") gotnum.opNegate (lhnum);
|
||||
else if (op=="+") gotnum.opAdd (lhnum,rhnum);
|
||||
else if (op=="-") gotnum.opSub (lhnum,rhnum);
|
||||
else if (op=="*") gotnum.opMul (lhnum,rhnum);
|
||||
@@ -96,8 +96,8 @@ int main() {
|
||||
test("32'b0x","|","32'b10","32'b1x");
|
||||
test("32'b10","&","32'b11","32'b10");
|
||||
test("32'b10","+","32'b10","32'b100");
|
||||
test("3'b000","unaryMin","","3'b000");
|
||||
test("3'b001","unaryMin","","3'b111");
|
||||
test("3'b000","negate","","3'b000");
|
||||
test("3'b001","negate","","3'b111");
|
||||
test("32'b11","-","32'b001","32'b10");
|
||||
test("3'b000","-","3'b111","3'b001");
|
||||
test("3'b000","-","3'b000","3'b000");
|
||||
|
||||
+35
-4
@@ -194,18 +194,33 @@ string V3Options::filenameNonExt (const string& filename) {
|
||||
|
||||
string V3Options::filenameSubstitute (const string& filename) {
|
||||
string out;
|
||||
enum { NONE, PAREN, CURLY } brackets = NONE;
|
||||
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;
|
||||
while ((endpos+1) < filename.length()
|
||||
&& (isalnum(filename[endpos+1]) || filename[endpos+1]=='_'))
|
||||
while (((endpos+1) < filename.length()) &&
|
||||
(((brackets==NONE) && (isalnum(filename[endpos+1]) || filename[endpos+1]=='_')) ||
|
||||
((brackets==CURLY) && (filename[endpos+1]!='}')) ||
|
||||
((brackets==PAREN) && (filename[endpos+1]!=')'))))
|
||||
++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);
|
||||
const char* envvalue = NULL;
|
||||
if (envvar != "") envvalue = getenv(envvar.c_str());
|
||||
if (envvalue) {
|
||||
out += envvalue;
|
||||
pos = endpos;
|
||||
if (brackets==NONE) pos = endpos;
|
||||
else pos = endpos+1;
|
||||
} else {
|
||||
out += filename[pos]; // *pos == '$'
|
||||
}
|
||||
@@ -214,6 +229,7 @@ string V3Options::filenameSubstitute (const string& filename) {
|
||||
}
|
||||
}
|
||||
return out;
|
||||
|
||||
}
|
||||
|
||||
bool V3Options::filenameIsRel(const string& filename) {
|
||||
@@ -756,6 +772,14 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
||||
shift;
|
||||
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)) {
|
||||
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")) {
|
||||
FileLine::globalWarnStyleOff(true);
|
||||
}
|
||||
else if (!strcmp (sw, "-Wno-fatal")) {
|
||||
m_warnFatal = false;
|
||||
}
|
||||
else {
|
||||
string msg = sw+strlen("-Wno-");
|
||||
if (!(FileLine::globalWarnOff(msg, true))) {
|
||||
@@ -1056,6 +1083,7 @@ V3Options::V3Options() {
|
||||
m_makeDepend = true;
|
||||
m_makePhony = false;
|
||||
m_outFormatOk = false;
|
||||
m_warnFatal = true;
|
||||
m_pinsBv = 65;
|
||||
m_profileCFuncs = false;
|
||||
m_preprocOnly = false;
|
||||
@@ -1077,6 +1105,8 @@ V3Options::V3Options() {
|
||||
m_outputSplitCFuncs = 0;
|
||||
m_outputSplitCTrace = 0;
|
||||
m_traceDepth = 0;
|
||||
m_traceMaxArray = 32;
|
||||
m_traceMaxWidth = 256;
|
||||
m_unrollCount = 64;
|
||||
m_unrollStmts = 30000;
|
||||
|
||||
@@ -1095,6 +1125,7 @@ V3Options::V3Options() {
|
||||
// Default +libext+
|
||||
addLibExt(""); // So include "filename.v" will find the same file
|
||||
addLibExt(".v");
|
||||
addLibExt(".sv");
|
||||
// Default -I
|
||||
addIncDir("."); // Looks better than {long_cwd_path}/...
|
||||
}
|
||||
|
||||
@@ -113,6 +113,7 @@ class V3Options {
|
||||
bool m_l2Name; // main switch: --l2name
|
||||
bool m_lintOnly; // main switch: --lint-only
|
||||
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_profileCFuncs;// main switch: --profile-cfuncs
|
||||
bool m_psl; // main switch: --psl
|
||||
@@ -134,6 +135,8 @@ class V3Options {
|
||||
int m_outputSplitCTrace;// main switch: --output-split-ctrace
|
||||
int m_pinsBv; // main switch: --pins-bv
|
||||
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_unrollStmts; // main switch: --unroll-stmts
|
||||
|
||||
@@ -238,6 +241,7 @@ class V3Options {
|
||||
bool traceUnderscore() const { return m_traceUnderscore; }
|
||||
bool outFormatOk() const { return m_outFormatOk; }
|
||||
bool keepTempFiles() const { return (V3Error::debugDefault()!=0); }
|
||||
bool warnFatal() const { return m_warnFatal; }
|
||||
bool pinsUint8() const { return m_pinsUint8; }
|
||||
bool profileCFuncs() const { return m_profileCFuncs; }
|
||||
bool psl() const { return m_psl; }
|
||||
@@ -255,6 +259,8 @@ class V3Options {
|
||||
int outputSplitCTrace() const { return m_outputSplitCTrace; }
|
||||
int pinsBv() const { return m_pinsBv; }
|
||||
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 unrollStmts() const { return m_unrollStmts; }
|
||||
|
||||
|
||||
@@ -43,7 +43,6 @@
|
||||
#include "V3Case.h"
|
||||
#include "V3Const.h"
|
||||
#include "V3Width.h"
|
||||
#include "V3Signed.h"
|
||||
#include "V3Unroll.h"
|
||||
|
||||
//######################################################################
|
||||
|
||||
@@ -254,6 +254,7 @@ public:
|
||||
void verilatorCmtLintSave();
|
||||
void verilatorCmtLintRestore();
|
||||
void verilatorCmtBad(const char* text);
|
||||
double parseDouble(const char* text, size_t length);
|
||||
void pushBeginKeywords(int state) { m_inBeginKwd++; m_lastVerilogState=state; }
|
||||
bool popBeginKeywords() { if (m_inBeginKwd) { m_inBeginKwd--; return true; } else return false; }
|
||||
int lastVerilogState() { return m_lastVerilogState; }
|
||||
|
||||
@@ -393,6 +393,9 @@ void V3PreProcImp::comment(const string& text) {
|
||||
} else if (0==(strncmp(cp,"cadence",strlen("cadence")))) {
|
||||
cp+=strlen("cadence");
|
||||
synth = true;
|
||||
} else if (0==(strncmp(cp,"pragma",strlen("pragma")))) {
|
||||
cp+=strlen("pragma");
|
||||
synth = true;
|
||||
} else if (0==(strncmp(cp,"ambit synthesis",strlen("ambit synthesis")))) {
|
||||
cp+=strlen("ambit synthesis");
|
||||
synth = true;
|
||||
|
||||
+6
-6
@@ -208,12 +208,12 @@ private:
|
||||
// Then over shifting gives the sign bit, not all zeros
|
||||
// Note *NOT* clean output -- just like normal shift!
|
||||
// Create equivalent of VL_SIGNONES_(node_width)
|
||||
constzerop = new AstUnaryMin (nodep->fileline(),
|
||||
new AstShiftR(nodep->fileline(),
|
||||
nodep->lhsp()->cloneTree(false),
|
||||
new AstConst(nodep->fileline(),
|
||||
nodep->widthMin()-1),
|
||||
nodep->width()));
|
||||
constzerop = new AstNegate (nodep->fileline(),
|
||||
new AstShiftR(nodep->fileline(),
|
||||
nodep->lhsp()->cloneTree(false),
|
||||
new AstConst(nodep->fileline(),
|
||||
nodep->widthMin()-1),
|
||||
nodep->width()));
|
||||
} else {
|
||||
V3Number zeronum (nodep->fileline(), nodep->width(), 0);
|
||||
constzerop = new AstConst(nodep->fileline(), zeronum);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -53,6 +53,7 @@ class SliceCloneVisitor : public AstNVisitor {
|
||||
// Inputs:
|
||||
// AstArraySel::user1p() -> AstVarRef. The VarRef that the final ArraySel points to
|
||||
// AstNodeAssign::user2() -> int. The number of clones needed for this assign
|
||||
// AstArraySel::user3() -> bool. Error detected
|
||||
|
||||
// ENUMS
|
||||
enum RedOp { // The type of unary operation to be expanded
|
||||
@@ -221,6 +222,7 @@ class SliceVisitor : public AstNVisitor {
|
||||
// AstNode::user2() -> int. The number of clones needed for this node
|
||||
AstUser1InUse m_inuser1;
|
||||
AstUser2InUse m_inuser2;
|
||||
AstUser3InUse m_inuser3;
|
||||
|
||||
// TYPEDEFS
|
||||
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_assignError = true;
|
||||
}
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
|
||||
virtual void visit(AstArraySel* nodep, AstNUser*) {
|
||||
if (!m_assignp) return;
|
||||
if (nodep->user3()) return; // Prevent recursion on just created nodes
|
||||
unsigned dim = explicitDimensions(nodep);
|
||||
AstVarRef* refp = nodep->user1p()->castNode()->castVarRef();
|
||||
pair<uint32_t,uint32_t> arrDim = refp->varp()->dimensions();
|
||||
@@ -340,16 +342,18 @@ class SliceVisitor : public AstNVisitor {
|
||||
if (implicit > 0) {
|
||||
AstArraySel* newp = insertImplicit(nodep->cloneTree(false), dim+1, implicit);
|
||||
nodep->replaceWith(newp); nodep = newp;
|
||||
nodep->user3(true);
|
||||
}
|
||||
int clones = countClones(nodep);
|
||||
if (m_assignp->user2() > 0 && m_assignp->user2() != clones) {
|
||||
m_assignp->v3error("Slices of arrays in assignments must have the same unpacked dimensions");
|
||||
} else if (m_assignp->user2() == 0 && !m_assignError) {
|
||||
if (m_extend && clones > 1) {
|
||||
} else if (!m_assignp->user2()) {
|
||||
if (m_extend && clones > 1 && !m_assignError) {
|
||||
m_assignp->v3error("Unsupported: Assignment between packed arrays of different dimensions");
|
||||
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
|
||||
m_assignp->v3error("Unsupported: Slices in a non-delayed assignment with the same Var on both sides");
|
||||
m_assignError = true;
|
||||
|
||||
+1
-1
@@ -304,7 +304,7 @@ private:
|
||||
if (debug()>5) nodep->dumpTree(cout," substw_old: ");
|
||||
AstNode* newp = substp->cloneTree(true);
|
||||
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: ");
|
||||
nodep->replaceWith(newp);
|
||||
|
||||
+12
-5
@@ -587,8 +587,12 @@ private:
|
||||
// Someday we'll have better type support, and this can make variables and casts.
|
||||
// But for now, we'll just text-bash it.
|
||||
if (bitvec) {
|
||||
// We only support quads, so don't need to sweat longer stuff
|
||||
stmt += "VL_SET_WQ("+portp->name()+toSuffix+", "+portp->name()+frSuffix+")";
|
||||
if (portp->isWide()) {
|
||||
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 {
|
||||
if (isPtr) stmt += "*"; // DPI outputs are pointers
|
||||
stmt += portp->name()+toSuffix+" = ";
|
||||
@@ -605,7 +609,7 @@ private:
|
||||
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
|
||||
AstVar* portp = portvscp->varp();
|
||||
string stmt;
|
||||
@@ -614,6 +618,9 @@ private:
|
||||
stmt += "VL_CVT_VP_Q(";
|
||||
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 += ket;
|
||||
// Use a AstCMath, as we want V3Clean to mask off bits that don't make sense.
|
||||
@@ -680,7 +687,7 @@ private:
|
||||
argnodesp = argnodesp->addNextNull(refp);
|
||||
|
||||
if (portp->isInput()) {
|
||||
dpip->addStmtsp(createAssignDpiToInternal(outvscp, portp->name()));
|
||||
dpip->addStmtsp(createAssignDpiToInternal(outvscp, portp->name(), false));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -795,7 +802,7 @@ private:
|
||||
if (AstVar* portp = stmtp->castVar()) {
|
||||
if (portp->isIO() && (portp->isOutput() || portp->isFuncReturn())) {
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -75,8 +75,8 @@ private:
|
||||
if (prettyName.find("._") != string::npos)
|
||||
return "Inlined leading underscore";
|
||||
}
|
||||
if (nodep->width() > 256) return "Wide bus > 256 bits";
|
||||
if (nodep->arrayElements() > 32) return "Wide memory > 32 ents";
|
||||
if ((int)nodep->width() > v3Global.opt.traceMaxWidth()) return "Wide bus > --trace-max-width bits";
|
||||
if ((int)nodep->arrayElements() > v3Global.opt.traceMaxArray()) return "Wide memory > --trace-max-array ents";
|
||||
if (!(nodep->dtypeSkipRefp()->castBasicDType()
|
||||
|| (nodep->dtypeSkipRefp()->castArrayDType()
|
||||
&& nodep->dtypeSkipRefp()->castArrayDType()->dtypeSkipRefp()->castBasicDType()))) {
|
||||
|
||||
+38
-7
@@ -159,8 +159,8 @@ private:
|
||||
// assign x = (OE) ? 'hz : y;
|
||||
|
||||
// see if this a COND and separate out the __en logic from the output logic if it is
|
||||
if (nodep->rhsp()->castCond()) {
|
||||
AstCond* condp = nodep->rhsp()->castCond();
|
||||
if (AstCond* condp = nodep->rhsp()->castCond()) {
|
||||
//if (debug()>=9) nodep->dumpTree(cout,"- cond-in: ");
|
||||
AstNode* oep = condp->condp();
|
||||
AstNode* expr1p = condp->expr1p();
|
||||
AstNode* expr2p = condp->expr2p();
|
||||
@@ -192,17 +192,44 @@ private:
|
||||
|
||||
// replace the old assign logic with the new one
|
||||
AstAssignW* newassp = new AstAssignW(nodep->fileline(), outp,outrhsp);
|
||||
//if (debug()>=9) newassp->dumpTreeAndNext(cout,"- cond-out: ");
|
||||
nodep->replaceWith(newassp);
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
AstVar* enp = new AstVar (outrefp->varp()->fileline(),
|
||||
AstVarType::MODULETEMP,
|
||||
@@ -218,10 +245,14 @@ private:
|
||||
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(new AstAssignW (enp->fileline(),
|
||||
new AstVarRef (enp->fileline(), enp, true),
|
||||
enrhsp));
|
||||
m_modp->addStmtp(newassp);
|
||||
|
||||
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
|
||||
|
||||
+2
-1
@@ -187,8 +187,9 @@ private:
|
||||
UINFO(8," In Numbers: for (v="<<valInit<<"; v<"<<valStop<<"; v=v+"<<valInc<<")\n");
|
||||
//
|
||||
if (!m_generate) {
|
||||
UINFO(8, " ~Iters: "<<((valStop - valInit)/valInc)<<" c="<<unrollCount()<<endl);
|
||||
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())
|
||||
return cantUnroll(nodep, "too many iterations");
|
||||
|
||||
|
||||
+1076
-540
File diff suppressed because it is too large
Load Diff
@@ -34,7 +34,6 @@ public:
|
||||
static void width(AstNetlist* nodep);
|
||||
// Smaller step... Only do a single node for parameter propagation
|
||||
static AstNode* widthParamsEdit(AstNode* nodep);
|
||||
static AstNode* widthParamsEditIfNeed(AstNode* nodep);
|
||||
// Final step... Mark all widths as equal
|
||||
static void widthCommit(AstNetlist* nodep);
|
||||
|
||||
|
||||
@@ -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
@@ -111,12 +111,12 @@ private:
|
||||
// We must make sure sub gets sign of original value
|
||||
AstNode* newp = new AstSub(lhsp->fileline(), lhsp,
|
||||
new AstConst(lhsp->fileline(), AstConst::Unsized32(), rhs));
|
||||
newp->signedFrom(lhsp);
|
||||
newp->numericFrom(lhsp);
|
||||
return newp;
|
||||
} else { // rhs < 0;
|
||||
AstNode* newp = new AstAdd(lhsp->fileline(), lhsp,
|
||||
new AstConst(lhsp->fileline(), AstConst::Unsized32(), -rhs));
|
||||
newp->signedFrom(lhsp);
|
||||
newp->numericFrom(lhsp);
|
||||
return newp;
|
||||
}
|
||||
}
|
||||
@@ -126,7 +126,7 @@ private:
|
||||
AstNode* newp = new AstSub(rhsp->fileline(),
|
||||
new AstConst(rhsp->fileline(), AstConst::Unsized32(), lhs),
|
||||
rhsp);
|
||||
newp->signedFrom(rhsp); // Important as AstSub default is lhs's sign
|
||||
newp->numericFrom(rhsp); // Important as AstSub default is lhs's sign
|
||||
return newp;
|
||||
}
|
||||
|
||||
|
||||
+2
-7
@@ -74,7 +74,6 @@
|
||||
#include "V3PreShell.h"
|
||||
#include "V3Premit.h"
|
||||
#include "V3Scope.h"
|
||||
#include "V3Signed.h"
|
||||
#include "V3Slice.h"
|
||||
#include "V3Split.h"
|
||||
#include "V3SplitAs.h"
|
||||
@@ -168,9 +167,6 @@ void process () {
|
||||
V3Width::width(v3Global.rootp());
|
||||
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("width.tree"));
|
||||
|
||||
// Compute signed/unsigned
|
||||
V3Signed::signedAll(v3Global.rootp());
|
||||
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("signed.tree"));
|
||||
V3Error::abortIfErrors();
|
||||
|
||||
// Commit to the widths we've chosen; Make widthMin==width
|
||||
@@ -571,9 +567,6 @@ int main(int argc, char** argv, char** env) {
|
||||
v3Global.opt.bin(argv[0]);
|
||||
string argString = V3Options::argString(argc-1, argv+1);
|
||||
v3Global.opt.parseOpts(new FileLine("COMMAND_LINE",0), argc-1, argv+1);
|
||||
if (v3Global.opt.coverage() && !v3Global.opt.systemPerl() && !v3Global.opt.lintOnly()) {
|
||||
v3fatal("Unsupported: Coverage analysis requires --sp output.");
|
||||
}
|
||||
if (!v3Global.opt.outFormatOk()
|
||||
&& !v3Global.opt.preprocOnly()
|
||||
&& !v3Global.opt.lintOnly()
|
||||
@@ -630,6 +623,8 @@ int main(int argc, char** argv, char** env) {
|
||||
V3File::writeTimes(v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"__verFiles.dat", argString);
|
||||
}
|
||||
|
||||
// Final writing shouldn't throw warnings, but...
|
||||
V3Error::abortIfWarnings();
|
||||
#ifdef VL_LEAK_CHECKS
|
||||
// Cleanup memory for valgrind leak analysis
|
||||
v3Global.clear();
|
||||
|
||||
+95
-22
@@ -9,7 +9,7 @@ use Pod::Usage;
|
||||
use strict;
|
||||
use vars qw ($Debug $VERSION);
|
||||
|
||||
$VERSION = '3.202';
|
||||
$VERSION = '3.307';
|
||||
|
||||
our $Self;
|
||||
|
||||
@@ -74,9 +74,10 @@ sub parameter {
|
||||
sub process {
|
||||
remove_outputs();
|
||||
|
||||
clean_input($Opt_Input, tmp_prefix().".y");
|
||||
$Self->{bison_version} = bison_version_check();
|
||||
my $supports_report = ($Self->{bison_version} >= 2.3);
|
||||
|
||||
my $supports_report = (bison_version_check() >= 2.3);
|
||||
clean_input($Opt_Input, tmp_prefix().".y");
|
||||
|
||||
# Run bison
|
||||
my $command = ($Opt_Yacc
|
||||
@@ -100,11 +101,11 @@ sub process {
|
||||
die "bisonpre: %Error: $Opt_Yacc version $v run failed due to errors\n";
|
||||
}
|
||||
|
||||
clean_output(tmp_prefix().".output",output_prefix().".output", 1);
|
||||
clean_output(tmp_prefix().".output",output_prefix().".output", 1,0);
|
||||
warning_check(output_prefix().".output");
|
||||
|
||||
clean_output(tmp_prefix().".c", output_prefix().".c", 0);
|
||||
clean_output(tmp_prefix().".h", output_prefix().".h", 0);
|
||||
clean_output(tmp_prefix().".c", output_prefix().".c", 0,1);
|
||||
clean_output(tmp_prefix().".h", output_prefix().".h", 0,1);
|
||||
remove_tmp();
|
||||
}
|
||||
|
||||
@@ -150,15 +151,17 @@ sub clean_output {
|
||||
my $filename = shift;
|
||||
my $outname = shift || $filename;
|
||||
my $is_output = shift;
|
||||
my $is_c = shift;
|
||||
print " edit $filename $outname\n";
|
||||
|
||||
my $fh = IO::File->new("<$filename") or die "%Error: $! $filename\n";
|
||||
my @lines = $fh->getlines;
|
||||
$fh->close;
|
||||
|
||||
(my $basename = tmp_prefix().".y") =~ s!.*/!!;
|
||||
(my $basename = tmp_prefix().".") =~ s!.*/!!;
|
||||
$basename = quotemeta($basename);
|
||||
(my $newbase = $Opt_Input) =~ s!.*/!!;
|
||||
$newbase =~ s/\.y/./;
|
||||
|
||||
if ($is_output) {
|
||||
my %state_line; my $l=0;
|
||||
@@ -178,6 +181,28 @@ sub clean_output {
|
||||
}
|
||||
@lines = @out; @out = ();
|
||||
}
|
||||
if ($is_c) {
|
||||
my %token_values;
|
||||
my $in_en=0;
|
||||
foreach my $line (@lines) {
|
||||
$in_en=1 if $line =~ /enum\s+yytokentype/;
|
||||
$in_en=0 if $line =~ /;/;
|
||||
$token_values{$2} = $1 if $in_en && $line =~ /\b(\S+) = (\d+)/;
|
||||
}
|
||||
my @out;
|
||||
foreach my $line (@lines) {
|
||||
if ($line =~ /BISONPRE_TOKEN_NAMES/) {
|
||||
push @out, $line;
|
||||
foreach my $tv (sort keys %token_values) {
|
||||
push @out, sprintf("\tcase %d: return \"%s\";\n",
|
||||
$tv, $token_values{$tv});
|
||||
}
|
||||
next;
|
||||
}
|
||||
push @out, $line;
|
||||
}
|
||||
@lines = @out; @out = ();
|
||||
}
|
||||
|
||||
$fh = IO::File->new(">$outname") or die "%Error: $! writing $outname\n";
|
||||
foreach my $line (@lines) {
|
||||
@@ -211,6 +236,7 @@ sub clean_input {
|
||||
my $outname = shift || $filename; # Can == filename if desired
|
||||
print " edit $filename $outname\n";
|
||||
|
||||
$Self->{filename} = $filename;
|
||||
my $fh = IO::File->new("<$filename") or die "%Error: $! $filename\n";
|
||||
my @lines = $fh->getlines;
|
||||
$fh->close;
|
||||
@@ -232,7 +258,7 @@ sub clean_input {
|
||||
$section++;
|
||||
if ($section==2) { $last_rule = undef; }
|
||||
}
|
||||
elsif ($line =~ s/^([a-zA-Z0-9_]+)<(\S+)>:/$1:/) {
|
||||
elsif ($line =~ s/^([a-zA-Z0-9_]+)<(\S*)>:/$1:/) {
|
||||
!$rules{$1}{name} or die "%Error: $filename:$l: Redeclaring '$1': $line\n";
|
||||
$types{$2}{$1} = 1;
|
||||
$rules{$1}{name} = $1;
|
||||
@@ -272,6 +298,25 @@ sub clean_input {
|
||||
|
||||
#use Data::Dumper; print Dumper(\%rules);
|
||||
|
||||
# Replace BISONPRE_VERSION(ver,,...) with expanded list
|
||||
{
|
||||
my @linesin = @lines; @lines=(); my $l=0;
|
||||
foreach my $line (@linesin) {
|
||||
$l++;
|
||||
if ($line =~ /BISONPRE_VERSION/) {
|
||||
($line =~ /BISONPRE_VERSION\((\S+)\s*,\s*([^\),]+)\)\s*$/)
|
||||
or die "%Error: $filename:$l: Bad form of BISONPRE_VERSION: $line\n";
|
||||
my $ver=$1; my $cmd=$2;
|
||||
if ($Self->{bison_version} >= $1) {
|
||||
$line = $cmd."\n";
|
||||
} else {
|
||||
$line = "//NOP: $line";
|
||||
}
|
||||
}
|
||||
push @lines, $line;
|
||||
}
|
||||
}
|
||||
|
||||
# Replace BISONPRE_NOT(type,...) with expanded list
|
||||
{
|
||||
my @linesin = @lines; @lines=(); my $l=0;
|
||||
@@ -308,20 +353,7 @@ sub clean_input {
|
||||
foreach my $line (@linesin) {
|
||||
$l++;
|
||||
if ($line =~ /BISONPRE_COPY/) {
|
||||
($line =~ s/BISONPRE_COPY\((\S+)\s*,\s*{([^}]*)}\s*\)/{HERE}/)
|
||||
or die "%Error: $filename:$l: Bad form of BISONPRE_NOT: $line\n";
|
||||
my $rule = $1; my $code = $2;
|
||||
$rules{$rule} or die "%Error: $filename:$l: Can't find definition for rule: $rule\n";
|
||||
# Push it all onto one line to avoid error messages changing
|
||||
my $insert = $rules{$rule}{rules_and_productions};
|
||||
$insert =~ s/^\S+://g; # Strip rule name
|
||||
#print "COPY code $code\n";
|
||||
#print "COPY in $insert\n";
|
||||
$_=$insert; eval("$code; \$_;"); $insert = $_;
|
||||
#print "COPY out $insert\n";
|
||||
while ($insert =~ s/[ \t\n]+\n/\n/go) {}
|
||||
while ($insert =~ s/\n/ /go) {} # Optional - preserve line numbering
|
||||
$line =~ s/{HERE}/$insert/;
|
||||
$line = _bisonpre_copy($line,$l,0);
|
||||
}
|
||||
push @lines, $line;
|
||||
}
|
||||
@@ -346,6 +378,7 @@ sub clean_input {
|
||||
if ($line =~ m!//BISONPRE_TYPES!) {
|
||||
push @lines, $line;
|
||||
foreach my $type (sort keys %types) {
|
||||
next if !$type;
|
||||
my $line = "%type<$type>\t";
|
||||
foreach my $rule (sort keys %{$types{$type}}) {
|
||||
$line.=" ".$rule;
|
||||
@@ -372,6 +405,37 @@ sub clean_input {
|
||||
$fh->close;
|
||||
}
|
||||
|
||||
sub _bisonpre_copy {
|
||||
my $text = shift;
|
||||
my $l = shift;
|
||||
my $depth = shift;
|
||||
while ($text =~ /BISONPRE_COPY/) {
|
||||
($text =~ s/BISONPRE_COPY(_ONCE)?\((\S+)\s*,\s*{([^}]*)}\s*\)/{HERE}/)
|
||||
or die "%Error: $Self->{filename}:$l: Bad form of BISONPRE_NOT: $text\n";
|
||||
my $once = $1; my $rule = $2; my $code = $3;
|
||||
$Self->{rules}{$rule} or die "%Error: $Self->{filename}:$l: Can't find definition for rule: $rule\n";
|
||||
if ($depth > 0 && $once) {
|
||||
# _ONCE means don't inherit
|
||||
$text =~ s/\|[ \t]+{HERE}//; # Don't OR in nothing
|
||||
$text =~ s/{HERE}//;
|
||||
} else {
|
||||
# Push it all onto one line to avoid error messages changing
|
||||
my $insert = $Self->{rules}{$rule}{rules_and_productions};
|
||||
$insert =~ s/^\S+://g; # Strip rule name
|
||||
# Recurse so BISONPRE under B
|
||||
#print "COPY $l code $code\n";
|
||||
#print "COPY $l in $insert\n";
|
||||
$_=$insert; eval("$code; \$_;"); $insert = $_;
|
||||
#print "COPY $l out $insert\n";
|
||||
while ($insert =~ s/[ \t\n]+\n/\n/go) {}
|
||||
while ($insert =~ s/\n/ /go) {} # Optional - preserve line numbering
|
||||
$text =~ s/{HERE}/$insert/;
|
||||
}
|
||||
$depth++;
|
||||
}
|
||||
return $text;
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
__END__
|
||||
|
||||
@@ -416,10 +480,19 @@ rule. The type will be inserted where /*BISONPRE_TYPES*/ is encountered.
|
||||
Copy the rules and productions from the specified rule, filter through the
|
||||
Perl code provided in the {} and insert here into the output file.
|
||||
|
||||
=item BISONPRE_COPY_ONCE(rule, {code})
|
||||
|
||||
As with BISONPRE_COPY, but if called from underneath another BISONPRE_COPY
|
||||
rule, ignore it.
|
||||
|
||||
=item BISONPRE_NOT(token[, token...])
|
||||
|
||||
Create a rule that matches every token except for those specified.
|
||||
|
||||
=item BISONPRE_VERSION(ver, cmd)
|
||||
|
||||
If the bison version is >= the specified version, include the given command.
|
||||
|
||||
=back
|
||||
|
||||
=head1 ARGUMENTS
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
//**********************************************************************
|
||||
//**** Version and host name
|
||||
|
||||
#define DTVERSION "Verilator 3.811 2011/02/14"
|
||||
#define DTVERSION "Verilator 3.820 2011/07/28"
|
||||
|
||||
//**********************************************************************
|
||||
//**** Functions
|
||||
|
||||
+32
-8
@@ -174,6 +174,7 @@ word [a-zA-Z0-9_]+
|
||||
/* Extensions to Verilog set, some specified by PSL */
|
||||
"$c"[0-9]* { FL; return yD_C; } /*Verilator only*/
|
||||
/* System Tasks */
|
||||
"$bitstoreal" { FL; return yD_BITSTOREAL; }
|
||||
"$display" { FL; return yD_DISPLAY; }
|
||||
"$fclose" { FL; return yD_FCLOSE; }
|
||||
"$fdisplay" { FL; return yD_FDISPLAY; }
|
||||
@@ -187,15 +188,18 @@ word [a-zA-Z0-9_]+
|
||||
"$fullskew" { FL; return yaTIMINGSPEC; }
|
||||
"$fwrite" { FL; return yD_FWRITE; }
|
||||
"$hold" { FL; return yaTIMINGSPEC; }
|
||||
"$itor" { FL; return yD_ITOR; }
|
||||
"$nochange" { FL; return yaTIMINGSPEC; }
|
||||
"$period" { FL; return yaTIMINGSPEC; }
|
||||
"$random" { FL; return yD_RANDOM; }
|
||||
"$readmemb" { FL; return yD_READMEMB; }
|
||||
"$readmemh" { FL; return yD_READMEMH; }
|
||||
"$realtime" { FL; return yD_TIME; }
|
||||
"$realtime" { FL; return yD_REALTIME; }
|
||||
"$realtobits" { FL; return yD_REALTOBITS; }
|
||||
"$recovery" { FL; return yaTIMINGSPEC; }
|
||||
"$recrem" { FL; return yaTIMINGSPEC; }
|
||||
"$removal" { FL; return yaTIMINGSPEC; }
|
||||
"$rtoi" { FL; return yD_RTOI; }
|
||||
"$setup" { FL; return yaTIMINGSPEC; }
|
||||
"$setuphold" { FL; return yaTIMINGSPEC; }
|
||||
"$sformat" { FL; return yD_SFORMAT; }
|
||||
@@ -261,6 +265,8 @@ word [a-zA-Z0-9_]+
|
||||
"pulldown" { FL; return yPULLDOWN; }
|
||||
"pullup" { FL; return yPULLUP; }
|
||||
"rcmos" { FL; return yRCMOS; }
|
||||
"real" { FL; return yREAL; }
|
||||
"realtime" { FL; return yREALTIME; }
|
||||
"reg" { FL; return yREG; }
|
||||
"repeat" { FL; return yREPEAT; }
|
||||
"rnmos" { FL; return yRNMOS; }
|
||||
@@ -310,8 +316,6 @@ word [a-zA-Z0-9_]+
|
||||
"medium" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
|
||||
"pull0" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
|
||||
"pull1" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
|
||||
"real" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
|
||||
"realtime" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
|
||||
"release" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
|
||||
"small" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
|
||||
"strong0" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
|
||||
@@ -478,12 +482,12 @@ word [a-zA-Z0-9_]+
|
||||
<S05,S09>{
|
||||
/* Keywords */
|
||||
"assert" { FL; return yASSERT; }
|
||||
"const" { FL; return yCONST__LEX; }
|
||||
"cover" { FL; return yCOVER; }
|
||||
"property" { FL; return yPROPERTY; }
|
||||
/* Generic unsupported warnings */
|
||||
"assume" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); }
|
||||
"before" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); }
|
||||
"const" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); }
|
||||
"sequence" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); }
|
||||
"union" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); }
|
||||
"within" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); }
|
||||
@@ -812,11 +816,11 @@ word [a-zA-Z0-9_]+
|
||||
return yaINTNUM;
|
||||
}
|
||||
[0-9][_0-9]*(\.[_0-9]+)([eE][-+]?[_0-9]+)? {
|
||||
FL; yylval.cdouble = 0; /* Only for delays, not used yet */
|
||||
FL; yylval.cdouble = PARSEP->parseDouble(yytext, yyleng);
|
||||
return yaFLOATNUM;
|
||||
}
|
||||
[0-9][_0-9]*(\.[_0-9]+)?([eE][-+]?[_0-9]+) {
|
||||
FL; yylval.cdouble = 0; /* Only for delays, not used yet */
|
||||
FL; yylval.cdouble = PARSEP->parseDouble(yytext, yyleng);
|
||||
return yaFLOATNUM;
|
||||
}
|
||||
[0-9][_0-9]*(\.[_0-9]+)?(fs|ps|ns|us|ms|s|step) {
|
||||
@@ -949,6 +953,21 @@ word [a-zA-Z0-9_]+
|
||||
%%
|
||||
int V3ParseImp::stateVerilogRecent() { return STATE_VERILOG_RECENT; }
|
||||
|
||||
double V3ParseImp::parseDouble(const char* textp, size_t length) {
|
||||
char* strgp = new char[length+1];
|
||||
char* dp=strgp;
|
||||
for (const char* sp=textp; sp<(textp+length);) {
|
||||
if (*sp != '_') *dp++ = *sp++;
|
||||
else sp++;
|
||||
}
|
||||
*dp++ = '\0';
|
||||
char* endp = strgp;
|
||||
double d = strtod(strgp, &endp);
|
||||
if ((endp-strgp) != length) { yyerrorf("Syntax error parsing real: %s",strgp); }
|
||||
delete strgp;
|
||||
return d;
|
||||
}
|
||||
|
||||
int V3ParseImp::lexToken() {
|
||||
// called from lexToBison, has a "this"
|
||||
// Fetch next token from prefetch or real lexer
|
||||
@@ -964,7 +983,8 @@ int V3ParseImp::lexToken() {
|
||||
//yylval // Set by yylexThis()
|
||||
}
|
||||
// If a paren, read another
|
||||
if (token == yGLOBAL__LEX
|
||||
if (token == yCONST__LEX
|
||||
|| token == yGLOBAL__LEX
|
||||
// Never put yID_* here; below symbol table resolution would break
|
||||
) {
|
||||
if (debugFlex()) { cout<<" lexToken: reading ahead to find possible strength"<<endl; }
|
||||
@@ -975,7 +995,11 @@ int V3ParseImp::lexToken() {
|
||||
m_aheadVal = yylval;
|
||||
yylval = curValue;
|
||||
// Now potentially munge the current token
|
||||
if (token == yGLOBAL__LEX) {
|
||||
if (token == yCONST__LEX) {
|
||||
//UNSUP if (nexttok == yREF) token = yCONST__REF;
|
||||
token = yCONST__ETC;
|
||||
}
|
||||
else if (token == yGLOBAL__LEX) {
|
||||
if (nexttok == yCLOCKING) token = yGLOBAL__CLOCKING;
|
||||
else { token = yaID__LEX; yylval.strp = PARSEP->newString("global"); } // Avoid 2009 "global" conflicting with old code when we can
|
||||
}
|
||||
|
||||
+96
-37
@@ -274,6 +274,8 @@ class AstSenTree;
|
||||
%token<fl> yCASEZ "casez"
|
||||
%token<fl> yCHANDLE "chandle"
|
||||
%token<fl> yCLOCKING "clocking"
|
||||
%token<fl> yCONST__ETC "const"
|
||||
%token<fl> yCONST__LEX "const-in-lex"
|
||||
%token<fl> yCMOS "cmos"
|
||||
%token<fl> yCONTEXT "context"
|
||||
%token<fl> yCONTINUE "continue"
|
||||
@@ -340,6 +342,8 @@ class AstSenTree;
|
||||
%token<fl> yPULLUP "pullup"
|
||||
%token<fl> yPURE "pure"
|
||||
%token<fl> yRCMOS "rcmos"
|
||||
%token<fl> yREAL "real"
|
||||
%token<fl> yREALTIME "realtime"
|
||||
%token<fl> yREG "reg"
|
||||
%token<fl> yREPEAT "repeat"
|
||||
%token<fl> yRETURN "return"
|
||||
@@ -380,6 +384,7 @@ class AstSenTree;
|
||||
%token<fl> yXOR "xor"
|
||||
|
||||
%token<fl> yD_BITS "$bits"
|
||||
%token<fl> yD_BITSTOREAL "$bitstoreal"
|
||||
%token<fl> yD_C "$c"
|
||||
%token<fl> yD_CLOG2 "$clog2"
|
||||
%token<fl> yD_COUNTONES "$countones"
|
||||
@@ -398,11 +403,15 @@ class AstSenTree;
|
||||
%token<fl> yD_FWRITE "$fwrite"
|
||||
%token<fl> yD_INFO "$info"
|
||||
%token<fl> yD_ISUNKNOWN "$isunknown"
|
||||
%token<fl> yD_ITOR "$itor"
|
||||
%token<fl> yD_ONEHOT "$onehot"
|
||||
%token<fl> yD_ONEHOT0 "$onehot0"
|
||||
%token<fl> yD_RANDOM "$random"
|
||||
%token<fl> yD_READMEMB "$readmemb"
|
||||
%token<fl> yD_READMEMH "$readmemh"
|
||||
%token<fl> yD_REALTIME "$realtime"
|
||||
%token<fl> yD_REALTOBITS "$realtobits"
|
||||
%token<fl> yD_RTOI "$rtoi"
|
||||
%token<fl> yD_SFORMAT "$sformat"
|
||||
%token<fl> yD_SIGNED "$signed"
|
||||
%token<fl> yD_SSCANF "$sscanf"
|
||||
@@ -833,7 +842,7 @@ port<nodep>: // ==IEEE: port
|
||||
| portDirNetE /*implicit*/ portSig variable_dimensionListE sigAttrListE '=' constExpr
|
||||
{ $$=$2; /*VARDTYPE-same*/ AstVar* vp=VARDONEP($$,$3,$4); $$->addNextNull(vp); vp->valuep($6); }
|
||||
;
|
||||
|
||||
|
||||
portDirNetE: // IEEE: part of port, optional net type and/or direction
|
||||
/* empty */ { }
|
||||
// // Per spec, if direction given default the nettype.
|
||||
@@ -842,12 +851,12 @@ 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
|
||||
| net_type { } // net_type calls VARNET
|
||||
;
|
||||
|
||||
|
||||
port_declNetE: // IEEE: part of port_declaration, optional net type
|
||||
/* empty */ { }
|
||||
| net_type { } // net_type calls VARNET
|
||||
;
|
||||
|
||||
|
||||
portSig<nodep>:
|
||||
id/*port*/ { $$ = new AstPort($<fl>1,PINNUMINC(),*$1); }
|
||||
| idSVKwd { $$ = new AstPort($<fl>1,PINNUMINC(),*$1); }
|
||||
@@ -1065,6 +1074,12 @@ integer_vector_type<bdtypep>: // ==IEEE: integer_atom_type
|
||||
| yREG { $$ = new AstBasicDType($1,AstBasicDTypeKwd::LOGIC); } // logic==reg
|
||||
;
|
||||
|
||||
non_integer_type<bdtypep>: // ==IEEE: non_integer_type
|
||||
yREAL { $$ = new AstBasicDType($1,AstBasicDTypeKwd::DOUBLE); }
|
||||
| yREALTIME { $$ = new AstBasicDType($1,AstBasicDTypeKwd::DOUBLE); }
|
||||
//UNSUP ySHORTREAL { $$ = new AstBasicDType($1,AstBasicDTypeKwd::FLOAT); }
|
||||
;
|
||||
|
||||
signingE<signstate>: // IEEE: signing - plus empty
|
||||
/*empty*/ { $$ = signedst_NOP; }
|
||||
| signing { $$ = $1; }
|
||||
@@ -1078,6 +1093,31 @@ signing<signstate>: // ==IEEE: signing
|
||||
//************************************************
|
||||
// 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
|
||||
// // This expansion also replicated elsewhere, IE data_type__AndID
|
||||
data_typeNoRef { $$ = $1; }
|
||||
@@ -1093,7 +1133,7 @@ data_type<dtypep>: // ==IEEE: data_type
|
||||
data_typeBasic<dtypep>: // IEEE: part of data_type
|
||||
integer_vector_type signingE rangeListE { $1->setSignedState($2); $$ = GRAMMARP->addRange($1,$3,true); }
|
||||
| integer_atom_type signingE { $1->setSignedState($2); $$ = $1; }
|
||||
//UNSUP non_integer_type { UNSUP }
|
||||
| non_integer_type { $$ = $1; }
|
||||
;
|
||||
|
||||
data_typeNoRef<dtypep>: // ==IEEE: data_type, excluding class_type etc references
|
||||
@@ -1244,23 +1284,24 @@ data_declarationVar<nodep>: // IEEE: part of data_declaration
|
||||
;
|
||||
|
||||
data_declarationVarFront: // IEEE: part of data_declaration
|
||||
// // Expanded: "constE yVAR lifetimeE data_type"
|
||||
// // implicit_type expanded into /*empty*/ or "signingE rangeList"
|
||||
constE yVAR lifetimeE data_type { /*VARRESET-in-ddVar*/ VARDTYPE($4); }
|
||||
| constE yVAR lifetimeE { /*VARRESET-in-ddVar*/ VARDTYPE(new AstBasicDType($<fl>2, LOGIC_IMPLICIT)); }
|
||||
| constE yVAR lifetimeE signingE rangeList { /*VARRESET-in-ddVar*/ VARDTYPE(GRAMMARP->addRange(new AstBasicDType($<fl>2, LOGIC_IMPLICIT, $4),$5,false)); }
|
||||
/**/ yVAR lifetimeE data_type { /*VARRESET-in-ddVar*/ VARDTYPE($3); }
|
||||
| /**/ yVAR lifetimeE { /*VARRESET-in-ddVar*/ VARDTYPE(new AstBasicDType($<fl>1, LOGIC_IMPLICIT)); }
|
||||
| /**/ yVAR lifetimeE signingE rangeList { /*VARRESET-in-ddVar*/ VARDTYPE(GRAMMARP->addRange(new AstBasicDType($<fl>1, LOGIC_IMPLICIT, $3), $4,false)); }
|
||||
//
|
||||
// // implicit_type expanded into /*empty*/ or "signingE rangeList"
|
||||
| yCONST__ETC yVAR lifetimeE data_type { /*VARRESET-in-ddVar*/ VARDTYPE(new AstConstDType($<fl>1, $4)); }
|
||||
| yCONST__ETC yVAR lifetimeE { /*VARRESET-in-ddVar*/ VARDTYPE(new AstConstDType($<fl>1, new AstBasicDType($<fl>2, LOGIC_IMPLICIT))); }
|
||||
| yCONST__ETC yVAR lifetimeE signingE rangeList { /*VARRESET-in-ddVar*/ VARDTYPE(new AstConstDType($<fl>1, GRAMMARP->addRange(new AstBasicDType($<fl>2, LOGIC_IMPLICIT, $4), $5,false))); }
|
||||
//
|
||||
// // Expanded: "constE lifetimeE data_type"
|
||||
| /**/ data_type { /*VARRESET-in-ddVar*/ VARDTYPE($1); }
|
||||
| /**/ lifetime data_type { /*VARRESET-in-ddVar*/ VARDTYPE($2); }
|
||||
//UNSUP yCONST__ETC lifetimeE data_type { /*VARRESET-in-ddVar*/ VARDTYPE($3); }
|
||||
| yCONST__ETC lifetimeE data_type { /*VARRESET-in-ddVar*/ VARDTYPE(new AstConstDType($<fl>1, $3)); }
|
||||
// // = class_new is in variable_decl_assignment
|
||||
;
|
||||
|
||||
constE: // IEEE: part of data_declaration
|
||||
/* empty */ { }
|
||||
//UNSUP yCONST__ETC { UNSUP }
|
||||
;
|
||||
|
||||
implicit_typeE<dtypep>: // IEEE: part of *data_type_or_implicit
|
||||
// // Also expanded in data_declaration
|
||||
/* empty */ { $$ = NULL; }
|
||||
@@ -1499,8 +1540,7 @@ delay_value: // ==IEEE:delay_value
|
||||
|
||||
delayExpr:
|
||||
expr { }
|
||||
// // Verilator doesn't support yaFLOATNUM/yaTIMENUM, so not in expr
|
||||
| yaFLOATNUM { }
|
||||
// // Verilator doesn't support yaTIMENUM, so not in expr
|
||||
| yaTIMENUM { }
|
||||
;
|
||||
|
||||
@@ -1685,8 +1725,6 @@ cellpinItemE<pinp>: // IEEE: named_port_connection + named_parameter_assignment
|
||||
| expr { $$ = new AstPin($1->fileline(),PINNUMINC(),"",$1); }
|
||||
//UNSUP expr ':' expr { }
|
||||
//UNSUP expr ':' expr ':' expr { }
|
||||
// // Floatnum should only occur with UDPs, but since ports aren't floats, it's legal to round always
|
||||
| yaFLOATNUM { $$ = new AstPin($<fl>1,PINNUMINC(),"",new AstConst($<fl>1,AstConst::Unsized32(),(int)(($1<0)?($1-0.5):($1+0.5)))); }
|
||||
;
|
||||
|
||||
//************************************************
|
||||
@@ -1861,7 +1899,7 @@ statement_item<nodep>: // IEEE: statement_item
|
||||
| statementVerilatorPragmas { $$ = $1; }
|
||||
//
|
||||
// // IEEE: disable_statement
|
||||
//UNSUP yDISABLE idAny/*hierarchical_identifier-task_or_block*/ ';' { UNSUP }
|
||||
| yDISABLE idAny/*hierarchical_identifier-task_or_block*/ ';' { $$ = new AstDisable($1,*$2); }
|
||||
//UNSUP yDISABLE yFORK ';' { UNSUP }
|
||||
// // IEEE: event_trigger
|
||||
//UNSUP yP_MINUSGT hierarchical_identifier/*event*/ ';' { UNSUP }
|
||||
@@ -2115,6 +2153,8 @@ system_f_call<nodep>: // IEEE: system_tf_call (as func)
|
||||
| yaD_DPI '(' exprList ')' { $$ = new AstFuncRef($2,*$1,$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_CLOG2 '(' expr ')' { $$ = new AstCLog2($1,$3); }
|
||||
| yD_COUNTONES '(' expr ')' { $$ = new AstCountOnes($1,$3); }
|
||||
@@ -2124,10 +2164,14 @@ system_f_call<nodep>: // IEEE: system_tf_call (as func)
|
||||
| yD_FSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstFScanF($1,*$5,$3,$6); }
|
||||
| yD_SSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstSScanF($1,*$5,$3,$6); }
|
||||
| yD_ISUNKNOWN '(' expr ')' { $$ = new AstIsUnknown($1,$3); }
|
||||
| yD_ITOR '(' expr ')' { $$ = new AstIToRD($1,$3); }
|
||||
| yD_ONEHOT '(' expr ')' { $$ = new AstOneHot($1,$3); }
|
||||
| yD_ONEHOT0 '(' expr ')' { $$ = new AstOneHot0($1,$3); }
|
||||
| yD_RANDOM '(' expr ')' { $1->v3error("Unsupported: Seeding $random doesn't map to C++, use $c(\"srand\")"); }
|
||||
| yD_RANDOM parenE { $$ = new AstRand($1); }
|
||||
| yD_REALTIME parenE { $$ = new AstTimeD($1); }
|
||||
| yD_REALTOBITS '(' expr ')' { $$ = new AstRealToBits($1,$3); }
|
||||
| yD_RTOI '(' expr ')' { $$ = new AstRToIS($1,$3); }
|
||||
//| yD_SFORMATF '(' str commaEListE ')' { $$ = new AstSFormatF($1,*$3,false,$4); } // Have AST, just need testing and debug
|
||||
| yD_SIGNED '(' expr ')' { $$ = new AstSigned($1,$3); }
|
||||
| yD_STIME parenE { $$ = new AstSel($1,new AstTime($1),0,32); }
|
||||
@@ -2348,7 +2392,7 @@ expr<nodep>: // IEEE: part of expression/constant_expression/primary
|
||||
//
|
||||
// // IEEE: unary_operator primary
|
||||
'+' ~r~expr %prec prUNARYARITH { $$ = $2; }
|
||||
| '-' ~r~expr %prec prUNARYARITH { $$ = new AstUnaryMin ($1,$2); }
|
||||
| '-' ~r~expr %prec prUNARYARITH { $$ = new AstNegate ($1,$2); }
|
||||
| '!' ~r~expr %prec prNEGATION { $$ = new AstLogNot ($1,$2); }
|
||||
| '&' ~r~expr %prec prREDUCTION { $$ = new AstRedAnd ($1,$2); }
|
||||
| '~' ~r~expr %prec prNEGATION { $$ = new AstNot ($1,$2); }
|
||||
@@ -2426,7 +2470,7 @@ expr<nodep>: // IEEE: part of expression/constant_expression/primary
|
||||
//
|
||||
// // IEEE: primary_literal (minus string, which is handled specially)
|
||||
| yaINTNUM { $$ = new AstConst($<fl>1,*$1); }
|
||||
//UNSUP yaFLOATNUM { UNSUP }
|
||||
| yaFLOATNUM { $$ = new AstConst($<fl>1,AstConst::RealDouble(),$1); }
|
||||
//UNSUP yaTIMENUM { UNSUP }
|
||||
| strAsInt~noStr__IGNORE~ { $$ = $1; }
|
||||
//
|
||||
@@ -2454,7 +2498,10 @@ expr<nodep>: // IEEE: part of expression/constant_expression/primary
|
||||
| '_' '(' statePushVlg expr statePop ')' { $$ = $4; } // Arbitrary Verilog inside PSL
|
||||
//
|
||||
// // 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
|
||||
// // We'll be more general, and later assert LHS was a type.
|
||||
//UNSUP ~l~expr yP_TICK '(' expr ')' { UNSUP }
|
||||
@@ -2681,46 +2728,58 @@ gateUnsupList<nodep>:
|
||||
;
|
||||
|
||||
gateBuf<nodep>:
|
||||
gateIdE instRangeE '(' idClassSel ',' expr ')' { $$ = new AstAssignW ($3,$4,$6); }
|
||||
gateIdE instRangeE '(' variable_lvalue ',' expr ')'
|
||||
{ $$ = new AstAssignW ($3,$4,$6); }
|
||||
;
|
||||
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>:
|
||||
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>:
|
||||
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>:
|
||||
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>:
|
||||
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>:
|
||||
gateIdE instRangeE '(' idClassSel ',' gateAndPinList ')' { $$ = new AstAssignW ($3,$4,$6); }
|
||||
gateIdE instRangeE '(' variable_lvalue ',' gateAndPinList ')'
|
||||
{ $$ = new AstAssignW ($3,$4,$6); }
|
||||
;
|
||||
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>:
|
||||
gateIdE instRangeE '(' idClassSel ',' gateOrPinList ')' { $$ = new AstAssignW ($3,$4,$6); }
|
||||
gateIdE instRangeE '(' variable_lvalue ',' gateOrPinList ')'
|
||||
{ $$ = new AstAssignW ($3,$4,$6); }
|
||||
;
|
||||
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>:
|
||||
gateIdE instRangeE '(' idClassSel ',' gateXorPinList ')' { $$ = new AstAssignW ($3,$4,$6); }
|
||||
gateIdE instRangeE '(' variable_lvalue ',' gateXorPinList ')'
|
||||
{ $$ = new AstAssignW ($3,$4,$6); }
|
||||
;
|
||||
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>:
|
||||
gateIdE instRangeE '(' idClassSel ')' { $$ = new AstPull ($3, $4, true); }
|
||||
gateIdE instRangeE '(' variable_lvalue ')' { $$ = new AstPull ($3, $4, true); }
|
||||
;
|
||||
gatePulldown<nodep>:
|
||||
gateIdE instRangeE '(' idClassSel ')' { $$ = new AstPull ($3, $4, false); }
|
||||
gateIdE instRangeE '(' variable_lvalue ')' { $$ = new AstPull ($3, $4, false); }
|
||||
;
|
||||
gateUnsup<nodep>:
|
||||
gateIdE instRangeE '(' gateUnsupPinList ')' { $$ = new AstImplicit ($3,$4); }
|
||||
@@ -2797,7 +2856,7 @@ junkToSemiList:
|
||||
junkToSemi { } /* ignored */
|
||||
| junkToSemiList junkToSemi { } /* ignored */
|
||||
;
|
||||
|
||||
|
||||
junkToSemi:
|
||||
BISONPRE_NOT(';',yENDSPECIFY,yENDMODULE) { }
|
||||
| error {}
|
||||
@@ -3068,7 +3127,7 @@ vltOffFront<errcodeen>:
|
||||
|
||||
int V3ParseImp::bisonParse() {
|
||||
if (PARSEP->debugBison()>=9) yydebug = 1;
|
||||
return yyparse();
|
||||
return yyparse();
|
||||
}
|
||||
|
||||
const char* V3ParseImp::tokenName(int token) {
|
||||
|
||||
+64
-42
@@ -110,8 +110,8 @@ if ($#opt_tests<0) {
|
||||
}
|
||||
|
||||
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 @fails;
|
||||
|
||||
@@ -161,16 +161,17 @@ sub one_test {
|
||||
push @fails, "\t\tmake$j && test_regress/"
|
||||
.$test->{pl_filename}." ".join(' ',@Orig_ARGV_Sw)."\n";
|
||||
$failcnt++;
|
||||
report(\@fails, $Log_Filename);
|
||||
if ($opt_stop) { die "%Error: --stop and errors found\n"; }
|
||||
}
|
||||
$leftcnt--;
|
||||
print "==SUMMARY: Left $leftcnt Passed $okcnt Skipped $skcnt Failed $failcnt\n";
|
||||
print STDERR "==SUMMARY: Left $leftcnt Passed $okcnt Skipped $skcnt Failed $failcnt\n";
|
||||
},
|
||||
)->ready();
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@@ -303,8 +304,9 @@ sub new {
|
||||
ivrun_flags => [],
|
||||
# VCS
|
||||
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
|
||||
vcsrun_flags => [split(/\s+/,"+vcs+lic_wait")],
|
||||
# NC
|
||||
nc => 0,
|
||||
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->{coverage_filename} ||= "$self->{obj_dir}/vlt_coverage.pl";
|
||||
$self->{vcd_filename} ||= "$self->{obj_dir}/sim.vcd";
|
||||
$self->{main_filename} ||= "$self->{obj_dir}/$self->{VM_PREFIX}__main.cpp";
|
||||
($self->{top_filename} = $self->{pl_filename}) =~ s/\.pl$/\.v/;
|
||||
if (!$self->{make_top_shell}) {
|
||||
$self->{top_shell_filename} = $self->{top_filename};
|
||||
@@ -408,11 +411,10 @@ sub read_status {
|
||||
#----------------------------------------------------------------------
|
||||
# Methods invoked by tests
|
||||
|
||||
sub compile {
|
||||
sub compile_vlt_flags {
|
||||
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");
|
||||
|
||||
my $checkflags = join(' ',@{$param{v_flags}},
|
||||
@{$param{v_flags2}},
|
||||
@@ -423,6 +425,48 @@ sub compile {
|
||||
$self->{trace} = 1 if ($opt_trace || $checkflags =~ /-trace\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}) {
|
||||
$self->_make_top();
|
||||
$self->_run(logfile=>"$self->{obj_dir}/atsim_compile.log",
|
||||
@@ -482,37 +526,8 @@ sub compile {
|
||||
cmd=>\@cmd);
|
||||
}
|
||||
if ($param{vlt}) {
|
||||
$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 = $self->compile_vlt_flags(%param);
|
||||
|
||||
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}) {
|
||||
$self->skip("Test requires SystemC; ignore error since not installed\n");
|
||||
return 1;
|
||||
@@ -522,16 +537,18 @@ sub compile {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!$param{fails} && $param{verilator_make_gcc}
|
||||
&& $param{make_main}) {
|
||||
$self->_make_main();
|
||||
}
|
||||
|
||||
$self->_run(logfile=>"$self->{obj_dir}/vlt_compile.log",
|
||||
fails=>$param{fails},
|
||||
expect=>$param{expect},
|
||||
cmd=>\@vlargs);
|
||||
cmd=>\@cmdargs);
|
||||
return 1 if $self->errors || $self->skips;
|
||||
|
||||
if (!$param{fails} && $param{verilator_make_gcc}) {
|
||||
if ($param{make_main}) {
|
||||
$self->_make_main();
|
||||
}
|
||||
if ($self->sp) {
|
||||
$self->_sp_preproc(%param);
|
||||
}
|
||||
@@ -590,6 +607,7 @@ sub execute {
|
||||
#$fh->print("quit\n"); $fh->close;
|
||||
$self->_run(logfile=>"$self->{obj_dir}/vcs_sim.log",
|
||||
cmd=>["echo q | ".$run_env."./simv",
|
||||
@{$param{vcsrun_flags}},
|
||||
@{$param{all_run_flags}},
|
||||
],
|
||||
%param,
|
||||
@@ -791,7 +809,7 @@ sub _make_main {
|
||||
|
||||
$self->_read_inputs();
|
||||
|
||||
my $filename = "$self->{obj_dir}/$self->{VM_PREFIX}__main.cpp";
|
||||
my $filename = $self->{main_filename};
|
||||
my $fh = IO::File->new(">$filename") or die "%Error: $! $filename,";
|
||||
|
||||
print $fh "// Test defines\n";
|
||||
@@ -879,8 +897,12 @@ sub _make_main {
|
||||
print $fh ' vl_fatal(__FILE__,__LINE__,"main", "%Error: Timeout; never got a $finish");',"\n";
|
||||
print $fh " }\n";
|
||||
print $fh " topp->final();\n";
|
||||
print $fh " SpCoverage::write(\"",$self->{coverage_filename},"\");\n" if $self->{coverage};
|
||||
|
||||
if ($self->{coverage}) {
|
||||
$fh->print("#if VM_COVERAGE\n");
|
||||
$fh->print(" SpCoverage::write(\"",$self->{coverage_filename},"\");\n");
|
||||
$fh->print("#endif //VM_COVERAGE\n");
|
||||
}
|
||||
if ($self->{trace}) {
|
||||
$fh->print("#if VM_TRACE\n");
|
||||
$fh->print(" if (tfp) tfp->close();\n");
|
||||
|
||||
@@ -47,7 +47,7 @@ module t (/*AUTOARG*/
|
||||
endcase
|
||||
end
|
||||
|
||||
`ifdef NOT_YET_verilator
|
||||
`ifdef NOT_YET_VERILATOR // Unsupported
|
||||
// ambit synthesis one_hot "a, b_oh"
|
||||
// cadence one_cold "a_l, b_oc_l"
|
||||
`endif
|
||||
|
||||
@@ -25,7 +25,7 @@ module t_case_huge_sub2 (/*AUTOARG*/
|
||||
|
||||
always @(/*AS*/index) begin
|
||||
case (index[7:0])
|
||||
`ifdef verilator
|
||||
`ifdef VERILATOR // Harder test
|
||||
8'h00: begin outa = $c("0"); end // Makes whole table non-optimizable
|
||||
`else
|
||||
8'h00: begin outa = 10'h0; end
|
||||
|
||||
@@ -2497,11 +2497,7 @@ module t_case_write1_tasks ();
|
||||
endtask
|
||||
|
||||
task big_case;
|
||||
`ifdef verilator
|
||||
input [ 63:0] fd;
|
||||
`else
|
||||
input [ 31:0] fd;
|
||||
`endif
|
||||
input [ 31:0] foo;
|
||||
reg [STRLEN*8: 1] foobar;
|
||||
// verilator no_inline_task
|
||||
|
||||
@@ -10,11 +10,7 @@ module t_case_write2_tasks ();
|
||||
// verilator lint_off WIDTH
|
||||
// verilator lint_off CASEINCOMPLETE
|
||||
|
||||
`ifdef verilator
|
||||
`define FD_BITS 63:0
|
||||
`else
|
||||
`define FD_BITS 31:0
|
||||
`endif
|
||||
|
||||
parameter STRLEN = 78;
|
||||
task ozonerab;
|
||||
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,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
|
||||
@@ -86,7 +86,7 @@ module Test (/*AUTOARG*/
|
||||
end
|
||||
|
||||
reg displayit;
|
||||
`ifdef verilator
|
||||
`ifdef VERILATOR // Harder test
|
||||
initial displayit = $c1("0"); // Something that won't optimize away
|
||||
`else
|
||||
initial displayit = '0;
|
||||
|
||||
@@ -59,7 +59,9 @@ module t (/*AUTOARG*/
|
||||
|
||||
reg [7:0] cyc; initial cyc=0;
|
||||
always @ (posedge clk) begin
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("[%0t] rs %x cyc %d cg1f %x cnt %x cg %x\n",$time,reset_l,cyc,clkgate_e1f,count,countgated);
|
||||
`endif
|
||||
cyc <= cyc + 8'd1;
|
||||
case (cyc)
|
||||
8'd00: begin
|
||||
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003-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;
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
top_filename("t/t_cover_line.v");
|
||||
|
||||
compile (
|
||||
verilator_flags2 => ['--sc --coverage-line'],
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
# Read the input .v file and do any CHECK_COVER requests
|
||||
inline_checks();
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -7,6 +7,8 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
top_filename("t/t_cover_line.v");
|
||||
|
||||
compile (
|
||||
verilator_flags2 => ['--sp --coverage-line'],
|
||||
);
|
||||
@@ -19,10 +19,12 @@ execute (
|
||||
[0] In top.v.sub2
|
||||
[0] In top.v.sub2.subblock2
|
||||
[0] Back \ Quote "
|
||||
[0] %X=0c %D=12 %0X=c %0O=14 %B=001100
|
||||
[0] %x=0c %d=12 %0x=c %0o=14 %b=001100
|
||||
[0] %X=00c %0X=c %0O=14 %B=000001100
|
||||
[0] %x=00c %0x=c %0o=14 %b=000001100
|
||||
[0] %D= 12 %d= 12 %01d=12 %06d=000012 %6d= 12
|
||||
[0] %x=00abbbbcccc %0x=abbbbcccc %o=00527356746314 %b=00000101010111011101110111100110011001100
|
||||
[0] %x=00abc1234567812345678 %0x=abc1234567812345678 %o=012570110642547402215053170 %b=000001010101111000001001000110100010101100111100000010010001101000101011001111000
|
||||
[0] %t= 0 %03t= 0 %0t=0
|
||||
|
||||
[0] %s=! %s= what! %s= hmmm!1234
|
||||
[0] hello, from a very long string. Percent %s are literally substituted in.
|
||||
|
||||
@@ -9,6 +9,7 @@ module t;
|
||||
reg [31:0] str; initial str = "\000\277\021\n";
|
||||
reg [47:0] str2; initial str2 = "\000what!";
|
||||
reg [79:0] str3; initial str3 = "\000hmmm!1234";
|
||||
reg [8:0] nine;
|
||||
|
||||
sub sub ();
|
||||
sub2 sub2 ();
|
||||
@@ -22,14 +23,19 @@ module t;
|
||||
$display("[%0t] Back \\ Quote \"", $time); // Old bug when \" last on the line.
|
||||
|
||||
// Display formatting
|
||||
$display("[%0t] %%X=%X %%D=%D %%0X=%0X %%0O=%0O %%B=%B", $time,
|
||||
quad[5:0], quad[5:0], quad[5:0], quad[5:0], quad[5:0]);
|
||||
$display("[%0t] %%x=%x %%d=%d %%0x=%0x %%0o=%0o %%b=%b", $time,
|
||||
quad[5:0], quad[5:0], quad[5:0], quad[5:0], quad[5:0]);
|
||||
nine = {3'd0,quad[5:0]};
|
||||
$display("[%0t] %%X=%X %%0X=%0X %%0O=%0O %%B=%B", $time,
|
||||
nine, nine, nine, nine);
|
||||
$display("[%0t] %%x=%x %%0x=%0x %%0o=%0o %%b=%b", $time,
|
||||
nine, nine, nine, nine);
|
||||
$display("[%0t] %%D=%D %%d=%d %%01d=%01d %%06d=%06d %%6d=%6d", $time,
|
||||
nine, nine, nine, nine, nine);
|
||||
$display("[%0t] %%x=%x %%0x=%0x %%o=%o %%b=%b", $time,
|
||||
quad, quad, quad, quad);
|
||||
$display("[%0t] %%x=%x %%0x=%0x %%o=%o %%b=%b", $time,
|
||||
wide, wide, wide, wide);
|
||||
$display("[%0t] %%t=%t %%03t=%03t %%0t=%0t", $time,
|
||||
$time, $time, $time);
|
||||
$display;
|
||||
// Not testing %0s, it does different things in different simulators
|
||||
$display("[%0t] %%s=%s %%s=%s %%s=%s", $time,
|
||||
|
||||
@@ -22,10 +22,12 @@ execute (
|
||||
[0] In top.v.sub2
|
||||
[0] In top.v.sub2.subblock2
|
||||
[0] Back \ Quote "
|
||||
[0] %X=0c %D=12 %0X=c %0O=14 %B=001100
|
||||
[0] %x=0c %d=12 %0x=c %0o=14 %b=001100
|
||||
[0] %X=00c %0X=c %0O=14 %B=000001100
|
||||
[0] %x=00c %0x=c %0o=14 %b=000001100
|
||||
[0] %D= 12 %d= 12 %01d=12 %06d=000012 %6d= 12
|
||||
[0] %x=00abbbbcccc %0x=abbbbcccc %o=00527356746314 %b=00000101010111011101110111100110011001100
|
||||
[0] %x=00abc1234567812345678 %0x=abc1234567812345678 %o=012570110642547402215053170 %b=000001010101111000001001000110100010101100111100000010010001101000101011001111000
|
||||
[0] %t= 0 %03t= 0 %0t=0
|
||||
|
||||
[0] %s=! %s= what! %s= hmmm!1234
|
||||
[0] hello, from a very long string. Percent %s are literally substituted in.
|
||||
|
||||
Executable
+39
@@ -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;
|
||||
@@ -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
|
||||
Executable
+42
@@ -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;
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
$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;
|
||||
@@ -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
|
||||
@@ -23,6 +23,7 @@ module t;
|
||||
function int dpix_int123(); dpix_int123 = 32'h123; endfunction
|
||||
|
||||
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_byte;
|
||||
export "DPI-C" function dpix_f_shortint;
|
||||
@@ -30,12 +31,18 @@ module t;
|
||||
export "DPI-C" function dpix_f_chandle;
|
||||
|
||||
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 byte dpix_f_byte (byte i); dpix_f_byte = ~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 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;
|
||||
|
||||
initial begin
|
||||
|
||||
@@ -123,8 +123,11 @@ int dpix_run_tests() {
|
||||
CHECK_RESULT (int, o, 0x458UL);
|
||||
#endif
|
||||
|
||||
svBitVecVal vec10[1] = {0x10};
|
||||
|
||||
CHECK_RESULT (int, dpix_f_bit(1), 0x0);
|
||||
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
|
||||
CHECK_RESULT (int, dpix_f_int(1) & 0xffffffffUL, 0xfffffffeUL);
|
||||
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 (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.b",2)) return bad;
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
`ifdef NC
|
||||
`define NO_SHORTREAL
|
||||
`endif
|
||||
`ifdef VERILATOR
|
||||
`ifdef VERILATOR // Unsupported
|
||||
`define NO_SHORTREAL
|
||||
`endif
|
||||
|
||||
@@ -39,9 +39,7 @@ module t ();
|
||||
import "DPI-C" pure function longint dpii_f_longint (input longint i);
|
||||
import "DPI-C" pure function chandle dpii_f_chandle (input chandle i);
|
||||
import "DPI-C" pure function string dpii_f_string (input string i);
|
||||
`ifndef VERILATOR
|
||||
import "DPI-C" pure function real dpii_f_real (input real i);
|
||||
`endif
|
||||
`ifndef NO_SHORTREAL
|
||||
import "DPI-C" pure function shortreal dpii_f_shortreal(input shortreal i);
|
||||
`endif
|
||||
@@ -53,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_chandle (input chandle i, output chandle o);
|
||||
import "DPI-C" pure function void dpii_v_string (input string i, output string o);
|
||||
`ifndef VERILATOR
|
||||
import "DPI-C" pure function void dpii_v_real (input real i, output real o);
|
||||
`endif
|
||||
`ifndef NO_SHORTREAL
|
||||
import "DPI-C" pure function void dpii_v_shortreal(input shortreal i, output shortreal o);
|
||||
`endif
|
||||
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);
|
||||
|
||||
@@ -82,6 +80,8 @@ module t ();
|
||||
bit [31:0] i_b32, o_b32;
|
||||
bit [32:0] i_b33, o_b33;
|
||||
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;
|
||||
byte i_y, o_y;
|
||||
@@ -89,9 +89,7 @@ module t ();
|
||||
longint i_l, o_l;
|
||||
chandle i_c, o_c;
|
||||
string i_n, o_n;
|
||||
`ifndef VERILATOR
|
||||
real i_d, o_d;
|
||||
`endif
|
||||
`ifndef NO_SHORTREAL
|
||||
shortreal i_f, o_f;
|
||||
`endif
|
||||
@@ -111,11 +109,17 @@ module t ();
|
||||
i_b32 = {1'b1,wide[32-2:0]};
|
||||
i_b33 = {1'b1,wide[33-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_y = {1'b1,wide[8-2:0]};
|
||||
i_s = {1'b1,wide[16-2:0]};
|
||||
i_l = {1'b1,wide[64-2:0]};
|
||||
i_d = 32.1;
|
||||
`ifndef NO_SHORTREAL
|
||||
i_f = 30.2;
|
||||
`endif
|
||||
|
||||
if (dpii_f_bit (i_b) !== ~i_b) $stop;
|
||||
if (dpii_f_bit8 (i_b8) !== ~i_b8) $stop;
|
||||
@@ -139,9 +143,7 @@ module t ();
|
||||
if (dpii_f_longint (i_l) !== ~i_l) $stop;
|
||||
if (dpii_f_chandle (i_c) !== i_c) $stop;
|
||||
if (dpii_f_string (i_n) != i_n) $stop;
|
||||
`ifndef VERILATOR
|
||||
if (dpii_f_real (i_d) != i_d+1.5) $stop;
|
||||
`endif
|
||||
`ifndef NO_SHORTREAL
|
||||
if (dpii_f_shortreal(i_f) != i_f+1.5) $stop;
|
||||
`endif
|
||||
@@ -153,12 +155,12 @@ module t ();
|
||||
dpii_v_longint (i_l,o_l); if (o_l !== ~i_l) $stop;
|
||||
dpii_v_chandle (i_c,o_c); if (o_c !== i_c) $stop;
|
||||
dpii_v_string (i_n,o_n); if (o_n != i_n) $stop;
|
||||
`ifndef VERILATOR
|
||||
dpii_v_real (i_d,o_d); if (o_d != i_d+1.5) $stop;
|
||||
`endif
|
||||
`ifndef NO_SHORTREAL
|
||||
dpii_v_shortreal(i_f,o_f); if (o_f != i_f+1.5) $stop;
|
||||
`endif
|
||||
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 ("s")!=1) $stop;
|
||||
|
||||
@@ -33,13 +33,14 @@
|
||||
extern "C" {
|
||||
|
||||
extern unsigned char dpii_f_bit (unsigned char i);
|
||||
extern svBitVecVal dpii_f_bit8 (const svBitVecVal *i);
|
||||
extern svBitVecVal dpii_f_bit9 (const svBitVecVal *i);
|
||||
extern svBitVecVal dpii_f_bit16 (const svBitVecVal *i);
|
||||
extern svBitVecVal dpii_f_bit17 (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_bit64 (const svBitVecVal *i);
|
||||
extern svBitVecVal dpii_f_bit8 (const svBitVecVal* i);
|
||||
extern svBitVecVal dpii_f_bit9 (const svBitVecVal* i);
|
||||
extern svBitVecVal dpii_f_bit16 (const svBitVecVal* i);
|
||||
extern svBitVecVal dpii_f_bit17 (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_bit64 (const svBitVecVal* i);
|
||||
extern long long dpii_f_bit95 (const svBitVecVal* i, svBitVecVal* o);
|
||||
extern int dpii_f_int (int i);
|
||||
extern char dpii_f_byte (char i);
|
||||
extern short int dpii_f_shortint(short int i);
|
||||
@@ -49,7 +50,7 @@ extern "C" {
|
||||
extern double dpii_f_real (double 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_byte (char i, char *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_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); }
|
||||
|
||||
//======================================================================
|
||||
|
||||
Executable
+51
@@ -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;
|
||||
@@ -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
|
||||
@@ -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););
|
||||
}
|
||||
@@ -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
|
||||
@@ -0,0 +1,90 @@
|
||||
// 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_wrap (/*AUTOARG*/
|
||||
// Outputs
|
||||
bit_out, vec_out, wide_out, did_init_out,
|
||||
// Inputs
|
||||
clk, bit_in, vec_in, wide_in, is_ref
|
||||
);
|
||||
|
||||
/*AUTOINOUTMODULE("t_embed1_child")*/
|
||||
// Beginning of automatic in/out/inouts (from specific module)
|
||||
output bit_out;
|
||||
output [30:0] vec_out;
|
||||
output [123:0] wide_out;
|
||||
output did_init_out;
|
||||
input clk;
|
||||
input bit_in;
|
||||
input [30:0] vec_in;
|
||||
input [123:0] wide_in;
|
||||
input is_ref;
|
||||
// End of automatics
|
||||
|
||||
`ifdef verilator
|
||||
// Import $t_embed_child__initial etc as a DPI function
|
||||
`endif
|
||||
|
||||
//TODO would like __'s as in {PREFIX}__initial but presently illegal for users to do this
|
||||
import "DPI-C" context function void t_embed_child_initial();
|
||||
import "DPI-C" context function void t_embed_child_final();
|
||||
import "DPI-C" context function void t_embed_child_eval();
|
||||
import "DPI-C" context function void t_embed_child_io_eval
|
||||
(
|
||||
//TODO we support bit, but not logic
|
||||
input bit clk,
|
||||
input bit bit_in,
|
||||
input bit [30:0] vec_in,
|
||||
input bit [123:0] wide_in,
|
||||
input bit is_ref,
|
||||
output bit bit_out,
|
||||
output bit [30:0] vec_out,
|
||||
output bit [123:0] wide_out,
|
||||
output bit did_init_out);
|
||||
|
||||
initial begin
|
||||
// Load all values
|
||||
t_embed_child_initial();
|
||||
end
|
||||
|
||||
// Only if system verilog, and if a "final" block in the code
|
||||
final begin
|
||||
t_embed_child_final();
|
||||
end
|
||||
|
||||
bit _temp_bit_out;
|
||||
bit _temp_did_init_out;
|
||||
bit [30:0] _temp_vec_out;
|
||||
bit [123:0] _temp_wide_out;
|
||||
always @* begin
|
||||
t_embed_child_io_eval(
|
||||
clk,
|
||||
bit_in,
|
||||
vec_in,
|
||||
wide_in,
|
||||
is_ref,
|
||||
_temp_bit_out,
|
||||
_temp_vec_out,
|
||||
_temp_wide_out,
|
||||
_temp_did_init_out
|
||||
);
|
||||
// TODO might eliminate these temporaries
|
||||
bit_out = _temp_bit_out;
|
||||
did_init_out = _temp_did_init_out;
|
||||
end
|
||||
|
||||
|
||||
// Send all variables every cycle,
|
||||
// or have a sensitivity routine for each?
|
||||
// How to make sure we call eval at end of variable changes?
|
||||
// #0 (though not verilator compatible!)
|
||||
|
||||
// TODO for now, we know what changes when
|
||||
always @ (posedge clk) begin
|
||||
vec_out <= _temp_vec_out;
|
||||
wide_out <= _temp_wide_out;
|
||||
end
|
||||
|
||||
endmodule
|
||||
@@ -3,6 +3,13 @@
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2009 by Wilson Snyder.
|
||||
|
||||
typedef enum logic [4:0]
|
||||
{
|
||||
BIT0 = 5'd0,
|
||||
BIT1 = 5'd1,
|
||||
BIT2 = 5'd2
|
||||
} three_t;
|
||||
|
||||
module t (/*AUTOARG*/);
|
||||
|
||||
localparam FIVE = 5;
|
||||
@@ -48,6 +55,11 @@ module t (/*AUTOARG*/);
|
||||
if (three != 3'b111) $stop;
|
||||
|
||||
if ($bits(sized_based_on_enum) != 8) $stop;
|
||||
if ($bits(three_t) != 3) $stop;
|
||||
|
||||
if (FIVE[BIT0] != 1'b1) $stop;
|
||||
if (FIVE[BIT1] != 1'b0) $stop;
|
||||
if (FIVE[BIT2] != 1'b1) $stop;
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
|
||||
@@ -55,7 +55,7 @@ module t (/*AUTOARG*/
|
||||
#error "`systemc_header didn't work"
|
||||
#endif
|
||||
bool m_did_ctor;
|
||||
uint32_t my_function() {
|
||||
vluint32_t my_function() {
|
||||
if (!m_did_ctor) vl_fatal(__FILE__,__LINE__,__FILE__,"`systemc_ctor didn't work");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Test that environment substitutions work
|
||||
-f $VERILATOR_ROOT/test_regress/t/t_flag_f__2.vc
|
||||
// Env var with .v file
|
||||
$VERILATOR_ROOT/test_regress/t/t_flag_f__3.v
|
||||
// Env var with .v file, and parens
|
||||
${VERILATOR_ROOT}/test_regress/t/t_flag_f__3.v
|
||||
// Test -f
|
||||
-F $VERILATOR_ROOT/test_regress/t/tsub/t_flag_f_tsub.vc
|
||||
|
||||
Executable
+25
@@ -0,0 +1,25 @@
|
||||
#!/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_flag_wfatal.v");
|
||||
|
||||
compile (
|
||||
v_flags2 => ["--lint-only -Wno-fatal"],
|
||||
fails=>0,
|
||||
verilator_make_gcc => 0,
|
||||
make_top_shell => 0,
|
||||
make_main => 0,
|
||||
expect=>
|
||||
q{%Warning-WIDTH: t/t_flag_wfatal.v:\d+: Operator ASSIGNW expects 4 bits on the Assign RHS, but Assign RHS.s CONST '6'h2e' generates 6 bits.
|
||||
%Warning-WIDTH: Use .* and lint_on around source to disable this message.
|
||||
},
|
||||
) if $Self->{v3};
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,11 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2005 by Wilson Snyder.
|
||||
|
||||
module t (/*AUTOARG*/);
|
||||
|
||||
// Width error below
|
||||
wire [3:0] foo = 6'h2e;
|
||||
|
||||
endmodule
|
||||
@@ -92,8 +92,17 @@ module t (/*AUTOARG*/
|
||||
input [3:0] loop_continue;
|
||||
integer i;
|
||||
|
||||
// Placeholder
|
||||
return Test0(loop_stop,loop_break,loop_continue);
|
||||
Test1 = 0;
|
||||
begin : outer_block
|
||||
for (i=1; i<20; i=i+1) begin : inner_block
|
||||
Test1 = Test1 + 1;
|
||||
// continue, IE jump to end-of-inner_block. Must be inside inner_block.
|
||||
if (i[3:0] == loop_continue) disable inner_block;
|
||||
// break, IE jump to end-of-outer_block. Must be inside outer_block.
|
||||
if (i[3:0] == loop_break) disable outer_block;
|
||||
Test1 = Test1 + i[15:0];
|
||||
end : inner_block
|
||||
end : outer_block
|
||||
endfunction
|
||||
|
||||
function [15:0] Test2;
|
||||
|
||||
@@ -13,8 +13,6 @@ compile (
|
||||
expect=>
|
||||
q{%Error: t/t_func_bad.v:\d+: Too few arguments in function call to FUNC 'add'
|
||||
%Error: t/t_func_bad.v:\d+: Too few arguments in function call to FUNC 'add'
|
||||
%Error: t/t_func_bad.v:\d+: Too few arguments in function call to FUNC 'add'
|
||||
%Error: t/t_func_bad.v:\d+: Too few arguments in function call to FUNC 'add'
|
||||
%Error: t/t_func_bad.v:\d+: Too many arguments in function call to FUNC 'add'
|
||||
%Error: t/t_func_bad.v:\d+: Too few arguments in function call to TASK 'x'
|
||||
%Error: t/t_func_bad.v:\d+: Too few arguments in function call to TASK 'x'
|
||||
|
||||
@@ -100,7 +100,7 @@ module tpub (
|
||||
if (1'b1 != got_bool) $stop;
|
||||
$c("publicGetLong(got_long);");
|
||||
if (24'h11bca != got_long) $stop;
|
||||
$c("{ uint64_t qq; publicGetQuad(qq); got_quad=qq; }");
|
||||
$c("{ vluint64_t qq; publicGetQuad(qq); got_quad=qq; }");
|
||||
if (60'haaaa_bbbb_cccc != got_quad) $stop;
|
||||
$c("{ WData gw[3]; publicGetWide(gw); VL_ASSIGN_W(72,got_wide,gw); }");
|
||||
if (72'hac_abca_aaaa_bbbb_1234 != got_wide) $stop;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user