Four-state logic squash - signals interleave
Signed-off-by: Igor Zaworski <izaworski@antmicro.com>
This commit is contained in:
parent
e5dcf11cb8
commit
b498f1db3f
|
|
@ -199,6 +199,13 @@ jobs:
|
||||||
- {os: ubuntu-26.04, cc: gcc, reloc: 0, suite: vltmt-0}
|
- {os: ubuntu-26.04, cc: gcc, reloc: 0, suite: vltmt-0}
|
||||||
- {os: ubuntu-26.04, cc: gcc, reloc: 0, suite: vltmt-1}
|
- {os: ubuntu-26.04, cc: gcc, reloc: 0, suite: vltmt-1}
|
||||||
- {os: ubuntu-26.04, cc: gcc, reloc: 0, suite: vltmt-2}
|
- {os: ubuntu-26.04, cc: gcc, reloc: 0, suite: vltmt-2}
|
||||||
|
- {os: ubuntu-26.04, cc: gcc, reloc: 0, suite: dist-vlt4-0}
|
||||||
|
- {os: ubuntu-26.04, cc: gcc, reloc: 0, suite: dist-vlt4-1}
|
||||||
|
- {os: ubuntu-26.04, cc: gcc, reloc: 0, suite: dist-vlt4-2}
|
||||||
|
- {os: ubuntu-26.04, cc: gcc, reloc: 0, suite: dist-vlt4-3}
|
||||||
|
- {os: ubuntu-26.04, cc: gcc, reloc: 0, suite: vltmt4-0}
|
||||||
|
- {os: ubuntu-26.04, cc: gcc, reloc: 0, suite: vltmt4-1}
|
||||||
|
- {os: ubuntu-26.04, cc: gcc, reloc: 0, suite: vltmt4-2}
|
||||||
|
|
||||||
test-2604-clang:
|
test-2604-clang:
|
||||||
name: Test | ${{ matrix.os }} | ${{ matrix.cc }} | ${{ matrix.reloc && 'reloc | ' || '' }} ${{ matrix.suite }}
|
name: Test | ${{ matrix.os }} | ${{ matrix.cc }} | ${{ matrix.reloc && 'reloc | ' || '' }} ${{ matrix.suite }}
|
||||||
|
|
@ -223,6 +230,13 @@ jobs:
|
||||||
- {os: ubuntu-26.04, cc: clang, reloc: 0, suite: vltmt-0}
|
- {os: ubuntu-26.04, cc: clang, reloc: 0, suite: vltmt-0}
|
||||||
- {os: ubuntu-26.04, cc: clang, reloc: 0, suite: vltmt-1}
|
- {os: ubuntu-26.04, cc: clang, reloc: 0, suite: vltmt-1}
|
||||||
- {os: ubuntu-26.04, cc: clang, reloc: 0, suite: vltmt-2}
|
- {os: ubuntu-26.04, cc: clang, reloc: 0, suite: vltmt-2}
|
||||||
|
- {os: ubuntu-26.04, cc: clang, reloc: 0, suite: dist-vlt4-0}
|
||||||
|
- {os: ubuntu-26.04, cc: clang, reloc: 0, suite: dist-vlt4-1}
|
||||||
|
- {os: ubuntu-26.04, cc: clang, reloc: 0, suite: dist-vlt4-2}
|
||||||
|
- {os: ubuntu-26.04, cc: clang, reloc: 0, suite: dist-vlt4-3}
|
||||||
|
- {os: ubuntu-26.04, cc: clang, reloc: 0, suite: vltmt4-0}
|
||||||
|
- {os: ubuntu-26.04, cc: clang, reloc: 0, suite: vltmt4-1}
|
||||||
|
- {os: ubuntu-26.04, cc: clang, reloc: 0, suite: vltmt4-2}
|
||||||
|
|
||||||
test-2404-gcc:
|
test-2404-gcc:
|
||||||
name: Test | ${{ matrix.os }} | ${{ matrix.cc }} | ${{ matrix.reloc && 'reloc | ' || '' }} ${{ matrix.suite }}
|
name: Test | ${{ matrix.os }} | ${{ matrix.cc }} | ${{ matrix.reloc && 'reloc | ' || '' }} ${{ matrix.suite }}
|
||||||
|
|
@ -247,6 +261,13 @@ jobs:
|
||||||
- {os: ubuntu-24.04, cc: gcc, reloc: 0, suite: vltmt-0}
|
- {os: ubuntu-24.04, cc: gcc, reloc: 0, suite: vltmt-0}
|
||||||
- {os: ubuntu-24.04, cc: gcc, reloc: 0, suite: vltmt-1}
|
- {os: ubuntu-24.04, cc: gcc, reloc: 0, suite: vltmt-1}
|
||||||
- {os: ubuntu-24.04, cc: gcc, reloc: 0, suite: vltmt-2}
|
- {os: ubuntu-24.04, cc: gcc, reloc: 0, suite: vltmt-2}
|
||||||
|
- {os: ubuntu-24.04, cc: gcc, reloc: 0, suite: dist-vlt4-0}
|
||||||
|
- {os: ubuntu-24.04, cc: gcc, reloc: 0, suite: dist-vlt4-1}
|
||||||
|
- {os: ubuntu-24.04, cc: gcc, reloc: 0, suite: dist-vlt4-2}
|
||||||
|
- {os: ubuntu-24.04, cc: gcc, reloc: 0, suite: dist-vlt4-3}
|
||||||
|
- {os: ubuntu-24.04, cc: gcc, reloc: 0, suite: vltmt4-0}
|
||||||
|
- {os: ubuntu-24.04, cc: gcc, reloc: 0, suite: vltmt4-1}
|
||||||
|
- {os: ubuntu-24.04, cc: gcc, reloc: 0, suite: vltmt4-2}
|
||||||
|
|
||||||
test-2404-clang:
|
test-2404-clang:
|
||||||
name: Test | ${{ matrix.os }} | ${{ matrix.cc }} | ${{ matrix.reloc && 'reloc | ' || '' }} ${{ matrix.suite }}
|
name: Test | ${{ matrix.os }} | ${{ matrix.cc }} | ${{ matrix.reloc && 'reloc | ' || '' }} ${{ matrix.suite }}
|
||||||
|
|
@ -271,6 +292,13 @@ jobs:
|
||||||
- {os: ubuntu-24.04, cc: clang, reloc: 0, suite: vltmt-0}
|
- {os: ubuntu-24.04, cc: clang, reloc: 0, suite: vltmt-0}
|
||||||
- {os: ubuntu-24.04, cc: clang, reloc: 0, suite: vltmt-1}
|
- {os: ubuntu-24.04, cc: clang, reloc: 0, suite: vltmt-1}
|
||||||
- {os: ubuntu-24.04, cc: clang, reloc: 0, suite: vltmt-2}
|
- {os: ubuntu-24.04, cc: clang, reloc: 0, suite: vltmt-2}
|
||||||
|
- {os: ubuntu-24.04, cc: clang, reloc: 0, suite: dist-vlt4-0}
|
||||||
|
- {os: ubuntu-24.04, cc: clang, reloc: 0, suite: dist-vlt4-1}
|
||||||
|
- {os: ubuntu-24.04, cc: clang, reloc: 0, suite: dist-vlt4-2}
|
||||||
|
- {os: ubuntu-24.04, cc: clang, reloc: 0, suite: dist-vlt4-3}
|
||||||
|
- {os: ubuntu-24.04, cc: clang, reloc: 0, suite: vltmt4-0}
|
||||||
|
- {os: ubuntu-24.04, cc: clang, reloc: 0, suite: vltmt4-1}
|
||||||
|
- {os: ubuntu-24.04, cc: clang, reloc: 0, suite: vltmt4-2}
|
||||||
|
|
||||||
test-2204-gcc:
|
test-2204-gcc:
|
||||||
name: Test | ${{ matrix.os }} | ${{ matrix.cc }} | ${{ matrix.reloc && 'reloc | ' || '' }} ${{ matrix.suite }}
|
name: Test | ${{ matrix.os }} | ${{ matrix.cc }} | ${{ matrix.reloc && 'reloc | ' || '' }} ${{ matrix.suite }}
|
||||||
|
|
@ -295,6 +323,13 @@ jobs:
|
||||||
- {os: ubuntu-22.04, cc: gcc, reloc: 0, suite: vltmt-0}
|
- {os: ubuntu-22.04, cc: gcc, reloc: 0, suite: vltmt-0}
|
||||||
- {os: ubuntu-22.04, cc: gcc, reloc: 0, suite: vltmt-1}
|
- {os: ubuntu-22.04, cc: gcc, reloc: 0, suite: vltmt-1}
|
||||||
- {os: ubuntu-22.04, cc: gcc, reloc: 0, suite: vltmt-2}
|
- {os: ubuntu-22.04, cc: gcc, reloc: 0, suite: vltmt-2}
|
||||||
|
- {os: ubuntu-22.04, cc: gcc, reloc: 0, suite: dist-vlt4-0}
|
||||||
|
- {os: ubuntu-22.04, cc: gcc, reloc: 0, suite: dist-vlt4-1}
|
||||||
|
- {os: ubuntu-22.04, cc: gcc, reloc: 0, suite: dist-vlt4-2}
|
||||||
|
- {os: ubuntu-22.04, cc: gcc, reloc: 0, suite: dist-vlt4-3}
|
||||||
|
- {os: ubuntu-22.04, cc: gcc, reloc: 0, suite: vltmt4-0}
|
||||||
|
- {os: ubuntu-22.04, cc: gcc, reloc: 0, suite: vltmt4-1}
|
||||||
|
- {os: ubuntu-22.04, cc: gcc, reloc: 0, suite: vltmt4-2}
|
||||||
|
|
||||||
lint-py:
|
lint-py:
|
||||||
name: Lint Python
|
name: Lint Python
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ jobs:
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
test: [coverage-vlt-, coverage-vltmt-]
|
test: [coverage-vlt-, coverage-vltmt-, coverage-vlt4-, coverage-vltmt4-]
|
||||||
num: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
num: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||||
include:
|
include:
|
||||||
- {test: coverage-dist, num: ''}
|
- {test: coverage-dist, num: ''}
|
||||||
|
|
|
||||||
|
|
@ -628,6 +628,8 @@ detailed descriptions of these arguments.
|
||||||
--x-initial <mode> Assign initial Xs to this value
|
--x-initial <mode> Assign initial Xs to this value
|
||||||
--x-initial-edge Enable initial X->0 and X->1 edge triggers
|
--x-initial-edge Enable initial X->0 and X->1 edge triggers
|
||||||
-y <dir> Directory to search for modules
|
-y <dir> Directory to search for modules
|
||||||
|
--zero-top-ports Enables initialization of top level ports with zeros in fourstate logic mode
|
||||||
|
--no-zero-top-ports Disables initialization of top level ports with zeros in fourstate logic mode
|
||||||
|
|
||||||
This is a short summary of the simulation runtime arguments, i.e. for the
|
This is a short summary of the simulation runtime arguments, i.e. for the
|
||||||
final Verilated simulation runtime models. See
|
final Verilated simulation runtime models. See
|
||||||
|
|
|
||||||
|
|
@ -128,6 +128,27 @@ elif [ "$CI_BUILD_STAGE_NAME" = "test" ]; then
|
||||||
vltmt-2)
|
vltmt-2)
|
||||||
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--vltmt --driver-clean" DRIVER_HASHSET=--hashset=2/3
|
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--vltmt --driver-clean" DRIVER_HASHSET=--hashset=2/3
|
||||||
;;
|
;;
|
||||||
|
dist-vlt4-0)
|
||||||
|
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--dist --vlt4 --driver-clean" DRIVER_HASHSET=--hashset=0/4
|
||||||
|
;;
|
||||||
|
dist-vlt4-1)
|
||||||
|
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--dist --vlt4 --driver-clean" DRIVER_HASHSET=--hashset=1/4
|
||||||
|
;;
|
||||||
|
dist-vlt4-2)
|
||||||
|
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--dist --vlt4 --driver-clean" DRIVER_HASHSET=--hashset=2/4
|
||||||
|
;;
|
||||||
|
dist-vlt4-3)
|
||||||
|
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--dist --vlt4 --driver-clean" DRIVER_HASHSET=--hashset=3/4
|
||||||
|
;;
|
||||||
|
vltmt4-0)
|
||||||
|
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--vltmt4 --driver-clean" DRIVER_HASHSET=--hashset=0/3
|
||||||
|
;;
|
||||||
|
vltmt4-1)
|
||||||
|
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--vltmt4 --driver-clean" DRIVER_HASHSET=--hashset=1/3
|
||||||
|
;;
|
||||||
|
vltmt4-2)
|
||||||
|
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--vltmt4 --driver-clean" DRIVER_HASHSET=--hashset=2/3
|
||||||
|
;;
|
||||||
coverage-dist)
|
coverage-dist)
|
||||||
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--dist"
|
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--dist"
|
||||||
;;
|
;;
|
||||||
|
|
@ -191,6 +212,66 @@ elif [ "$CI_BUILD_STAGE_NAME" = "test" ]; then
|
||||||
coverage-vltmt-9)
|
coverage-vltmt-9)
|
||||||
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--vltmt" DRIVER_HASHSET=--hashset=9/10
|
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--vltmt" DRIVER_HASHSET=--hashset=9/10
|
||||||
;;
|
;;
|
||||||
|
coverage-vlt4-0)
|
||||||
|
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--vlt4" DRIVER_HASHSET=--hashset=0/10
|
||||||
|
;;
|
||||||
|
coverage-vlt4-1)
|
||||||
|
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--vlt4" DRIVER_HASHSET=--hashset=1/10
|
||||||
|
;;
|
||||||
|
coverage-vlt4-2)
|
||||||
|
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--vlt4" DRIVER_HASHSET=--hashset=2/10
|
||||||
|
;;
|
||||||
|
coverage-vlt4-3)
|
||||||
|
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--vlt4" DRIVER_HASHSET=--hashset=3/10
|
||||||
|
;;
|
||||||
|
coverage-vlt4-4)
|
||||||
|
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--vlt4" DRIVER_HASHSET=--hashset=4/10
|
||||||
|
;;
|
||||||
|
coverage-vlt4-5)
|
||||||
|
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--vlt4" DRIVER_HASHSET=--hashset=5/10
|
||||||
|
;;
|
||||||
|
coverage-vlt4-6)
|
||||||
|
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--vlt4" DRIVER_HASHSET=--hashset=6/10
|
||||||
|
;;
|
||||||
|
coverage-vlt4-7)
|
||||||
|
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--vlt4" DRIVER_HASHSET=--hashset=7/10
|
||||||
|
;;
|
||||||
|
coverage-vlt4-8)
|
||||||
|
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--vlt4" DRIVER_HASHSET=--hashset=8/10
|
||||||
|
;;
|
||||||
|
coverage-vlt4-9)
|
||||||
|
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--vlt4" DRIVER_HASHSET=--hashset=9/10
|
||||||
|
;;
|
||||||
|
coverage-vltmt4-0)
|
||||||
|
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--vltmt4" DRIVER_HASHSET=--hashset=0/10
|
||||||
|
;;
|
||||||
|
coverage-vltmt4-1)
|
||||||
|
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--vltmt4" DRIVER_HASHSET=--hashset=1/10
|
||||||
|
;;
|
||||||
|
coverage-vltmt4-2)
|
||||||
|
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--vltmt4" DRIVER_HASHSET=--hashset=2/10
|
||||||
|
;;
|
||||||
|
coverage-vltmt4-3)
|
||||||
|
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--vltmt4" DRIVER_HASHSET=--hashset=3/10
|
||||||
|
;;
|
||||||
|
coverage-vltmt4-4)
|
||||||
|
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--vltmt4" DRIVER_HASHSET=--hashset=4/10
|
||||||
|
;;
|
||||||
|
coverage-vltmt4-5)
|
||||||
|
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--vltmt4" DRIVER_HASHSET=--hashset=5/10
|
||||||
|
;;
|
||||||
|
coverage-vltmt4-6)
|
||||||
|
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--vltmt4" DRIVER_HASHSET=--hashset=6/10
|
||||||
|
;;
|
||||||
|
coverage-vltmt4-7)
|
||||||
|
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--vltmt4" DRIVER_HASHSET=--hashset=7/10
|
||||||
|
;;
|
||||||
|
coverage-vltmt4-8)
|
||||||
|
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--vltmt4" DRIVER_HASHSET=--hashset=8/10
|
||||||
|
;;
|
||||||
|
coverage-vltmt4-9)
|
||||||
|
"$MAKE" -C "$TEST_REGRESS" SCENARIOS="--vltmt4" DRIVER_HASHSET=--hashset=9/10
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
fatal "Unknown TESTS: $TESTS"
|
fatal "Unknown TESTS: $TESTS"
|
||||||
;;
|
;;
|
||||||
|
|
|
||||||
|
|
@ -2380,3 +2380,12 @@ Summary:
|
||||||
user-specified directories. This allows '-y "$(pwd)"' to be used if
|
user-specified directories. This allows '-y "$(pwd)"' to be used if
|
||||||
absolute filenames are desired for error messages instead of relative
|
absolute filenames are desired for error messages instead of relative
|
||||||
filenames.
|
filenames.
|
||||||
|
|
||||||
|
.. option:: --zero-top-ports
|
||||||
|
|
||||||
|
.. option:: --no-zero-top-ports
|
||||||
|
|
||||||
|
Options used with :vlopt:`--fourstate` to enable/disable
|
||||||
|
initialization of top module ports with zeros instead of `x`.
|
||||||
|
This is useful to keep the backward compatibility with existing C++.
|
||||||
|
Enabled by default with :vlopt:`--fourstate`.
|
||||||
|
|
|
||||||
|
|
@ -638,9 +638,29 @@ WDataOutP VL_RAND_RESET_W(int obits, WDataOutP outwp) VL_MT_SAFE {
|
||||||
outwp[VL_WORDS_I(obits) - 1] = VL_RAND_RESET_I(32) & VL_MASK_E(obits);
|
outwp[VL_WORDS_I(obits) - 1] = VL_RAND_RESET_I(32) & VL_MASK_E(obits);
|
||||||
return outwp;
|
return outwp;
|
||||||
}
|
}
|
||||||
WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp) VL_MT_SAFE {
|
WDataOutP VL_ZERO_RESET_W_T(int obits, WDataOutP outwp) VL_MT_SAFE {
|
||||||
// Not inlined to speed up compilation of slowpath code
|
// Not inlined to speed up compilation of slowpath code
|
||||||
return VL_ZERO_W(obits, outwp);
|
return VL_ZERO_W_T(obits, outwp);
|
||||||
|
}
|
||||||
|
WDataOutP VL_ZERO_RESET_W_V(int obits, WDataOutP outwp) VL_MT_SAFE {
|
||||||
|
// Not inlined to speed up compilation of slowpath code
|
||||||
|
return VL_ZERO_W_V(obits, outwp);
|
||||||
|
}
|
||||||
|
WDataOutP VL_ZERO_RESET_W_X(int obits, WDataOutP outwp) VL_MT_SAFE {
|
||||||
|
// Not inlined to speed up compilation of slowpath code
|
||||||
|
return VL_ZERO_W_X(obits, outwp);
|
||||||
|
}
|
||||||
|
WDataOutP VL_ALLONES_RESET_W_T(int obits, WDataOutP outwp) VL_MT_SAFE {
|
||||||
|
// Not inlined to speed up compilation of slowpath code
|
||||||
|
return VL_ALLONES_W_T(obits, outwp);
|
||||||
|
}
|
||||||
|
WDataOutP VL_ALLONES_RESET_W_V(int obits, WDataOutP outwp) VL_MT_SAFE {
|
||||||
|
// Not inlined to speed up compilation of slowpath code
|
||||||
|
return VL_ALLONES_W_V(obits, outwp);
|
||||||
|
}
|
||||||
|
WDataOutP VL_ALLONES_RESET_W_X(int obits, WDataOutP outwp) VL_MT_SAFE {
|
||||||
|
// Not inlined to speed up compilation of slowpath code
|
||||||
|
return VL_ALLONES_W_X(obits, outwp);
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
@ -655,20 +675,39 @@ void _vl_debug_print_w(int lbits, const WDataInP iwp) VL_MT_SAFE {
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
// Slow expressions
|
// Slow expressions
|
||||||
|
|
||||||
WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, const WDataInP lwp, const WDataInP rwp,
|
WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, bool is_modulus,
|
||||||
bool is_modulus) VL_MT_SAFE {
|
const int outputOffset, int outputJump, const int lhsOffset, int lhsJump,
|
||||||
|
const int rhsOffset, int rhsJump) VL_MT_SAFE {
|
||||||
// See Knuth Algorithm D. Computes u/v = q.r
|
// See Knuth Algorithm D. Computes u/v = q.r
|
||||||
// This isn't massively tuned, as wide division is rare
|
// This isn't massively tuned, as wide division is rare
|
||||||
// for debug see V3Number version
|
// for debug see V3Number version
|
||||||
// Requires clean input
|
// Requires clean input
|
||||||
|
VL_DEBUG_IFDEF(assert((outputOffset == 0 && (outputJump == 1 || outputJump == 2))
|
||||||
|
|| (outputOffset == 1 && outputJump == 2)););
|
||||||
|
VL_DEBUG_IFDEF(assert((lhsOffset == 0 && (lhsJump == 1 || lhsJump == 2))
|
||||||
|
|| (lhsOffset == 1 && lhsJump == 2)););
|
||||||
|
VL_DEBUG_IFDEF(assert((rhsOffset == 0 && (rhsJump == 1 || rhsJump == 2))
|
||||||
|
|| (rhsOffset == 1 && rhsJump == 2)););
|
||||||
const int words = VL_WORDS_I(lbits);
|
const int words = VL_WORDS_I(lbits);
|
||||||
for (int i = 0; i < words; ++i) owp[i] = 0;
|
|
||||||
// Find MSB and check for zero.
|
// Find MSB and check for zero.
|
||||||
const int umsbp1 = VL_MOSTSETBITP1_W(words, lwp); // dividend
|
const int umsbp1 = (lhsJump == 2) ? (lhsOffset ? VL_MOSTSETBITP1_W_X(words, lwp)
|
||||||
const int vmsbp1 = VL_MOSTSETBITP1_W(words, rwp); // divisor
|
: VL_MOSTSETBITP1_W_V(words, lwp))
|
||||||
|
: VL_MOSTSETBITP1_W_T(words, lwp); // dividend
|
||||||
|
const int vmsbp1 = (rhsJump == 2) ? (rhsOffset ? VL_MOSTSETBITP1_W_X(words, rwp)
|
||||||
|
: VL_MOSTSETBITP1_W_V(words, rwp))
|
||||||
|
: VL_MOSTSETBITP1_W_T(words, rwp); // divisor
|
||||||
|
const WDataOutP resultp = owp;
|
||||||
|
owp += outputOffset;
|
||||||
|
lwp += lhsOffset;
|
||||||
|
rwp += rhsOffset;
|
||||||
|
// Since jump may be 1 or 2 we substract one to just use bit-shift left
|
||||||
|
--outputJump;
|
||||||
|
--lhsJump;
|
||||||
|
--rhsJump;
|
||||||
|
for (int i = 0; i < words; ++i) owp[i << outputJump] = 0;
|
||||||
if (VL_UNLIKELY(vmsbp1 == 0) // rwp==0 so division by zero. Return 0.
|
if (VL_UNLIKELY(vmsbp1 == 0) // rwp==0 so division by zero. Return 0.
|
||||||
|| VL_UNLIKELY(umsbp1 == 0)) { // 0/x so short circuit and return 0
|
|| VL_UNLIKELY(umsbp1 == 0)) { // 0/x so short circuit and return 0
|
||||||
return owp;
|
return resultp;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int uw = VL_WORDS_I(umsbp1); // aka "m" in the algorithm
|
const int uw = VL_WORDS_I(umsbp1); // aka "m" in the algorithm
|
||||||
|
|
@ -679,15 +718,16 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, const WDataInP lwp, const WData
|
||||||
if (vw == 1) { // Single divisor word breaks rest of algorithm
|
if (vw == 1) { // Single divisor word breaks rest of algorithm
|
||||||
uint64_t k = 0;
|
uint64_t k = 0;
|
||||||
for (int j = uw - 1; j >= 0; --j) {
|
for (int j = uw - 1; j >= 0; --j) {
|
||||||
const uint64_t unw64 = ((k << 32ULL) + static_cast<uint64_t>(lwp[j]));
|
const uint64_t unw64 = ((k << 32ULL) + static_cast<uint64_t>(lwp[j << lhsJump]));
|
||||||
owp[j] = unw64 / static_cast<uint64_t>(rwp[0]);
|
owp[j << outputJump] = unw64 / static_cast<uint64_t>(rwp[0]);
|
||||||
k = unw64 - static_cast<uint64_t>(owp[j]) * static_cast<uint64_t>(rwp[0]);
|
k = unw64
|
||||||
|
- static_cast<uint64_t>(owp[j << outputJump]) * static_cast<uint64_t>(rwp[0]);
|
||||||
}
|
}
|
||||||
if (is_modulus) {
|
if (is_modulus) {
|
||||||
owp[0] = k;
|
owp[0] = k;
|
||||||
for (int i = 1; i < words; ++i) owp[i] = 0;
|
for (int i = 1; i < words; ++i) owp[i << outputJump] = 0;
|
||||||
}
|
}
|
||||||
return owp;
|
return resultp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// +1 word as we may shift during normalization
|
// +1 word as we may shift during normalization
|
||||||
|
|
@ -703,16 +743,20 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, const WDataInP lwp, const WData
|
||||||
const int s = 31 - VL_BITBIT_I(vmsbp1 - 1); // shift amount (0...31)
|
const int s = 31 - VL_BITBIT_I(vmsbp1 - 1); // shift amount (0...31)
|
||||||
// Copy and shift dividend by same amount; may set new upper word
|
// Copy and shift dividend by same amount; may set new upper word
|
||||||
if (s) {
|
if (s) {
|
||||||
for (int i = vw - 1; i > 0; --i) vn[i] = (rwp[i] << s) | (rwp[i - 1] >> (32 - s));
|
for (int i = vw - 1; i > 0; --i) {
|
||||||
|
vn[i] = (rwp[i << rhsJump] << s) | (rwp[(i - 1) << rhsJump] >> (32 - s));
|
||||||
|
}
|
||||||
vn[0] = rwp[0] << s;
|
vn[0] = rwp[0] << s;
|
||||||
un[uw] = lwp[uw - 1] >> (32 - s);
|
un[uw] = lwp[(uw - 1) << lhsJump] >> (32 - s);
|
||||||
for (int i = uw - 1; i > 0; --i) un[i] = (lwp[i] << s) | (lwp[i - 1] >> (32 - s));
|
for (int i = uw - 1; i > 0; --i) {
|
||||||
|
un[i] = (lwp[i << lhsJump] << s) | (lwp[(i - 1) << lhsJump] >> (32 - s));
|
||||||
|
}
|
||||||
un[0] = lwp[0] << s;
|
un[0] = lwp[0] << s;
|
||||||
} else {
|
} else {
|
||||||
for (int i = vw - 1; i > 0; --i) vn[i] = rwp[i];
|
for (int i = vw - 1; i > 0; --i) vn[i] = rwp[i << rhsJump];
|
||||||
vn[0] = rwp[0];
|
vn[0] = rwp[0];
|
||||||
un[uw] = 0;
|
un[uw] = 0;
|
||||||
for (int i = uw - 1; i > 0; --i) un[i] = lwp[i];
|
for (int i = uw - 1; i > 0; --i) un[i] = lwp[i << lhsJump];
|
||||||
un[0] = lwp[0];
|
un[0] = lwp[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -741,11 +785,11 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, const WDataInP lwp, const WData
|
||||||
}
|
}
|
||||||
t = un[j + vw] - k;
|
t = un[j + vw] - k;
|
||||||
un[j + vw] = t;
|
un[j + vw] = t;
|
||||||
owp[j] = qhat; // Save quotient digit
|
owp[j << outputJump] = qhat; // Save quotient digit
|
||||||
|
|
||||||
if (t < 0) {
|
if (t < 0) {
|
||||||
// Over subtracted; correct by adding back
|
// Over subtracted; correct by adding back
|
||||||
owp[j]--;
|
owp[j << outputJump]--;
|
||||||
k = 0;
|
k = 0;
|
||||||
for (int i = 0; i < vw; ++i) {
|
for (int i = 0; i < vw; ++i) {
|
||||||
t = static_cast<uint64_t>(un[i + j]) + static_cast<uint64_t>(vn[i]) + k;
|
t = static_cast<uint64_t>(un[i + j]) + static_cast<uint64_t>(vn[i]) + k;
|
||||||
|
|
@ -759,15 +803,17 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, const WDataInP lwp, const WData
|
||||||
if (is_modulus) { // modulus
|
if (is_modulus) { // modulus
|
||||||
// Need to reverse normalization on copy to output
|
// Need to reverse normalization on copy to output
|
||||||
if (s) {
|
if (s) {
|
||||||
for (int i = 0; i < vw; ++i) owp[i] = (un[i] >> s) | (un[i + 1] << (32 - s));
|
for (int i = 0; i < vw; ++i) {
|
||||||
|
owp[i << outputJump] = (un[i] >> s) | (un[i + 1] << (32 - s));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < vw; ++i) owp[i] = un[i];
|
for (int i = 0; i < vw; ++i) owp[i << outputJump] = un[i];
|
||||||
}
|
}
|
||||||
for (int i = vw; i < words; ++i) owp[i] = 0;
|
for (int i = vw; i < words; ++i) owp[i << outputJump] = 0;
|
||||||
return owp;
|
return resultp;
|
||||||
}
|
}
|
||||||
// division
|
// division
|
||||||
return owp;
|
return resultp;
|
||||||
}
|
}
|
||||||
|
|
||||||
WDataOutP VL_POW_WWW(int obits, int, int rbits, WDataOutP owp, const WDataInP lwp,
|
WDataOutP VL_POW_WWW(int obits, int, int rbits, WDataOutP owp, const WDataInP lwp,
|
||||||
|
|
@ -780,15 +826,15 @@ WDataOutP VL_POW_WWW(int obits, int, int rbits, WDataOutP owp, const WDataInP lw
|
||||||
VlWide<VL_MULS_MAX_WORDS> powstore; // Fixed size, as MSVC++ doesn't allow [words] here
|
VlWide<VL_MULS_MAX_WORDS> powstore; // Fixed size, as MSVC++ doesn't allow [words] here
|
||||||
VlWide<VL_MULS_MAX_WORDS> lastpowstore; // Fixed size, as MSVC++ doesn't allow [words] here
|
VlWide<VL_MULS_MAX_WORDS> lastpowstore; // Fixed size, as MSVC++ doesn't allow [words] here
|
||||||
VlWide<VL_MULS_MAX_WORDS> lastoutstore; // Fixed size, as MSVC++ doesn't allow [words] here
|
VlWide<VL_MULS_MAX_WORDS> lastoutstore; // Fixed size, as MSVC++ doesn't allow [words] here
|
||||||
VL_ASSIGN_W(obits, powstore, lwp);
|
VL_ASSIGN_W_TT(obits, powstore, lwp);
|
||||||
for (int bit = 0; bit < rbits; ++bit) {
|
for (int bit = 0; bit < rbits; ++bit) {
|
||||||
if (bit > 0) { // power = power*power
|
if (bit > 0) { // power = power*power
|
||||||
VL_ASSIGN_W(obits, lastpowstore, powstore);
|
VL_ASSIGN_W_TT(obits, lastpowstore, powstore);
|
||||||
VL_MUL_W(owords, powstore, lastpowstore, lastpowstore);
|
VL_MUL_W_TTT(owords, powstore, lastpowstore, lastpowstore);
|
||||||
}
|
}
|
||||||
if (VL_BITISSET_W(rwp, bit)) { // out *= power
|
if (VL_BITISSET_W(rwp, bit)) { // out *= power
|
||||||
VL_ASSIGN_W(obits, lastoutstore, owp);
|
VL_ASSIGN_W_TT(obits, lastoutstore, owp);
|
||||||
VL_MUL_W(owords, owp, lastoutstore, powstore);
|
VL_MUL_W_TTT(owords, owp, lastoutstore, powstore);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return owp;
|
return owp;
|
||||||
|
|
@ -796,7 +842,7 @@ WDataOutP VL_POW_WWW(int obits, int, int rbits, WDataOutP owp, const WDataInP lw
|
||||||
WDataOutP VL_POW_WWQ(int obits, int lbits, int rbits, WDataOutP owp, const WDataInP lwp,
|
WDataOutP VL_POW_WWQ(int obits, int lbits, int rbits, WDataOutP owp, const WDataInP lwp,
|
||||||
QData rhs) VL_MT_SAFE {
|
QData rhs) VL_MT_SAFE {
|
||||||
VlWide<VL_WQ_WORDS_E> rhsw;
|
VlWide<VL_WQ_WORDS_E> rhsw;
|
||||||
VL_SET_WQ(rhsw, rhs);
|
VL_SET_WQ_T(rhsw, rhs);
|
||||||
return VL_POW_WWW(obits, lbits, rbits, owp, lwp, rhsw);
|
return VL_POW_WWW(obits, lbits, rbits, owp, lwp, rhsw);
|
||||||
}
|
}
|
||||||
QData VL_POW_QQW(int, int, int rbits, QData lhs, const WDataInP rwp) VL_MT_SAFE {
|
QData VL_POW_QQW(int, int, int rbits, QData lhs, const WDataInP rwp) VL_MT_SAFE {
|
||||||
|
|
@ -817,9 +863,9 @@ QData VL_POW_QQW(int, int, int rbits, QData lhs, const WDataInP rwp) VL_MT_SAFE
|
||||||
WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, const WDataInP lwp,
|
WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, const WDataInP lwp,
|
||||||
const WDataInP rwp, bool lsign, bool rsign) VL_MT_SAFE {
|
const WDataInP rwp, bool lsign, bool rsign) VL_MT_SAFE {
|
||||||
// obits==lbits, rbits can be different
|
// obits==lbits, rbits can be different
|
||||||
if (rsign && VL_SIGN_W(rbits, rwp)) {
|
if (rsign && VL_SIGN_W_T(rbits, rwp)) {
|
||||||
const int words = VL_WORDS_I(obits);
|
const int words = VL_WORDS_I(obits);
|
||||||
VL_ZERO_W(obits, owp);
|
VL_ZERO_W_T(obits, owp);
|
||||||
EData lor = 0; // 0=all zeros, ~0=all ones, else mix
|
EData lor = 0; // 0=all zeros, ~0=all ones, else mix
|
||||||
for (int i = 1; i < (words - 1); ++i) lor |= lwp[i];
|
for (int i = 1; i < (words - 1); ++i) lor |= lwp[i];
|
||||||
lor |= ((lwp[words - 1] == VL_MASK_E(rbits)) ? ~VL_EUL(0) : 0);
|
lor |= ((lwp[words - 1] == VL_MASK_E(rbits)) ? ~VL_EUL(0) : 0);
|
||||||
|
|
@ -832,7 +878,7 @@ WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, const WDataInP
|
||||||
}
|
}
|
||||||
if (lsign && lor == ~VL_EUL(0) && lwp[0] == ~VL_EUL(0)) { // -1
|
if (lsign && lor == ~VL_EUL(0) && lwp[0] == ~VL_EUL(0)) { // -1
|
||||||
if (rwp[0] & 1) { // -1^odd=-1
|
if (rwp[0] & 1) { // -1^odd=-1
|
||||||
return VL_ALLONES_W(obits, owp);
|
return VL_ALLONES_W_T(obits, owp);
|
||||||
}
|
}
|
||||||
// -1^even=1
|
// -1^even=1
|
||||||
owp[0] = 1;
|
owp[0] = 1;
|
||||||
|
|
@ -845,13 +891,13 @@ WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, const WDataInP
|
||||||
WDataOutP VL_POWSS_WWQ(int obits, int lbits, int rbits, WDataOutP owp, const WDataInP lwp,
|
WDataOutP VL_POWSS_WWQ(int obits, int lbits, int rbits, WDataOutP owp, const WDataInP lwp,
|
||||||
QData rhs, bool lsign, bool rsign) VL_MT_SAFE {
|
QData rhs, bool lsign, bool rsign) VL_MT_SAFE {
|
||||||
VlWide<VL_WQ_WORDS_E> rhsw;
|
VlWide<VL_WQ_WORDS_E> rhsw;
|
||||||
VL_SET_WQ(rhsw, rhs);
|
VL_SET_WQ_T(rhsw, rhs);
|
||||||
return VL_POWSS_WWW(obits, lbits, rbits, owp, lwp, rhsw, lsign, rsign);
|
return VL_POWSS_WWW(obits, lbits, rbits, owp, lwp, rhsw, lsign, rsign);
|
||||||
}
|
}
|
||||||
QData VL_POWSS_QQW(int obits, int, int rbits, QData lhs, const WDataInP rwp, bool lsign,
|
QData VL_POWSS_QQW(int obits, int, int rbits, QData lhs, const WDataInP rwp, bool lsign,
|
||||||
bool rsign) VL_MT_SAFE {
|
bool rsign) VL_MT_SAFE {
|
||||||
// Skip check for rhs == 0, as short-circuit doesn't save time
|
// Skip check for rhs == 0, as short-circuit doesn't save time
|
||||||
if (rsign && VL_SIGN_W(rbits, rwp)) {
|
if (rsign && VL_SIGN_W_T(rbits, rwp)) {
|
||||||
if (lhs == 0) return 0; // "X"
|
if (lhs == 0) return 0; // "X"
|
||||||
if (lhs == 1) return 1;
|
if (lhs == 1) return 1;
|
||||||
if (lsign && lhs == VL_MASK_Q(obits)) { // -1
|
if (lsign && lhs == VL_MASK_Q(obits)) { // -1
|
||||||
|
|
@ -880,12 +926,12 @@ double VL_ITOR_D_W(int lbits, const WDataInP lwp) VL_PURE {
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
double VL_ISTOR_D_W(int lbits, const WDataInP lwp) VL_MT_SAFE {
|
double VL_ISTOR_D_W(int lbits, const WDataInP lwp) VL_MT_SAFE {
|
||||||
if (!VL_SIGN_W(lbits, lwp)) return VL_ITOR_D_W(lbits, lwp);
|
if (!VL_SIGN_W_T(lbits, lwp)) return VL_ITOR_D_W(lbits, lwp);
|
||||||
const int words = VL_WORDS_I(lbits);
|
const int words = VL_WORDS_I(lbits);
|
||||||
VL_DEBUG_IFDEF(assert(words <= VL_MULS_MAX_WORDS););
|
VL_DEBUG_IFDEF(assert(words <= VL_MULS_MAX_WORDS););
|
||||||
VlWide<VL_MULS_MAX_WORDS + 1> pos;
|
VlWide<VL_MULS_MAX_WORDS + 1> pos;
|
||||||
VL_NEGATE_W(words, pos, lwp);
|
VL_NEGATE_W_TT(words, pos, lwp);
|
||||||
_vl_clean_inplace_w(lbits, pos);
|
_vl_clean_inplace_w_T(lbits, pos);
|
||||||
return -VL_ITOR_D_W(lbits, pos);
|
return -VL_ITOR_D_W(lbits, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -898,7 +944,7 @@ std::string VL_DECIMAL_NW(int width, const WDataInP lwp) VL_MT_SAFE {
|
||||||
// Or (maxdecwidth+7)/8], but can't have more than 4 BCD bits per word
|
// Or (maxdecwidth+7)/8], but can't have more than 4 BCD bits per word
|
||||||
std::vector<EData> bcd(VL_WORDS_I(maxdecwidth));
|
std::vector<EData> bcd(VL_WORDS_I(maxdecwidth));
|
||||||
WDataOutP bcdp = WDataOutP::external(bcd.data());
|
WDataOutP bcdp = WDataOutP::external(bcd.data());
|
||||||
VL_ZERO_W(maxdecwidth, bcdp);
|
VL_ZERO_W_T(maxdecwidth, bcdp);
|
||||||
std::vector<EData> tmp(VL_WORDS_I(maxdecwidth));
|
std::vector<EData> tmp(VL_WORDS_I(maxdecwidth));
|
||||||
std::vector<EData> tmp2(VL_WORDS_I(maxdecwidth));
|
std::vector<EData> tmp2(VL_WORDS_I(maxdecwidth));
|
||||||
WDataOutP tmpp = WDataOutP::external(tmp.data());
|
WDataOutP tmpp = WDataOutP::external(tmp.data());
|
||||||
|
|
@ -911,15 +957,15 @@ std::string VL_DECIMAL_NW(int width, const WDataInP lwp) VL_MT_SAFE {
|
||||||
// Any digits >= 5 need an add 3 (via tmp)
|
// Any digits >= 5 need an add 3 (via tmp)
|
||||||
for (int nibble_bit = 0; nibble_bit < maxdecwidth; nibble_bit += 4) {
|
for (int nibble_bit = 0; nibble_bit < maxdecwidth; nibble_bit += 4) {
|
||||||
if ((VL_BITRSHIFT_W(bcd, nibble_bit) & 0xf) >= 5) {
|
if ((VL_BITRSHIFT_W(bcd, nibble_bit) & 0xf) >= 5) {
|
||||||
VL_ZERO_W(maxdecwidth, tmp2p);
|
VL_ZERO_W_T(maxdecwidth, tmp2p);
|
||||||
tmp2[VL_BITWORD_E(nibble_bit)] |= VL_EUL(0x3) << VL_BITBIT_E(nibble_bit);
|
tmp2[VL_BITWORD_E(nibble_bit)] |= VL_EUL(0x3) << VL_BITBIT_E(nibble_bit);
|
||||||
VL_ASSIGN_W(maxdecwidth, tmpp, bcdp);
|
VL_ASSIGN_W_TT(maxdecwidth, tmpp, bcdp);
|
||||||
VL_ADD_W(VL_WORDS_I(maxdecwidth), bcdp, tmpp, tmp2p);
|
VL_ADD_W_TTT(VL_WORDS_I(maxdecwidth), bcdp, tmpp, tmp2p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Shift; bcd = bcd << 1
|
// Shift; bcd = bcd << 1
|
||||||
VL_ASSIGN_W(maxdecwidth, tmpp, bcdp);
|
VL_ASSIGN_W_TT(maxdecwidth, tmpp, bcdp);
|
||||||
VL_SHIFTL_WWI(maxdecwidth, maxdecwidth, 32, bcdp, tmpp, 1);
|
VL_SHIFTL_WWI_TTT(maxdecwidth, maxdecwidth, 32, bcdp, tmpp, 1);
|
||||||
// bcd[0] = lwp[from_bit]
|
// bcd[0] = lwp[from_bit]
|
||||||
if (VL_BITISSET_W(lwp, from_bit)) bcd[0] |= 1;
|
if (VL_BITISSET_W(lwp, from_bit)) bcd[0] |= 1;
|
||||||
}
|
}
|
||||||
|
|
@ -951,36 +997,36 @@ std::string _vl_vsformat_time(std::string& tmp, T ld, int timeunit, bool left,
|
||||||
VlWide<w> tmp2;
|
VlWide<w> tmp2;
|
||||||
VlWide<w> tmp3;
|
VlWide<w> tmp3;
|
||||||
|
|
||||||
WDataInP shifted = VL_EXTEND_WQ(b, 0, tmp0, static_cast<QData>(ld));
|
WDataInP shifted = VL_EXTEND_WQ_TT(b, 0, tmp0, static_cast<QData>(ld));
|
||||||
if (shift < 0) {
|
if (shift < 0) {
|
||||||
const WDataInP pow10 = VL_EXTEND_WQ(b, 0, tmp1, vl_time_pow10(-shift));
|
const WDataInP pow10 = VL_EXTEND_WQ_TT(b, 0, tmp1, vl_time_pow10(-shift));
|
||||||
shifted = VL_DIV_WWW(b, tmp2, shifted, pow10);
|
shifted = VL_DIV_WWW_TTT(b, tmp2, shifted, pow10);
|
||||||
} else {
|
} else {
|
||||||
const WDataInP pow10 = VL_EXTEND_WQ(b, 0, tmp1, vl_time_pow10(shift));
|
const WDataInP pow10 = VL_EXTEND_WQ_TT(b, 0, tmp1, vl_time_pow10(shift));
|
||||||
shifted = VL_MUL_W(w, tmp2, shifted, pow10);
|
shifted = VL_MUL_W_TTT(w, tmp2, shifted, pow10);
|
||||||
}
|
}
|
||||||
|
|
||||||
const WDataInP fracDigitsPow10 = VL_EXTEND_WQ(b, 0, tmp3, vl_time_pow10(fracDigits));
|
const WDataInP fracDigitsPow10 = VL_EXTEND_WQ_TT(b, 0, tmp3, vl_time_pow10(fracDigits));
|
||||||
const WDataInP integer = VL_DIV_WWW(b, tmp0, shifted, fracDigitsPow10);
|
const WDataInP integer = VL_DIV_WWW_TTT(b, tmp0, shifted, fracDigitsPow10);
|
||||||
const WDataInP frac = VL_MODDIV_WWW(b, tmp1, shifted, fracDigitsPow10);
|
const WDataInP frac = VL_MODDIV_WWW_TTT(b, tmp1, shifted, fracDigitsPow10);
|
||||||
const WDataInP max64Bit
|
const WDataInP max64Bit
|
||||||
= VL_EXTEND_WQ(b, 0, tmp2, std::numeric_limits<uint64_t>::max()); // breaks shifted
|
= VL_EXTEND_WQ_TT(b, 0, tmp2, std::numeric_limits<uint64_t>::max()); // breaks shifted
|
||||||
if (VL_GT_W(w, integer, max64Bit)) {
|
if (VL_GT_W_TT(w, integer, max64Bit)) {
|
||||||
WDataOutP v = VL_ASSIGN_W(b, tmp3, integer); // breaks fracDigitsPow10
|
WDataOutP v = VL_ASSIGN_W_TT(b, tmp3, integer); // breaks fracDigitsPow10
|
||||||
VlWide<w> zero;
|
VlWide<w> zero;
|
||||||
VlWide<w> ten;
|
VlWide<w> ten;
|
||||||
VL_ZERO_W(b, zero);
|
VL_ZERO_W_T(b, zero);
|
||||||
VL_EXTEND_WI(b, 0, ten, 10);
|
VL_EXTEND_WI_TT(b, 0, ten, 10);
|
||||||
char buf[128]; // 128B is obviously long enough to represent 128bit integer in decimal
|
char buf[128]; // 128B is obviously long enough to represent 128bit integer in decimal
|
||||||
char* ptr = buf + sizeof(buf) - 1;
|
char* ptr = buf + sizeof(buf) - 1;
|
||||||
*ptr = '\0';
|
*ptr = '\0';
|
||||||
while (VL_GT_W(w, v, zero)) {
|
while (VL_GT_W_TT(w, v, zero)) {
|
||||||
--ptr;
|
--ptr;
|
||||||
const WDataInP mod = VL_MODDIV_WWW(b, tmp2, v, ten); // breaks max64Bit
|
const WDataInP mod = VL_MODDIV_WWW_TTT(b, tmp2, v, ten); // breaks max64Bit
|
||||||
*ptr = "0123456789"[VL_SET_QW(mod)];
|
*ptr = "0123456789"[VL_SET_QW(mod)];
|
||||||
VlWide<w> divided;
|
VlWide<w> divided;
|
||||||
VL_DIV_WWW(b, divided, v, ten);
|
VL_DIV_WWW_TTT(b, divided, v, ten);
|
||||||
VL_ASSIGN_W(b, v, divided);
|
VL_ASSIGN_W_TT(b, v, divided);
|
||||||
}
|
}
|
||||||
if (!fracDigits) {
|
if (!fracDigits) {
|
||||||
digits = _vl_snprintf_string(tmp, "%s%s", ptr, suffix.c_str());
|
digits = _vl_snprintf_string(tmp, "%s%s", ptr, suffix.c_str());
|
||||||
|
|
@ -1166,7 +1212,7 @@ void _vl_vsformat(std::string& output, const std::string& format, int argc,
|
||||||
ld = VL_RTOIROUND_Q_D(real);
|
ld = VL_RTOIROUND_Q_D(real);
|
||||||
strwide.resize(2);
|
strwide.resize(2);
|
||||||
WDataOutP strwidep = WDataOutP::external(strwide.data());
|
WDataOutP strwidep = WDataOutP::external(strwide.data());
|
||||||
VL_SET_WQ(strwidep, ld);
|
VL_SET_WQ_T(strwidep, ld);
|
||||||
lwp = strwidep;
|
lwp = strwidep;
|
||||||
lbits = 64;
|
lbits = 64;
|
||||||
// Not changint fmt == 'p' to fmt = 'g', as need fmts correct
|
// Not changint fmt == 'p' to fmt = 'g', as need fmts correct
|
||||||
|
|
@ -1179,7 +1225,7 @@ void _vl_vsformat(std::string& output, const std::string& format, int argc,
|
||||||
ld = VL_VA_ARG_Q_(ap, lbits);
|
ld = VL_VA_ARG_Q_(ap, lbits);
|
||||||
strwide.resize(2);
|
strwide.resize(2);
|
||||||
WDataOutP strwidep = WDataOutP::external(strwide.data());
|
WDataOutP strwidep = WDataOutP::external(strwide.data());
|
||||||
VL_SET_WQ(strwidep, ld);
|
VL_SET_WQ_T(strwidep, ld);
|
||||||
lwp = strwidep;
|
lwp = strwidep;
|
||||||
lsb = lbits - 1;
|
lsb = lbits - 1;
|
||||||
++argn; // Enum value is followed by the generated name string argument
|
++argn; // Enum value is followed by the generated name string argument
|
||||||
|
|
@ -1207,7 +1253,7 @@ void _vl_vsformat(std::string& output, const std::string& format, int argc,
|
||||||
ld = VL_VA_ARG_Q_(ap, lbits);
|
ld = VL_VA_ARG_Q_(ap, lbits);
|
||||||
strwide.resize(2);
|
strwide.resize(2);
|
||||||
WDataOutP strwidep = WDataOutP::external(strwide.data());
|
WDataOutP strwidep = WDataOutP::external(strwide.data());
|
||||||
VL_SET_WQ(strwidep, ld);
|
VL_SET_WQ_T(strwidep, ld);
|
||||||
lwp = strwidep;
|
lwp = strwidep;
|
||||||
} else {
|
} else {
|
||||||
lwp = WDataInP::external(va_arg(ap, EData*));
|
lwp = WDataInP::external(va_arg(ap, EData*));
|
||||||
|
|
@ -1291,13 +1337,13 @@ void _vl_vsformat(std::string& output, const std::string& format, int argc,
|
||||||
if (lbits <= VL_QUADSIZE) {
|
if (lbits <= VL_QUADSIZE) {
|
||||||
digits = _vl_snprintf_string(
|
digits = _vl_snprintf_string(
|
||||||
t_tmp, "%" PRId64,
|
t_tmp, "%" PRId64,
|
||||||
static_cast<int64_t>(VL_EXTENDS_QQ(lbits, lbits, ld)));
|
static_cast<int64_t>(VL_EXTENDS_QQ_TT(lbits, lbits, ld)));
|
||||||
append = t_tmp;
|
append = t_tmp;
|
||||||
} else {
|
} else {
|
||||||
if (VL_SIGN_E(lbits, lwp[VL_WORDS_I(lbits) - 1])) {
|
if (VL_SIGN_E_T(lbits, lwp[VL_WORDS_I(lbits) - 1])) {
|
||||||
std::vector<EData> neg(VL_WORDS_I(lbits));
|
std::vector<EData> neg(VL_WORDS_I(lbits));
|
||||||
WDataOutP negp = WDataOutP::external(neg.data());
|
WDataOutP negp = WDataOutP::external(neg.data());
|
||||||
VL_NEGATE_W(VL_WORDS_I(lbits), negp, lwp);
|
VL_NEGATE_W_TT(VL_WORDS_I(lbits), negp, lwp);
|
||||||
append = "-"s + VL_DECIMAL_NW(lbits, negp);
|
append = "-"s + VL_DECIMAL_NW(lbits, negp);
|
||||||
} else {
|
} else {
|
||||||
append = VL_DECIMAL_NW(lbits, lwp);
|
append = VL_DECIMAL_NW(lbits, lwp);
|
||||||
|
|
@ -1372,7 +1418,7 @@ void _vl_vsformat(std::string& output, const std::string& format, int argc,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (widthSet || left) {
|
if (widthSet || left) {
|
||||||
lsb = VL_MOSTSETBITP1_W(VL_WORDS_I(lbits), lwp);
|
lsb = VL_MOSTSETBITP1_W_T(VL_WORDS_I(lbits), lwp);
|
||||||
lsb = (lsb < 1) ? 0 : (lsb - 1);
|
lsb = (lsb < 1) ? 0 : (lsb - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1527,7 +1573,7 @@ static void _vl_vsss_setbit(WDataOutP iowp, int obits, int lsb, int nbits, IData
|
||||||
void _vl_vsss_based(WDataOutP owp, int obits, int baseLog2, const char* strp, size_t posstart,
|
void _vl_vsss_based(WDataOutP owp, int obits, int baseLog2, const char* strp, size_t posstart,
|
||||||
size_t posend) VL_MT_SAFE {
|
size_t posend) VL_MT_SAFE {
|
||||||
// Read in base "2^^baseLog2" digits from strp[posstart..posend-1] into owp of size obits.
|
// Read in base "2^^baseLog2" digits from strp[posstart..posend-1] into owp of size obits.
|
||||||
VL_ZERO_W(obits, owp);
|
VL_ZERO_W_T(obits, owp);
|
||||||
int lsb = 0;
|
int lsb = 0;
|
||||||
for (int i = 0, pos = static_cast<int>(posend) - 1;
|
for (int i = 0, pos = static_cast<int>(posend) - 1;
|
||||||
i < obits && pos >= static_cast<int>(posstart); --pos, ++i) {
|
i < obits && pos >= static_cast<int>(posstart); --pos, ++i) {
|
||||||
|
|
@ -1648,7 +1694,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
||||||
double real = 0;
|
double real = 0;
|
||||||
|
|
||||||
VlWide<VL_WQ_WORDS_E> qowp;
|
VlWide<VL_WQ_WORDS_E> qowp;
|
||||||
VL_SET_WQ(qowp, 0ULL);
|
VL_SET_WQ_T(qowp, 0ULL);
|
||||||
WDataOutP owp = WDataOutP::external((obits <= 64) ? qowp.data()
|
WDataOutP owp = WDataOutP::external((obits <= 64) ? qowp.data()
|
||||||
: static_cast<EData*>(thingp));
|
: static_cast<EData*>(thingp));
|
||||||
|
|
||||||
|
|
@ -1684,11 +1730,11 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
||||||
if (formatAttr == VL_VFORMATATTR_SIGNED) {
|
if (formatAttr == VL_VFORMATATTR_SIGNED) {
|
||||||
QData ld = 0;
|
QData ld = 0;
|
||||||
std::sscanf(t_tmp.c_str(), "%30" PRIu64, &ld);
|
std::sscanf(t_tmp.c_str(), "%30" PRIu64, &ld);
|
||||||
VL_SET_WQ(owp, ld);
|
VL_SET_WQ_T(owp, ld);
|
||||||
} else if (formatAttr == VL_VFORMATATTR_UNSIGNED) {
|
} else if (formatAttr == VL_VFORMATATTR_UNSIGNED) {
|
||||||
int64_t ld = 0;
|
int64_t ld = 0;
|
||||||
std::sscanf(t_tmp.c_str(), "%30" PRId64, &ld);
|
std::sscanf(t_tmp.c_str(), "%30" PRId64, &ld);
|
||||||
VL_SET_WQ(owp, ld);
|
VL_SET_WQ_T(owp, ld);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -1706,7 +1752,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
||||||
} u;
|
} u;
|
||||||
real = std::strtod(t_tmp.c_str(), nullptr);
|
real = std::strtod(t_tmp.c_str(), nullptr);
|
||||||
u.r = real;
|
u.r = real;
|
||||||
VL_SET_WQ(owp, u.ld);
|
VL_SET_WQ_T(owp, u.ld);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 't': { // Time
|
case 't': { // Time
|
||||||
|
|
@ -1720,7 +1766,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
||||||
// 0..-15
|
// 0..-15
|
||||||
const int shift = -userUnits + timeunit; // 0..-15
|
const int shift = -userUnits + timeunit; // 0..-15
|
||||||
real = std::strtod(t_tmp.c_str(), nullptr) * vl_time_multiplier(-shift);
|
real = std::strtod(t_tmp.c_str(), nullptr) * vl_time_multiplier(-shift);
|
||||||
VL_SET_WQ(owp, static_cast<uint64_t>(real));
|
VL_SET_WQ_T(owp, static_cast<uint64_t>(real));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'b': {
|
case 'b': {
|
||||||
|
|
@ -1807,7 +1853,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
||||||
QData* const p = static_cast<QData*>(thingp);
|
QData* const p = static_cast<QData*>(thingp);
|
||||||
*p = VL_CLEAN_QQ(obits, obits, VL_SET_QW(owp));
|
*p = VL_CLEAN_QQ(obits, obits, VL_SET_QW(owp));
|
||||||
} else {
|
} else {
|
||||||
_vl_clean_inplace_w(obits, owp);
|
_vl_clean_inplace_w_T(obits, owp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // switch
|
} // switch
|
||||||
|
|
@ -2137,7 +2183,7 @@ IData VL_SSCANF_IINX(int lbits, IData ld, const std::string& format, int argc, .
|
||||||
}
|
}
|
||||||
IData VL_SSCANF_IQNX(int lbits, QData ld, const std::string& format, int argc, ...) VL_MT_SAFE {
|
IData VL_SSCANF_IQNX(int lbits, QData ld, const std::string& format, int argc, ...) VL_MT_SAFE {
|
||||||
VlWide<VL_WQ_WORDS_E> fnw;
|
VlWide<VL_WQ_WORDS_E> fnw;
|
||||||
VL_SET_WQ(fnw, ld);
|
VL_SET_WQ_T(fnw, ld);
|
||||||
|
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, argc);
|
va_start(ap, argc);
|
||||||
|
|
@ -2245,7 +2291,7 @@ IData VL_FREAD_I(int width, int array_lsb, int array_size, void* memp, IData fpi
|
||||||
} else {
|
} else {
|
||||||
const WDataOutP datap = WDataOutP::external(
|
const WDataOutP datap = WDataOutP::external(
|
||||||
&(reinterpret_cast<EData*>(memp))[entry * VL_WORDS_I(width)]);
|
&(reinterpret_cast<EData*>(memp))[entry * VL_WORDS_I(width)]);
|
||||||
if (shift == start_shift) VL_ZERO_W(width, datap);
|
if (shift == start_shift) VL_ZERO_W_T(width, datap);
|
||||||
datap[VL_BITWORD_E(shift)] |= (static_cast<EData>(c) << VL_BITBIT_E(shift));
|
datap[VL_BITWORD_E(shift)] |= (static_cast<EData>(c) << VL_BITBIT_E(shift));
|
||||||
}
|
}
|
||||||
// Prep for next
|
// Prep for next
|
||||||
|
|
@ -2331,7 +2377,7 @@ void VL_STACKTRACE() VL_MT_SAFE {
|
||||||
|
|
||||||
IData VL_SYSTEM_IQ(QData lhs) VL_MT_SAFE {
|
IData VL_SYSTEM_IQ(QData lhs) VL_MT_SAFE {
|
||||||
VlWide<VL_WQ_WORDS_E> lhsw;
|
VlWide<VL_WQ_WORDS_E> lhsw;
|
||||||
VL_SET_WQ(lhsw, lhs);
|
VL_SET_WQ_T(lhsw, lhs);
|
||||||
return VL_SYSTEM_IW(VL_WQ_WORDS_E, lhsw);
|
return VL_SYSTEM_IW(VL_WQ_WORDS_E, lhsw);
|
||||||
}
|
}
|
||||||
IData VL_SYSTEM_IW(int lhswords, const WDataInP lhsp) VL_MT_SAFE {
|
IData VL_SYSTEM_IW(int lhswords, const WDataInP lhsp) VL_MT_SAFE {
|
||||||
|
|
@ -2383,12 +2429,12 @@ IData VL_VALUEPLUSARGS_INW(int rbits, const std::string& ld, WDataOutP rwp) VL_M
|
||||||
const char* const dp = match.c_str() + 1 /*leading + */ + prefix.length();
|
const char* const dp = match.c_str() + 1 /*leading + */ + prefix.length();
|
||||||
if (match.empty()) return 0;
|
if (match.empty()) return 0;
|
||||||
|
|
||||||
VL_ZERO_W(rbits, rwp);
|
VL_ZERO_W_T(rbits, rwp);
|
||||||
switch (std::tolower(fmt)) {
|
switch (std::tolower(fmt)) {
|
||||||
case 'd': {
|
case 'd': {
|
||||||
int64_t lld = 0;
|
int64_t lld = 0;
|
||||||
std::sscanf(dp, "%30" PRId64, &lld);
|
std::sscanf(dp, "%30" PRId64, &lld);
|
||||||
VL_SET_WQ(rwp, lld);
|
VL_SET_WQ_T(rwp, lld);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'b': _vl_vsss_based(rwp, rbits, 1, dp, 0, std::strlen(dp)); break;
|
case 'b': _vl_vsss_based(rwp, rbits, 1, dp, 0, std::strlen(dp)); break;
|
||||||
|
|
@ -2406,25 +2452,25 @@ IData VL_VALUEPLUSARGS_INW(int rbits, const std::string& ld, WDataOutP rwp) VL_M
|
||||||
case 'e': {
|
case 'e': {
|
||||||
double temp = 0.F;
|
double temp = 0.F;
|
||||||
std::sscanf(dp, "%le", &temp);
|
std::sscanf(dp, "%le", &temp);
|
||||||
VL_SET_WQ(rwp, VL_CVT_Q_D(temp));
|
VL_SET_WQ_T(rwp, VL_CVT_Q_D(temp));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'f': {
|
case 'f': {
|
||||||
double temp = 0.F;
|
double temp = 0.F;
|
||||||
std::sscanf(dp, "%lf", &temp);
|
std::sscanf(dp, "%lf", &temp);
|
||||||
VL_SET_WQ(rwp, VL_CVT_Q_D(temp));
|
VL_SET_WQ_T(rwp, VL_CVT_Q_D(temp));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'g': {
|
case 'g': {
|
||||||
double temp = 0.F;
|
double temp = 0.F;
|
||||||
std::sscanf(dp, "%lg", &temp);
|
std::sscanf(dp, "%lg", &temp);
|
||||||
VL_SET_WQ(rwp, VL_CVT_Q_D(temp));
|
VL_SET_WQ_T(rwp, VL_CVT_Q_D(temp));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: // Other simulators return 0 in these cases and don't error out
|
default: // Other simulators return 0 in these cases and don't error out
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
_vl_clean_inplace_w(rbits, rwp);
|
_vl_clean_inplace_w_T(rbits, rwp);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
IData VL_VALUEPLUSARGS_INN(int, const std::string& ld, std::string& rdr) VL_MT_SAFE {
|
IData VL_VALUEPLUSARGS_INN(int, const std::string& ld, std::string& rdr) VL_MT_SAFE {
|
||||||
|
|
@ -2744,7 +2790,7 @@ void VlReadMem::setData(void* valuep, const std::string& rhs) {
|
||||||
& VL_MASK_Q(m_bits);
|
& VL_MASK_Q(m_bits);
|
||||||
} else {
|
} else {
|
||||||
const WDataOutP datap = WDataOutP::external(reinterpret_cast<EData*>(valuep));
|
const WDataOutP datap = WDataOutP::external(reinterpret_cast<EData*>(valuep));
|
||||||
if (!innum) VL_ZERO_W(m_bits, datap);
|
if (!innum) VL_ZERO_W_T(m_bits, datap);
|
||||||
_vl_shiftl_inplace_w(m_bits, datap, static_cast<IData>(shift));
|
_vl_shiftl_inplace_w(m_bits, datap, static_cast<IData>(shift));
|
||||||
datap[0] |= value;
|
datap[0] |= value;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -286,7 +286,7 @@ static void _vl_svGetBitArrElemVecVal(svBitVecVal* d, const svOpenArrayHandle s,
|
||||||
case VLVT_UINT32: d[0] = *(reinterpret_cast<IData*>(datap)); return;
|
case VLVT_UINT32: d[0] = *(reinterpret_cast<IData*>(datap)); return;
|
||||||
case VLVT_UINT64: {
|
case VLVT_UINT64: {
|
||||||
VlWide<2> lwp;
|
VlWide<2> lwp;
|
||||||
VL_SET_WQ(lwp, *(reinterpret_cast<QData*>(datap)));
|
VL_SET_WQ_T(lwp, *(reinterpret_cast<QData*>(datap)));
|
||||||
d[0] = lwp[0];
|
d[0] = lwp[0];
|
||||||
d[1] = lwp[1];
|
d[1] = lwp[1];
|
||||||
break;
|
break;
|
||||||
|
|
@ -323,7 +323,7 @@ static void _vl_svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandl
|
||||||
return;
|
return;
|
||||||
case VLVT_UINT64: {
|
case VLVT_UINT64: {
|
||||||
VlWide<2> lwp;
|
VlWide<2> lwp;
|
||||||
VL_SET_WQ(lwp, *(reinterpret_cast<QData*>(datap)));
|
VL_SET_WQ_T(lwp, *(reinterpret_cast<QData*>(datap)));
|
||||||
d[0].aval = lwp[0];
|
d[0].aval = lwp[0];
|
||||||
d[0].bval = 0;
|
d[0].bval = 0;
|
||||||
d[1].aval = lwp[1];
|
d[1].aval = lwp[1];
|
||||||
|
|
@ -781,7 +781,7 @@ int svGetTime(const svScope /*scope*/, svTimeVal* time) {
|
||||||
if (VL_UNLIKELY(!time)) return -1;
|
if (VL_UNLIKELY(!time)) return -1;
|
||||||
const QData qtime = VL_TIME_Q();
|
const QData qtime = VL_TIME_Q();
|
||||||
VlWide<2> itime;
|
VlWide<2> itime;
|
||||||
VL_SET_WQ(itime, qtime);
|
VL_SET_WQ_T(itime, qtime);
|
||||||
time->low = itime[0];
|
time->low = itime[0];
|
||||||
time->high = itime[1];
|
time->high = itime[1];
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ static inline void VL_SET_SVBV_W(int obits, svBitVecVal* owp, const WDataInP lwp
|
||||||
}
|
}
|
||||||
static inline void VL_SET_SVBV_I(int, svBitVecVal* owp, const IData ld) VL_MT_SAFE { owp[0] = ld; }
|
static inline void VL_SET_SVBV_I(int, svBitVecVal* owp, const IData ld) VL_MT_SAFE { owp[0] = ld; }
|
||||||
static inline void VL_SET_SVBV_Q(int, svBitVecVal* owp, const QData ld) VL_MT_SAFE {
|
static inline void VL_SET_SVBV_Q(int, svBitVecVal* owp, const QData ld) VL_MT_SAFE {
|
||||||
VL_SET_WQ(WDataOutP::external(owp), ld);
|
VL_SET_WQ_T(WDataOutP::external(owp), ld);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert svLogicVecVal to Verilator internal data
|
// Convert svLogicVecVal to Verilator internal data
|
||||||
|
|
@ -100,7 +100,7 @@ static inline void VL_SET_SVLV_I(int, svLogicVecVal* owp, const IData ld) VL_MT_
|
||||||
}
|
}
|
||||||
static inline void VL_SET_SVLV_Q(int, svLogicVecVal* owp, const QData ld) VL_MT_SAFE {
|
static inline void VL_SET_SVLV_Q(int, svLogicVecVal* owp, const QData ld) VL_MT_SAFE {
|
||||||
VlWide<2> lwp;
|
VlWide<2> lwp;
|
||||||
VL_SET_WQ(lwp, ld);
|
VL_SET_WQ_T(lwp, ld);
|
||||||
owp[0].aval = lwp[0];
|
owp[0].aval = lwp[0];
|
||||||
owp[0].bval = 0;
|
owp[0].bval = 0;
|
||||||
owp[1].aval = lwp[1];
|
owp[1].aval = lwp[1];
|
||||||
|
|
|
||||||
|
|
@ -182,7 +182,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
WDataInP rhswp = WDataInP::external(static_cast<const EData*>(entry.m_rhsDatap));
|
WDataInP rhswp = WDataInP::external(static_cast<const EData*>(entry.m_rhsDatap));
|
||||||
return VL_SEL_QWII(rhsWidth, rhswp, rhsLsb, width) & mask;
|
return VL_SEL_QWII_TTTT(rhsWidth, rhswp, rhsLsb, width) & mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|
@ -260,7 +260,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
void readSel(int lbits, WDataInP valp, WDataOutP reswp, int lsb, int width) const {
|
void readSel(int lbits, WDataInP valp, WDataOutP reswp, int lsb, int width) const {
|
||||||
VL_SEL_WWII(width, lbits, reswp, valp, lsb, width);
|
VL_SEL_WWII_TTTT(width, lbits, reswp, valp, lsb, width);
|
||||||
const int msb = lsb + width - 1;
|
const int msb = lsb + width - 1;
|
||||||
auto it = std::lower_bound(m_entries.begin(), m_entries.end(), lsb,
|
auto it = std::lower_bound(m_entries.begin(), m_entries.end(), lsb,
|
||||||
[](const Entry& e, int bit) { return e.m_msb < bit; });
|
[](const Entry& e, int bit) { return e.m_msb < bit; });
|
||||||
|
|
|
||||||
|
|
@ -459,21 +459,11 @@ void VerilatedFstBuffer::emitWData(uint32_t code, const WDataInP newval, int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
VL_ATTR_ALWINLINE
|
VL_ATTR_ALWINLINE
|
||||||
void VerilatedFstBuffer::emitFourstateWData(uint32_t code, const WDataInP newval,
|
void VerilatedFstBuffer::emitFourstateWData(uint32_t code, const WDataInP newval, int) {
|
||||||
const WDataInP newvalXZ, int bits) {
|
|
||||||
VL_DEBUG_IFDEF(assert(m_symbolp[code]);); // LCOV_EXCL_BR_LINE
|
VL_DEBUG_IFDEF(assert(m_symbolp[code]);); // LCOV_EXCL_BR_LINE
|
||||||
// TODO: When four-states will be shuffled remove it since copying will be no longer necessary
|
|
||||||
std::vector<uint32_t> newvals;
|
|
||||||
const size_t wordCount = static_cast<size_t>(VL_WORDS_I(bits));
|
|
||||||
newvals.resize(wordCount);
|
|
||||||
for (size_t i = 0; i < wordCount; ++i) {
|
|
||||||
newvals.push_back(newval[i]);
|
|
||||||
newvals.push_back(newvalXZ[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_owner.emitTimeChangeMaybe();
|
m_owner.emitTimeChangeMaybe();
|
||||||
// call emitValueChange(handle, uint32_t*)
|
// call emitValueChange(handle, uint32_t*)
|
||||||
m_fst->emitValueChange(m_symbolp[code], newvals.data());
|
m_fst->emitValueChange(m_symbolp[code], newval);
|
||||||
}
|
}
|
||||||
|
|
||||||
VL_ATTR_ALWINLINE
|
VL_ATTR_ALWINLINE
|
||||||
|
|
|
||||||
|
|
@ -238,8 +238,7 @@ class VerilatedFstBuffer VL_NOT_FINAL {
|
||||||
VL_ATTR_ALWINLINE void emitQData(uint32_t code, QData newval, int);
|
VL_ATTR_ALWINLINE void emitQData(uint32_t code, QData newval, int);
|
||||||
VL_ATTR_ALWINLINE void emitFourstateQData(uint32_t code, QData newval, QData newvalXZ, int);
|
VL_ATTR_ALWINLINE void emitFourstateQData(uint32_t code, QData newval, QData newvalXZ, int);
|
||||||
VL_ATTR_ALWINLINE void emitWData(uint32_t code, WDataInP newval, int);
|
VL_ATTR_ALWINLINE void emitWData(uint32_t code, WDataInP newval, int);
|
||||||
VL_ATTR_ALWINLINE void emitFourstateWData(uint32_t code, WDataInP newval, WDataInP newvalXZ,
|
VL_ATTR_ALWINLINE void emitFourstateWData(uint32_t code, WDataInP newval, int);
|
||||||
int bits);
|
|
||||||
VL_ATTR_ALWINLINE void emitDouble(uint32_t code, double newval);
|
VL_ATTR_ALWINLINE void emitDouble(uint32_t code, double newval);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -386,11 +386,11 @@ static bool parseSMTNum(int obits, WDataOutP owp, const std::string& val) {
|
||||||
}
|
}
|
||||||
bool VlRandomVar::set(const std::string& idx, const std::string& val) const {
|
bool VlRandomVar::set(const std::string& idx, const std::string& val) const {
|
||||||
VlWide<VL_WQ_WORDS_E> qowp;
|
VlWide<VL_WQ_WORDS_E> qowp;
|
||||||
VL_SET_WQ(qowp, 0ULL);
|
VL_SET_WQ_T(qowp, 0ULL);
|
||||||
WDataOutP owp = qowp;
|
WDataOutP owp = qowp;
|
||||||
const int obits = width();
|
const int obits = width();
|
||||||
VlWide<VL_WQ_WORDS_E> qiwp;
|
VlWide<VL_WQ_WORDS_E> qiwp;
|
||||||
VL_SET_WQ(qiwp, 0ULL);
|
VL_SET_WQ_T(qiwp, 0ULL);
|
||||||
if (!idx.empty() && !parseSMTNum(64, qiwp, idx)) return false;
|
if (!idx.empty() && !parseSMTNum(64, qiwp, idx)) return false;
|
||||||
const int nidx = qiwp[0];
|
const int nidx = qiwp[0];
|
||||||
if (obits > VL_QUADSIZE) owp = WDataOutP::external(reinterpret_cast<EData*>(datap(nidx)));
|
if (obits > VL_QUADSIZE) owp = WDataOutP::external(reinterpret_cast<EData*>(datap(nidx)));
|
||||||
|
|
@ -409,7 +409,7 @@ bool VlRandomVar::set(const std::string& idx, const std::string& val) const {
|
||||||
QData* const p = static_cast<QData*>(datap(nidx));
|
QData* const p = static_cast<QData*>(datap(nidx));
|
||||||
*p = VL_CLEAN_QQ(obits, obits, VL_SET_QW(owp));
|
*p = VL_CLEAN_QQ(obits, obits, VL_SET_QW(owp));
|
||||||
} else {
|
} else {
|
||||||
_vl_clean_inplace_w(obits, owp);
|
_vl_clean_inplace_w_T(obits, owp);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -137,8 +137,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
VL_ATTR_ALWINLINE void emitWData(uint64_t time, WDataInP newval, uint32_t bits);
|
VL_ATTR_ALWINLINE void emitWData(uint64_t time, WDataInP newval, uint32_t bits);
|
||||||
VL_ATTR_ALWINLINE void emitFourstateWData(uint64_t time, WDataInP newval, WDataInP newvalXZ,
|
VL_ATTR_ALWINLINE void emitFourstateWData(uint64_t time, WDataInP newval, uint32_t bits);
|
||||||
uint32_t bits);
|
|
||||||
VL_ATTR_ALWINLINE void updateLastTime(uint64_t val) { m_lastTime = val; }
|
VL_ATTR_ALWINLINE void updateLastTime(uint64_t val) { m_lastTime = val; }
|
||||||
|
|
||||||
// ACCESSORS
|
// ACCESSORS
|
||||||
|
|
@ -272,13 +271,13 @@ void VerilatedSaifActivityVar::emitWData(const uint64_t time, const WDataInP new
|
||||||
|
|
||||||
VL_ATTR_ALWINLINE
|
VL_ATTR_ALWINLINE
|
||||||
void VerilatedSaifActivityVar::emitFourstateWData(const uint64_t time, const WDataInP newval,
|
void VerilatedSaifActivityVar::emitFourstateWData(const uint64_t time, const WDataInP newval,
|
||||||
const WDataInP newvalXZ, const uint32_t bits) {
|
const uint32_t bits) {
|
||||||
assert(m_lastTime <= time);
|
assert(m_lastTime <= time);
|
||||||
const uint64_t dt = time - m_lastTime;
|
const uint64_t dt = time - m_lastTime;
|
||||||
for (std::size_t i = 0; i < std::min(m_width, bits); ++i) {
|
for (std::size_t i = 0; i < std::min(m_width, bits) * 2; i += 2) {
|
||||||
const size_t wordIndex = i / VL_EDATASIZE;
|
const size_t wordIndex = i / VL_EDATASIZE;
|
||||||
m_bits[i].aggregateVal(dt, (newval[wordIndex] >> VL_BITBIT_E(i)) & 1,
|
m_bits[i].aggregateVal(dt, (newval[wordIndex] >> VL_BITBIT_E(i)) & 1,
|
||||||
(newvalXZ[wordIndex] >> VL_BITBIT_E(i)) & 1);
|
(newval[wordIndex | 1] >> VL_BITBIT_E(i)) & 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateLastTime(time);
|
updateLastTime(time);
|
||||||
|
|
@ -772,12 +771,12 @@ void VerilatedSaifBuffer::emitWData(const uint32_t code, const WDataInP newval,
|
||||||
|
|
||||||
VL_ATTR_ALWINLINE
|
VL_ATTR_ALWINLINE
|
||||||
void VerilatedSaifBuffer::emitFourstateWData(const uint32_t code, const WDataInP newval,
|
void VerilatedSaifBuffer::emitFourstateWData(const uint32_t code, const WDataInP newval,
|
||||||
const WDataInP newvalXZ, const int bits) {
|
const int bits) {
|
||||||
assert(m_owner.m_activityAccumulators.at(m_fidx)->m_activity.count(code)
|
assert(m_owner.m_activityAccumulators.at(m_fidx)->m_activity.count(code)
|
||||||
&& "Activity must be declared earlier");
|
&& "Activity must be declared earlier");
|
||||||
VerilatedSaifActivityVar& activity
|
VerilatedSaifActivityVar& activity
|
||||||
= m_owner.m_activityAccumulators.at(m_fidx)->m_activity.at(code);
|
= m_owner.m_activityAccumulators.at(m_fidx)->m_activity.at(code);
|
||||||
activity.emitFourstateWData(m_owner.currentTime(), newval, newvalXZ, bits);
|
activity.emitFourstateWData(m_owner.currentTime(), newval, bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
VL_ATTR_ALWINLINE
|
VL_ATTR_ALWINLINE
|
||||||
|
|
|
||||||
|
|
@ -257,8 +257,7 @@ class VerilatedSaifBuffer VL_NOT_FINAL {
|
||||||
VL_ATTR_ALWINLINE void emitFourstateQData(uint32_t code, QData newval, QData newvalXZ,
|
VL_ATTR_ALWINLINE void emitFourstateQData(uint32_t code, QData newval, QData newvalXZ,
|
||||||
int bits);
|
int bits);
|
||||||
VL_ATTR_ALWINLINE void emitWData(uint32_t code, WDataInP newval, int bits);
|
VL_ATTR_ALWINLINE void emitWData(uint32_t code, WDataInP newval, int bits);
|
||||||
VL_ATTR_ALWINLINE void emitFourstateWData(uint32_t code, WDataInP newval, WDataInP newvalXZ,
|
VL_ATTR_ALWINLINE void emitFourstateWData(uint32_t code, WDataInP newval, int bits);
|
||||||
int bits);
|
|
||||||
VL_ATTR_ALWINLINE void emitDouble(uint32_t code, double newval);
|
VL_ATTR_ALWINLINE void emitDouble(uint32_t code, double newval);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -395,7 +395,7 @@ public:
|
||||||
void fullQData(uint32_t* oldp, QData newval, int bits);
|
void fullQData(uint32_t* oldp, QData newval, int bits);
|
||||||
void fullFourstateQData(uint32_t* oldp, QData newval, QData newvalXZ, int bits);
|
void fullFourstateQData(uint32_t* oldp, QData newval, QData newvalXZ, int bits);
|
||||||
void fullWData(uint32_t* oldp, WDataInP newval, int bits);
|
void fullWData(uint32_t* oldp, WDataInP newval, int bits);
|
||||||
void fullFourstateWData(uint32_t* oldp, WDataInP newval, WDataInP newvalXZ, int bits);
|
void fullFourstateWData(uint32_t* oldp, WDataInP newval, int bits);
|
||||||
void fullDouble(uint32_t* oldp, double newval);
|
void fullDouble(uint32_t* oldp, double newval);
|
||||||
void fullEvent(uint32_t* oldp, const VlEventBase* newvalp);
|
void fullEvent(uint32_t* oldp, const VlEventBase* newvalp);
|
||||||
void fullEventTriggered(uint32_t* oldp);
|
void fullEventTriggered(uint32_t* oldp);
|
||||||
|
|
@ -460,12 +460,10 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VL_ATTR_ALWINLINE void chgFourstateWData(uint32_t* oldp, const WDataInP newval,
|
VL_ATTR_ALWINLINE void chgFourstateWData(uint32_t* oldp, const WDataInP newval, int bits) {
|
||||||
const WDataInP newvalXZ, int bits) {
|
|
||||||
for (int i = 0; i < VL_WORDS_I(bits); ++i) {
|
for (int i = 0; i < VL_WORDS_I(bits); ++i) {
|
||||||
const int oldIdx = i << 1;
|
if (VL_UNLIKELY(oldp[i] ^ newval[i])) {
|
||||||
if (VL_UNLIKELY((oldp[oldIdx] ^ newval[i]) | (oldp[oldIdx | 1] ^ newvalXZ[i]))) {
|
fullFourstateWData(oldp, newval, bits);
|
||||||
fullFourstateWData(oldp, newval, newvalXZ, bits);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -665,15 +665,11 @@ void VerilatedTraceBuffer<VL_BUF_T>::fullWData(uint32_t* oldp, const WDataInP ne
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void VerilatedTraceBuffer<VL_BUF_T>::fullFourstateWData(uint32_t* oldp, const WDataInP newval,
|
void VerilatedTraceBuffer<VL_BUF_T>::fullFourstateWData(uint32_t* oldp, const WDataInP newval,
|
||||||
const WDataInP newvalXZp, int bits) {
|
int bits) {
|
||||||
const uint32_t code = oldp - m_sigs_oldvalp;
|
const uint32_t code = oldp - m_sigs_oldvalp;
|
||||||
for (int i = 0; i < VL_WORDS_I(bits); ++i) {
|
for (int i = 0; i < VL_WORDS_I(bits) * 2; ++i) oldp[i] = newval[i];
|
||||||
const int oldIdx = i << 1;
|
|
||||||
oldp[oldIdx] = newval[i];
|
|
||||||
oldp[oldIdx | 1] = newvalXZp[i];
|
|
||||||
}
|
|
||||||
if (VL_UNLIKELY(m_sigs_enabledp && !(VL_BITISSET_W(m_sigs_enabledp, code)))) return;
|
if (VL_UNLIKELY(m_sigs_enabledp && !(VL_BITISSET_W(m_sigs_enabledp, code)))) return;
|
||||||
emitFourstateWData(code, newval, newvalXZp, bits);
|
emitFourstateWData(code, newval, bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
|
|
||||||
|
|
@ -95,37 +95,37 @@ struct VlWide final {
|
||||||
return std::memcmp(m_storage, that.m_storage, N_Words * sizeof(EData)) == 0;
|
return std::memcmp(m_storage, that.m_storage, N_Words * sizeof(EData)) == 0;
|
||||||
}
|
}
|
||||||
bool operator!=(const VlWide<N_Words>& that) const VL_PURE { return !(*this == that); }
|
bool operator!=(const VlWide<N_Words>& that) const VL_PURE { return !(*this == that); }
|
||||||
EData& operator[](size_t index) VL_MT_SAFE { return m_storage[index]; }
|
EData& operator[](size_t index) VL_PURE { return m_storage[index]; }
|
||||||
const EData& operator[](size_t index) const VL_MT_SAFE { return m_storage[index]; }
|
const EData& operator[](size_t index) const VL_PURE { return m_storage[index]; }
|
||||||
VlWide<N_Words>& operator&=(const VlWide& rhs) {
|
VlWide<N_Words>& operator&=(const VlWide& rhs) {
|
||||||
VL_AND_W(N_Words, *this, *this, rhs);
|
VL_AND_W_TTT(N_Words, *this, *this, rhs);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
VlWide<N_Words>& operator|=(const VlWide& rhs) {
|
VlWide<N_Words>& operator|=(const VlWide& rhs) {
|
||||||
VL_OR_W(N_Words, *this, *this, rhs);
|
VL_OR_W_TTT(N_Words, *this, *this, rhs);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
VlWide<N_Words>& operator^=(const VlWide& rhs) {
|
VlWide<N_Words>& operator^=(const VlWide& rhs) {
|
||||||
VL_XOR_W(N_Words, *this, *this, rhs);
|
VL_XOR_W_TTT(N_Words, *this, *this, rhs);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
VlWide<N_Words>& operator+=(const VlWide& rhs) {
|
VlWide<N_Words>& operator+=(const VlWide& rhs) {
|
||||||
VL_ADD_W(N_Words, *this, *this, rhs);
|
VL_ADD_W_TTT(N_Words, *this, *this, rhs);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
VlWide<N_Words>& operator*=(const VlWide& rhs) {
|
VlWide<N_Words>& operator*=(const VlWide& rhs) {
|
||||||
VlWide<N_Words> out{};
|
VlWide<N_Words> out{};
|
||||||
VL_MUL_W(N_Words, out, *this, rhs);
|
VL_MUL_W_TTT(N_Words, out, *this, rhs);
|
||||||
for (size_t i = 0; i < N_Words; ++i) m_storage[i] = out.m_storage[i];
|
for (size_t i = 0; i < N_Words; ++i) m_storage[i] = out.m_storage[i];
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
EData& at(size_t index) VL_MT_SAFE { return m_storage[index]; }
|
EData& at(size_t index) VL_MT_SAFE VL_PURE { return m_storage[index]; }
|
||||||
const EData& at(size_t index) const VL_MT_SAFE { return m_storage[index]; }
|
const EData& at(size_t index) const VL_MT_SAFE VL_PURE { return m_storage[index]; }
|
||||||
size_t size() const VL_PURE { return N_Words; }
|
size_t size() const VL_PURE { return N_Words; }
|
||||||
EData* data() VL_MT_SAFE { return &m_storage[0]; }
|
EData* data() VL_MT_SAFE VL_PURE { return &m_storage[0]; }
|
||||||
const EData* data() const VL_MT_SAFE { return &m_storage[0]; }
|
const EData* data() const VL_MT_SAFE VL_PURE { return &m_storage[0]; }
|
||||||
inline bool operator<(const VlWide<N_Words>& rhs) const VL_PURE;
|
inline bool operator<(const VlWide<N_Words>& rhs) const VL_PURE;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -169,9 +169,28 @@ public:
|
||||||
// METHODS
|
// METHODS
|
||||||
EData* datap() const VL_PURE { return m_datap; }
|
EData* datap() const VL_PURE { return m_datap; }
|
||||||
operator bool() const VL_PURE { return m_datap; }
|
operator bool() const VL_PURE { return m_datap; }
|
||||||
|
EData& operator*() const VL_PURE { return *m_datap; }
|
||||||
EData& operator[](size_t index) const VL_PURE { return m_datap[index]; }
|
EData& operator[](size_t index) const VL_PURE { return m_datap[index]; }
|
||||||
WDataOutP operator+(size_t index) const VL_PURE { return WDataOutP(m_datap + index); }
|
WDataOutP operator+(size_t index) const VL_PURE { return WDataOutP(m_datap + index); }
|
||||||
WDataOutP operator+(int index) const VL_PURE { return WDataOutP(m_datap + index); }
|
WDataOutP operator+(int index) const VL_PURE { return WDataOutP(m_datap + index); }
|
||||||
|
WDataOutP& operator+=(size_t index) {
|
||||||
|
m_datap += index;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
WDataOutP& operator+=(int index) {
|
||||||
|
m_datap += index;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
WDataOutP operator-(size_t index) const VL_PURE { return WDataOutP(m_datap - index); }
|
||||||
|
WDataOutP operator-(int index) const VL_PURE { return WDataOutP(m_datap - index); }
|
||||||
|
WDataOutP& operator-=(size_t index) {
|
||||||
|
m_datap -= index;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
WDataOutP& operator-=(int index) {
|
||||||
|
m_datap -= index;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
static_assert(sizeof(WDataOutP) == sizeof(EData*), "WDataOutP should be a single pointer");
|
static_assert(sizeof(WDataOutP) == sizeof(EData*), "WDataOutP should be a single pointer");
|
||||||
|
|
||||||
|
|
@ -208,17 +227,36 @@ public:
|
||||||
// METHODS
|
// METHODS
|
||||||
const EData* datap() const VL_PURE { return m_datap; }
|
const EData* datap() const VL_PURE { return m_datap; }
|
||||||
operator bool() const VL_PURE { return m_datap; }
|
operator bool() const VL_PURE { return m_datap; }
|
||||||
|
const EData& operator*() const VL_PURE { return *m_datap; }
|
||||||
const EData& operator[](size_t index) const VL_PURE { return m_datap[index]; }
|
const EData& operator[](size_t index) const VL_PURE { return m_datap[index]; }
|
||||||
WDataInP operator+(size_t index) const VL_PURE { return WDataInP(m_datap + index); }
|
WDataInP operator+(size_t index) const VL_PURE { return WDataInP(m_datap + index); }
|
||||||
WDataInP operator+(int index) const VL_PURE { return WDataInP(m_datap + index); }
|
WDataInP operator+(int index) const VL_PURE { return WDataInP(m_datap + index); }
|
||||||
|
WDataInP& operator+=(size_t index) {
|
||||||
|
m_datap += index;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
WDataInP& operator+=(int index) {
|
||||||
|
m_datap += index;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
WDataInP operator-(size_t index) const VL_PURE { return WDataInP(m_datap - index); }
|
||||||
|
WDataInP operator-(int index) const VL_PURE { return WDataInP(m_datap - index); }
|
||||||
|
WDataInP& operator-=(size_t index) {
|
||||||
|
m_datap -= index;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
WDataInP& operator-=(int index) {
|
||||||
|
m_datap -= index;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
static_assert(sizeof(WDataInP) == sizeof(EData*), "WDataInP should be a single pointer");
|
static_assert(sizeof(WDataInP) == sizeof(EData*), "WDataInP should be a single pointer");
|
||||||
|
|
||||||
static int _vl_cmp_w(int words, WDataInP const lwp, WDataInP const rwp) VL_PURE;
|
static int _vl_cmp_w_TT(int words, WDataInP const lwp, WDataInP const rwp) VL_PURE;
|
||||||
|
|
||||||
template <std::size_t N_Words>
|
template <std::size_t N_Words>
|
||||||
bool VlWide<N_Words>::operator<(const VlWide<N_Words>& rhs) const VL_PURE {
|
bool VlWide<N_Words>::operator<(const VlWide<N_Words>& rhs) const VL_PURE {
|
||||||
return _vl_cmp_w(N_Words, *this, rhs) < 0;
|
return _vl_cmp_w_TT(N_Words, *this, rhs) < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//===================================================================
|
//===================================================================
|
||||||
|
|
|
||||||
|
|
@ -749,23 +749,22 @@ void VerilatedVcdBuffer::emitWData(uint32_t code, const WDataInP newval, int bit
|
||||||
}
|
}
|
||||||
|
|
||||||
VL_ATTR_ALWINLINE
|
VL_ATTR_ALWINLINE
|
||||||
void VerilatedVcdBuffer::emitFourstateWData(uint32_t code, const WDataInP newval,
|
void VerilatedVcdBuffer::emitFourstateWData(uint32_t code, const WDataInP newval, int bits) {
|
||||||
const WDataInP newvalXZ, int bits) {
|
|
||||||
char* wp = m_writep;
|
char* wp = m_writep;
|
||||||
*wp++ = 'b';
|
*wp++ = 'b';
|
||||||
const int lastIdx = (bits - 1) / VL_EDATASIZE;
|
const int lastIdx = ((bits - 1) / VL_EDATASIZE) << 1;
|
||||||
{
|
{
|
||||||
const EData value = newval[lastIdx];
|
const EData value = newval[lastIdx];
|
||||||
const EData xz = newvalXZ[lastIdx];
|
const EData xz = newval[lastIdx | 1];
|
||||||
for (int i = (bits - 1) % VL_EDATASIZE; i >= 0; --i) {
|
for (int i = (bits - 1) % VL_EDATASIZE; i >= 0; --i) {
|
||||||
const EData mask = 1 << i;
|
const EData mask = 1 << i;
|
||||||
*wp++ = (xz & mask) ? (value & mask ? 'x' : 'z')
|
*wp++ = (xz & mask) ? (value & mask ? 'x' : 'z')
|
||||||
: ('0' | (static_cast<char>(value >> i) & 1));
|
: ('0' | (static_cast<char>(value >> i) & 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int w = lastIdx - 1; w >= 0; --w) {
|
for (int w = lastIdx - 2; w >= 0; w -= 2) {
|
||||||
const EData value = newval[w];
|
const EData value = newval[w];
|
||||||
const EData xz = newvalXZ[w];
|
const EData xz = newval[w | 1];
|
||||||
for (int i = VL_EDATASIZE - 1; i >= 0; --i) {
|
for (int i = VL_EDATASIZE - 1; i >= 0; --i) {
|
||||||
const EData mask = 1 << i;
|
const EData mask = 1 << i;
|
||||||
*wp++ = (xz & mask) ? (value & mask ? 'x' : 'z')
|
*wp++ = (xz & mask) ? (value & mask ? 'x' : 'z')
|
||||||
|
|
|
||||||
|
|
@ -261,8 +261,7 @@ class VerilatedVcdBuffer VL_NOT_FINAL {
|
||||||
VL_ATTR_ALWINLINE void emitFourstateQData(uint32_t code, QData newval, QData newvalXZ,
|
VL_ATTR_ALWINLINE void emitFourstateQData(uint32_t code, QData newval, QData newvalXZ,
|
||||||
int bits);
|
int bits);
|
||||||
VL_ATTR_ALWINLINE void emitWData(uint32_t code, WDataInP newval, int bits);
|
VL_ATTR_ALWINLINE void emitWData(uint32_t code, WDataInP newval, int bits);
|
||||||
VL_ATTR_ALWINLINE void emitFourstateWData(uint32_t code, WDataInP newval, WDataInP newvalXZ,
|
VL_ATTR_ALWINLINE void emitFourstateWData(uint32_t code, WDataInP newval, int bits);
|
||||||
int bits);
|
|
||||||
VL_ATTR_ALWINLINE void emitDouble(uint32_t code, double newval);
|
VL_ATTR_ALWINLINE void emitDouble(uint32_t code, double newval);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4466,7 +4466,7 @@ void vpi_get_time(vpiHandle object, p_vpi_time time_p) {
|
||||||
if (time_p->type == vpiSimTime) {
|
if (time_p->type == vpiSimTime) {
|
||||||
const QData qtime = VL_TIME_Q();
|
const QData qtime = VL_TIME_Q();
|
||||||
VlWide<2> itime;
|
VlWide<2> itime;
|
||||||
VL_SET_WQ(itime, qtime);
|
VL_SET_WQ_T(itime, qtime);
|
||||||
time_p->low = itime[0];
|
time_p->low = itime[0];
|
||||||
time_p->high = itime[1];
|
time_p->high = itime[1];
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -131,6 +131,19 @@ AstNode::AstNode(VNType t, FileLine* fl)
|
||||||
editCountInc();
|
editCountInc();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int AstNode::widthWords() const {
|
||||||
|
UASSERT_OBJ(m_dtypep, this, "DType is not set");
|
||||||
|
return VL_WORDS_I(width()) * (m_dtypep->isShuffledFourstate() ? 2 : 1);
|
||||||
|
}
|
||||||
|
bool AstNode::isQuad() const VL_MT_STABLE {
|
||||||
|
UASSERT_OBJ(m_dtypep, this, "DType is not set");
|
||||||
|
return !m_dtypep->isShuffledFourstate() && (width() > VL_IDATASIZE && width() <= VL_QUADSIZE);
|
||||||
|
}
|
||||||
|
bool AstNode::isWide() const VL_MT_STABLE {
|
||||||
|
UASSERT_OBJ(m_dtypep, this, "DType is not set");
|
||||||
|
return m_dtypep->isShuffledFourstate() || (width() > VL_QUADSIZE);
|
||||||
|
}
|
||||||
|
|
||||||
AstNode* AstNode::abovep() const {
|
AstNode* AstNode::abovep() const {
|
||||||
// m_headtailp only valid at beginning or end of list
|
// m_headtailp only valid at beginning or end of list
|
||||||
// Avoid supporting at other locations as would require walking
|
// Avoid supporting at other locations as would require walking
|
||||||
|
|
@ -1601,28 +1614,30 @@ void AstNode::dtypeChgWidthSigned(int width, int widthMin, VSigning numeric) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNodeDType* AstNode::findBasicDType(VBasicDTypeKwd kwd) const {
|
AstNodeDType* AstNode::findBasicDType(VBasicDTypeKwd kwd, bool isShuffledFourstate) const {
|
||||||
// For 'simple' types we use the global directory. These are all unsized.
|
// For 'simple' types we use the global directory. These are all unsized.
|
||||||
// More advanced types land under the module/task/etc
|
// More advanced types land under the module/task/etc
|
||||||
return v3Global.rootp()->typeTablep()->findBasicDType(fileline(), kwd);
|
return v3Global.rootp()->typeTablep()->findBasicDType(fileline(), kwd, isShuffledFourstate);
|
||||||
}
|
}
|
||||||
AstNodeDType* AstNode::findBitDType(int width, int widthMin, VSigning numeric) const {
|
AstNodeDType* AstNode::findBitDType(int width, int widthMin, VSigning numeric,
|
||||||
return v3Global.rootp()->typeTablep()->findLogicBitDType(fileline(), VBasicDTypeKwd::BIT,
|
bool isShuffledFourstate) const {
|
||||||
width, widthMin, numeric);
|
return v3Global.rootp()->typeTablep()->findLogicBitDType(
|
||||||
|
fileline(), VBasicDTypeKwd::BIT, width, widthMin, numeric, isShuffledFourstate);
|
||||||
}
|
}
|
||||||
AstNodeDType* AstNode::findLogicDType(int width, int widthMin, VSigning numeric) const {
|
AstNodeDType* AstNode::findLogicDType(int width, int widthMin, VSigning numeric,
|
||||||
return v3Global.rootp()->typeTablep()->findLogicBitDType(fileline(), VBasicDTypeKwd::LOGIC,
|
bool isShuffledFourstate) const {
|
||||||
width, widthMin, numeric);
|
return v3Global.rootp()->typeTablep()->findLogicBitDType(
|
||||||
|
fileline(), VBasicDTypeKwd::LOGIC, width, widthMin, numeric, isShuffledFourstate);
|
||||||
}
|
}
|
||||||
AstNodeDType* AstNode::findLogicRangeDType(const VNumRange& range, int widthMin,
|
AstNodeDType* AstNode::findLogicRangeDType(const VNumRange& range, int widthMin, VSigning numeric,
|
||||||
VSigning numeric) const {
|
bool isShuffledFourstate) const {
|
||||||
return v3Global.rootp()->typeTablep()->findLogicBitDType(fileline(), VBasicDTypeKwd::LOGIC,
|
return v3Global.rootp()->typeTablep()->findLogicBitDType(
|
||||||
range, widthMin, numeric);
|
fileline(), VBasicDTypeKwd::LOGIC, range, widthMin, numeric, isShuffledFourstate);
|
||||||
}
|
}
|
||||||
AstNodeDType* AstNode::findBitRangeDType(const VNumRange& range, int widthMin,
|
AstNodeDType* AstNode::findBitRangeDType(const VNumRange& range, int widthMin, VSigning numeric,
|
||||||
VSigning numeric) const {
|
bool isShuffledFourstate) const {
|
||||||
return v3Global.rootp()->typeTablep()->findLogicBitDType(fileline(), VBasicDTypeKwd::BIT,
|
return v3Global.rootp()->typeTablep()->findLogicBitDType(
|
||||||
range, widthMin, numeric);
|
fileline(), VBasicDTypeKwd::BIT, range, widthMin, numeric, isShuffledFourstate);
|
||||||
}
|
}
|
||||||
AstBasicDType* AstNode::findInsertSameDType(AstBasicDType* nodep) {
|
AstBasicDType* AstNode::findInsertSameDType(AstBasicDType* nodep) {
|
||||||
return v3Global.rootp()->typeTablep()->findInsertSameDType(nodep);
|
return v3Global.rootp()->typeTablep()->findInsertSameDType(nodep);
|
||||||
|
|
|
||||||
22
src/V3Ast.h
22
src/V3Ast.h
|
|
@ -644,9 +644,9 @@ public:
|
||||||
int widthMinV() const {
|
int widthMinV() const {
|
||||||
return v3Global.widthMinUsage() == VWidthMinUsage::VERILOG_WIDTH ? widthMin() : width();
|
return v3Global.widthMinUsage() == VWidthMinUsage::VERILOG_WIDTH ? widthMin() : width();
|
||||||
}
|
}
|
||||||
int widthWords() const { return VL_WORDS_I(width()); }
|
int widthWords() const;
|
||||||
bool isQuad() const VL_MT_STABLE { return (width() > VL_IDATASIZE && width() <= VL_QUADSIZE); }
|
bool isQuad() const VL_MT_STABLE;
|
||||||
bool isWide() const VL_MT_STABLE { return (width() > VL_QUADSIZE); }
|
bool isWide() const VL_MT_STABLE;
|
||||||
inline bool isCHandle() const VL_MT_STABLE;
|
inline bool isCHandle() const VL_MT_STABLE;
|
||||||
inline bool isDouble() const VL_MT_STABLE;
|
inline bool isDouble() const VL_MT_STABLE;
|
||||||
inline bool isSigned() const VL_MT_STABLE;
|
inline bool isSigned() const VL_MT_STABLE;
|
||||||
|
|
@ -793,18 +793,20 @@ public:
|
||||||
AstNodeDType* findQueueIndexDType() const;
|
AstNodeDType* findQueueIndexDType() const;
|
||||||
AstNodeDType* findStreamDType() const;
|
AstNodeDType* findStreamDType() const;
|
||||||
AstNodeDType* findVoidDType() const;
|
AstNodeDType* findVoidDType() const;
|
||||||
AstNodeDType* findBitDType(int width, int widthMin, VSigning numeric) const;
|
AstNodeDType* findBitDType(int width, int widthMin, VSigning numeric,
|
||||||
AstNodeDType* findLogicDType(int width, int widthMin, VSigning numeric) const;
|
bool isShuffledFourstate = false) const;
|
||||||
|
AstNodeDType* findLogicDType(int width, int widthMin, VSigning numeric,
|
||||||
|
bool isShuffledFourstate = false) const;
|
||||||
AstNodeDType* findBitOrLogicDType(int width, int widthMin, VSigning numeric,
|
AstNodeDType* findBitOrLogicDType(int width, int widthMin, VSigning numeric,
|
||||||
bool isFourstate) const {
|
bool isFourstate) const {
|
||||||
return isFourstate ? findLogicDType(width, widthMin, numeric)
|
return isFourstate ? findLogicDType(width, widthMin, numeric)
|
||||||
: findBitDType(width, widthMin, numeric);
|
: findBitDType(width, widthMin, numeric);
|
||||||
}
|
}
|
||||||
AstNodeDType* findLogicRangeDType(const VNumRange& range, int widthMin,
|
AstNodeDType* findLogicRangeDType(const VNumRange& range, int widthMin, VSigning numeric,
|
||||||
VSigning numeric) const VL_MT_STABLE;
|
bool isShuffledFourstate = false) const VL_MT_STABLE;
|
||||||
AstNodeDType* findBitRangeDType(const VNumRange& range, int widthMin,
|
AstNodeDType* findBitRangeDType(const VNumRange& range, int widthMin, VSigning numeric,
|
||||||
VSigning numeric) const VL_MT_STABLE;
|
bool isShuffledFourstate = false) const VL_MT_STABLE;
|
||||||
AstNodeDType* findBasicDType(VBasicDTypeKwd kwd) const;
|
AstNodeDType* findBasicDType(VBasicDTypeKwd kwd, bool isShuffledFourstate = false) const;
|
||||||
static AstBasicDType* findInsertSameDType(AstBasicDType* nodep);
|
static AstBasicDType* findInsertSameDType(AstBasicDType* nodep);
|
||||||
|
|
||||||
static VCastable computeCastable(const AstNodeDType* toDtp, const AstNodeDType* fromDtp,
|
static VCastable computeCastable(const AstNodeDType* toDtp, const AstNodeDType* fromDtp,
|
||||||
|
|
|
||||||
|
|
@ -2172,9 +2172,11 @@ public:
|
||||||
const VNumRange m_nrange; // From AstBasicDType: Numeric msb/lsb (if non-opaque keyword)
|
const VNumRange m_nrange; // From AstBasicDType: Numeric msb/lsb (if non-opaque keyword)
|
||||||
const VSigning m_numeric; // From AstNodeDType: Node is signed
|
const VSigning m_numeric; // From AstNodeDType: Node is signed
|
||||||
const VBasicDTypeKwd m_keyword; // From AstBasicDType: What keyword created basic type
|
const VBasicDTypeKwd m_keyword; // From AstBasicDType: What keyword created basic type
|
||||||
|
const bool m_isShuffledFourstate; // Whether it is a shuffled fourstate
|
||||||
bool operator==(const VBasicTypeKey& rhs) const {
|
bool operator==(const VBasicTypeKey& rhs) const {
|
||||||
return m_width == rhs.m_width && m_widthMin == rhs.m_widthMin && m_numeric == rhs.m_numeric
|
return m_width == rhs.m_width && m_widthMin == rhs.m_widthMin && m_numeric == rhs.m_numeric
|
||||||
&& m_keyword == rhs.m_keyword && m_nrange == rhs.m_nrange;
|
&& m_keyword == rhs.m_keyword && m_nrange == rhs.m_nrange
|
||||||
|
&& m_isShuffledFourstate == rhs.m_isShuffledFourstate;
|
||||||
}
|
}
|
||||||
bool operator<(const VBasicTypeKey& rhs) const {
|
bool operator<(const VBasicTypeKey& rhs) const {
|
||||||
if ((m_width < rhs.m_width)) return true;
|
if ((m_width < rhs.m_width)) return true;
|
||||||
|
|
@ -2187,15 +2189,17 @@ public:
|
||||||
if (!(m_keyword == rhs.m_keyword)) return false; // lhs > rhs
|
if (!(m_keyword == rhs.m_keyword)) return false; // lhs > rhs
|
||||||
if ((m_nrange < rhs.m_nrange)) return true;
|
if ((m_nrange < rhs.m_nrange)) return true;
|
||||||
if (!(m_nrange == rhs.m_nrange)) return false; // lhs > rhs
|
if (!(m_nrange == rhs.m_nrange)) return false; // lhs > rhs
|
||||||
|
if (!m_isShuffledFourstate && rhs.m_isShuffledFourstate) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
VBasicTypeKey(int width, int widthMin, VSigning numeric, VBasicDTypeKwd kwd,
|
VBasicTypeKey(int width, int widthMin, VSigning numeric, VBasicDTypeKwd kwd,
|
||||||
const VNumRange& nrange)
|
const VNumRange& nrange, bool isShuffledFourstate)
|
||||||
: m_width{width}
|
: m_width{width}
|
||||||
, m_widthMin{widthMin}
|
, m_widthMin{widthMin}
|
||||||
, m_nrange{nrange}
|
, m_nrange{nrange}
|
||||||
, m_numeric{numeric}
|
, m_numeric{numeric}
|
||||||
, m_keyword{kwd} {}
|
, m_keyword{kwd}
|
||||||
|
, m_isShuffledFourstate{isShuffledFourstate} {}
|
||||||
~VBasicTypeKey() = default;
|
~VBasicTypeKey() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -158,7 +158,9 @@ public:
|
||||||
bool isSigned() const VL_MT_STABLE { return m_numeric.isSigned(); }
|
bool isSigned() const VL_MT_STABLE { return m_numeric.isSigned(); }
|
||||||
bool isNosign() const VL_MT_SAFE { return m_numeric.isNosign(); }
|
bool isNosign() const VL_MT_SAFE { return m_numeric.isNosign(); }
|
||||||
VSigning numeric() const VL_MT_STABLE { return m_numeric; }
|
VSigning numeric() const VL_MT_STABLE { return m_numeric; }
|
||||||
int widthWords() const VL_MT_STABLE { return VL_WORDS_I(width()); }
|
int widthWords() const VL_MT_STABLE {
|
||||||
|
return VL_WORDS_I(width()) * (isShuffledFourstate() ? 2 : 1);
|
||||||
|
}
|
||||||
int widthMin() const VL_MT_STABLE { // If sized, the size,
|
int widthMin() const VL_MT_STABLE { // If sized, the size,
|
||||||
// if unsized the min digits to represent it
|
// if unsized the min digits to represent it
|
||||||
return m_widthMin ? m_widthMin : m_width;
|
return m_widthMin ? m_widthMin : m_width;
|
||||||
|
|
@ -183,6 +185,7 @@ public:
|
||||||
// Represents a C++ LiteralType? (can be constexpr)
|
// Represents a C++ LiteralType? (can be constexpr)
|
||||||
bool isLiteralType() const VL_MT_STABLE;
|
bool isLiteralType() const VL_MT_STABLE;
|
||||||
virtual bool isDynamicallySized() const { return false; }
|
virtual bool isDynamicallySized() const { return false; }
|
||||||
|
virtual bool isShuffledFourstate() const VL_MT_STABLE { return false; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class CTypeRecursed;
|
class CTypeRecursed;
|
||||||
|
|
@ -407,37 +410,47 @@ class AstBasicDType final : public AstNodeDType {
|
||||||
struct Members final {
|
struct Members final {
|
||||||
VBasicDTypeKwd m_keyword; // (also in VBasicTypeKey) What keyword created basic type
|
VBasicDTypeKwd m_keyword; // (also in VBasicTypeKey) What keyword created basic type
|
||||||
VNumRange m_nrange; // (also in VBasicTypeKey) Numeric msb/lsb (if non-opaque keyword)
|
VNumRange m_nrange; // (also in VBasicTypeKey) Numeric msb/lsb (if non-opaque keyword)
|
||||||
|
bool m_isShuffledFourstate; // (also in VBasicTypeKey) whether it is a shuffled four-state
|
||||||
|
// value (forty shuffled bits will be represented as 80bits in
|
||||||
|
// 128 bits VlWide) - shuffled implies wide that stores values
|
||||||
|
// as described in:
|
||||||
|
// IEEE 1800-2023 38. VPI routine definitions
|
||||||
|
// Figure 38-8 - s_vpi_vecval structure definition
|
||||||
bool operator==(const Members& rhs) const {
|
bool operator==(const Members& rhs) const {
|
||||||
return rhs.m_keyword == m_keyword && rhs.m_nrange == m_nrange;
|
return rhs.m_keyword == m_keyword && rhs.m_nrange == m_nrange
|
||||||
|
&& rhs.m_isShuffledFourstate == m_isShuffledFourstate;
|
||||||
}
|
}
|
||||||
} m;
|
} m;
|
||||||
// See also in AstNodeDType: m_width, m_widthMin, m_numeric(issigned)
|
// See also in AstNodeDType: m_width, m_widthMin, m_numeric(issigned)
|
||||||
public:
|
public:
|
||||||
AstBasicDType(FileLine* fl, VBasicDTypeKwd kwd, const VSigning& signst = VSigning::NOSIGN)
|
AstBasicDType(FileLine* fl, VBasicDTypeKwd kwd, const VSigning& signst = VSigning::NOSIGN,
|
||||||
|
bool isShuffledFourstate = false)
|
||||||
: ASTGEN_SUPER_BasicDType(fl) {
|
: ASTGEN_SUPER_BasicDType(fl) {
|
||||||
init(kwd, signst, 0, -1, nullptr);
|
init(kwd, signst, 0, -1, nullptr, isShuffledFourstate);
|
||||||
}
|
}
|
||||||
AstBasicDType(FileLine* fl, VFlagLogicPacked, int wantwidth)
|
AstBasicDType(FileLine* fl, VFlagLogicPacked, int wantwidth, bool isShuffledFourstate = false)
|
||||||
: ASTGEN_SUPER_BasicDType(fl) {
|
: ASTGEN_SUPER_BasicDType(fl) {
|
||||||
init(VBasicDTypeKwd::LOGIC, VSigning::NOSIGN, wantwidth, -1, nullptr);
|
init(VBasicDTypeKwd::LOGIC, VSigning::NOSIGN, wantwidth, -1, nullptr, isShuffledFourstate);
|
||||||
}
|
}
|
||||||
AstBasicDType(FileLine* fl, VFlagBitPacked, int wantwidth)
|
AstBasicDType(FileLine* fl, VFlagBitPacked, int wantwidth, bool isShuffledFourstate = false)
|
||||||
: ASTGEN_SUPER_BasicDType(fl) {
|
: ASTGEN_SUPER_BasicDType(fl) {
|
||||||
init(VBasicDTypeKwd::BIT, VSigning::NOSIGN, wantwidth, -1, nullptr);
|
init(VBasicDTypeKwd::BIT, VSigning::NOSIGN, wantwidth, -1, nullptr, isShuffledFourstate);
|
||||||
}
|
}
|
||||||
AstBasicDType(FileLine* fl, VBasicDTypeKwd kwd, VSigning numer, int wantwidth, int widthmin)
|
AstBasicDType(FileLine* fl, VBasicDTypeKwd kwd, VSigning numer, int wantwidth, int widthmin,
|
||||||
|
bool isShuffledFourstate = false)
|
||||||
: ASTGEN_SUPER_BasicDType(fl) {
|
: ASTGEN_SUPER_BasicDType(fl) {
|
||||||
init(kwd, numer, wantwidth, widthmin, nullptr);
|
init(kwd, numer, wantwidth, widthmin, nullptr, isShuffledFourstate);
|
||||||
}
|
}
|
||||||
AstBasicDType(FileLine* fl, VBasicDTypeKwd kwd, VSigning numer, VNumRange range, int widthmin)
|
AstBasicDType(FileLine* fl, VBasicDTypeKwd kwd, VSigning numer, VNumRange range, int widthmin,
|
||||||
|
bool isShuffledFourstate = false)
|
||||||
: ASTGEN_SUPER_BasicDType(fl) {
|
: ASTGEN_SUPER_BasicDType(fl) {
|
||||||
init(kwd, numer, range.elements(), widthmin, nullptr);
|
init(kwd, numer, range.elements(), widthmin, nullptr, isShuffledFourstate);
|
||||||
m.m_nrange = range; // as init() presumes lsb==0, but range.lsb() might not be
|
m.m_nrange = range; // as init() presumes lsb==0, but range.lsb() might not be
|
||||||
}
|
}
|
||||||
// See also addRange in verilog.y
|
// See also addRange in verilog.y
|
||||||
private:
|
private:
|
||||||
void init(VBasicDTypeKwd kwd, VSigning numer, int wantwidth, int wantwidthmin,
|
void init(VBasicDTypeKwd kwd, VSigning numer, int wantwidth, int wantwidthmin,
|
||||||
AstRange* rangep);
|
AstRange* rangep, bool isShuffledFourstate);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ASTGEN_MEMBERS_AstBasicDType;
|
ASTGEN_MEMBERS_AstBasicDType;
|
||||||
|
|
@ -521,6 +534,7 @@ public:
|
||||||
void cvtRangeConst(); // Convert to smaller representation
|
void cvtRangeConst(); // Convert to smaller representation
|
||||||
bool isCompound() const override { return isString(); }
|
bool isCompound() const override { return isString(); }
|
||||||
bool isIntegralOrPacked() const override { return keyword().isIntNumeric(); }
|
bool isIntegralOrPacked() const override { return keyword().isIntNumeric(); }
|
||||||
|
bool isShuffledFourstate() const VL_MT_STABLE override { return m.m_isShuffledFourstate; }
|
||||||
};
|
};
|
||||||
class AstBracketArrayDType final : public AstNodeDType {
|
class AstBracketArrayDType final : public AstNodeDType {
|
||||||
// Associative/Queue/Normal array data type, ie "[dtype_or_expr]"
|
// Associative/Queue/Normal array data type, ie "[dtype_or_expr]"
|
||||||
|
|
|
||||||
|
|
@ -487,6 +487,8 @@ private:
|
||||||
VSelfPointerText m_selfPointer
|
VSelfPointerText m_selfPointer
|
||||||
= VSelfPointerText{VSelfPointerText::Empty()}; // Output code object
|
= VSelfPointerText{VSelfPointerText::Empty()}; // Output code object
|
||||||
// pointer (e.g.: 'this')
|
// pointer (e.g.: 'this')
|
||||||
|
bool m_fourstateXZPart : 1; // If references four-state shuffled var true for XZ part and
|
||||||
|
// false for value part
|
||||||
protected:
|
protected:
|
||||||
AstNodeVarRef(VNType t, FileLine* fl, AstVar* varp, const VAccess& access)
|
AstNodeVarRef(VNType t, FileLine* fl, AstVar* varp, const VAccess& access)
|
||||||
: AstNodeExpr{t, fl}
|
: AstNodeExpr{t, fl}
|
||||||
|
|
@ -516,6 +518,8 @@ public:
|
||||||
AstNodeModule* classOrPackagep() const { return m_classOrPackagep; }
|
AstNodeModule* classOrPackagep() const { return m_classOrPackagep; }
|
||||||
void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; }
|
void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; }
|
||||||
static AstNodeVarRef* varRefLValueRecurse(AstNode* nodep);
|
static AstNodeVarRef* varRefLValueRecurse(AstNode* nodep);
|
||||||
|
void fourstateXZPart(bool xz) { m_fourstateXZPart = xz; }
|
||||||
|
bool fourstateXZPart() const { return m_fourstateXZPart; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// === Concrete node types =====================================================
|
// === Concrete node types =====================================================
|
||||||
|
|
@ -3122,7 +3126,7 @@ public:
|
||||||
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
||||||
out.opConcat(lhs, rhs);
|
out.opConcat(lhs, rhs);
|
||||||
}
|
}
|
||||||
string emitC() override { return "VL_CONCAT_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
string emitC() override { return "VL_CONCAT_%nq%lq%rq_%nf%lf%rf(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||||
string emitSMT() const override { return "(concat %l %r)"; }
|
string emitSMT() const override { return "(concat %l %r)"; }
|
||||||
bool cleanOut() const override { return true; }
|
bool cleanOut() const override { return true; }
|
||||||
bool cleanLhs() const override { return true; }
|
bool cleanLhs() const override { return true; }
|
||||||
|
|
@ -3164,7 +3168,7 @@ public:
|
||||||
out.opDiv(lhs, rhs);
|
out.opDiv(lhs, rhs);
|
||||||
}
|
}
|
||||||
string emitVerilog() override { return "%k(%l %f/ %r)"; }
|
string emitVerilog() override { return "%k(%l %f/ %r)"; }
|
||||||
string emitC() override { return "VL_DIV_%nq%lq%rq(%lw, %P, %li, %ri)"; }
|
string emitC() override { return "VL_DIV_%nq%lq%rq_%nf%lf%rf(%lw, %P, %li, %ri)"; }
|
||||||
string emitSMT() const override { return "(bvudiv %l %r)"; }
|
string emitSMT() const override { return "(bvudiv %l %r)"; }
|
||||||
bool emitCheckMaxWords() override { return true; }
|
bool emitCheckMaxWords() override { return true; }
|
||||||
bool cleanOut() const override { return false; }
|
bool cleanOut() const override { return false; }
|
||||||
|
|
@ -3207,7 +3211,7 @@ public:
|
||||||
out.opDivS(lhs, rhs);
|
out.opDivS(lhs, rhs);
|
||||||
}
|
}
|
||||||
string emitVerilog() override { return "%k(%l %f/ %r)"; }
|
string emitVerilog() override { return "%k(%l %f/ %r)"; }
|
||||||
string emitC() override { return "VL_DIVS_%nq%lq%rq(%lw, %P, %li, %ri)"; }
|
string emitC() override { return "VL_DIVS_%nq%lq%rq_%nf%lf%rf(%lw, %P, %li, %ri)"; }
|
||||||
string emitSMT() const override { return "(bvsdiv %l %r)"; }
|
string emitSMT() const override { return "(bvsdiv %l %r)"; }
|
||||||
bool emitCheckMaxWords() override { return true; }
|
bool emitCheckMaxWords() override { return true; }
|
||||||
bool cleanOut() const override { return false; }
|
bool cleanOut() const override { return false; }
|
||||||
|
|
@ -3242,7 +3246,7 @@ public:
|
||||||
if (v3Global.opt.fourstate()) {
|
if (v3Global.opt.fourstate()) {
|
||||||
V3ERROR_NA_RETURN("");
|
V3ERROR_NA_RETURN("");
|
||||||
} else {
|
} else {
|
||||||
return "VL_EQ_%lq(%lW, %P, %li, %ri)";
|
return "VL_EQ_%lq_%lf%rf(%lW, %P, %li, %ri)";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
string emitSMT() const override { return "(__Vbv (= %l %r))"; }
|
string emitSMT() const override { return "(__Vbv (= %l %r))"; }
|
||||||
|
|
@ -3355,7 +3359,7 @@ public:
|
||||||
out.opGt(lhs, rhs);
|
out.opGt(lhs, rhs);
|
||||||
}
|
}
|
||||||
string emitVerilog() override { return "%k(%l %f> %r)"; }
|
string emitVerilog() override { return "%k(%l %f> %r)"; }
|
||||||
string emitC() override { return "VL_GT_%lq(%lW, %P, %li, %ri)"; }
|
string emitC() override { return "VL_GT_%lq_%lf%rf(%lW, %P, %li, %ri)"; }
|
||||||
string emitSMT() const override { return "(__Vbv (bvugt %l %r))"; }
|
string emitSMT() const override { return "(__Vbv (bvugt %l %r))"; }
|
||||||
string emitSimpleOperator() override { return ">"; }
|
string emitSimpleOperator() override { return ">"; }
|
||||||
bool cleanOut() const override { return true; }
|
bool cleanOut() const override { return true; }
|
||||||
|
|
@ -3418,7 +3422,7 @@ public:
|
||||||
out.opGtS(lhs, rhs);
|
out.opGtS(lhs, rhs);
|
||||||
}
|
}
|
||||||
string emitVerilog() override { return "%k(%l %f> %r)"; }
|
string emitVerilog() override { return "%k(%l %f> %r)"; }
|
||||||
string emitC() override { return "VL_GTS_%nq%lq%rq(%lw, %P, %li, %ri)"; }
|
string emitC() override { return "VL_GTS_%nq%lq%rq_%lf%rf(%lw, %P, %li, %ri)"; }
|
||||||
string emitSMT() const override { return "(__Vbv (bvsgt %l %r))"; }
|
string emitSMT() const override { return "(__Vbv (bvsgt %l %r))"; }
|
||||||
string emitSimpleOperator() override { return ""; }
|
string emitSimpleOperator() override { return ""; }
|
||||||
bool cleanOut() const override { return true; }
|
bool cleanOut() const override { return true; }
|
||||||
|
|
@ -3440,7 +3444,7 @@ public:
|
||||||
out.opGte(lhs, rhs);
|
out.opGte(lhs, rhs);
|
||||||
}
|
}
|
||||||
string emitVerilog() override { return "%k(%l %f>= %r)"; }
|
string emitVerilog() override { return "%k(%l %f>= %r)"; }
|
||||||
string emitC() override { return "VL_GTE_%lq(%lW, %P, %li, %ri)"; }
|
string emitC() override { return "VL_GTE_%lq_%lf%rf(%lW, %P, %li, %ri)"; }
|
||||||
string emitSMT() const override { return "(__Vbv (bvuge %l %r))"; }
|
string emitSMT() const override { return "(__Vbv (bvuge %l %r))"; }
|
||||||
string emitSimpleOperator() override { return ">="; }
|
string emitSimpleOperator() override { return ">="; }
|
||||||
bool cleanOut() const override { return true; }
|
bool cleanOut() const override { return true; }
|
||||||
|
|
@ -3503,7 +3507,7 @@ public:
|
||||||
out.opGteS(lhs, rhs);
|
out.opGteS(lhs, rhs);
|
||||||
}
|
}
|
||||||
string emitVerilog() override { return "%k(%l %f>= %r)"; }
|
string emitVerilog() override { return "%k(%l %f>= %r)"; }
|
||||||
string emitC() override { return "VL_GTES_%nq%lq%rq(%lw, %P, %li, %ri)"; }
|
string emitC() override { return "VL_GTES_%nq%lq%rq_%lf%rf(%lw, %P, %li, %ri)"; }
|
||||||
string emitSMT() const override { return "(__Vbv (bvsge %l %r))"; }
|
string emitSMT() const override { return "(__Vbv (bvsge %l %r))"; }
|
||||||
string emitSimpleOperator() override { return ""; }
|
string emitSimpleOperator() override { return ""; }
|
||||||
bool cleanOut() const override { return true; }
|
bool cleanOut() const override { return true; }
|
||||||
|
|
@ -3525,7 +3529,7 @@ public:
|
||||||
out.opLogAnd(lhs, rhs);
|
out.opLogAnd(lhs, rhs);
|
||||||
}
|
}
|
||||||
string emitVerilog() override { return "%k(%l %f&& %r)"; }
|
string emitVerilog() override { return "%k(%l %f&& %r)"; }
|
||||||
string emitC() override { return "VL_LOGAND_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
||||||
string emitSMT() const override { return "(bvand %l %r)"; }
|
string emitSMT() const override { return "(bvand %l %r)"; }
|
||||||
string emitSimpleOperator() override { return "&&"; }
|
string emitSimpleOperator() override { return "&&"; }
|
||||||
bool cleanOut() const override { return true; }
|
bool cleanOut() const override { return true; }
|
||||||
|
|
@ -3547,7 +3551,7 @@ public:
|
||||||
out.opLogIf(lhs, rhs);
|
out.opLogIf(lhs, rhs);
|
||||||
}
|
}
|
||||||
string emitVerilog() override { return "%k(%l %f-> %r)"; }
|
string emitVerilog() override { return "%k(%l %f-> %r)"; }
|
||||||
string emitC() override { return "VL_LOGIF_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
||||||
string emitSMT() const override { return "(__Vbv (=> (__Vbool %l) (__Vbool %r)))"; }
|
string emitSMT() const override { return "(__Vbv (=> (__Vbool %l) (__Vbool %r)))"; }
|
||||||
string emitSimpleOperator() override { return "->"; }
|
string emitSimpleOperator() override { return "->"; }
|
||||||
bool cleanOut() const override { return true; }
|
bool cleanOut() const override { return true; }
|
||||||
|
|
@ -3569,7 +3573,7 @@ public:
|
||||||
out.opLogOr(lhs, rhs);
|
out.opLogOr(lhs, rhs);
|
||||||
}
|
}
|
||||||
string emitVerilog() override { return "%k(%l %f|| %r)"; }
|
string emitVerilog() override { return "%k(%l %f|| %r)"; }
|
||||||
string emitC() override { return "VL_LOGOR_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
||||||
string emitSMT() const override { return "(bvor %l %r)"; }
|
string emitSMT() const override { return "(bvor %l %r)"; }
|
||||||
string emitSimpleOperator() override { return "||"; }
|
string emitSimpleOperator() override { return "||"; }
|
||||||
bool cleanOut() const override { return true; }
|
bool cleanOut() const override { return true; }
|
||||||
|
|
@ -3591,7 +3595,7 @@ public:
|
||||||
out.opLt(lhs, rhs);
|
out.opLt(lhs, rhs);
|
||||||
}
|
}
|
||||||
string emitVerilog() override { return "%k(%l %f< %r)"; }
|
string emitVerilog() override { return "%k(%l %f< %r)"; }
|
||||||
string emitC() override { return "VL_LT_%lq(%lW, %P, %li, %ri)"; }
|
string emitC() override { return "VL_LT_%lq_%lf%rf(%lW, %P, %li, %ri)"; }
|
||||||
string emitSMT() const override { return "(__Vbv (bvult %l %r))"; }
|
string emitSMT() const override { return "(__Vbv (bvult %l %r))"; }
|
||||||
string emitSimpleOperator() override { return "<"; }
|
string emitSimpleOperator() override { return "<"; }
|
||||||
bool cleanOut() const override { return true; }
|
bool cleanOut() const override { return true; }
|
||||||
|
|
@ -3654,7 +3658,7 @@ public:
|
||||||
out.opLtS(lhs, rhs);
|
out.opLtS(lhs, rhs);
|
||||||
}
|
}
|
||||||
string emitVerilog() override { return "%k(%l %f< %r)"; }
|
string emitVerilog() override { return "%k(%l %f< %r)"; }
|
||||||
string emitC() override { return "VL_LTS_%nq%lq%rq(%lw, %P, %li, %ri)"; }
|
string emitC() override { return "VL_LTS_%nq%lq%rq_%lf%rf(%lw, %P, %li, %ri)"; }
|
||||||
string emitSMT() const override { return "(__Vbv (bvslt %l %r))"; }
|
string emitSMT() const override { return "(__Vbv (bvslt %l %r))"; }
|
||||||
string emitSimpleOperator() override { return ""; }
|
string emitSimpleOperator() override { return ""; }
|
||||||
bool cleanOut() const override { return true; }
|
bool cleanOut() const override { return true; }
|
||||||
|
|
@ -3676,7 +3680,7 @@ public:
|
||||||
out.opLte(lhs, rhs);
|
out.opLte(lhs, rhs);
|
||||||
}
|
}
|
||||||
string emitVerilog() override { return "%k(%l %f<= %r)"; }
|
string emitVerilog() override { return "%k(%l %f<= %r)"; }
|
||||||
string emitC() override { return "VL_LTE_%lq(%lW, %P, %li, %ri)"; }
|
string emitC() override { return "VL_LTE_%lq_%lf%rf(%lW, %P, %li, %ri)"; }
|
||||||
string emitSMT() const override { return "(__Vbv (bvule %l %r))"; }
|
string emitSMT() const override { return "(__Vbv (bvule %l %r))"; }
|
||||||
string emitSimpleOperator() override { return "<="; }
|
string emitSimpleOperator() override { return "<="; }
|
||||||
bool cleanOut() const override { return true; }
|
bool cleanOut() const override { return true; }
|
||||||
|
|
@ -3739,7 +3743,7 @@ public:
|
||||||
out.opLteS(lhs, rhs);
|
out.opLteS(lhs, rhs);
|
||||||
}
|
}
|
||||||
string emitVerilog() override { return "%k(%l %f<= %r)"; }
|
string emitVerilog() override { return "%k(%l %f<= %r)"; }
|
||||||
string emitC() override { return "VL_LTES_%nq%lq%rq(%lw, %P, %li, %ri)"; }
|
string emitC() override { return "VL_LTES_%nq%lq%rq_%lf%rf(%lw, %P, %li, %ri)"; }
|
||||||
string emitSMT() const override { return "(__Vbv (bvsle %l %r))"; }
|
string emitSMT() const override { return "(__Vbv (bvsle %l %r))"; }
|
||||||
string emitSimpleOperator() override { return ""; }
|
string emitSimpleOperator() override { return ""; }
|
||||||
bool cleanOut() const override { return true; }
|
bool cleanOut() const override { return true; }
|
||||||
|
|
@ -3761,7 +3765,7 @@ public:
|
||||||
out.opModDiv(lhs, rhs);
|
out.opModDiv(lhs, rhs);
|
||||||
}
|
}
|
||||||
string emitVerilog() override { return "%k(%l %f%% %r)"; }
|
string emitVerilog() override { return "%k(%l %f%% %r)"; }
|
||||||
string emitC() override { return "VL_MODDIV_%nq%lq%rq(%lw, %P, %li, %ri)"; }
|
string emitC() override { return "VL_MODDIV_%nq%lq%rq_%nf%lf%rf(%lw, %P, %li, %ri)"; }
|
||||||
string emitSMT() const override { return "(bvurem %l %r)"; }
|
string emitSMT() const override { return "(bvurem %l %r)"; }
|
||||||
bool emitCheckMaxWords() override { return true; }
|
bool emitCheckMaxWords() override { return true; }
|
||||||
bool cleanOut() const override { return false; }
|
bool cleanOut() const override { return false; }
|
||||||
|
|
@ -3783,7 +3787,7 @@ public:
|
||||||
out.opModDivS(lhs, rhs);
|
out.opModDivS(lhs, rhs);
|
||||||
}
|
}
|
||||||
string emitVerilog() override { return "%k(%l %f%% %r)"; }
|
string emitVerilog() override { return "%k(%l %f%% %r)"; }
|
||||||
string emitC() override { return "VL_MODDIVS_%nq%lq%rq(%lw, %P, %li, %ri)"; }
|
string emitC() override { return "VL_MODDIVS_%nq%lq%rq_%nf%lf%rf(%lw, %P, %li, %ri)"; }
|
||||||
string emitSMT() const override { return "(bvsmod %l %r)"; }
|
string emitSMT() const override { return "(bvsmod %l %r)"; }
|
||||||
bool emitCheckMaxWords() override { return true; }
|
bool emitCheckMaxWords() override { return true; }
|
||||||
bool cleanOut() const override { return false; }
|
bool cleanOut() const override { return false; }
|
||||||
|
|
@ -3815,7 +3819,7 @@ public:
|
||||||
if (v3Global.opt.fourstate()) {
|
if (v3Global.opt.fourstate()) {
|
||||||
V3ERROR_NA_RETURN("");
|
V3ERROR_NA_RETURN("");
|
||||||
} else {
|
} else {
|
||||||
return "VL_NEQ_%lq(%lW, %P, %li, %ri)";
|
return "VL_NEQ_%lq_%lf%rf(%lW, %P, %li, %ri)";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
string emitSimpleOperator() override {
|
string emitSimpleOperator() override {
|
||||||
|
|
@ -3950,9 +3954,17 @@ public:
|
||||||
if (const AstConst* const constp = VN_CAST(rhsp, Const)) {
|
if (const AstConst* const constp = VN_CAST(rhsp, Const)) {
|
||||||
if (constp->num().isFourState()
|
if (constp->num().isFourState()
|
||||||
|| (constp->dtypep()->isSigned() && constp->num().isNegative())) {
|
|| (constp->dtypep()->isSigned() && constp->num().isNegative())) {
|
||||||
dtypeSetLogicSized(lhsp->width(), VSigning::UNSIGNED); // V3Width warns
|
if (lhsp->dtypep() && !lhsp->dtypep()->isFourstate()) {
|
||||||
|
dtypeSetBitSized(lhsp->width(), VSigning::UNSIGNED); // V3Width warns
|
||||||
|
} else {
|
||||||
|
dtypeSetLogicSized(lhsp->width(), VSigning::UNSIGNED); // V3Width warns
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
dtypeSetLogicSized(lhsp->width() * constp->toSInt(), VSigning::UNSIGNED);
|
if (lhsp->dtypep() && !lhsp->dtypep()->isFourstate()) {
|
||||||
|
dtypeSetBitSized(lhsp->width() * constp->toSInt(), VSigning::UNSIGNED);
|
||||||
|
} else {
|
||||||
|
dtypeSetLogicSized(lhsp->width() * constp->toSInt(), VSigning::UNSIGNED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3964,7 +3976,7 @@ public:
|
||||||
out.opRepl(lhs, rhs);
|
out.opRepl(lhs, rhs);
|
||||||
}
|
}
|
||||||
string emitVerilog() override { return "%f{%r{%k%l}}"; }
|
string emitVerilog() override { return "%f{%r{%k%l}}"; }
|
||||||
string emitC() override { return "VL_REPLICATE_%nq%lq%rq(%lw, %P, %li, %ri)"; }
|
string emitC() override { return "VL_REPLICATE_%nq%lq%rq_%nf%lf%rf(%lw, %P, %li, %ri)"; }
|
||||||
string emitSMT() const override {
|
string emitSMT() const override {
|
||||||
return "((_ repeat " + cvtToStr(width() / lhsp()->width()) + ") %l)";
|
return "((_ repeat " + cvtToStr(width() / lhsp()->width()) + ") %l)";
|
||||||
}
|
}
|
||||||
|
|
@ -4127,7 +4139,15 @@ public:
|
||||||
: ASTGEN_SUPER_Sel(fl, fromp, lsbp)
|
: ASTGEN_SUPER_Sel(fl, fromp, lsbp)
|
||||||
, m_declElWidth{1}
|
, m_declElWidth{1}
|
||||||
, m_widthConst{bitwidth} {
|
, m_widthConst{bitwidth} {
|
||||||
dtypeSetLogicSized(bitwidth, VSigning::UNSIGNED);
|
if (const AstNodeDType* const dtypep = fromp->dtypep()) {
|
||||||
|
if (dtypep->isFourstate()) {
|
||||||
|
dtypeSetLogicSized(bitwidth, VSigning::UNSIGNED);
|
||||||
|
} else {
|
||||||
|
dtypeSetBitSized(bitwidth, VSigning::UNSIGNED);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dtypeSetLogicSized(bitwidth, VSigning::UNSIGNED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
AstSel(FileLine* fl, AstNodeExpr* fromp, int lsb, int bitwidth)
|
AstSel(FileLine* fl, AstNodeExpr* fromp, int lsb, int bitwidth)
|
||||||
: ASTGEN_SUPER_Sel(fl, fromp, new AstConst(fl, lsb)) // Need () constructor
|
: ASTGEN_SUPER_Sel(fl, fromp, new AstConst(fl, lsb)) // Need () constructor
|
||||||
|
|
@ -4143,9 +4163,9 @@ public:
|
||||||
}
|
}
|
||||||
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
|
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
|
||||||
string emitC() override {
|
string emitC() override {
|
||||||
return widthConst() == 1 ? "VL_BITSEL_%nq%lq%rqI(%lw, %P, %li, %ri)"
|
return widthConst() == 1 ? "VL_BITSEL_%nq%lq%rqI_%nf%lf%rfT(%lw, %P, %li, %ri)"
|
||||||
: isWide() ? "VL_SEL_%nq%lq%rqI(%nw, %lw, %P, %li, %ri, %nw)"
|
: isWide() ? "VL_SEL_%nq%lq%rqI_%nf%lf%rfT(%nw, %lw, %P, %li, %ri, %nw)"
|
||||||
: "VL_SEL_%nq%lq%rqI(%lw, %P, %li, %ri, %nw)";
|
: "VL_SEL_%nq%lq%rqI_%nf%lf%rfT(%lw, %P, %li, %ri, %nw)";
|
||||||
}
|
}
|
||||||
string emitSMT() const override { return "((_ extract %t %r) %l)"; }
|
string emitSMT() const override { return "((_ extract %t %r) %l)"; }
|
||||||
bool cleanOut() const override { return false; }
|
bool cleanOut() const override { return false; }
|
||||||
|
|
@ -4192,7 +4212,7 @@ public:
|
||||||
out.opShiftL(lhs, rhs);
|
out.opShiftL(lhs, rhs);
|
||||||
}
|
}
|
||||||
string emitVerilog() override { return "%k(%l %f<< %r)"; }
|
string emitVerilog() override { return "%k(%l %f<< %r)"; }
|
||||||
string emitC() override { return "VL_SHIFTL_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
string emitC() override { return "VL_SHIFTL_%nq%lq%rq_%nf%lf%rf(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||||
string emitSMT() const override { return "(bvshl %l %r)"; }
|
string emitSMT() const override { return "(bvshl %l %r)"; }
|
||||||
string emitSimpleOperator() override {
|
string emitSimpleOperator() override {
|
||||||
return (rhsp()->isWide() || rhsp()->isQuad()) ? "" : "<<";
|
return (rhsp()->isWide() || rhsp()->isQuad()) ? "" : "<<";
|
||||||
|
|
@ -4209,14 +4229,25 @@ class AstShiftLOvr final : public AstNodeBiop {
|
||||||
public:
|
public:
|
||||||
AstShiftLOvr(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp, int setwidth = 0)
|
AstShiftLOvr(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp, int setwidth = 0)
|
||||||
: ASTGEN_SUPER_ShiftLOvr(fl, lhsp, rhsp) {
|
: ASTGEN_SUPER_ShiftLOvr(fl, lhsp, rhsp) {
|
||||||
if (setwidth) dtypeSetLogicSized(setwidth, VSigning::UNSIGNED);
|
if (lhsp->dtypep() && rhsp->dtypep() && !lhsp->dtypep()->isFourstate()
|
||||||
|
&& !rhsp->dtypep()->isFourstate()) {
|
||||||
|
dtypeSetBitUnsized(setwidth ? setwidth : lhsp->width(),
|
||||||
|
setwidth ? 0 : lhsp->dtypep()->widthMin(),
|
||||||
|
lhsp->dtypep()->numeric());
|
||||||
|
} else if (lhsp->dtypep()) {
|
||||||
|
dtypeSetLogicUnsized(setwidth ? setwidth : lhsp->width(),
|
||||||
|
setwidth ? 0 : lhsp->dtypep()->widthMin(),
|
||||||
|
lhsp->dtypep()->numeric());
|
||||||
|
} else {
|
||||||
|
dtypeSetLogicSized(setwidth, VSigning::UNSIGNED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstShiftLOvr;
|
ASTGEN_MEMBERS_AstShiftLOvr;
|
||||||
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
||||||
out.opShiftL(lhs, rhs);
|
out.opShiftL(lhs, rhs);
|
||||||
}
|
}
|
||||||
string emitVerilog() override { return "%k(%l %f<< %r)"; }
|
string emitVerilog() override { return "%k(%l %f<< %r)"; }
|
||||||
string emitC() override { return "VL_SHIFTL_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
string emitC() override { return "VL_SHIFTL_%nq%lq%rq_%nf%lf%rf(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||||
string emitSimpleOperator() override { return ""; }
|
string emitSimpleOperator() override { return ""; }
|
||||||
bool cleanOut() const override { return false; }
|
bool cleanOut() const override { return false; }
|
||||||
bool cleanLhs() const override { return false; }
|
bool cleanLhs() const override { return false; }
|
||||||
|
|
@ -4247,7 +4278,7 @@ public:
|
||||||
out.opShiftR(lhs, rhs);
|
out.opShiftR(lhs, rhs);
|
||||||
}
|
}
|
||||||
string emitVerilog() override { return "%k(%l %f>> %r)"; }
|
string emitVerilog() override { return "%k(%l %f>> %r)"; }
|
||||||
string emitC() override { return "VL_SHIFTR_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
string emitC() override { return "VL_SHIFTR_%nq%lq%rq_%nf%lf%rf(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||||
string emitSMT() const override { return "(bvlshr %l %r)"; }
|
string emitSMT() const override { return "(bvlshr %l %r)"; }
|
||||||
string emitSimpleOperator() override {
|
string emitSimpleOperator() override {
|
||||||
return (rhsp()->isWide() || rhsp()->isQuad()) ? "" : ">>";
|
return (rhsp()->isWide() || rhsp()->isQuad()) ? "" : ">>";
|
||||||
|
|
@ -4265,14 +4296,25 @@ class AstShiftROvr final : public AstNodeBiop {
|
||||||
public:
|
public:
|
||||||
AstShiftROvr(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp, int setwidth = 0)
|
AstShiftROvr(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp, int setwidth = 0)
|
||||||
: ASTGEN_SUPER_ShiftROvr(fl, lhsp, rhsp) {
|
: ASTGEN_SUPER_ShiftROvr(fl, lhsp, rhsp) {
|
||||||
if (setwidth) dtypeSetLogicSized(setwidth, VSigning::UNSIGNED);
|
if (lhsp->dtypep() && rhsp->dtypep() && !lhsp->dtypep()->isFourstate()
|
||||||
|
&& !rhsp->dtypep()->isFourstate()) {
|
||||||
|
dtypeSetBitUnsized(setwidth ? setwidth : lhsp->width(),
|
||||||
|
setwidth ? 0 : lhsp->dtypep()->widthMin(),
|
||||||
|
lhsp->dtypep()->numeric());
|
||||||
|
} else if (lhsp->dtypep()) {
|
||||||
|
dtypeSetLogicUnsized(setwidth ? setwidth : lhsp->width(),
|
||||||
|
setwidth ? 0 : lhsp->dtypep()->widthMin(),
|
||||||
|
lhsp->dtypep()->numeric());
|
||||||
|
} else {
|
||||||
|
dtypeSetLogicSized(setwidth, VSigning::UNSIGNED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstShiftROvr;
|
ASTGEN_MEMBERS_AstShiftROvr;
|
||||||
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
||||||
out.opShiftR(lhs, rhs);
|
out.opShiftR(lhs, rhs);
|
||||||
}
|
}
|
||||||
string emitVerilog() override { return "%k(%l %f>> %r)"; }
|
string emitVerilog() override { return "%k(%l %f>> %r)"; }
|
||||||
string emitC() override { return "VL_SHIFTR_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
string emitC() override { return "VL_SHIFTR_%nq%lq%rq_%nf%lf%rf(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||||
string emitSimpleOperator() override { return ""; }
|
string emitSimpleOperator() override { return ""; }
|
||||||
bool cleanOut() const override { return true; }
|
bool cleanOut() const override { return true; }
|
||||||
bool cleanLhs() const override { return true; }
|
bool cleanLhs() const override { return true; }
|
||||||
|
|
@ -4289,7 +4331,18 @@ public:
|
||||||
AstShiftRS(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp, int setwidth = 0)
|
AstShiftRS(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp, int setwidth = 0)
|
||||||
: ASTGEN_SUPER_ShiftRS(fl, lhsp, rhsp) {
|
: ASTGEN_SUPER_ShiftRS(fl, lhsp, rhsp) {
|
||||||
// Important that widthMin be correct, as opExtend requires it after V3Expand
|
// Important that widthMin be correct, as opExtend requires it after V3Expand
|
||||||
if (setwidth) dtypeSetLogicSized(setwidth, VSigning::SIGNED);
|
if (lhsp->dtypep() && rhsp->dtypep() && !lhsp->dtypep()->isFourstate()
|
||||||
|
&& !rhsp->dtypep()->isFourstate()) {
|
||||||
|
dtypeSetBitUnsized(setwidth ? setwidth : lhsp->width(),
|
||||||
|
setwidth ? 0 : lhsp->dtypep()->widthMin(),
|
||||||
|
lhsp->dtypep()->numeric());
|
||||||
|
} else if (lhsp->dtypep()) {
|
||||||
|
dtypeSetLogicUnsized(setwidth ? setwidth : lhsp->width(),
|
||||||
|
setwidth ? 0 : lhsp->dtypep()->widthMin(),
|
||||||
|
lhsp->dtypep()->numeric());
|
||||||
|
} else {
|
||||||
|
dtypeSetLogicSized(setwidth, VSigning::UNSIGNED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstShiftRS;
|
ASTGEN_MEMBERS_AstShiftRS;
|
||||||
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
||||||
|
|
@ -4297,7 +4350,7 @@ public:
|
||||||
}
|
}
|
||||||
string emitVerilog() override { return "%k(%l %f>>> %r)"; }
|
string emitVerilog() override { return "%k(%l %f>>> %r)"; }
|
||||||
string emitSMT() const override { return "(bvashr %l %r)"; }
|
string emitSMT() const override { return "(bvashr %l %r)"; }
|
||||||
string emitC() override { return "VL_SHIFTRS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
string emitC() override { return "VL_SHIFTRS_%nq%lq%rq_%nf%lf%rf(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||||
string emitSimpleOperator() override { return ""; }
|
string emitSimpleOperator() override { return ""; }
|
||||||
bool cleanOut() const override { return false; }
|
bool cleanOut() const override { return false; }
|
||||||
bool cleanLhs() const override { return true; }
|
bool cleanLhs() const override { return true; }
|
||||||
|
|
@ -4314,14 +4367,25 @@ public:
|
||||||
AstShiftRSOvr(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp, int setwidth = 0)
|
AstShiftRSOvr(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp, int setwidth = 0)
|
||||||
: ASTGEN_SUPER_ShiftRSOvr(fl, lhsp, rhsp) {
|
: ASTGEN_SUPER_ShiftRSOvr(fl, lhsp, rhsp) {
|
||||||
// Important that widthMin be correct, as opExtend requires it after V3Expand
|
// Important that widthMin be correct, as opExtend requires it after V3Expand
|
||||||
if (setwidth) dtypeSetLogicSized(setwidth, VSigning::SIGNED);
|
if (lhsp->dtypep() && rhsp->dtypep() && !lhsp->dtypep()->isFourstate()
|
||||||
|
&& !rhsp->dtypep()->isFourstate()) {
|
||||||
|
dtypeSetBitUnsized(setwidth ? setwidth : lhsp->width(),
|
||||||
|
setwidth ? 0 : lhsp->dtypep()->widthMin(),
|
||||||
|
lhsp->dtypep()->numeric());
|
||||||
|
} else if (lhsp->dtypep()) {
|
||||||
|
dtypeSetLogicUnsized(setwidth ? setwidth : lhsp->width(),
|
||||||
|
setwidth ? 0 : lhsp->dtypep()->widthMin(),
|
||||||
|
lhsp->dtypep()->numeric());
|
||||||
|
} else {
|
||||||
|
dtypeSetLogicSized(setwidth, VSigning::UNSIGNED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstShiftRSOvr;
|
ASTGEN_MEMBERS_AstShiftRSOvr;
|
||||||
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
||||||
out.opShiftRS(lhs, rhs, lhsp()->widthMinV());
|
out.opShiftRS(lhs, rhs, lhsp()->widthMinV());
|
||||||
}
|
}
|
||||||
string emitVerilog() override { return "%k(%l %f>>> %r)"; }
|
string emitVerilog() override { return "%k(%l %f>>> %r)"; }
|
||||||
string emitC() override { return "VL_SHIFTRS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
string emitC() override { return "VL_SHIFTRS_%nq%lq%rq_%nf%lf%rf(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||||
string emitSimpleOperator() override { return ""; }
|
string emitSimpleOperator() override { return ""; }
|
||||||
bool cleanOut() const override { return false; }
|
bool cleanOut() const override { return false; }
|
||||||
bool cleanLhs() const override { return true; }
|
bool cleanLhs() const override { return true; }
|
||||||
|
|
@ -4342,7 +4406,7 @@ public:
|
||||||
out.opSub(lhs, rhs);
|
out.opSub(lhs, rhs);
|
||||||
}
|
}
|
||||||
string emitVerilog() override { return "%k(%l %f- %r)"; }
|
string emitVerilog() override { return "%k(%l %f- %r)"; }
|
||||||
string emitC() override { return "VL_SUB_%lq(%lW, %P, %li, %ri)"; }
|
string emitC() override { return "VL_SUB_%lq_%nf%lf%rf(%lW, %P, %li, %ri)"; }
|
||||||
string emitSMT() const override { return "(bvsub %l %r)"; }
|
string emitSMT() const override { return "(bvsub %l %r)"; }
|
||||||
string emitSimpleOperator() override { return "-"; }
|
string emitSimpleOperator() override { return "-"; }
|
||||||
bool cleanOut() const override { return false; }
|
bool cleanOut() const override { return false; }
|
||||||
|
|
@ -4415,7 +4479,7 @@ public:
|
||||||
out.opEq(lhs, rhs);
|
out.opEq(lhs, rhs);
|
||||||
}
|
}
|
||||||
string emitVerilog() override { return "%k(%l %f== %r)"; }
|
string emitVerilog() override { return "%k(%l %f== %r)"; }
|
||||||
string emitC() override { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; }
|
string emitC() override { return "VL_EQ_%lq_%lf%rf(%lW, %P, %li, %ri)"; }
|
||||||
string emitSMT() const override { return "(__Vbv (= %l %r))"; }
|
string emitSMT() const override { return "(__Vbv (= %l %r))"; }
|
||||||
string emitSimpleOperator() override { return "=="; }
|
string emitSimpleOperator() override { return "=="; }
|
||||||
bool cleanOut() const override { return true; }
|
bool cleanOut() const override { return true; }
|
||||||
|
|
@ -4436,7 +4500,7 @@ public:
|
||||||
out.opCaseEq(lhs, rhs);
|
out.opCaseEq(lhs, rhs);
|
||||||
}
|
}
|
||||||
string emitVerilog() override { return "%k(%l %f=== %r)"; }
|
string emitVerilog() override { return "%k(%l %f=== %r)"; }
|
||||||
string emitC() override { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; }
|
string emitC() override { return "VL_EQ_%lq_%lf%rf(%lW, %P, %li, %ri)"; }
|
||||||
string emitSimpleOperator() override { return "=="; }
|
string emitSimpleOperator() override { return "=="; }
|
||||||
bool cleanOut() const override { return true; }
|
bool cleanOut() const override { return true; }
|
||||||
bool cleanLhs() const override { return true; }
|
bool cleanLhs() const override { return true; }
|
||||||
|
|
@ -4517,7 +4581,7 @@ public:
|
||||||
out.opLogEq(lhs, rhs);
|
out.opLogEq(lhs, rhs);
|
||||||
}
|
}
|
||||||
string emitVerilog() override { return "%k(%l %f<-> %r)"; }
|
string emitVerilog() override { return "%k(%l %f<-> %r)"; }
|
||||||
string emitC() override { return "VL_LOGEQ_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
||||||
string emitSMT() const override { return "(bvxnor %l %r)"; }
|
string emitSMT() const override { return "(bvxnor %l %r)"; }
|
||||||
string emitSimpleOperator() override { return "<->"; }
|
string emitSimpleOperator() override { return "<->"; }
|
||||||
bool cleanOut() const override { return true; }
|
bool cleanOut() const override { return true; }
|
||||||
|
|
@ -4545,7 +4609,7 @@ public:
|
||||||
out.opNeq(lhs, rhs);
|
out.opNeq(lhs, rhs);
|
||||||
}
|
}
|
||||||
string emitVerilog() override { return "%k(%l %f!= %r)"; }
|
string emitVerilog() override { return "%k(%l %f!= %r)"; }
|
||||||
string emitC() override { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; }
|
string emitC() override { return "VL_NEQ_%lq_%lf%rf(%lW, %P, %li, %ri)"; }
|
||||||
string emitSimpleOperator() override { return "!="; }
|
string emitSimpleOperator() override { return "!="; }
|
||||||
string emitSMT() const override { return "(__Vbv (not (= %l %r)))"; }
|
string emitSMT() const override { return "(__Vbv (not (= %l %r)))"; }
|
||||||
bool cleanOut() const override { return true; }
|
bool cleanOut() const override { return true; }
|
||||||
|
|
@ -4566,7 +4630,7 @@ public:
|
||||||
out.opCaseNeq(lhs, rhs);
|
out.opCaseNeq(lhs, rhs);
|
||||||
}
|
}
|
||||||
string emitVerilog() override { return "%k(%l %f!== %r)"; }
|
string emitVerilog() override { return "%k(%l %f!== %r)"; }
|
||||||
string emitC() override { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; }
|
string emitC() override { return "VL_NEQ_%lq_%lf%rf(%lW, %P, %li, %ri)"; }
|
||||||
string emitSimpleOperator() override { return "!="; }
|
string emitSimpleOperator() override { return "!="; }
|
||||||
bool cleanOut() const override { return true; }
|
bool cleanOut() const override { return true; }
|
||||||
bool cleanLhs() const override { return true; }
|
bool cleanLhs() const override { return true; }
|
||||||
|
|
@ -4649,7 +4713,7 @@ public:
|
||||||
out.opAdd(lhs, rhs);
|
out.opAdd(lhs, rhs);
|
||||||
}
|
}
|
||||||
string emitVerilog() override { return "%k(%l %f+ %r)"; }
|
string emitVerilog() override { return "%k(%l %f+ %r)"; }
|
||||||
string emitC() override { return "VL_ADD_%lq(%lW, %P, %li, %ri)"; }
|
string emitC() override { return "VL_ADD_%lq_%nf%lf%rf(%lW, %P, %li, %ri)"; }
|
||||||
string emitSMT() const override { return "(bvadd %l %r)"; }
|
string emitSMT() const override { return "(bvadd %l %r)"; }
|
||||||
string emitSimpleOperator() override { return "+"; }
|
string emitSimpleOperator() override { return "+"; }
|
||||||
bool cleanOut() const override { return false; }
|
bool cleanOut() const override { return false; }
|
||||||
|
|
@ -4691,7 +4755,7 @@ public:
|
||||||
out.opAnd(lhs, rhs);
|
out.opAnd(lhs, rhs);
|
||||||
}
|
}
|
||||||
string emitVerilog() override { return "%k(%l %f& %r)"; }
|
string emitVerilog() override { return "%k(%l %f& %r)"; }
|
||||||
string emitC() override { return "VL_AND_%lq(%lW, %P, %li, %ri)"; }
|
string emitC() override { return "VL_AND_%lq_%nf%lf%rf(%lW, %P, %li, %ri)"; }
|
||||||
string emitSMT() const override { return "(bvand %l %r)"; }
|
string emitSMT() const override { return "(bvand %l %r)"; }
|
||||||
string emitSimpleOperator() override { return "&"; }
|
string emitSimpleOperator() override { return "&"; }
|
||||||
bool cleanOut() const override { V3ERROR_NA_RETURN(false); }
|
bool cleanOut() const override { V3ERROR_NA_RETURN(false); }
|
||||||
|
|
@ -4713,7 +4777,7 @@ public:
|
||||||
out.opMul(lhs, rhs);
|
out.opMul(lhs, rhs);
|
||||||
}
|
}
|
||||||
string emitVerilog() override { return "%k(%l %f* %r)"; }
|
string emitVerilog() override { return "%k(%l %f* %r)"; }
|
||||||
string emitC() override { return "VL_MUL_%lq(%lW, %P, %li, %ri)"; }
|
string emitC() override { return "VL_MUL_%lq_%nf%lf%rf(%lW, %P, %li, %ri)"; }
|
||||||
string emitSMT() const override { return "(bvmul %l %r)"; }
|
string emitSMT() const override { return "(bvmul %l %r)"; }
|
||||||
string emitSimpleOperator() override { return "*"; }
|
string emitSimpleOperator() override { return "*"; }
|
||||||
bool cleanOut() const override { return false; }
|
bool cleanOut() const override { return false; }
|
||||||
|
|
@ -4756,7 +4820,7 @@ public:
|
||||||
out.opMulS(lhs, rhs);
|
out.opMulS(lhs, rhs);
|
||||||
}
|
}
|
||||||
string emitVerilog() override { return "%k(%l %f* %r)"; }
|
string emitVerilog() override { return "%k(%l %f* %r)"; }
|
||||||
string emitC() override { return "VL_MULS_%nq%lq%rq(%lw, %P, %li, %ri)"; }
|
string emitC() override { return "VL_MULS_%nq%lq%rq_%nf%lf%rf(%lw, %P, %li, %ri)"; }
|
||||||
string emitSMT() const override { return "(bvmul %l %r)"; }
|
string emitSMT() const override { return "(bvmul %l %r)"; }
|
||||||
string emitSimpleOperator() override { return ""; }
|
string emitSimpleOperator() override { return ""; }
|
||||||
bool emitCheckMaxWords() override { return true; }
|
bool emitCheckMaxWords() override { return true; }
|
||||||
|
|
@ -4780,7 +4844,7 @@ public:
|
||||||
out.opOr(lhs, rhs);
|
out.opOr(lhs, rhs);
|
||||||
}
|
}
|
||||||
string emitVerilog() override { return "%k(%l %f| %r)"; }
|
string emitVerilog() override { return "%k(%l %f| %r)"; }
|
||||||
string emitC() override { return "VL_OR_%lq(%lW, %P, %li, %ri)"; }
|
string emitC() override { return "VL_OR_%lq_%nf%lf%rf(%lW, %P, %li, %ri)"; }
|
||||||
string emitSMT() const override { return "(bvor %l %r)"; }
|
string emitSMT() const override { return "(bvor %l %r)"; }
|
||||||
string emitSimpleOperator() override { return "|"; }
|
string emitSimpleOperator() override { return "|"; }
|
||||||
bool cleanOut() const override { V3ERROR_NA_RETURN(false); }
|
bool cleanOut() const override { V3ERROR_NA_RETURN(false); }
|
||||||
|
|
@ -4802,7 +4866,7 @@ public:
|
||||||
out.opXor(lhs, rhs);
|
out.opXor(lhs, rhs);
|
||||||
}
|
}
|
||||||
string emitVerilog() override { return "%k(%l %f^ %r)"; }
|
string emitVerilog() override { return "%k(%l %f^ %r)"; }
|
||||||
string emitC() override { return "VL_XOR_%lq(%lW, %P, %li, %ri)"; }
|
string emitC() override { return "VL_XOR_%lq_%nf%lf%rf(%lW, %P, %li, %ri)"; }
|
||||||
string emitSMT() const override { return "(bvxor %l %r)"; }
|
string emitSMT() const override { return "(bvxor %l %r)"; }
|
||||||
string emitSimpleOperator() override { return "^"; }
|
string emitSimpleOperator() override { return "^"; }
|
||||||
bool cleanOut() const override { return false; } // Lclean && Rclean
|
bool cleanOut() const override { return false; } // Lclean && Rclean
|
||||||
|
|
@ -4990,7 +5054,7 @@ public:
|
||||||
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
|
||||||
out.opAssign(lhs);
|
out.opAssign(lhs);
|
||||||
}
|
}
|
||||||
string emitC() override { return isWide() ? "VL_ASSIGN_W(%nw, %P, %li)" : "%li"; }
|
string emitC() override { return isWide() ? "VL_ASSIGN_W_%lf%rf(%nw, %P, %li)" : "%li"; }
|
||||||
bool cleanOut() const override { return false; }
|
bool cleanOut() const override { return false; }
|
||||||
bool cleanLhs() const override { return false; }
|
bool cleanLhs() const override { return false; }
|
||||||
bool cleanRhs() const override { return false; }
|
bool cleanRhs() const override { return false; }
|
||||||
|
|
@ -5219,7 +5283,7 @@ class AstInferredDisable final : public AstNodeTermop {
|
||||||
public:
|
public:
|
||||||
explicit AstInferredDisable(FileLine* fl)
|
explicit AstInferredDisable(FileLine* fl)
|
||||||
: ASTGEN_SUPER_InferredDisable(fl) {
|
: ASTGEN_SUPER_InferredDisable(fl) {
|
||||||
dtypeSetLogicSized(1, VSigning::UNSIGNED);
|
dtypeSetBitSized(1, VSigning::UNSIGNED);
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstInferredDisable;
|
ASTGEN_MEMBERS_AstInferredDisable;
|
||||||
string emitVerilog() override { return "%f$inferred_disable"; }
|
string emitVerilog() override { return "%f$inferred_disable"; }
|
||||||
|
|
@ -5288,7 +5352,7 @@ public:
|
||||||
out.opAssign(lhs.isNeqZero() ? rhs : ths);
|
out.opAssign(lhs.isNeqZero() ? rhs : ths);
|
||||||
}
|
}
|
||||||
string emitVerilog() override { return "%k(%l %f? %r %k: %t)"; }
|
string emitVerilog() override { return "%k(%l %f? %r %k: %t)"; }
|
||||||
string emitC() override { return "VL_COND_%nq%lq%rq%tq(%nw, %P, %li, %ri, %ti)"; }
|
string emitC() override { return "VL_COND_%nq%lq%rq%tq_%nf%lf%rf%tf(%nw, %P, %li, %ri, %ti)"; }
|
||||||
string emitSMT() const override { return "(ite (__Vbool %l) %r %t)"; }
|
string emitSMT() const override { return "(ite (__Vbool %l) %r %t)"; }
|
||||||
bool cleanOut() const override { return false; } // clean if e1 & e2 clean
|
bool cleanOut() const override { return false; } // clean if e1 & e2 clean
|
||||||
bool cleanLhs() const override { return true; }
|
bool cleanLhs() const override { return true; }
|
||||||
|
|
@ -5571,12 +5635,20 @@ public:
|
||||||
: ASTGEN_SUPER_Extend(fl, lhsp) {}
|
: ASTGEN_SUPER_Extend(fl, lhsp) {}
|
||||||
AstExtend(FileLine* fl, AstNodeExpr* lhsp, int width)
|
AstExtend(FileLine* fl, AstNodeExpr* lhsp, int width)
|
||||||
: ASTGEN_SUPER_Extend(fl, lhsp) {
|
: ASTGEN_SUPER_Extend(fl, lhsp) {
|
||||||
dtypeSetLogicSized(width, VSigning::UNSIGNED);
|
if (const AstNodeDType* const dtypep = lhsp->dtypep()) {
|
||||||
|
if (dtypep->isFourstate()) {
|
||||||
|
dtypeSetLogicSized(width, VSigning::UNSIGNED);
|
||||||
|
} else {
|
||||||
|
dtypeSetBitSized(width, VSigning::UNSIGNED);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dtypeSetLogicSized(width, VSigning::UNSIGNED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstExtend;
|
ASTGEN_MEMBERS_AstExtend;
|
||||||
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opAssign(lhs); }
|
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opAssign(lhs); }
|
||||||
string emitVerilog() override { return "%l"; }
|
string emitVerilog() override { return "%l"; }
|
||||||
string emitC() override { return "VL_EXTEND_%nq%lq(%nw,%lw, %P, %li)"; }
|
string emitC() override { return "VL_EXTEND_%nq%lq_%nf%lf(%nw,%lw, %P, %li)"; }
|
||||||
string emitSMT() const override {
|
string emitSMT() const override {
|
||||||
return "((_ zero_extend " + cvtToStr(width() - lhsp()->width()) + ") %l)";
|
return "((_ zero_extend " + cvtToStr(width() - lhsp()->width()) + ") %l)";
|
||||||
}
|
}
|
||||||
|
|
@ -5596,14 +5668,22 @@ public:
|
||||||
AstExtendS(FileLine* fl, AstNodeExpr* lhsp, int width)
|
AstExtendS(FileLine* fl, AstNodeExpr* lhsp, int width)
|
||||||
// Important that widthMin be correct, as opExtend requires it after V3Expand
|
// Important that widthMin be correct, as opExtend requires it after V3Expand
|
||||||
: ASTGEN_SUPER_ExtendS(fl, lhsp) {
|
: ASTGEN_SUPER_ExtendS(fl, lhsp) {
|
||||||
dtypeSetLogicSized(width, VSigning::UNSIGNED);
|
if (const AstNodeDType* const dtypep = lhsp->dtypep()) {
|
||||||
|
if (dtypep->isFourstate()) {
|
||||||
|
dtypeSetLogicSized(width, VSigning::UNSIGNED);
|
||||||
|
} else {
|
||||||
|
dtypeSetBitSized(width, VSigning::UNSIGNED);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dtypeSetLogicSized(width, VSigning::UNSIGNED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstExtendS;
|
ASTGEN_MEMBERS_AstExtendS;
|
||||||
void numberOperate(V3Number& out, const V3Number& lhs) override {
|
void numberOperate(V3Number& out, const V3Number& lhs) override {
|
||||||
out.opExtendS(lhs, lhsp()->widthMinV());
|
out.opExtendS(lhs, lhsp()->widthMinV());
|
||||||
}
|
}
|
||||||
string emitVerilog() override { return "%l"; }
|
string emitVerilog() override { return "%l"; }
|
||||||
string emitC() override { return "VL_EXTENDS_%nq%lq(%nw,%lw, %P, %li)"; }
|
string emitC() override { return "VL_EXTENDS_%nq%lq_%nf%lf(%nw,%lw, %P, %li)"; }
|
||||||
string emitSMT() const override {
|
string emitSMT() const override {
|
||||||
return "((_ sign_extend " + cvtToStr(width() - lhsp()->width()) + ") %l)";
|
return "((_ sign_extend " + cvtToStr(width() - lhsp()->width()) + ") %l)";
|
||||||
}
|
}
|
||||||
|
|
@ -5749,7 +5829,7 @@ public:
|
||||||
ASTGEN_MEMBERS_AstLogNot;
|
ASTGEN_MEMBERS_AstLogNot;
|
||||||
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opLogNot(lhs); }
|
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opLogNot(lhs); }
|
||||||
string emitVerilog() override { return "%f(! %l)"; }
|
string emitVerilog() override { return "%f(! %l)"; }
|
||||||
string emitC() override { return "VL_LOGNOT_%nq%lq(%nw,%lw, %P, %li)"; }
|
string emitC() override { V3ERROR_NA_RETURN(""); }
|
||||||
string emitSMT() const override { return "(__Vbv (not (__Vbool %l)))"; }
|
string emitSMT() const override { return "(__Vbv (not (__Vbool %l)))"; }
|
||||||
string emitSimpleOperator() override { return "!"; }
|
string emitSimpleOperator() override { return "!"; }
|
||||||
bool cleanOut() const override { return true; }
|
bool cleanOut() const override { return true; }
|
||||||
|
|
@ -5769,7 +5849,7 @@ public:
|
||||||
ASTGEN_MEMBERS_AstMostSetBitP1;
|
ASTGEN_MEMBERS_AstMostSetBitP1;
|
||||||
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opMostSetBitP1(lhs); }
|
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opMostSetBitP1(lhs); }
|
||||||
string emitVerilog() override { return "%f$mostsetbitp1(%l)"; }
|
string emitVerilog() override { return "%f$mostsetbitp1(%l)"; }
|
||||||
string emitC() override { return "VL_MOSTSETBITP1_%lq(%lW, %P, %li)"; }
|
string emitC() override { return "VL_MOSTSETBITP1_%lq_%lf(%lW, %P, %li)"; }
|
||||||
bool cleanOut() const override { return true; }
|
bool cleanOut() const override { return true; }
|
||||||
bool cleanLhs() const override { return true; }
|
bool cleanLhs() const override { return true; }
|
||||||
bool sizeMattersLhs() const override { return false; }
|
bool sizeMattersLhs() const override { return false; }
|
||||||
|
|
@ -5800,7 +5880,7 @@ public:
|
||||||
ASTGEN_MEMBERS_AstNegate;
|
ASTGEN_MEMBERS_AstNegate;
|
||||||
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opNegate(lhs); }
|
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opNegate(lhs); }
|
||||||
string emitVerilog() override { return "%f(- %l)"; }
|
string emitVerilog() override { return "%f(- %l)"; }
|
||||||
string emitC() override { return "VL_NEGATE_%lq(%lW, %P, %li)"; }
|
string emitC() override { return "VL_NEGATE_%lq_%nf%lf(%lW, %P, %li)"; }
|
||||||
string emitSMT() const override { return "(bvneg %l)"; }
|
string emitSMT() const override { return "(bvneg %l)"; }
|
||||||
string emitSimpleOperator() override { return "-"; }
|
string emitSimpleOperator() override { return "-"; }
|
||||||
bool cleanOut() const override { return false; }
|
bool cleanOut() const override { return false; }
|
||||||
|
|
@ -5834,7 +5914,7 @@ public:
|
||||||
ASTGEN_MEMBERS_AstNot;
|
ASTGEN_MEMBERS_AstNot;
|
||||||
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opNot(lhs); }
|
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opNot(lhs); }
|
||||||
string emitVerilog() override { return "%f(~ %l)"; }
|
string emitVerilog() override { return "%f(~ %l)"; }
|
||||||
string emitC() override { return "VL_NOT_%lq(%lW, %P, %li)"; }
|
string emitC() override { return "VL_NOT_%lq_%nf%lf(%lW, %P, %li)"; }
|
||||||
string emitSMT() const override { return "(bvnot %l)"; }
|
string emitSMT() const override { return "(bvnot %l)"; }
|
||||||
string emitSimpleOperator() override { return "~"; }
|
string emitSimpleOperator() override { return "~"; }
|
||||||
bool cleanOut() const override { return false; }
|
bool cleanOut() const override { return false; }
|
||||||
|
|
@ -6026,7 +6106,7 @@ public:
|
||||||
ASTGEN_MEMBERS_AstRedAnd;
|
ASTGEN_MEMBERS_AstRedAnd;
|
||||||
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedAnd(lhs); }
|
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedAnd(lhs); }
|
||||||
string emitVerilog() override { return "%f(& %l)"; }
|
string emitVerilog() override { return "%f(& %l)"; }
|
||||||
string emitC() override { return "VL_REDAND_%nq%lq(%lw, %P, %li)"; }
|
string emitC() override { return "VL_REDAND_%lq_%lf(%lw, %P, %li)"; }
|
||||||
bool cleanOut() const override { return true; }
|
bool cleanOut() const override { return true; }
|
||||||
bool cleanLhs() const override { return true; }
|
bool cleanLhs() const override { return true; }
|
||||||
bool sizeMattersLhs() const override { return false; }
|
bool sizeMattersLhs() const override { return false; }
|
||||||
|
|
@ -6041,7 +6121,7 @@ public:
|
||||||
ASTGEN_MEMBERS_AstRedOr;
|
ASTGEN_MEMBERS_AstRedOr;
|
||||||
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedOr(lhs); }
|
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedOr(lhs); }
|
||||||
string emitVerilog() override { return "%f(| %l)"; }
|
string emitVerilog() override { return "%f(| %l)"; }
|
||||||
string emitC() override { return "VL_REDOR_%lq(%lW, %P, %li)"; }
|
string emitC() override { return "VL_REDOR_%lq_%lf(%lW, %P, %li)"; }
|
||||||
bool cleanOut() const override { return true; }
|
bool cleanOut() const override { return true; }
|
||||||
bool cleanLhs() const override { return true; }
|
bool cleanLhs() const override { return true; }
|
||||||
bool sizeMattersLhs() const override { return false; }
|
bool sizeMattersLhs() const override { return false; }
|
||||||
|
|
@ -6056,7 +6136,7 @@ public:
|
||||||
ASTGEN_MEMBERS_AstRedXor;
|
ASTGEN_MEMBERS_AstRedXor;
|
||||||
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedXor(lhs); }
|
void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedXor(lhs); }
|
||||||
string emitVerilog() override { return "%f(^ %l)"; }
|
string emitVerilog() override { return "%f(^ %l)"; }
|
||||||
string emitC() override { return "VL_REDXOR_%lq(%lW, %P, %li)"; }
|
string emitC() override { return "VL_REDXOR_%lq_%lf(%lW, %P, %li)"; }
|
||||||
bool cleanOut() const override { return false; }
|
bool cleanOut() const override { return false; }
|
||||||
bool cleanLhs() const override {
|
bool cleanLhs() const override {
|
||||||
const int w = lhsp()->width();
|
const int w = lhsp()->width();
|
||||||
|
|
|
||||||
|
|
@ -1960,11 +1960,12 @@ public:
|
||||||
ASTGEN_MEMBERS_AstTypeTable;
|
ASTGEN_MEMBERS_AstTypeTable;
|
||||||
bool maybePointedTo() const override VL_MT_SAFE { return true; }
|
bool maybePointedTo() const override VL_MT_SAFE { return true; }
|
||||||
void cloneRelink() override { V3ERROR_NA; } // Not cloneable
|
void cloneRelink() override { V3ERROR_NA; } // Not cloneable
|
||||||
AstBasicDType* findBasicDType(FileLine* fl, VBasicDTypeKwd kwd);
|
AstBasicDType* findBasicDType(FileLine* fl, VBasicDTypeKwd kwd,
|
||||||
|
bool isShuffledFourstate = false);
|
||||||
AstBasicDType* findLogicBitDType(FileLine* fl, VBasicDTypeKwd kwd, int width, int widthMin,
|
AstBasicDType* findLogicBitDType(FileLine* fl, VBasicDTypeKwd kwd, int width, int widthMin,
|
||||||
VSigning numeric);
|
VSigning numeric, bool isShuffledFourstate);
|
||||||
AstBasicDType* findLogicBitDType(FileLine* fl, VBasicDTypeKwd kwd, const VNumRange& range,
|
AstBasicDType* findLogicBitDType(FileLine* fl, VBasicDTypeKwd kwd, const VNumRange& range,
|
||||||
int widthMin, VSigning numeric);
|
int widthMin, VSigning numeric, bool isShuffledFourstate);
|
||||||
AstBasicDType* findCreateSameDType(AstBasicDType& node);
|
AstBasicDType* findCreateSameDType(AstBasicDType& node);
|
||||||
AstBasicDType* findInsertSameDType(AstBasicDType* nodep);
|
AstBasicDType* findInsertSameDType(AstBasicDType* nodep);
|
||||||
AstConstraintRefDType* findConstraintRefDType(FileLine* fl);
|
AstConstraintRefDType* findConstraintRefDType(FileLine* fl);
|
||||||
|
|
@ -2195,6 +2196,7 @@ class AstVar final : public AstNode {
|
||||||
bool m_processQueue : 1; // Process queue variable
|
bool m_processQueue : 1; // Process queue variable
|
||||||
bool m_mtaskCacheLineAlign : 1; // Start MTask affinity group on a cache line
|
bool m_mtaskCacheLineAlign : 1; // Start MTask affinity group on a cache line
|
||||||
bool m_isFourstateComplement : 1; // Set in four-state xz part
|
bool m_isFourstateComplement : 1; // Set in four-state xz part
|
||||||
|
bool m_isTopLevelPort : 1; // Whether this variable used to be a top level input
|
||||||
void init() {
|
void init() {
|
||||||
m_fourstateOriginalDTypeKwd = VBasicDTypeKwd::UNKNOWN;
|
m_fourstateOriginalDTypeKwd = VBasicDTypeKwd::UNKNOWN;
|
||||||
m_ansi = false;
|
m_ansi = false;
|
||||||
|
|
@ -2261,6 +2263,7 @@ class AstVar final : public AstNode {
|
||||||
m_processQueue = false;
|
m_processQueue = false;
|
||||||
m_mtaskCacheLineAlign = false;
|
m_mtaskCacheLineAlign = false;
|
||||||
m_isFourstateComplement = false;
|
m_isFourstateComplement = false;
|
||||||
|
m_isTopLevelPort = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -2364,18 +2367,35 @@ public:
|
||||||
void declTyped(bool flag) { m_declTyped = flag; }
|
void declTyped(bool flag) { m_declTyped = flag; }
|
||||||
void sensIfacep(AstIface* nodep) { m_sensIfacep = nodep; }
|
void sensIfacep(AstIface* nodep) { m_sensIfacep = nodep; }
|
||||||
void fourstateComplementp(AstVar* const varp) {
|
void fourstateComplementp(AstVar* const varp) {
|
||||||
UASSERT_OBJ(!isFourstateComplement(), this, "Varp is four-state complement i");
|
UASSERT_OBJ(!isFourstateComplement(), this,
|
||||||
UASSERT_OBJ(!m_fourstateComplementp, this, "Varp already has a complement");
|
"The variable is a four-state complement itself");
|
||||||
UASSERT_OBJ(!varp->isFourstateComplement(), varp, "It is already a four-state complement");
|
UASSERT_OBJ(!m_fourstateComplementp, this, "Four-state complement is already added");
|
||||||
|
UASSERT_OBJ(!varp->isFourstateComplement(), varp,
|
||||||
|
"Varp is already a four-state complement");
|
||||||
|
UASSERT_OBJ(!varp->fourstateComplementp(), varp,
|
||||||
|
"Varp has a complement - it can't can be a complement at the same time");
|
||||||
varp->m_isFourstateComplement = true;
|
varp->m_isFourstateComplement = true;
|
||||||
m_fourstateComplementp = varp;
|
m_fourstateComplementp = varp;
|
||||||
}
|
}
|
||||||
|
AstVar* cloneWithFourstateComplementp() {
|
||||||
|
UASSERT_OBJ(fourstateComplementp(), this, "Variable has no complement");
|
||||||
|
AstVar* const newp = cloneTree(false);
|
||||||
|
newp->m_fourstateComplementp = fourstateComplementp()->cloneTree(false);
|
||||||
|
return newp;
|
||||||
|
}
|
||||||
AstVar* fourstateComplementp() const { return m_fourstateComplementp; }
|
AstVar* fourstateComplementp() const { return m_fourstateComplementp; }
|
||||||
VBasicDTypeKwd fourstateOriginalDTypeKwd() const { return m_fourstateOriginalDTypeKwd; }
|
VBasicDTypeKwd fourstateOriginalDTypeKwd() const { return m_fourstateOriginalDTypeKwd; }
|
||||||
void fourstateOriginalDTypeKwd(const VBasicDTypeKwd dtypeKwd) {
|
void fourstateOriginalDTypeKwd(const VBasicDTypeKwd dtypeKwd) {
|
||||||
m_fourstateOriginalDTypeKwd = dtypeKwd;
|
m_fourstateOriginalDTypeKwd = dtypeKwd;
|
||||||
}
|
}
|
||||||
bool isFourstateComplement() const { return m_isFourstateComplement; }
|
bool isFourstateComplement() const { return m_isFourstateComplement; }
|
||||||
|
void unsetIsFourstateComplement() { m_isFourstateComplement = false; }
|
||||||
|
bool isFourstateConstruct() const {
|
||||||
|
return m_isFourstateComplement || dtypep()->isShuffledFourstate()
|
||||||
|
|| fourstateComplementp();
|
||||||
|
}
|
||||||
|
bool isTopLevelPort() const { return m_isTopLevelPort; }
|
||||||
|
void setIsTopLevelPort() { m_isTopLevelPort = true; }
|
||||||
void attrFileDescr(bool flag) { m_fileDescr = flag; }
|
void attrFileDescr(bool flag) { m_fileDescr = flag; }
|
||||||
void attrScBv(bool flag) { m_attrScBv = flag; }
|
void attrScBv(bool flag) { m_attrScBv = flag; }
|
||||||
void attrScBigUint(bool flag) { m_attrScBigUint = flag; }
|
void attrScBigUint(bool flag) { m_attrScBigUint = flag; }
|
||||||
|
|
@ -2585,6 +2605,7 @@ public:
|
||||||
&& !noCReset() && !(basicp() && basicp()->isEvent());
|
&& !noCReset() && !(basicp() && basicp()->isEvent());
|
||||||
}
|
}
|
||||||
static AstVar* scVarRecurse(AstNode* nodep);
|
static AstVar* scVarRecurse(AstNode* nodep);
|
||||||
|
const char* broken() const override;
|
||||||
};
|
};
|
||||||
class AstVarScope final : public AstNode {
|
class AstVarScope final : public AstNode {
|
||||||
// A particular scoped usage of a variable
|
// A particular scoped usage of a variable
|
||||||
|
|
|
||||||
|
|
@ -199,11 +199,12 @@ void AstAddrOfCFunc::dump(std::ostream& str) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AstBasicDType::init(VBasicDTypeKwd kwd, VSigning numer, int wantwidth, int wantwidthmin,
|
void AstBasicDType::init(VBasicDTypeKwd kwd, VSigning numer, int wantwidth, int wantwidthmin,
|
||||||
AstRange* rangep) {
|
AstRange* rangep, bool isShuffledFourstate) {
|
||||||
// wantwidth=0 means figure it out, but if a widthmin is >=0
|
// wantwidth=0 means figure it out, but if a widthmin is >=0
|
||||||
// we allow width 0 so that {{0{x}},y} works properly
|
// we allow width 0 so that {{0{x}},y} works properly
|
||||||
// wantwidthmin=-1: default, use wantwidth if it is non-zero
|
// wantwidthmin=-1: default, use wantwidth if it is non-zero
|
||||||
m.m_keyword = kwd;
|
m.m_keyword = kwd;
|
||||||
|
m.m_isShuffledFourstate = isShuffledFourstate;
|
||||||
// Implicitness: // "parameter X" is implicit and sized from initial
|
// Implicitness: // "parameter X" is implicit and sized from initial
|
||||||
// value, "parameter reg x" not
|
// value, "parameter reg x" not
|
||||||
if (keyword() == VBasicDTypeKwd::LOGIC_IMPLICIT) {
|
if (keyword() == VBasicDTypeKwd::LOGIC_IMPLICIT) {
|
||||||
|
|
@ -1026,6 +1027,15 @@ AstVar* AstVar::scVarRecurse(AstNode* nodep) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* AstVar::broken() const {
|
||||||
|
BROKEN_RTN(v3Global.fourstateHandled() && dtypep()->isFourstate());
|
||||||
|
BROKEN_RTN(v3Global.fourstateShuffled() && dtypep()->isWide()
|
||||||
|
&& (isFourstateComplement()
|
||||||
|
|| name().rfind("__Vxz") // TODO: make this not a hard coded value
|
||||||
|
!= std::string::npos));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
const AstNodeDType* AstNodeDType::skipRefIterp(bool skipConst, bool skipEnum,
|
const AstNodeDType* AstNodeDType::skipRefIterp(bool skipConst, bool skipEnum,
|
||||||
bool assertOn) const VL_MT_STABLE {
|
bool assertOn) const VL_MT_STABLE {
|
||||||
static constexpr int MAX_TYPEDEF_DEPTH = 1000;
|
static constexpr int MAX_TYPEDEF_DEPTH = 1000;
|
||||||
|
|
@ -1221,7 +1231,8 @@ AstNodeDType::CTypeRecursed AstNodeDType::cTypeRecurse(bool compound, bool packe
|
||||||
// We don't print msb()/lsb() as multidim packed would require recursion,
|
// We don't print msb()/lsb() as multidim packed would require recursion,
|
||||||
// and may confuse users as C++ data is stored always with bit 0 used
|
// and may confuse users as C++ data is stored always with bit 0 used
|
||||||
const string bitvec = (!bdtypep->isOpaque() && !v3Global.opt.protectIds())
|
const string bitvec = (!bdtypep->isOpaque() && !v3Global.opt.protectIds())
|
||||||
? "/*" + cvtToStr(dtypep->width() - 1) + ":0*/"
|
? "/*" + cvtToStr(dtypep->width() - 1) + ":0"
|
||||||
|
+ (isShuffledFourstate() ? " 4-state" : "") + "*/"
|
||||||
: "";
|
: "";
|
||||||
if (bdtypep->keyword() == VBasicDTypeKwd::CHARPTR) {
|
if (bdtypep->keyword() == VBasicDTypeKwd::CHARPTR) {
|
||||||
info.m_type = "const char*";
|
info.m_type = "const char*";
|
||||||
|
|
@ -1249,6 +1260,8 @@ AstNodeDType::CTypeRecursed AstNodeDType::cTypeRecurse(bool compound, bool packe
|
||||||
info.m_type = "VlStdRandomizer";
|
info.m_type = "VlStdRandomizer";
|
||||||
} else if (bdtypep->isEvent()) {
|
} else if (bdtypep->isEvent()) {
|
||||||
info.m_type = v3Global.assignsEvents() ? "VlAssignableEvent" : "VlEvent";
|
info.m_type = v3Global.assignsEvents() ? "VlAssignableEvent" : "VlEvent";
|
||||||
|
} else if (dtypep->isWide()) {
|
||||||
|
info.m_type = "VlWide<" + cvtToStr(dtypep->widthWords()) + ">" + bitvec;
|
||||||
} else if (dtypep->widthMin() <= 8) { // Handle unpacked arrays; not bdtypep->width
|
} else if (dtypep->widthMin() <= 8) { // Handle unpacked arrays; not bdtypep->width
|
||||||
info.m_type = "CData" + bitvec;
|
info.m_type = "CData" + bitvec;
|
||||||
} else if (dtypep->widthMin() <= 16) {
|
} else if (dtypep->widthMin() <= 16) {
|
||||||
|
|
@ -1257,8 +1270,6 @@ AstNodeDType::CTypeRecursed AstNodeDType::cTypeRecurse(bool compound, bool packe
|
||||||
info.m_type = "IData" + bitvec;
|
info.m_type = "IData" + bitvec;
|
||||||
} else if (dtypep->isQuad()) {
|
} else if (dtypep->isQuad()) {
|
||||||
info.m_type = "QData" + bitvec;
|
info.m_type = "QData" + bitvec;
|
||||||
} else if (dtypep->isWide()) {
|
|
||||||
info.m_type = "VlWide<" + cvtToStr(dtypep->widthWords()) + ">" + bitvec;
|
|
||||||
}
|
}
|
||||||
// CData, SData, IData, QData or VlWide are packed type.
|
// CData, SData, IData, QData or VlWide are packed type.
|
||||||
const bool packedType = VString::startsWith(info.m_type, "CData")
|
const bool packedType = VString::startsWith(info.m_type, "CData")
|
||||||
|
|
@ -1604,32 +1615,34 @@ AstVoidDType* AstTypeTable::findVoidDType(FileLine* fl) {
|
||||||
return m_voidp;
|
return m_voidp;
|
||||||
}
|
}
|
||||||
|
|
||||||
AstBasicDType* AstTypeTable::findBasicDType(FileLine* fl, VBasicDTypeKwd kwd) {
|
AstBasicDType* AstTypeTable::findBasicDType(FileLine* fl, VBasicDTypeKwd kwd,
|
||||||
|
bool isShuffledFourstate) {
|
||||||
// Because the detailed map doesn't update m_basicps, check the detailed
|
// Because the detailed map doesn't update m_basicps, check the detailed
|
||||||
// map for this same node. Also adds this new node to the detailed map
|
// map for this same node. Also adds this new node to the detailed map
|
||||||
if (!m_basicps[kwd]) {
|
if (!m_basicps[kwd]) {
|
||||||
AstBasicDType basic{fl, kwd};
|
AstBasicDType basic{fl, kwd, VSigning::NOSIGN, isShuffledFourstate};
|
||||||
m_basicps[kwd] = findCreateSameDType(basic);
|
m_basicps[kwd] = findCreateSameDType(basic);
|
||||||
}
|
}
|
||||||
return m_basicps[kwd];
|
return m_basicps[kwd];
|
||||||
}
|
}
|
||||||
|
|
||||||
AstBasicDType* AstTypeTable::findLogicBitDType(FileLine* fl, VBasicDTypeKwd kwd, int width,
|
AstBasicDType* AstTypeTable::findLogicBitDType(FileLine* fl, VBasicDTypeKwd kwd, int width,
|
||||||
int widthMin, VSigning numeric) {
|
int widthMin, VSigning numeric,
|
||||||
AstBasicDType basic{fl, kwd, numeric, width, widthMin};
|
bool isShuffledFourstate) {
|
||||||
|
AstBasicDType basic{fl, kwd, numeric, width, widthMin, isShuffledFourstate};
|
||||||
return findCreateSameDType(basic);
|
return findCreateSameDType(basic);
|
||||||
}
|
}
|
||||||
|
|
||||||
AstBasicDType* AstTypeTable::findLogicBitDType(FileLine* fl, VBasicDTypeKwd kwd,
|
AstBasicDType* AstTypeTable::findLogicBitDType(FileLine* fl, VBasicDTypeKwd kwd,
|
||||||
const VNumRange& range, int widthMin,
|
const VNumRange& range, int widthMin,
|
||||||
VSigning numeric) {
|
VSigning numeric, bool isShuffledFourstate) {
|
||||||
AstBasicDType basic{fl, kwd, numeric, range, widthMin};
|
AstBasicDType basic{fl, kwd, numeric, range, widthMin, isShuffledFourstate};
|
||||||
return findCreateSameDType(basic);
|
return findCreateSameDType(basic);
|
||||||
}
|
}
|
||||||
|
|
||||||
AstBasicDType* AstTypeTable::findCreateSameDType(AstBasicDType& node) {
|
AstBasicDType* AstTypeTable::findCreateSameDType(AstBasicDType& node) {
|
||||||
const VBasicTypeKey key{node.width(), node.widthMin(), node.numeric(), node.keyword(),
|
const VBasicTypeKey key{node.width(), node.widthMin(), node.numeric(),
|
||||||
node.nrange()};
|
node.keyword(), node.nrange(), node.isShuffledFourstate()};
|
||||||
AstBasicDType*& entryr = m_detailedMap[key];
|
AstBasicDType*& entryr = m_detailedMap[key];
|
||||||
if (!entryr) {
|
if (!entryr) {
|
||||||
entryr = node.cloneTree(false);
|
entryr = node.cloneTree(false);
|
||||||
|
|
@ -1641,8 +1654,8 @@ AstBasicDType* AstTypeTable::findCreateSameDType(AstBasicDType& node) {
|
||||||
|
|
||||||
// cppcheck-suppress duplInheritedMember
|
// cppcheck-suppress duplInheritedMember
|
||||||
AstBasicDType* AstTypeTable::findInsertSameDType(AstBasicDType* nodep) {
|
AstBasicDType* AstTypeTable::findInsertSameDType(AstBasicDType* nodep) {
|
||||||
const VBasicTypeKey key{nodep->width(), nodep->widthMin(), nodep->numeric(), nodep->keyword(),
|
const VBasicTypeKey key{nodep->width(), nodep->widthMin(), nodep->numeric(),
|
||||||
nodep->nrange()};
|
nodep->keyword(), nodep->nrange(), nodep->isShuffledFourstate()};
|
||||||
auto pair = m_detailedMap.emplace(key, nodep);
|
auto pair = m_detailedMap.emplace(key, nodep);
|
||||||
if (pair.second) nodep->generic(true);
|
if (pair.second) nodep->generic(true);
|
||||||
// No addTypesp; the upper function that called new() is responsible for adding
|
// No addTypesp; the upper function that called new() is responsible for adding
|
||||||
|
|
@ -1956,6 +1969,7 @@ void AstAttrOf::dumpJson(std::ostream& str) const {
|
||||||
void AstBasicDType::dump(std::ostream& str) const {
|
void AstBasicDType::dump(std::ostream& str) const {
|
||||||
this->AstNodeDType::dump(str);
|
this->AstNodeDType::dump(str);
|
||||||
str << " kwd=" << keyword().ascii();
|
str << " kwd=" << keyword().ascii();
|
||||||
|
if (isShuffledFourstate()) str << " [SHUFFLED4STATE]";
|
||||||
if (isRanged() && !rangep()) str << " range=[" << left() << ":" << right() << "]";
|
if (isRanged() && !rangep()) str << " range=[" << left() << ":" << right() << "]";
|
||||||
}
|
}
|
||||||
void AstBasicDType::dumpJson(std::ostream& str) const {
|
void AstBasicDType::dumpJson(std::ostream& str) const {
|
||||||
|
|
@ -3285,6 +3299,10 @@ void AstVar::dump(std::ostream& str) const {
|
||||||
} else if (isFuncLocal()) {
|
} else if (isFuncLocal()) {
|
||||||
str << " [FUNC]";
|
str << " [FUNC]";
|
||||||
}
|
}
|
||||||
|
if (const AstVar* const varp = fourstateComplementp()) {
|
||||||
|
str << " [COMPL=" << nodeAddr(varp) << "]";
|
||||||
|
}
|
||||||
|
if (isFourstateComplement()) str << " [4STATECOMPL]";
|
||||||
if (hasUserInit()) str << " [UINIT]";
|
if (hasUserInit()) str << " [UINIT]";
|
||||||
if (icoMaybeWritten()) str << " [ICOMAYBEWRITTEN]";
|
if (icoMaybeWritten()) str << " [ICOMAYBEWRITTEN]";
|
||||||
if (isDpiOpenArray()) str << " [DPIOPENA]";
|
if (isDpiOpenArray()) str << " [DPIOPENA]";
|
||||||
|
|
|
||||||
|
|
@ -3709,6 +3709,16 @@ class ConstVisitor final : public VNVisitor {
|
||||||
if (!m_doNConst) return;
|
if (!m_doNConst) return;
|
||||||
const AstBasicDType* const bdtypep = VN_CAST(nodep->dtypep()->skipRefp(), BasicDType);
|
const AstBasicDType* const bdtypep = VN_CAST(nodep->dtypep()->skipRefp(), BasicDType);
|
||||||
if (!bdtypep) return;
|
if (!bdtypep) return;
|
||||||
|
{
|
||||||
|
const AstNodeExpr* const lhsp = VN_AS(nodep->abovep(), NodeAssign)->lhsp();
|
||||||
|
const AstVar* varp;
|
||||||
|
if (const AstMemberSel* memberSel = VN_CAST(lhsp, MemberSel)) {
|
||||||
|
varp = memberSel->varp();
|
||||||
|
} else {
|
||||||
|
varp = VN_AS(lhsp, NodeVarRef)->varp();
|
||||||
|
}
|
||||||
|
if (varp->isFourstateConstruct()) return;
|
||||||
|
}
|
||||||
if (!bdtypep->isZeroInit()) return;
|
if (!bdtypep->isZeroInit()) return;
|
||||||
AstConst* const newp = new AstConst{nodep->fileline(), V3Number{nodep, bdtypep}};
|
AstConst* const newp = new AstConst{nodep->fileline(), V3Number{nodep, bdtypep}};
|
||||||
UINFO(9, "CRESET(0) => CONST(0) " << nodep);
|
UINFO(9, "CRESET(0) => CONST(0) " << nodep);
|
||||||
|
|
@ -3846,7 +3856,7 @@ class ConstVisitor final : public VNVisitor {
|
||||||
nodep->condp(new AstLogNot{condp->fileline(),
|
nodep->condp(new AstLogNot{condp->fileline(),
|
||||||
condp}); // LogNot, as C++ optimization also possible
|
condp}); // LogNot, as C++ optimization also possible
|
||||||
nodep->addThensp(elsesp);
|
nodep->addThensp(elsesp);
|
||||||
} else if (v3Global.fourstateHandled()
|
} else if ((!v3Global.opt.fourstate() || v3Global.fourstateHandled())
|
||||||
&& ((VN_IS(nodep->condp(), Not) && nodep->condp()->width() == 1)
|
&& ((VN_IS(nodep->condp(), Not) && nodep->condp()->width() == 1)
|
||||||
|| VN_IS(nodep->condp(), LogNot))
|
|| VN_IS(nodep->condp(), LogNot))
|
||||||
&& nodep->thensp() && nodep->elsesp()) {
|
&& nodep->thensp() && nodep->elsesp()) {
|
||||||
|
|
@ -3860,7 +3870,8 @@ class ConstVisitor final : public VNVisitor {
|
||||||
ifp->branchPred(nodep->branchPred().invert());
|
ifp->branchPred(nodep->branchPred().invert());
|
||||||
nodep->replaceWith(ifp);
|
nodep->replaceWith(ifp);
|
||||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||||
} else if (v3Global.fourstateHandled() && ifSameAssign(nodep)) {
|
} else if ((!v3Global.opt.fourstate() || v3Global.fourstateHandled())
|
||||||
|
&& ifSameAssign(nodep)) {
|
||||||
UINFO(4,
|
UINFO(4,
|
||||||
"IF({a}) ASSIGN({b},{c}) else ASSIGN({b},{d}) => ASSIGN({b}, {a}?{c}:{d})");
|
"IF({a}) ASSIGN({b},{c}) else ASSIGN({b},{d}) => ASSIGN({b}, {a}?{c}:{d})");
|
||||||
AstNodeAssign* const thensp = VN_AS(nodep->thensp(), NodeAssign);
|
AstNodeAssign* const thensp = VN_AS(nodep->thensp(), NodeAssign);
|
||||||
|
|
|
||||||
|
|
@ -489,6 +489,76 @@ class DelayedVisitor final : public VNVisitor {
|
||||||
return varscp;
|
return varscp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AstVarScope* getFourstateComplementScope(const AstVarScope* const vscp) {
|
||||||
|
const AstVar* const varp = vscp->varp()->fourstateComplementp();
|
||||||
|
UASSERT_OBJ(varp, vscp, "Non four-state won't have a complement");
|
||||||
|
AstVarScope* resultp = VN_AS(vscp->nextp(), VarScope);
|
||||||
|
do {
|
||||||
|
// In most (if not in all) cases the complement VarScope is right after main part
|
||||||
|
if (resultp->varp() == varp) return resultp;
|
||||||
|
resultp = VN_AS(resultp->nextp(), VarScope);
|
||||||
|
} while (resultp);
|
||||||
|
// Fallback to looking elsewhere
|
||||||
|
resultp = vscp->scopep()->varsp();
|
||||||
|
while (resultp != vscp) {
|
||||||
|
// In most (if not in all) cases the complement VarScope is right after main part
|
||||||
|
if (resultp->varp() == varp) return resultp;
|
||||||
|
resultp = VN_AS(resultp->nextp(), VarScope);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
AstVarScope* createTemp(const std::string& prefix, AstVarScope* vscp, AstNodeDType* dtypep,
|
||||||
|
VarScopeInfo* vscpInfo = nullptr) {
|
||||||
|
const AstVar* const varp = vscp->varp();
|
||||||
|
AstScope* const scopep = vscp->scopep();
|
||||||
|
auto getName
|
||||||
|
= [this, &prefix, scopep](const AstVarScope* const vscp, VarScopeInfo* vscpInfo) {
|
||||||
|
return prefix
|
||||||
|
+ (vscpInfo ? uniqueTmpName(scopep, vscp, *vscpInfo)
|
||||||
|
: vscp->varp()->shortName());
|
||||||
|
};
|
||||||
|
FileLine* const flp = vscp->fileline();
|
||||||
|
|
||||||
|
AstNodeModule* const modp = scopep->modp();
|
||||||
|
// Get/create the corresponding AstVar
|
||||||
|
AstVar*& newVarp = m_varMap(modp)[getName(vscp, vscpInfo)];
|
||||||
|
bool newlyCreated = false;
|
||||||
|
if (!newVarp) {
|
||||||
|
newVarp = new AstVar{flp, VVarType::BLOCKTEMP, getName(vscp, vscpInfo), dtypep};
|
||||||
|
modp->addStmtsp(newVarp);
|
||||||
|
newlyCreated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (varp->fourstateComplementp()) {
|
||||||
|
if (AstVarScope* const complementVscp = getFourstateComplementScope(vscp)) {
|
||||||
|
std::string name
|
||||||
|
= getName(complementVscp, vscpInfo ? &m_vscpInfo(complementVscp) : nullptr);
|
||||||
|
AstVar*& newComplementVarp = m_varMap(modp)[name];
|
||||||
|
if (!newComplementVarp) {
|
||||||
|
newComplementVarp = new AstVar{flp, VVarType::BLOCKTEMP, name, dtypep};
|
||||||
|
modp->addStmtsp(newComplementVarp);
|
||||||
|
}
|
||||||
|
if (newlyCreated) newVarp->fourstateComplementp(newComplementVarp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We should be able to assert this here, but unfortuantely
|
||||||
|
// 'isAssignmentCompatible' does not exist as of right now.
|
||||||
|
// UASSERT_OBJ(isAssignmentCompatible(varp->dtypep(), dtypep), flp, "Invalid temporary");
|
||||||
|
|
||||||
|
// Create the AstVarScope
|
||||||
|
AstVarScope* const varscp = new AstVarScope{flp, scopep, newVarp};
|
||||||
|
scopep->addVarsp(varscp);
|
||||||
|
return varscp;
|
||||||
|
}
|
||||||
|
|
||||||
|
AstVarScope* createTemp(const std::string& prefix, AstVarScope* vscp, int width,
|
||||||
|
VarScopeInfo* vscpInfo = nullptr) {
|
||||||
|
return createTemp(prefix, vscp, vscp->findBitDType(width, width, VSigning::UNSIGNED),
|
||||||
|
vscpInfo);
|
||||||
|
}
|
||||||
|
|
||||||
// Same as above but create a 2-state scalar of the given 'width'
|
// Same as above but create a 2-state scalar of the given 'width'
|
||||||
AstVarScope* createTemp(FileLine* flp, AstScope* scopep, const std::string& name, int width) {
|
AstVarScope* createTemp(FileLine* flp, AstScope* scopep, const std::string& name, int width) {
|
||||||
AstNodeDType* const dtypep = scopep->findBitDType(width, width, VSigning::UNSIGNED);
|
AstNodeDType* const dtypep = scopep->findBitDType(width, width, VSigning::UNSIGNED);
|
||||||
|
|
@ -591,8 +661,7 @@ class DelayedVisitor final : public VNVisitor {
|
||||||
FileLine* const flp = vscp->fileline();
|
FileLine* const flp = vscp->fileline();
|
||||||
AstScope* const scopep = vscp->scopep();
|
AstScope* const scopep = vscp->scopep();
|
||||||
// Create the shadow variable
|
// Create the shadow variable
|
||||||
const std::string name = "__Vdly__" + vscp->varp()->shortName();
|
AstVarScope* const shadowVscp = createTemp("__Vdly__", vscp, vscp->dtypep());
|
||||||
AstVarScope* const shadowVscp = createTemp(flp, scopep, name, vscp->dtypep());
|
|
||||||
vscpInfo.shadowVariableKit().vscp = shadowVscp;
|
vscpInfo.shadowVariableKit().vscp = shadowVscp;
|
||||||
// Mark both for V3LifePsot
|
// Mark both for V3LifePsot
|
||||||
vscp->optimizeLifePost(true);
|
vscp->optimizeLifePost(true);
|
||||||
|
|
@ -631,12 +700,10 @@ class DelayedVisitor final : public VNVisitor {
|
||||||
FileLine* const flp = vscp->fileline();
|
FileLine* const flp = vscp->fileline();
|
||||||
AstScope* const scopep = vscp->scopep();
|
AstScope* const scopep = vscp->scopep();
|
||||||
// Create the shadow variable
|
// Create the shadow variable
|
||||||
const std::string shadowName = "__Vdly__" + vscp->varp()->shortName();
|
AstVarScope* const shadowVscp = createTemp("__Vdly__", vscp, vscp->dtypep());
|
||||||
AstVarScope* const shadowVscp = createTemp(flp, scopep, shadowName, vscp->dtypep());
|
|
||||||
vscpInfo.shadowVarMaskedKit().vscp = shadowVscp;
|
vscpInfo.shadowVarMaskedKit().vscp = shadowVscp;
|
||||||
// Create the makk variable
|
// Create the makk variable
|
||||||
const std::string maskName = "__VdlyMask__" + vscp->varp()->shortName();
|
AstVarScope* const maskVscp = createTemp("__VdlyMask__", vscp, vscp->dtypep());
|
||||||
AstVarScope* const maskVscp = createTemp(flp, scopep, maskName, vscp->dtypep());
|
|
||||||
maskVscp->varp()->setIgnorePostWrite();
|
maskVscp->varp()->setIgnorePostWrite();
|
||||||
vscpInfo.shadowVarMaskedKit().maskp = maskVscp;
|
vscpInfo.shadowVarMaskedKit().maskp = maskVscp;
|
||||||
// Create the AstActive for the Post logic
|
// Create the AstActive for the Post logic
|
||||||
|
|
@ -742,7 +809,7 @@ class DelayedVisitor final : public VNVisitor {
|
||||||
|
|
||||||
if (!reuseTheFlag) {
|
if (!reuseTheFlag) {
|
||||||
// Create new flag
|
// Create new flag
|
||||||
AstVarScope* const flagVscp = createTemp(flp, scopep, "__VdlySet" + baseName, 1);
|
AstVarScope* const flagVscp = createTemp("__VdlySet", vscp, 1, &vscpInfo);
|
||||||
// Set the flag at the original NBA
|
// Set the flag at the original NBA
|
||||||
nodep->addHereThisAsNext( //
|
nodep->addHereThisAsNext( //
|
||||||
new AstAssign{flp, new AstVarRef{flp, flagVscp, VAccess::WRITE},
|
new AstAssign{flp, new AstVarRef{flp, flagVscp, VAccess::WRITE},
|
||||||
|
|
@ -818,7 +885,7 @@ class DelayedVisitor final : public VNVisitor {
|
||||||
= captureLhs(scopep, nodep, nodep->lhsp()->unlinkFrBack(), baseName);
|
= captureLhs(scopep, nodep, nodep->lhsp()->unlinkFrBack(), baseName);
|
||||||
|
|
||||||
// Create new flag
|
// Create new flag
|
||||||
AstVarScope* const flagVscp = createTemp(flp, scopep, "__VdlySet" + baseName, 1);
|
AstVarScope* const flagVscp = createTemp("__VdlySet", vscp, 1, &vscpInfo);
|
||||||
flagVscp->varp()->setIgnorePostWrite();
|
flagVscp->varp()->setIgnorePostWrite();
|
||||||
// Set the flag at the original NBA
|
// Set the flag at the original NBA
|
||||||
nodep->addHereThisAsNext( //
|
nodep->addHereThisAsNext( //
|
||||||
|
|
@ -850,8 +917,7 @@ class DelayedVisitor final : public VNVisitor {
|
||||||
auto* const cqDTypep
|
auto* const cqDTypep
|
||||||
= new AstNBACommitQueueDType{flp, vscp->dtypep()->skipRefp(), N_Partial};
|
= new AstNBACommitQueueDType{flp, vscp->dtypep()->skipRefp(), N_Partial};
|
||||||
v3Global.rootp()->typeTablep()->addTypesp(cqDTypep);
|
v3Global.rootp()->typeTablep()->addTypesp(cqDTypep);
|
||||||
const std::string name = "__VdlyCommitQueue" + vscp->varp()->shortName();
|
AstVarScope* const queueVscp = createTemp("__VdlyCommitQueue", vscp, cqDTypep);
|
||||||
AstVarScope* const queueVscp = createTemp(flp, scopep, name, cqDTypep);
|
|
||||||
queueVscp->varp()->noReset(true);
|
queueVscp->varp()->noReset(true);
|
||||||
queueVscp->varp()->setIgnorePostWrite();
|
queueVscp->varp()->setIgnorePostWrite();
|
||||||
vscpInfo.valueQueueKit().vscp = queueVscp;
|
vscpInfo.valueQueueKit().vscp = queueVscp;
|
||||||
|
|
@ -1198,9 +1264,7 @@ class DelayedVisitor final : public VNVisitor {
|
||||||
AstNode* newp = cstmtp;
|
AstNode* newp = cstmtp;
|
||||||
if (nodep->isDelayed()) {
|
if (nodep->isDelayed()) {
|
||||||
const AstVarRef* const vrefp = VN_AS(eventp, VarRef);
|
const AstVarRef* const vrefp = VN_AS(eventp, VarRef);
|
||||||
const std::string newvarname = "__Vdly__" + vrefp->varp()->shortName();
|
AstVarScope* const dlyvscp = createTemp("__Vdly__", vrefp->varScopep(), 1);
|
||||||
AstVarScope* const dlyvscp
|
|
||||||
= createTemp(flp, vrefp->varScopep()->scopep(), newvarname, 1);
|
|
||||||
|
|
||||||
const auto dlyRef = [=](VAccess access) { //
|
const auto dlyRef = [=](VAccess access) { //
|
||||||
return new AstVarRef{flp, dlyvscp, access};
|
return new AstVarRef{flp, dlyvscp, access};
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ class DfgDataType final {
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
static AstNodeDType* canonicalPackedDType(uint32_t width) {
|
static AstNodeDType* canonicalPackedDType(uint32_t width) {
|
||||||
return v3Global.rootp()->typeTablep()->findLogicDType(width, width, VSigning::UNSIGNED);
|
return v3Global.rootp()->typeTablep()->findBitDType(width, width, VSigning::UNSIGNED);
|
||||||
}
|
}
|
||||||
static AstNodeDType* canonicalArrayDType(uint32_t size, const DfgDataType& elemType) {
|
static AstNodeDType* canonicalArrayDType(uint32_t size, const DfgDataType& elemType) {
|
||||||
AstNodeDType* const elemDTypep = elemType.m_astDtypep;
|
AstNodeDType* const elemDTypep = elemType.m_astDtypep;
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ template <>
|
||||||
AstCountOnes* makeNode<AstCountOnes, DfgCountOnes, AstNodeExpr*>( //
|
AstCountOnes* makeNode<AstCountOnes, DfgCountOnes, AstNodeExpr*>( //
|
||||||
const DfgCountOnes* vtxp, AstNodeExpr* op1) {
|
const DfgCountOnes* vtxp, AstNodeExpr* op1) {
|
||||||
AstCountOnes* const nodep = new AstCountOnes{vtxp->fileline(), op1};
|
AstCountOnes* const nodep = new AstCountOnes{vtxp->fileline(), op1};
|
||||||
nodep->dtypeSetLogicSized(vtxp->width(), VSigning::UNSIGNED);
|
nodep->dtypeSetBitSized(vtxp->width(), VSigning::UNSIGNED);
|
||||||
return nodep;
|
return nodep;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,16 @@ class EmitCConstInit VL_NOT_FINAL : public EmitCBaseVisitorConst {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
void emitTVX(const AstNode* const nodep) {
|
||||||
|
const AstVarRef* const varRefp = VN_CAST(nodep, VarRef);
|
||||||
|
if (varRefp && varRefp->varp()->dtypep()->isShuffledFourstate()) {
|
||||||
|
UASSERT_OBJ(v3Global.opt.fourstate(), nodep,
|
||||||
|
"Tried to use four-state function in two state mode");
|
||||||
|
puts(varRefp->fourstateXZPart() ? "X" : "V");
|
||||||
|
} else {
|
||||||
|
puts("T");
|
||||||
|
}
|
||||||
|
}
|
||||||
// VISITORS
|
// VISITORS
|
||||||
void visit(AstInitArray* nodep) override {
|
void visit(AstInitArray* nodep) override {
|
||||||
VL_RESTORER(m_unpackedWord);
|
VL_RESTORER(m_unpackedWord);
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ void EmitCFunc::emitOpName(AstNode* nodep, const string& format, AstNode* lhsp,
|
||||||
// and write out appropriate text.
|
// and write out appropriate text.
|
||||||
// %n* node
|
// %n* node
|
||||||
// %nq emitIQW on the [node]
|
// %nq emitIQW on the [node]
|
||||||
|
// %nf data format T/V/X
|
||||||
// %nw width in bits
|
// %nw width in bits
|
||||||
// %nW width in words
|
// %nW width in words
|
||||||
// %ni iterate
|
// %ni iterate
|
||||||
|
|
@ -50,6 +51,7 @@ void EmitCFunc::emitOpName(AstNode* nodep, const string& format, AstNode* lhsp,
|
||||||
// %t* thsp - if appropriate, then second char as above
|
// %t* thsp - if appropriate, then second char as above
|
||||||
// %k Potential line break
|
// %k Potential line break
|
||||||
// %P Wide temporary name
|
// %P Wide temporary name
|
||||||
|
// %p* Wide temporary - if appropriate, then second char as above
|
||||||
// , Commas suppressed if the previous field is suppressed
|
// , Commas suppressed if the previous field is suppressed
|
||||||
string out;
|
string out;
|
||||||
putnbs(nodep, "");
|
putnbs(nodep, "");
|
||||||
|
|
@ -128,6 +130,16 @@ void EmitCFunc::emitOpName(AstNode* nodep, const string& format, AstNode* lhsp,
|
||||||
needComma = true;
|
needComma = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
if (nodep->isWide()) {
|
||||||
|
UASSERT_OBJ(m_wideTempRefp, nodep,
|
||||||
|
"Wide Op w/ no temp, perhaps missing op in V3EmitC?");
|
||||||
|
detail = true;
|
||||||
|
detailp = m_wideTempRefp;
|
||||||
|
} else {
|
||||||
|
++pos;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default: nodep->v3fatalSrc("Unknown emitOperator format code: %" << pos[0]); break;
|
default: nodep->v3fatalSrc("Unknown emitOperator format code: %" << pos[0]); break;
|
||||||
}
|
}
|
||||||
|
|
@ -149,15 +161,22 @@ void EmitCFunc::emitOpName(AstNode* nodep, const string& format, AstNode* lhsp,
|
||||||
emitIQW(detailp);
|
emitIQW(detailp);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'f':
|
||||||
|
putOut();
|
||||||
|
emitTVX(detailp);
|
||||||
|
break;
|
||||||
case 'w':
|
case 'w':
|
||||||
commaOut();
|
commaOut();
|
||||||
out += cvtToStr(detailp->widthMin());
|
out += cvtToStr(detailp->widthMin());
|
||||||
needComma = true;
|
needComma = true;
|
||||||
break;
|
break;
|
||||||
case 'W':
|
case 'W':
|
||||||
if (lhsp->isWide()) {
|
if (detailp->isWide()) {
|
||||||
commaOut();
|
commaOut();
|
||||||
out += cvtToStr(lhsp->widthWords());
|
out += cvtToStr(VL_WORDS_I(
|
||||||
|
detailp->width())); // Even if signal is shuffled we want to emit
|
||||||
|
// width that does not take into account the fact
|
||||||
|
// that 4-states takes 2 bits
|
||||||
needComma = true;
|
needComma = true;
|
||||||
} else if (VN_IS(lhsp, StreamR)) {
|
} else if (VN_IS(lhsp, StreamR)) {
|
||||||
commaOut();
|
commaOut();
|
||||||
|
|
@ -521,6 +540,15 @@ void EmitCFunc::emitVarReset(const string& prefix, AstVar* varp, bool constructi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isModulePort(const AstVar* const varp) {
|
||||||
|
if (varp->varType() == VVarType::PORT) {
|
||||||
|
const AstNode* iter = varp;
|
||||||
|
while (!iter->firstAbovep()) iter = iter->backp();
|
||||||
|
if (VN_IS(iter->firstAbovep(), Module)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
string EmitCFunc::emitVarResetRecurse(const AstVar* varp, bool constructing,
|
string EmitCFunc::emitVarResetRecurse(const AstVar* varp, bool constructing,
|
||||||
const string& varNameProtected, AstNodeDType* dtypep,
|
const string& varNameProtected, AstNodeDType* dtypep,
|
||||||
int depth, const string& suffix, const AstNode* valuep) {
|
int depth, const string& suffix, const AstNode* valuep) {
|
||||||
|
|
@ -617,8 +645,47 @@ string EmitCFunc::emitVarResetRecurse(const AstVar* varp, bool constructing,
|
||||||
out += varNameProtected + suffix + "[" + cvtToStr(w) + "] = ";
|
out += varNameProtected + suffix + "[" + cvtToStr(w) + "] = ";
|
||||||
out += cvtToStr(constp->num().edataWord(w)) + "U;\n";
|
out += cvtToStr(constp->num().edataWord(w)) + "U;\n";
|
||||||
}
|
}
|
||||||
|
} else if (v3Global.opt.fourstate() && dtypep->isShuffledFourstate()) {
|
||||||
|
const std::string& reset = slow ? "RESET_" : "";
|
||||||
|
if (v3Global.opt.zeroTopPorts().isTrue() && varp->isTopLevelPort()) {
|
||||||
|
// Instead of using VL_ZERO_RESET_W V and X we just use T and pretend the
|
||||||
|
// signal is twice as wide. this way we resets whole thing and sets to zero at
|
||||||
|
// once. We can do that because of the four-state internal representation
|
||||||
|
out += "VL_ZERO_" + reset + "W_T(";
|
||||||
|
out += cvtToStr(dtypep->widthMin() * 2);
|
||||||
|
out += ", " + varNameProtected + suffix;
|
||||||
|
out += ");\n";
|
||||||
|
} else if (varp->varType().isNet() || isModulePort(varp)) {
|
||||||
|
out += "VL_ZERO_" + reset + "W_V(";
|
||||||
|
out += cvtToStr(dtypep->widthMin());
|
||||||
|
out += ", " + varNameProtected + suffix;
|
||||||
|
out += ");\n";
|
||||||
|
out += "VL_ALLONES_" + reset + "W_X(";
|
||||||
|
out += cvtToStr(dtypep->widthMin());
|
||||||
|
out += ", " + varNameProtected + suffix;
|
||||||
|
out += ");\n";
|
||||||
|
} else {
|
||||||
|
// The same as above we can do a trick and use the internal representation to
|
||||||
|
// set everything up in one go but this time it is important to clear the
|
||||||
|
// result
|
||||||
|
out += "VL_ALLONES_" + reset + "W_T(";
|
||||||
|
out += cvtToStr(dtypep->widthWords() * VL_EDATASIZE);
|
||||||
|
out += ", " + varNameProtected + suffix;
|
||||||
|
out += ");\n";
|
||||||
|
if ((dtypep->widthMin() & VL_SIZEBITS_E) != 0) {
|
||||||
|
// Need cleaning
|
||||||
|
out += "_vl_clean_inplace_w_V(";
|
||||||
|
out += cvtToStr(dtypep->widthMin());
|
||||||
|
out += ", " + varNameProtected + suffix;
|
||||||
|
out += ");\n";
|
||||||
|
out += "_vl_clean_inplace_w_X(";
|
||||||
|
out += cvtToStr(dtypep->widthMin());
|
||||||
|
out += ", " + varNameProtected + suffix;
|
||||||
|
out += ");\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
out += zeroit ? (slow ? "VL_ZERO_RESET_W(" : "VL_ZERO_W(")
|
out += zeroit ? (slow ? "VL_ZERO_RESET_W_T(" : "VL_ZERO_W_T(")
|
||||||
: (varp->isXTemp() ? "VL_SCOPED_RAND_RESET_ASSIGN_W("
|
: (varp->isXTemp() ? "VL_SCOPED_RAND_RESET_ASSIGN_W("
|
||||||
: "VL_SCOPED_RAND_RESET_W(");
|
: "VL_SCOPED_RAND_RESET_W(");
|
||||||
out += cvtToStr(dtypep->widthMin());
|
out += cvtToStr(dtypep->widthMin());
|
||||||
|
|
@ -645,18 +712,11 @@ string EmitCFunc::emitVarResetRecurse(const AstVar* varp, bool constructing,
|
||||||
UASSERT_OBJ(constp, varp, "non-const initializer for variable");
|
UASSERT_OBJ(constp, varp, "non-const initializer for variable");
|
||||||
out += cvtToStr(constp->num().edataWord(0)) + "U;\n";
|
out += cvtToStr(constp->num().edataWord(0)) + "U;\n";
|
||||||
out += ";\n";
|
out += ";\n";
|
||||||
} else if (v3Global.opt.fourstate()
|
} else if (v3Global.opt.fourstate() && varp->isFourstateConstruct()) {
|
||||||
&& (varp->fourstateComplementp() || varp->isFourstateComplement())) {
|
|
||||||
V3Number xNum{varp->fileline(), varp->width(), 0};
|
V3Number xNum{varp->fileline(), varp->width(), 0};
|
||||||
bool setTozero = false;
|
if (!(v3Global.opt.zeroTopPorts().isTrue() && varp->isTopLevelPort())
|
||||||
if (varp->varType() == VVarType::PORT) {
|
&& (varp->isFourstateComplement()
|
||||||
const AstNode* iter = varp;
|
|| !(varp->varType().isNet() || isModulePort(varp)))) {
|
||||||
while (!iter->firstAbovep()) iter = iter->backp();
|
|
||||||
if (AstModule* const modep = VN_CAST(iter->firstAbovep(), Module)) {
|
|
||||||
setTozero = modep->isTop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!setTozero && (varp->isFourstateComplement() || !varp->varType().isNet())) {
|
|
||||||
xNum.setAllBits1();
|
xNum.setAllBits1();
|
||||||
}
|
}
|
||||||
out += " = ";
|
out += " = ";
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,6 @@
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
// Number of VL_CONST_W_*X's in verilated.h (IE VL_CONST_W_8X is last)
|
|
||||||
constexpr int EMITC_NUM_CONSTW = 8;
|
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// Emit lazy forward declarations
|
// Emit lazy forward declarations
|
||||||
|
|
||||||
|
|
@ -299,58 +296,23 @@ public:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int upWidth = nodep->num().widthToFit();
|
const int width = nodep->num().widthToFit();
|
||||||
int chunks = 0;
|
putnbs(nodep, "VL_CONST_W_");
|
||||||
if (upWidth > EMITC_NUM_CONSTW * VL_EDATASIZE) {
|
emitTVX(assigntop);
|
||||||
// Output e.g. 8 words in groups of e.g. 8
|
puts("(");
|
||||||
chunks = (upWidth - 1) / (EMITC_NUM_CONSTW * VL_EDATASIZE);
|
puts(cvtToStr(assigntop->width()));
|
||||||
upWidth %= (EMITC_NUM_CONSTW * VL_EDATASIZE);
|
puts(",");
|
||||||
if (upWidth == 0) upWidth = (EMITC_NUM_CONSTW * VL_EDATASIZE);
|
if (!assigntop->selfPointer().isEmpty()) {
|
||||||
|
emitDereference(assigntop, assigntop->selfPointerProtect(m_useSelfForThis));
|
||||||
}
|
}
|
||||||
{ // Upper e.g. 8 words
|
puts(assigntop->varp()->nameProtect());
|
||||||
if (chunks) {
|
puts(", {");
|
||||||
putnbs(nodep, "VL_CONSTHI_W_");
|
for (int word = 0; word < VL_WORDS_I(width); ++word) {
|
||||||
puts(cvtToStr(VL_WORDS_I(upWidth)));
|
// Only 32 bits - llx + long long here just to appease CPP format warning
|
||||||
puts("X(");
|
if (word) puts(",");
|
||||||
puts(cvtToStr(nodep->widthMin()));
|
ofp()->printf("0x%08" PRIx64, static_cast<uint64_t>(nodep->num().edataWord(word)));
|
||||||
puts(",");
|
|
||||||
puts(cvtToStr(chunks * EMITC_NUM_CONSTW * VL_EDATASIZE));
|
|
||||||
} else {
|
|
||||||
putnbs(nodep, "VL_CONST_W_");
|
|
||||||
puts(cvtToStr(VL_WORDS_I(upWidth)));
|
|
||||||
puts("X(");
|
|
||||||
puts(cvtToStr(nodep->widthMin()));
|
|
||||||
}
|
|
||||||
puts(",");
|
|
||||||
if (!assigntop->selfPointer().isEmpty()) {
|
|
||||||
emitDereference(assigntop, assigntop->selfPointerProtect(m_useSelfForThis));
|
|
||||||
}
|
|
||||||
puts(assigntop->varp()->nameProtect());
|
|
||||||
for (int word = VL_WORDS_I(upWidth) - 1; word >= 0; word--) {
|
|
||||||
// Only 32 bits - llx + long long here just to appease CPP format warning
|
|
||||||
ofp()->printf(",0x%08" PRIx64, static_cast<uint64_t>(nodep->num().edataWord(
|
|
||||||
word + chunks * EMITC_NUM_CONSTW)));
|
|
||||||
}
|
|
||||||
puts(")");
|
|
||||||
}
|
|
||||||
for (chunks--; chunks >= 0; chunks--) {
|
|
||||||
puts(";\n");
|
|
||||||
putbs("VL_CONSTLO_W_");
|
|
||||||
puts(cvtToStr(EMITC_NUM_CONSTW));
|
|
||||||
puts("X(");
|
|
||||||
puts(cvtToStr(chunks * EMITC_NUM_CONSTW * VL_EDATASIZE));
|
|
||||||
puts(",");
|
|
||||||
if (!assigntop->selfPointer().isEmpty()) {
|
|
||||||
emitDereference(assigntop, assigntop->selfPointerProtect(m_useSelfForThis));
|
|
||||||
}
|
|
||||||
puts(assigntop->varp()->nameProtect());
|
|
||||||
for (int word = EMITC_NUM_CONSTW - 1; word >= 0; word--) {
|
|
||||||
// Only 32 bits - llx + long long here just to appease CPP format warning
|
|
||||||
ofp()->printf(",0x%08" PRIx64, static_cast<uint64_t>(nodep->num().edataWord(
|
|
||||||
word + chunks * EMITC_NUM_CONSTW)));
|
|
||||||
}
|
|
||||||
puts(")");
|
|
||||||
}
|
}
|
||||||
|
puts("})");
|
||||||
}
|
}
|
||||||
|
|
||||||
void emitNodesWithText(AstNode* nodesp, bool useSelfForThis, bool tracking,
|
void emitNodesWithText(AstNode* nodesp, bool useSelfForThis, bool tracking,
|
||||||
|
|
@ -609,6 +571,9 @@ public:
|
||||||
putnbs(nodep, "VL_ASSIGNSEL_");
|
putnbs(nodep, "VL_ASSIGNSEL_");
|
||||||
emitIQW(selp->fromp());
|
emitIQW(selp->fromp());
|
||||||
emitIQW(nodep->rhsp());
|
emitIQW(nodep->rhsp());
|
||||||
|
puts("_");
|
||||||
|
emitTVX(selp->fromp());
|
||||||
|
emitTVX(nodep->rhsp());
|
||||||
puts("(");
|
puts("(");
|
||||||
putns(selp->fromp(), cvtToStr(selp->fromp()->widthMin()) + ", ");
|
putns(selp->fromp(), cvtToStr(selp->fromp()->widthMin()) + ", ");
|
||||||
puts(cvtToStr(nodep->widthMin()) + ", ");
|
puts(cvtToStr(nodep->widthMin()) + ", ");
|
||||||
|
|
@ -694,8 +659,10 @@ public:
|
||||||
m_wideTempRefp = VN_AS(nodep->lhsp(), VarRef);
|
m_wideTempRefp = VN_AS(nodep->lhsp(), VarRef);
|
||||||
paren = false;
|
paren = false;
|
||||||
} else if (nodep->isWide() && !unpackDtp && !VN_IS(nodep->rhsp(), Const)) {
|
} else if (nodep->isWide() && !unpackDtp && !VN_IS(nodep->rhsp(), Const)) {
|
||||||
putnbs(nodep, "VL_ASSIGN_W(");
|
putnbs(nodep, "VL_ASSIGN_W_");
|
||||||
puts(cvtToStr(nodep->widthMin()) + ", ");
|
emitTVX(nodep->lhsp());
|
||||||
|
emitTVX(nodep->rhsp());
|
||||||
|
puts("(" + cvtToStr(nodep->widthMin()) + ", ");
|
||||||
iterateAndNextConstNull(nodep->lhsp());
|
iterateAndNextConstNull(nodep->lhsp());
|
||||||
puts(", ");
|
puts(", ");
|
||||||
} else if (VN_IS(nodep->lhsp()->dtypep()->skipRefp(), QueueDType)
|
} else if (VN_IS(nodep->lhsp()->dtypep()->skipRefp(), QueueDType)
|
||||||
|
|
@ -1792,7 +1759,6 @@ public:
|
||||||
}
|
}
|
||||||
void visit(AstConst* nodep) override { //
|
void visit(AstConst* nodep) override { //
|
||||||
if (m_wideTempRefp && nodep->isWide()) {
|
if (m_wideTempRefp && nodep->isWide()) {
|
||||||
UASSERT_OBJ(m_wideTempRefp, nodep, "Wide Constant w/ no temp");
|
|
||||||
emitConstantW(nodep, m_wideTempRefp);
|
emitConstantW(nodep, m_wideTempRefp);
|
||||||
m_wideTempRefp = nullptr; // We used it, fail if set it a second time
|
m_wideTempRefp = nullptr; // We used it, fail if set it a second time
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -442,7 +442,9 @@ class EmitCHeader final : public EmitCConstInit {
|
||||||
puts(getfunc ? "VL_ASSIGNSEL_" : "VL_SELASSIGN_");
|
puts(getfunc ? "VL_ASSIGNSEL_" : "VL_SELASSIGN_");
|
||||||
puts(lhstype->charIQWN());
|
puts(lhstype->charIQWN());
|
||||||
puts(rhstype->charIQWN());
|
puts(rhstype->charIQWN());
|
||||||
puts("(" + std::to_string(lhstype->width()) + ", "); // LHS width
|
UASSERT_OBJ(!v3Global.opt.fourstate(), lhstype,
|
||||||
|
"Four-state currently do not support structs and unions");
|
||||||
|
puts("_TT(" + std::to_string(lhstype->width()) + ", "); // LHS width
|
||||||
if (getfunc) {
|
if (getfunc) {
|
||||||
puts(std::to_string(rhstype->width()) + ", "); // Number of copy bits
|
puts(std::to_string(rhstype->width()) + ", "); // Number of copy bits
|
||||||
puts(off + ", "); // LHS offset
|
puts(off + ", "); // LHS offset
|
||||||
|
|
|
||||||
|
|
@ -809,16 +809,26 @@ class EmitCTrace final : public EmitCFunc {
|
||||||
};
|
};
|
||||||
puts("(");
|
puts("(");
|
||||||
if (AstFourstateExpr* const exprp = VN_CAST(nodep->valuep(), FourstateExpr)) {
|
if (AstFourstateExpr* const exprp = VN_CAST(nodep->valuep(), FourstateExpr)) {
|
||||||
if (AstVarRef* const varrefp = VN_CAST(exprp->valuep(), VarRef)) {
|
AstVarRef* const valueVarrefp = VN_CAST(exprp->valuep(), VarRef);
|
||||||
putVarRef(varrefp);
|
AstVarRef* const xzVarrefp = VN_CAST(exprp->xzp(), VarRef);
|
||||||
|
if (valueVarrefp && xzVarrefp && valueVarrefp->varp() == xzVarrefp->varp()) {
|
||||||
|
UASSERT_OBJ(valueVarrefp->isWide()
|
||||||
|
&& valueVarrefp->varp()->dtypep()->isShuffledFourstate(),
|
||||||
|
nodep,
|
||||||
|
"This shall only happen with wide shuffled four-state variables");
|
||||||
|
putVarRef(valueVarrefp);
|
||||||
} else {
|
} else {
|
||||||
iterateConst(exprp->valuep());
|
if (!valueVarrefp) {
|
||||||
}
|
iterateConst(exprp->valuep());
|
||||||
puts("), (");
|
} else {
|
||||||
if (AstVarRef* const varrefp = VN_CAST(exprp->xzp(), VarRef)) {
|
putVarRef(valueVarrefp);
|
||||||
putVarRef(varrefp);
|
}
|
||||||
} else {
|
puts("), (");
|
||||||
iterateConst(exprp->xzp());
|
if (!xzVarrefp) {
|
||||||
|
iterateConst(exprp->xzp());
|
||||||
|
} else {
|
||||||
|
putVarRef(xzVarrefp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (AstVarRef* const varrefp = VN_CAST(nodep->valuep(), VarRef)) {
|
} else if (AstVarRef* const varrefp = VN_CAST(nodep->valuep(), VarRef)) {
|
||||||
putVarRef(varrefp);
|
putVarRef(varrefp);
|
||||||
|
|
|
||||||
|
|
@ -937,7 +937,7 @@ class ExpandVisitor final : public VNVisitor {
|
||||||
if (lhswidth == 1) {
|
if (lhswidth == 1) {
|
||||||
newp = new AstNegate{fl, lhsp->cloneTreePure(true)};
|
newp = new AstNegate{fl, lhsp->cloneTreePure(true)};
|
||||||
// Replicate always unsigned
|
// Replicate always unsigned
|
||||||
newp->dtypeSetLogicSized(VL_EDATASIZE, VSigning::UNSIGNED);
|
newp->dtypeSetBitSized(VL_EDATASIZE, VSigning::UNSIGNED);
|
||||||
} else {
|
} else {
|
||||||
newp = newAstWordSelClone(lhsp, w);
|
newp = newAstWordSelClone(lhsp, w);
|
||||||
FileLine* const rfl = rhsp->fileline();
|
FileLine* const rfl = rhsp->fileline();
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@
|
||||||
|
|
||||||
#include "V3Fourstate.h"
|
#include "V3Fourstate.h"
|
||||||
|
|
||||||
|
#include "V3Const.h"
|
||||||
|
#include "V3Stats.h"
|
||||||
#include "V3UniqueNames.h"
|
#include "V3UniqueNames.h"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
@ -38,10 +40,6 @@ VL_DEFINE_DEBUG_FUNCTIONS;
|
||||||
* - split asswignw into multiple statements
|
* - split asswignw into multiple statements
|
||||||
* - four-states printing
|
* - four-states printing
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define VALUE_SUFFIX "" // Needs to be empty so C++ api won't change
|
|
||||||
#define XZ_SUFFIX "__Vxz"
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct FourstatePair final {
|
struct FourstatePair final {
|
||||||
AstNodeExpr* valuep;
|
AstNodeExpr* valuep;
|
||||||
|
|
@ -51,16 +49,17 @@ struct FourstatePair final {
|
||||||
enum LogicType : char {
|
enum LogicType : char {
|
||||||
UNINITIALIZED = 0, // Logic type has not been evaluated
|
UNINITIALIZED = 0, // Logic type has not been evaluated
|
||||||
TWO_STATE, // Two-state expression
|
TWO_STATE, // Two-state expression
|
||||||
TWO_STATE_HARD, // Expression is guaranteed by user that it won't be a four-state (propagator
|
TWO_STATE_HARD, // Expression is guaranteed by user that it won't be a four-state
|
||||||
// may not change it)
|
// (propagator may not change it)
|
||||||
TWO_STATE_WITH_FOUR_STATE_IN_SUBTREE, // Two-state expression with four-state expression in
|
TWO_STATE_WITH_FOUR_STATE_IN_SUBTREE, // Two-state expression with four-state expression
|
||||||
// its subtree - this is necessary since some AstNodes
|
// in its subtree - this is necessary since some
|
||||||
// (e.g.: AstCastWrap or AstSel) may contain four-state
|
// AstNodes (e.g.: AstCastWrap or AstSel) may
|
||||||
// expression as a child but itself be a two-state. When
|
// contain four-state expression as a child but
|
||||||
// this occurs we need to know that for the sake of
|
// itself be a two-state. When this occurs we need
|
||||||
// short-circuiting (because we use precalculation
|
// to know that for the sake of short-circuiting
|
||||||
// statements we need to know that we cannot put them
|
// (because we use precalculation statements we need
|
||||||
// before current expression unconditionally)
|
// to know that we cannot put them before current
|
||||||
|
// expression unconditionally)
|
||||||
FOUR_STATE, // Four-state expression
|
FOUR_STATE, // Four-state expression
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -156,8 +155,7 @@ public:
|
||||||
"Tried to build a port map while another exists");
|
"Tried to build a port map while another exists");
|
||||||
for (AstNode* stmtp = ftaskp->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
|
for (AstNode* stmtp = ftaskp->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
|
||||||
if (AstVar* const varp = VN_CAST(stmtp, Var)) {
|
if (AstVar* const varp = VN_CAST(stmtp, Var)) {
|
||||||
if (varp->direction().isAny()
|
if (varp->direction().isAny() && !varp->isFourstateConstruct()) {
|
||||||
&& !(varp->fourstateComplementp() || varp->isFourstateComplement())) {
|
|
||||||
m_currentFTaskRefPortps.push_back(varp);
|
m_currentFTaskRefPortps.push_back(varp);
|
||||||
m_currentFTaskRefPortpsNamesToVarps[varp->name()] = varp;
|
m_currentFTaskRefPortpsNamesToVarps[varp->name()] = varp;
|
||||||
}
|
}
|
||||||
|
|
@ -1387,8 +1385,8 @@ class FourstateVisitor final : public VNVisitor {
|
||||||
new AstRedXor{flp, getFourstateExpressionValue(redXorp->lhsp(), false)}};
|
new AstRedXor{flp, getFourstateExpressionValue(redXorp->lhsp(), false)}};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename CompoarisonOp_T>
|
template <typename ComparisonOp_T>
|
||||||
void getFourstateExpressionArithmeticValue(CompoarisonOp_T* const biop) {
|
void getFourstateExpressionArithmeticValue(ComparisonOp_T* const biop) {
|
||||||
// |(a.xz | b.xz) ? '1 : (a op b)
|
// |(a.xz | b.xz) ? '1 : (a op b)
|
||||||
FileLine* const flp = biop->fileline();
|
FileLine* const flp = biop->fileline();
|
||||||
m_resultp = new AstCond{
|
m_resultp = new AstCond{
|
||||||
|
|
@ -1396,7 +1394,7 @@ class FourstateVisitor final : public VNVisitor {
|
||||||
new AstRedOr{flp, new AstOr{flp, getFourstateExpressionXZ(biop->lhsp()),
|
new AstRedOr{flp, new AstOr{flp, getFourstateExpressionXZ(biop->lhsp()),
|
||||||
getFourstateExpressionXZ(biop->rhsp())}},
|
getFourstateExpressionXZ(biop->rhsp())}},
|
||||||
createZeroOrOnesp(biop, true),
|
createZeroOrOnesp(biop, true),
|
||||||
new CompoarisonOp_T{
|
new ComparisonOp_T{
|
||||||
flp,
|
flp,
|
||||||
getFourstateExpressionValue(
|
getFourstateExpressionValue(
|
||||||
biop->lhsp(), true /*must be in tmp so it always gets evaluated*/),
|
biop->lhsp(), true /*must be in tmp so it always gets evaluated*/),
|
||||||
|
|
@ -1409,11 +1407,11 @@ class FourstateVisitor final : public VNVisitor {
|
||||||
void visit(AstMul* const mulp) override { getFourstateExpressionArithmeticValue(mulp); }
|
void visit(AstMul* const mulp) override { getFourstateExpressionArithmeticValue(mulp); }
|
||||||
void visit(AstMulS* const mulsp) override { getFourstateExpressionArithmeticValue(mulsp); }
|
void visit(AstMulS* const mulsp) override { getFourstateExpressionArithmeticValue(mulsp); }
|
||||||
|
|
||||||
template <typename CompoarisonOp_T>
|
template <typename ModDivOp_T>
|
||||||
void getFourstateExpressionDivValue(CompoarisonOp_T* const biop) {
|
void getFourstateExpressionDivValue(ModDivOp_T* const biop) {
|
||||||
// |(a.xz | b.xz) | ~|b.value ? '1 : (a op b)
|
// |(a.xz | b.xz) | ~|b.value ? '1 : (a op b)
|
||||||
FileLine* const flp = biop->fileline();
|
FileLine* const flp = biop->fileline();
|
||||||
CompoarisonOp_T* const resultp = new CompoarisonOp_T{
|
ModDivOp_T* const resultp = new ModDivOp_T{
|
||||||
flp,
|
flp,
|
||||||
getFourstateExpressionValue(biop->lhsp(),
|
getFourstateExpressionValue(biop->lhsp(),
|
||||||
true /*must be in tmp so it always gets evaluated*/),
|
true /*must be in tmp so it always gets evaluated*/),
|
||||||
|
|
@ -2078,7 +2076,7 @@ class FourstateVisitor final : public VNVisitor {
|
||||||
|
|
||||||
void visit(AstPin* const nodep) override {
|
void visit(AstPin* const nodep) override {
|
||||||
AstVar* const varp = nodep->modVarp();
|
AstVar* const varp = nodep->modVarp();
|
||||||
if (!(varp->fourstateComplementp() || varp->isFourstateComplement())) {
|
if (!varp->isFourstateConstruct()) {
|
||||||
if (AstNodeExpr* const exprp = VN_CAST(nodep->exprp(), NodeExpr)) {
|
if (AstNodeExpr* const exprp = VN_CAST(nodep->exprp(), NodeExpr)) {
|
||||||
if (VL_UNLIKELY(!(VN_IS(exprp, NodeVarRef) || VN_IS(exprp, Const)))) {
|
if (VL_UNLIKELY(!(VN_IS(exprp, NodeVarRef) || VN_IS(exprp, Const)))) {
|
||||||
// The issue lays in need for precalculations, potential side effects and lack
|
// The issue lays in need for precalculations, potential side effects and lack
|
||||||
|
|
@ -2389,7 +2387,7 @@ public:
|
||||||
triorTriandReduce(m_assignWToWire, triReducer);
|
triorTriandReduce(m_assignWToWire, triReducer);
|
||||||
V3Error::abortIfErrors();
|
V3Error::abortIfErrors();
|
||||||
{ FourstateLogicTypePropagator{netlistp}; }
|
{ FourstateLogicTypePropagator{netlistp}; }
|
||||||
netlistp->foreach([](const AstNodeExpr* const nodep) {
|
netlistp->foreach([](AstNodeExpr* const nodep) {
|
||||||
if (VN_IS(nodep, NodeFTaskRef)) {
|
if (VN_IS(nodep, NodeFTaskRef)) {
|
||||||
// Changing it in type propagador is unnecessary since those will be 100% handled
|
// Changing it in type propagador is unnecessary since those will be 100% handled
|
||||||
return;
|
return;
|
||||||
|
|
@ -2397,6 +2395,12 @@ public:
|
||||||
if (isFourstate(nodep)) {
|
if (isFourstate(nodep)) {
|
||||||
nodep->v3warn(E_UNSUPPORTED, "This four-state expression has not been handled");
|
nodep->v3warn(E_UNSUPPORTED, "This four-state expression has not been handled");
|
||||||
}
|
}
|
||||||
|
if (nodep->dtypep()->isFourstate()) {
|
||||||
|
// If it is not a fourstate expression according to the
|
||||||
|
// `FourstateLogicTypePropagator` lets set the bit
|
||||||
|
nodep->dtypeSetBitUnsized(nodep->width(), nodep->widthMin(),
|
||||||
|
nodep->dtypep()->numeric());
|
||||||
|
}
|
||||||
});
|
});
|
||||||
V3Error::abortIfErrors();
|
V3Error::abortIfErrors();
|
||||||
for (AstVar* const varp : m_varpsToRemove) varp->unlinkFrBack()->deleteTree();
|
for (AstVar* const varp : m_varpsToRemove) varp->unlinkFrBack()->deleteTree();
|
||||||
|
|
@ -2404,9 +2408,122 @@ public:
|
||||||
~FourstateVisitor() override = default;
|
~FourstateVisitor() override = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
void V3Fourstate::fourstateAll(AstNetlist* netlistp) {
|
// Creates one wide shuffled variable from two wide signals that together create a four-state
|
||||||
|
// From:
|
||||||
|
// VlWide<128> a_value;
|
||||||
|
// VlWide<128> a_xz;
|
||||||
|
// creates a:
|
||||||
|
// VlWide<256> a; // keeps [value1, xz1, value2, xz2,...]
|
||||||
|
class FourstateShuffleVisitor final : public VNVisitor {
|
||||||
|
const VNUser1InUse m_user1InUse;
|
||||||
|
|
||||||
|
// Node status
|
||||||
|
// AstVar*::user1p -> AstVar*. Four-state wide complemetary (xz part) variable keeps here
|
||||||
|
// a pointer to a newly created wide four-state shuffled
|
||||||
|
// signal
|
||||||
|
|
||||||
|
VDouble0 m_shuffledVars;
|
||||||
|
|
||||||
|
static bool needsShuffle(const AstVar* const varp) {
|
||||||
|
return varp->isWide() && (varp->fourstateComplementp() || varp->isFourstateComplement());
|
||||||
|
}
|
||||||
|
|
||||||
|
AstVar* getCreateShuffledVariantp(AstVar* varp) {
|
||||||
|
UASSERT_OBJ(
|
||||||
|
varp->fourstateComplementp() || varp->isFourstateComplement(), varp,
|
||||||
|
"This function is ment to be called on variables which create a four-state value");
|
||||||
|
UASSERT_OBJ(varp->isWide(), varp,
|
||||||
|
"This function is only ment to be called on wide wariables");
|
||||||
|
if (AstVar* newp = varp->fourstateComplementp()) varp = newp;
|
||||||
|
const size_t pos = varp->name().rfind(XZ_SUFFIX);
|
||||||
|
UASSERT_OBJ(pos != std::string::npos, varp,
|
||||||
|
"Four-state complementary value (xz part) shall have '"
|
||||||
|
<< XZ_SUFFIX << "', but it is named: " << varp->name());
|
||||||
|
if (AstVar* resultp = VN_AS(varp->user1p(), Var)) return resultp;
|
||||||
|
UINFO(4, "SHUFFLED4STATE: " << varp);
|
||||||
|
++m_shuffledVars;
|
||||||
|
AstVar* const resultp = varp->cloneTree(false);
|
||||||
|
resultp->unsetIsFourstateComplement();
|
||||||
|
resultp->name(resultp->name().erase(pos, sizeof(XZ_SUFFIX)));
|
||||||
|
resultp->dtypep(resultp->findBitDType(resultp->width(), resultp->dtypep()->widthMin(),
|
||||||
|
varp->dtypep()->numeric(), true));
|
||||||
|
varp->addNextHere(resultp);
|
||||||
|
varp->user1p(resultp);
|
||||||
|
return resultp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void visit(AstNodeCCall* const nodep) override {
|
||||||
|
iterateChildren(nodep);
|
||||||
|
if (nodep->funcp()->dpiImportPrototype()) return;
|
||||||
|
AstNodeExpr* exprp = nodep->argsp();
|
||||||
|
for (AstVar* varp = nodep->funcp()->argsp(); varp; varp = VN_AS(varp->nextp(), Var)) {
|
||||||
|
UASSERT_OBJ(exprp, varp, "Too little arguments");
|
||||||
|
if (needsShuffle(varp)) {
|
||||||
|
UASSERT_OBJ(!varp->isFourstateComplement(), varp,
|
||||||
|
"This loop shall never reach four-state complement");
|
||||||
|
if (AstVar* const complement = varp->fourstateComplementp()) {
|
||||||
|
getCreateShuffledVariantp(complement);
|
||||||
|
UASSERT_OBJ(
|
||||||
|
VN_IS(exprp, NodeVarRef) && VN_IS(exprp->nextp(), NodeVarRef), exprp,
|
||||||
|
"Wide four-state signals shall be passed only as lvalue references");
|
||||||
|
exprp->nextp()->unlinkFrBack()->deleteTree();
|
||||||
|
varp = VN_AS(varp->nextp()->nextp(), Var);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exprp = VN_AS(exprp->nextp(), NodeExpr);
|
||||||
|
}
|
||||||
|
UASSERT_OBJ(!exprp, exprp, "Too many arguments");
|
||||||
|
}
|
||||||
|
|
||||||
|
void visit(AstVar* const nodep) override {
|
||||||
|
iterateChildren(nodep);
|
||||||
|
if (needsShuffle(nodep)) {
|
||||||
|
getCreateShuffledVariantp(nodep);
|
||||||
|
pushDeletep(nodep->unlinkFrBack());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void visit(AstNodeVarRef* const nodep) override {
|
||||||
|
iterateChildren(nodep);
|
||||||
|
if (!needsShuffle(nodep->varp())) return;
|
||||||
|
AstVar* const varp = getCreateShuffledVariantp(nodep->varp());
|
||||||
|
FileLine* const flp = nodep->fileline();
|
||||||
|
if (AstVarScope* const oldVscp = nodep->varScopep()) {
|
||||||
|
AstVarScope* const vscp = new AstVarScope{flp, oldVscp->scopep(), varp};
|
||||||
|
vscp->trace(oldVscp->isTrace());
|
||||||
|
vscp->optimizeLifePost(oldVscp->optimizeLifePost());
|
||||||
|
nodep->varScopep(vscp);
|
||||||
|
}
|
||||||
|
nodep->fourstateXZPart(nodep->varp()->isFourstateComplement());
|
||||||
|
nodep->varp(varp);
|
||||||
|
if (AstWordSel* const wselp = VN_CAST(nodep->firstAbovep(), WordSel)) {
|
||||||
|
AstNodeExpr* idxp
|
||||||
|
= new AstMul{flp, wselp->bitp()->unlinkFrBack(), new AstConst{flp, 2}};
|
||||||
|
if (nodep->fourstateXZPart()) idxp = new AstAdd{flp, idxp, new AstConst{flp, 1}};
|
||||||
|
idxp = V3Const::constifyEdit(idxp);
|
||||||
|
wselp->bitp(idxp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void visit(AstNode* const nodep) override { iterateChildren(nodep); }
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit FourstateShuffleVisitor(AstNetlist* const netlistp) { iterate(netlistp); }
|
||||||
|
~FourstateShuffleVisitor() override {
|
||||||
|
V3Stats::addStat("Shuffled fourstate variables", m_shuffledVars);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void V3Fourstate::fourstateAll(AstNetlist* const netlistp) {
|
||||||
UINFO(2, __FUNCTION__ << ":");
|
UINFO(2, __FUNCTION__ << ":");
|
||||||
{ FourstateVisitor{netlistp}; }
|
{ FourstateVisitor{netlistp}; }
|
||||||
v3Global.setFourstateHandled();
|
v3Global.setFourstateHandled();
|
||||||
V3Global::dumpCheckGlobalTree("fourstate", 0, dumpTreeEitherLevel() >= 6);
|
V3Global::dumpCheckGlobalTree("fourstate", 0, dumpTreeEitherLevel() >= 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void V3Fourstate::fourstateShuffleAll(AstNetlist* const netlistp) {
|
||||||
|
UINFO(2, __FUNCTION__ << ":");
|
||||||
|
{ FourstateShuffleVisitor{netlistp}; }
|
||||||
|
v3Global.setFourstateShuffled();
|
||||||
|
V3Global::dumpCheckGlobalTree("fourstateShuffle", 0, dumpTreeEitherLevel() >= 6);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,9 +24,13 @@ class AstNetlist;
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
|
#define VALUE_SUFFIX "" // Needs to be empty so C++ api won't change
|
||||||
|
#define XZ_SUFFIX "__Vxz"
|
||||||
|
|
||||||
class V3Fourstate final {
|
class V3Fourstate final {
|
||||||
public:
|
public:
|
||||||
static void fourstateAll(AstNetlist* nodep) VL_MT_DISABLED;
|
static void fourstateAll(AstNetlist* nodep) VL_MT_DISABLED;
|
||||||
|
static void fourstateShuffleAll(AstNetlist* nodep) VL_MT_DISABLED;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // Guard
|
#endif // Guard
|
||||||
|
|
|
||||||
|
|
@ -136,6 +136,7 @@ class V3Global final {
|
||||||
bool m_useRandomizeMethods = false; // Need to define randomize() class methods
|
bool m_useRandomizeMethods = false; // Need to define randomize() class methods
|
||||||
bool m_hasPrintedObjects = false; // Design has format args printed with to_string()
|
bool m_hasPrintedObjects = false; // Design has format args printed with to_string()
|
||||||
bool m_fourstateHandled = false; // There should be no more fourstate values
|
bool m_fourstateHandled = false; // There should be no more fourstate values
|
||||||
|
bool m_fourstateShuffled = false; // There should be no more fourstate values
|
||||||
uint64_t m_currentHierBlockCost = 0; // Total cost of this hier block, used for scheduling
|
uint64_t m_currentHierBlockCost = 0; // Total cost of this hier block, used for scheduling
|
||||||
|
|
||||||
// Memory address to short string mapping (for debug)
|
// Memory address to short string mapping (for debug)
|
||||||
|
|
@ -226,7 +227,9 @@ public:
|
||||||
void useCovergroup(bool flag) { m_useCovergroup = flag; }
|
void useCovergroup(bool flag) { m_useCovergroup = flag; }
|
||||||
bool useRandomizeMethods() const { return m_useRandomizeMethods; }
|
bool useRandomizeMethods() const { return m_useRandomizeMethods; }
|
||||||
void setFourstateHandled() { m_fourstateHandled = true; }
|
void setFourstateHandled() { m_fourstateHandled = true; }
|
||||||
bool fourstateHandled() const { return !opt.fourstate() || m_fourstateHandled; }
|
bool fourstateHandled() const { return m_fourstateHandled; }
|
||||||
|
void setFourstateShuffled() { m_fourstateShuffled = true; }
|
||||||
|
bool fourstateShuffled() const { return m_fourstateShuffled; }
|
||||||
void useRandomizeMethods(bool flag) { m_useRandomizeMethods = flag; }
|
void useRandomizeMethods(bool flag) { m_useRandomizeMethods = flag; }
|
||||||
bool hasPrintedObjects() const { return m_hasPrintedObjects; }
|
bool hasPrintedObjects() const { return m_hasPrintedObjects; }
|
||||||
void hasPrintedObjects(bool flag) { m_hasPrintedObjects = flag; }
|
void hasPrintedObjects(bool flag) { m_hasPrintedObjects = flag; }
|
||||||
|
|
|
||||||
|
|
@ -222,10 +222,19 @@ class InlineCFuncsVisitor final : public VNVisitor {
|
||||||
|
|
||||||
// Clone local variables, add them to the local scope
|
// Clone local variables, add them to the local scope
|
||||||
for (AstVar* varp = calleep->varsp(); varp; varp = VN_AS(varp->nextp(), Var)) {
|
for (AstVar* varp = calleep->varsp(); varp; varp = VN_AS(varp->nextp(), Var)) {
|
||||||
AstVar* const newVarp = varp->cloneTree(false);
|
if (varp->isFourstateComplement()) continue;
|
||||||
|
AstVar* const complementp = varp->fourstateComplementp();
|
||||||
|
AstVar* const newVarp
|
||||||
|
= complementp ? varp->cloneWithFourstateComplementp() : varp->cloneTree(false);
|
||||||
newVarp->name(varPrefix + varp->name());
|
newVarp->name(varPrefix + varp->name());
|
||||||
lscopep->addStmtsp(newVarp);
|
lscopep->addStmtsp(newVarp);
|
||||||
varp->user2p(newVarp);
|
varp->user2p(newVarp);
|
||||||
|
if (complementp) {
|
||||||
|
AstVar* const newComplementp = newVarp->fourstateComplementp();
|
||||||
|
newComplementp->name(varPrefix + complementp->name());
|
||||||
|
lscopep->addStmtsp(newComplementp);
|
||||||
|
complementp->user2p(newComplementp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clone the function body
|
// Clone the function body
|
||||||
|
|
|
||||||
|
|
@ -111,16 +111,30 @@ class LocalizeVisitor final : public VNVisitor {
|
||||||
AstVar* const oldVarp = nodep->varp();
|
AstVar* const oldVarp = nodep->varp();
|
||||||
for (AstCFunc* const funcp : funcps) {
|
for (AstCFunc* const funcp : funcps) {
|
||||||
// Create the new local variable.
|
// Create the new local variable.
|
||||||
const string newName
|
string newName
|
||||||
= nodep->scopep() == funcp->scopep()
|
= nodep->scopep() == funcp->scopep()
|
||||||
? oldVarp->name()
|
? oldVarp->name()
|
||||||
: nodep->scopep()->nameDotless() + "__DOT__" + oldVarp->name();
|
: nodep->scopep()->nameDotless() + "__DOT__" + oldVarp->name();
|
||||||
AstVar* const newVarp
|
AstVar* const newVarp = new AstVar{oldVarp->fileline(), oldVarp->varType(),
|
||||||
= new AstVar{oldVarp->fileline(), oldVarp->varType(), newName, oldVarp};
|
std::move(newName), oldVarp};
|
||||||
newVarp->funcLocal(true);
|
newVarp->funcLocal(true);
|
||||||
newVarp->noReset(oldVarp->noReset());
|
newVarp->noReset(oldVarp->noReset());
|
||||||
newVarp->noSubst(oldVarp->noSubst());
|
newVarp->noSubst(oldVarp->noSubst());
|
||||||
funcp->addVarsp(newVarp);
|
funcp->addVarsp(newVarp);
|
||||||
|
if (AstVar* complementp = oldVarp->fourstateComplementp()) {
|
||||||
|
string newName
|
||||||
|
= nodep->scopep() == funcp->scopep()
|
||||||
|
? complementp->name()
|
||||||
|
: nodep->scopep()->nameDotless() + "__DOT__" + complementp->name();
|
||||||
|
AstVar* const newVarXZp
|
||||||
|
= new AstVar{complementp->fileline(), complementp->varType(),
|
||||||
|
std::move(newName), complementp};
|
||||||
|
newVarXZp->funcLocal(true);
|
||||||
|
newVarXZp->noReset(complementp->noReset());
|
||||||
|
newVarXZp->noSubst(complementp->noSubst());
|
||||||
|
funcp->addVarsp(newVarXZp);
|
||||||
|
newVarp->fourstateComplementp(newVarXZp);
|
||||||
|
}
|
||||||
|
|
||||||
// Fix up all the references within this function
|
// Fix up all the references within this function
|
||||||
const auto er = m_references(funcp).equal_range(nodep);
|
const auto er = m_references(funcp).equal_range(nodep);
|
||||||
|
|
@ -192,6 +206,8 @@ class LocalizeVisitor final : public VNVisitor {
|
||||||
&& !nodep->varp()->sensIfacep() // Not sensitive to an interface
|
&& !nodep->varp()->sensIfacep() // Not sensitive to an interface
|
||||||
&& !nodep->varp()->isVirtIface() // Not interface pointer
|
&& !nodep->varp()->isVirtIface() // Not interface pointer
|
||||||
&& !nodep->varp()->valuep() // Does not have an initializer
|
&& !nodep->varp()->valuep() // Does not have an initializer
|
||||||
|
&& !nodep->varp()->isFourstateComplement() // Don't optimize complements just optimize
|
||||||
|
// a value part
|
||||||
) {
|
) {
|
||||||
UINFO(4, "Consider for localization: " << nodep);
|
UINFO(4, "Consider for localization: " << nodep);
|
||||||
m_varScopeps.push_back(nodep);
|
m_varScopeps.push_back(nodep);
|
||||||
|
|
|
||||||
|
|
@ -522,6 +522,13 @@ V3Number& V3Number::setValue1() {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
V3Number& V3Number::setXZFromXZComplement(const V3Number& other) {
|
||||||
|
UASSERT(words() == other.words(), "Width mismatch");
|
||||||
|
UASSERT(!other.isAnyXZ(), "XZ in xz part");
|
||||||
|
for (int i = 1; i < words(); ++i) m_data.num()[i].m_valueX = other.m_data.num()[i].m_value;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
void V3Number::setBitX0(int bit) {
|
void V3Number::setBitX0(int bit) {
|
||||||
// Selection beyond bounds after V3Premit needs to have 0s
|
// Selection beyond bounds after V3Premit needs to have 0s
|
||||||
// in upper bits. Contrast to setAllBitsXRemoved which honors xAssign
|
// in upper bits. Contrast to setAllBitsXRemoved which honors xAssign
|
||||||
|
|
@ -1167,6 +1174,20 @@ bool V3Number::isAllX() const VL_MT_SAFE {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
bool V3Number::isAll0() const VL_MT_SAFE {
|
||||||
|
if (isDouble() || isString()) return false;
|
||||||
|
for (int i = 0; i < width(); ++i) {
|
||||||
|
if (!bitIs0(i)) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool V3Number::isAll1() const VL_MT_SAFE {
|
||||||
|
if (isDouble() || isString()) return false;
|
||||||
|
for (int i = 0; i < width(); ++i) {
|
||||||
|
if (!bitIs1(i)) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
bool V3Number::isEqZero() const VL_MT_SAFE {
|
bool V3Number::isEqZero() const VL_MT_SAFE {
|
||||||
if (isString()) return m_data.str().empty();
|
if (isString()) return m_data.str().empty();
|
||||||
for (int i = 0; i < words(); ++i) {
|
for (int i = 0; i < words(); ++i) {
|
||||||
|
|
|
||||||
|
|
@ -640,6 +640,7 @@ public:
|
||||||
V3Number& setAllBits0();
|
V3Number& setAllBits0();
|
||||||
V3Number& setAllBits1();
|
V3Number& setAllBits1();
|
||||||
V3Number& setValue1();
|
V3Number& setValue1();
|
||||||
|
V3Number& setXZFromXZComplement(const V3Number&);
|
||||||
// IE if nbits=1, then 0b1, if 2->0b11, if 3->0b111 etc
|
// IE if nbits=1, then 0b1, if 2->0b11, if 3->0b111 etc
|
||||||
V3Number& setMask(int nbits, int lsb = 0);
|
V3Number& setMask(int nbits, int lsb = 0);
|
||||||
|
|
||||||
|
|
@ -697,6 +698,8 @@ public:
|
||||||
}
|
}
|
||||||
bool isAllZ() const VL_MT_SAFE;
|
bool isAllZ() const VL_MT_SAFE;
|
||||||
bool isAllX() const VL_MT_SAFE;
|
bool isAllX() const VL_MT_SAFE;
|
||||||
|
bool isAll0() const VL_MT_SAFE;
|
||||||
|
bool isAll1() const VL_MT_SAFE;
|
||||||
bool isEqZero() const VL_MT_SAFE;
|
bool isEqZero() const VL_MT_SAFE;
|
||||||
bool isNeqZero() const;
|
bool isNeqZero() const;
|
||||||
bool isBitsZero(int msb, int lsb) const;
|
bool isBitsZero(int msb, int lsb) const;
|
||||||
|
|
|
||||||
|
|
@ -1057,6 +1057,12 @@ void V3Options::notify() VL_MT_DISABLED {
|
||||||
if (traceEnabledFst()) {
|
if (traceEnabledFst()) {
|
||||||
cmdfl->v3warn(E_UNSUPPORTED, "--fourstate is not supported with fst trace");
|
cmdfl->v3warn(E_UNSUPPORTED, "--fourstate is not supported with fst trace");
|
||||||
}
|
}
|
||||||
|
if (systemC()) cmdfl->v3warn(E_UNSUPPORTED, "--fourstate is not supported with --sc");
|
||||||
|
if (!m_xInitialDefault) cmdfl->v3error("--x-initial has no sense with --fourstate");
|
||||||
|
if (!m_xAssignDefault) cmdfl->v3error("--x-assign has no sense with --fourstate");
|
||||||
|
} else if (!m_zero_top_ports.isDefault()) {
|
||||||
|
cmdfl->v3error(
|
||||||
|
"--zero-top-ports and --no-zero-top-ports shall be used only with --fourstate");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (coverage() && savable()) {
|
if (coverage() && savable()) {
|
||||||
|
|
@ -1945,6 +1951,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc,
|
||||||
DECL_OPTION("-waiver-output", Set, &m_waiverOutput);
|
DECL_OPTION("-waiver-output", Set, &m_waiverOutput);
|
||||||
|
|
||||||
DECL_OPTION("-x-assign", CbVal, [this, fl](const char* valp) {
|
DECL_OPTION("-x-assign", CbVal, [this, fl](const char* valp) {
|
||||||
|
m_xAssignDefault = false;
|
||||||
if (!std::strcmp(valp, "0")) {
|
if (!std::strcmp(valp, "0")) {
|
||||||
m_xAssign = "0";
|
m_xAssign = "0";
|
||||||
} else if (!std::strcmp(valp, "1")) {
|
} else if (!std::strcmp(valp, "1")) {
|
||||||
|
|
@ -1960,6 +1967,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
DECL_OPTION("-x-initial", CbVal, [this, fl](const char* valp) {
|
DECL_OPTION("-x-initial", CbVal, [this, fl](const char* valp) {
|
||||||
|
m_xInitialDefault = false;
|
||||||
if (!std::strcmp(valp, "0")) {
|
if (!std::strcmp(valp, "0")) {
|
||||||
m_xInitial = "0";
|
m_xInitial = "0";
|
||||||
} else if (!std::strcmp(valp, "fast")) {
|
} else if (!std::strcmp(valp, "fast")) {
|
||||||
|
|
@ -1978,6 +1986,8 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc,
|
||||||
addIncDirUser(parseFileArg(optdir, string{valp}));
|
addIncDirUser(parseFileArg(optdir, string{valp}));
|
||||||
}).notForRerun();
|
}).notForRerun();
|
||||||
|
|
||||||
|
DECL_OPTION("-zero-top-ports", OnOff, &m_zero_top_ports).undocumented();
|
||||||
|
|
||||||
parser.finalize();
|
parser.finalize();
|
||||||
|
|
||||||
for (int i = 0; i < argc;) {
|
for (int i = 0; i < argc;) {
|
||||||
|
|
|
||||||
|
|
@ -311,6 +311,7 @@ private:
|
||||||
bool m_vpi = false; // main switch: --vpi
|
bool m_vpi = false; // main switch: --vpi
|
||||||
bool m_waiverMultiline = false; // main switch: --waiver-multiline
|
bool m_waiverMultiline = false; // main switch: --waiver-multiline
|
||||||
bool m_xInitialEdge = false; // main switch: --x-initial-edge
|
bool m_xInitialEdge = false; // main switch: --x-initial-edge
|
||||||
|
VOptionBool m_zero_top_ports{VOptionBool::OPT_DEFAULT_TRUE}; // main switch --zero-top-ports
|
||||||
|
|
||||||
int m_assertUnrollLimit = 1024; // main switch: --assert-unroll-limit
|
int m_assertUnrollLimit = 1024; // main switch: --assert-unroll-limit
|
||||||
int m_buildJobs = -1; // main switch: --build-jobs, -j
|
int m_buildJobs = -1; // main switch: --build-jobs, -j
|
||||||
|
|
@ -384,6 +385,8 @@ private:
|
||||||
string m_work = "work"; // main switch: --work {libname}
|
string m_work = "work"; // main switch: --work {libname}
|
||||||
string m_xAssign; // main switch: --x-assign
|
string m_xAssign; // main switch: --x-assign
|
||||||
string m_xInitial; // main switch: --x-initial
|
string m_xInitial; // main switch: --x-initial
|
||||||
|
bool m_xAssignDefault = true; // whether the value is default of explicitly provided by user
|
||||||
|
bool m_xInitialDefault = true; // whether the value is default of explicitly provided by user
|
||||||
|
|
||||||
// Language is now held in FileLine, on a per-node basis. However we still
|
// Language is now held in FileLine, on a per-node basis. However we still
|
||||||
// have a concept of the default language at a global level.
|
// have a concept of the default language at a global level.
|
||||||
|
|
@ -708,6 +711,7 @@ public:
|
||||||
bool isWaiverOutput() const { return !m_waiverOutput.empty(); }
|
bool isWaiverOutput() const { return !m_waiverOutput.empty(); }
|
||||||
string xAssign() const { return m_xAssign; }
|
string xAssign() const { return m_xAssign; }
|
||||||
string xInitial() const { return m_xInitial; }
|
string xInitial() const { return m_xInitial; }
|
||||||
|
VOptionBool zeroTopPorts() const { return m_zero_top_ports; }
|
||||||
|
|
||||||
const VStringSet& cppFiles() const { return m_cppFiles; }
|
const VStringSet& cppFiles() const { return m_cppFiles; }
|
||||||
const VStringList& cFlags() const { return m_cFlags; }
|
const VStringList& cFlags() const { return m_cFlags; }
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
#include "V3Premit.h"
|
#include "V3Premit.h"
|
||||||
|
|
||||||
|
#include "V3Fourstate.h"
|
||||||
#include "V3Stats.h"
|
#include "V3Stats.h"
|
||||||
#include "V3UniqueNames.h"
|
#include "V3UniqueNames.h"
|
||||||
|
|
||||||
|
|
@ -308,6 +309,42 @@ class PremitVisitor final : public VNVisitor {
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
checkNode(nodep);
|
checkNode(nodep);
|
||||||
}
|
}
|
||||||
|
void visit(AstFourstateExpr* nodep) override {
|
||||||
|
iterateChildren(nodep);
|
||||||
|
// Consider adding a temp for this expression.
|
||||||
|
if (!m_stmtp) return; // Not under a statement
|
||||||
|
if (nodep->user1SetOnce()) return; // Already processed
|
||||||
|
if (!nodep->valuep()->isWide()) return; // Not wide
|
||||||
|
if (m_assignLhs) return; // This is an lvalue!
|
||||||
|
UASSERT_OBJ(!VN_IS(nodep->firstAbovep(), ArraySel), nodep, "Should have been ignored");
|
||||||
|
// Keep as local temporary.
|
||||||
|
std::string name = "__Vtemp_" + std::to_string(m_tmpVarCnt);
|
||||||
|
std::string nameXz = "__Vtemp_" + std::to_string(++m_tmpVarCnt) + XZ_SUFFIX;
|
||||||
|
FileLine* const flp = nodep->fileline();
|
||||||
|
AstVar* const valueVarp
|
||||||
|
= new AstVar{flp, VVarType::STMTTEMP, std::move(name), nodep->valuep()->dtypep()};
|
||||||
|
AstVar* xzVarp
|
||||||
|
= new AstVar{flp, VVarType::STMTTEMP, std::move(nameXz), nodep->xzp()->dtypep()};
|
||||||
|
valueVarp->fourstateComplementp(xzVarp);
|
||||||
|
valueVarp->funcLocal(true);
|
||||||
|
xzVarp->funcLocal(true);
|
||||||
|
valueVarp->noReset(true);
|
||||||
|
xzVarp->noReset(true);
|
||||||
|
m_cfuncp->addVarsp(valueVarp);
|
||||||
|
m_cfuncp->addVarsp(xzVarp);
|
||||||
|
++m_temporaryVarsCreated;
|
||||||
|
|
||||||
|
// Assignment to put before the referencing statement
|
||||||
|
AstAssign* const assignValuep = new AstAssign{
|
||||||
|
flp, new AstVarRef{flp, valueVarp, VAccess::WRITE}, nodep->valuep()->unlinkFrBack()};
|
||||||
|
AstAssign* const assignXZp = new AstAssign{flp, new AstVarRef{flp, xzVarp, VAccess::WRITE},
|
||||||
|
nodep->xzp()->unlinkFrBack()};
|
||||||
|
// Insert before the statement
|
||||||
|
m_stmtp->addHereThisAsNext(assignValuep);
|
||||||
|
m_stmtp->addHereThisAsNext(assignXZp);
|
||||||
|
nodep->valuep(new AstVarRef{flp, valueVarp, VAccess::READ});
|
||||||
|
nodep->xzp(new AstVarRef{flp, xzVarp, VAccess::READ});
|
||||||
|
}
|
||||||
void visit(AstRand* nodep) override {
|
void visit(AstRand* nodep) override {
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
checkNode(nodep);
|
checkNode(nodep);
|
||||||
|
|
|
||||||
|
|
@ -1011,12 +1011,20 @@ class ConstraintExprVisitor final : public VNVisitor {
|
||||||
if (targetWidth > exprWidth) {
|
if (targetWidth > exprWidth) {
|
||||||
// Extend to match target width
|
// Extend to match target width
|
||||||
AstNodeExpr* const result = new AstExtend{fl, exprp, targetWidth};
|
AstNodeExpr* const result = new AstExtend{fl, exprp, targetWidth};
|
||||||
result->dtypeSetLogicSized(targetWidth, targetSigning);
|
if (exprp->dtypep()->isFourstate()) {
|
||||||
|
result->dtypeSetLogicSized(targetWidth, targetSigning);
|
||||||
|
} else {
|
||||||
|
result->dtypeSetBitSized(targetWidth, targetSigning);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
} else if (targetWidth < exprWidth) {
|
} else if (targetWidth < exprWidth) {
|
||||||
// Truncate to match target width
|
// Truncate to match target width
|
||||||
AstNodeExpr* const result = new AstSel{fl, exprp, 0, targetWidth};
|
AstNodeExpr* const result = new AstSel{fl, exprp, 0, targetWidth};
|
||||||
result->dtypeSetLogicSized(targetWidth, targetSigning);
|
if (exprp->dtypep()->isFourstate()) {
|
||||||
|
result->dtypeSetLogicSized(targetWidth, targetSigning);
|
||||||
|
} else {
|
||||||
|
result->dtypeSetBitSized(targetWidth, targetSigning);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
// Width already matches
|
// Width already matches
|
||||||
|
|
@ -1964,7 +1972,6 @@ class ConstraintExprVisitor final : public VNVisitor {
|
||||||
AstNodeExpr* indexp = nodep->bitp()->unlinkFrBack(&handle);
|
AstNodeExpr* indexp = nodep->bitp()->unlinkFrBack(&handle);
|
||||||
if (indexp->width() < 32) {
|
if (indexp->width() < 32) {
|
||||||
AstExtend* const extendp = new AstExtend{fl, indexp, 32};
|
AstExtend* const extendp = new AstExtend{fl, indexp, 32};
|
||||||
extendp->dtypeSetLogicSized(32, VSigning::UNSIGNED);
|
|
||||||
extendp->user1(true);
|
extendp->user1(true);
|
||||||
indexp = extendp;
|
indexp = extendp;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -66,8 +66,7 @@ class ReloopVisitor final : public VNVisitor {
|
||||||
static AstVar* createVarTemp(FileLine* fl, AstCFunc* cfuncp) {
|
static AstVar* createVarTemp(FileLine* fl, AstCFunc* cfuncp) {
|
||||||
UASSERT_OBJ(cfuncp, fl, "Assignment not under a function");
|
UASSERT_OBJ(cfuncp, fl, "Assignment not under a function");
|
||||||
const string newvarname{"__Vilp" + std::to_string(cfuncp->user1Inc() + 1)};
|
const string newvarname{"__Vilp" + std::to_string(cfuncp->user1Inc() + 1)};
|
||||||
AstVar* const varp
|
AstVar* const varp = new AstVar{fl, VVarType::STMTTEMP, newvarname, VFlagBitPacked{}, 32};
|
||||||
= new AstVar{fl, VVarType::STMTTEMP, newvarname, VFlagLogicPacked{}, 32};
|
|
||||||
cfuncp->addVarsp(varp);
|
cfuncp->addVarsp(varp);
|
||||||
return varp;
|
return varp;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -553,8 +553,9 @@ class TaskVisitor final : public VNVisitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void connectPort(AstVar* portp, AstArg* argp, const string& namePrefix, AstNode* beginp,
|
AstVarScope* connectPort(AstVar* portp, AstArg* argp, const string& namePrefix,
|
||||||
bool inlineTask) {
|
AstNode* beginp, bool inlineTask) {
|
||||||
|
AstVarScope* newvscp = nullptr;
|
||||||
AstNodeExpr* pinp = argp->exprp();
|
AstNodeExpr* pinp = argp->exprp();
|
||||||
if (inlineTask) {
|
if (inlineTask) {
|
||||||
portp->unlinkFrBack();
|
portp->unlinkFrBack();
|
||||||
|
|
@ -575,7 +576,7 @@ class TaskVisitor final : public VNVisitor {
|
||||||
+ std::to_string(m_unconVarNum++),
|
+ std::to_string(m_unconVarNum++),
|
||||||
portp->dtypep()};
|
portp->dtypep()};
|
||||||
m_modp->addStmtsp(varp);
|
m_modp->addStmtsp(varp);
|
||||||
AstVarScope* const newvscp = new AstVarScope{pinp->fileline(), m_scopep, varp};
|
newvscp = new AstVarScope{pinp->fileline(), m_scopep, varp};
|
||||||
m_scopep->addVarsp(newvscp);
|
m_scopep->addVarsp(newvscp);
|
||||||
AstVarRef* const repp = new AstVarRef{pinp->fileline(), newvscp, VAccess::WRITE};
|
AstVarRef* const repp = new AstVarRef{pinp->fileline(), newvscp, VAccess::WRITE};
|
||||||
pinp->replaceWith(repp);
|
pinp->replaceWith(repp);
|
||||||
|
|
@ -620,8 +621,7 @@ class TaskVisitor final : public VNVisitor {
|
||||||
} else if (portp->isInout()) {
|
} else if (portp->isInout()) {
|
||||||
// UINFOTREE(9, pinp, "", "pinrsize-");
|
// UINFOTREE(9, pinp, "", "pinrsize-");
|
||||||
|
|
||||||
AstVarScope* const newvscp
|
newvscp = createVarScope(portp, namePrefix + "__" + portp->shortName());
|
||||||
= createVarScope(portp, namePrefix + "__" + portp->shortName());
|
|
||||||
portp->user2p(newvscp);
|
portp->user2p(newvscp);
|
||||||
if (!inlineTask) {
|
if (!inlineTask) {
|
||||||
pinp->replaceWith(
|
pinp->replaceWith(
|
||||||
|
|
@ -642,8 +642,7 @@ class TaskVisitor final : public VNVisitor {
|
||||||
} else if (portp->isWritable()) {
|
} else if (portp->isWritable()) {
|
||||||
// Even if it's referencing a varref, we still make a temporary
|
// Even if it's referencing a varref, we still make a temporary
|
||||||
// Else task(x,x,x) might produce incorrect results
|
// Else task(x,x,x) might produce incorrect results
|
||||||
AstVarScope* const newvscp
|
newvscp = createVarScope(portp, namePrefix + "__" + portp->shortName());
|
||||||
= createVarScope(portp, namePrefix + "__" + portp->shortName());
|
|
||||||
portp->user2p(newvscp);
|
portp->user2p(newvscp);
|
||||||
if (!inlineTask) {
|
if (!inlineTask) {
|
||||||
pinp->replaceWith(new AstVarRef{newvscp->fileline(), newvscp, VAccess::WRITE});
|
pinp->replaceWith(new AstVarRef{newvscp->fileline(), newvscp, VAccess::WRITE});
|
||||||
|
|
@ -654,8 +653,7 @@ class TaskVisitor final : public VNVisitor {
|
||||||
beginp->addNext(postassp);
|
beginp->addNext(postassp);
|
||||||
} else if (inlineTask && portp->isNonOutput()) {
|
} else if (inlineTask && portp->isNonOutput()) {
|
||||||
// Make input variable
|
// Make input variable
|
||||||
AstVarScope* const newvscp
|
newvscp = createVarScope(portp, namePrefix + "__" + portp->shortName());
|
||||||
= createVarScope(portp, namePrefix + "__" + portp->shortName());
|
|
||||||
portp->user2p(newvscp);
|
portp->user2p(newvscp);
|
||||||
AstAssign* const preassp = connectPortMakeInAssign(pinp, newvscp, false);
|
AstAssign* const preassp = connectPortMakeInAssign(pinp, newvscp, false);
|
||||||
// Put assignment in FRONT of all other statements
|
// Put assignment in FRONT of all other statements
|
||||||
|
|
@ -666,6 +664,7 @@ class TaskVisitor final : public VNVisitor {
|
||||||
beginp->addNext(preassp);
|
beginp->addNext(preassp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return newvscp;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasRefArgument(AstNodeFTask* nodep) {
|
bool hasRefArgument(AstNodeFTask* nodep) {
|
||||||
|
|
@ -692,10 +691,25 @@ class TaskVisitor final : public VNVisitor {
|
||||||
AstNode::user2ClearTree();
|
AstNode::user2ClearTree();
|
||||||
{
|
{
|
||||||
const V3TaskConnects tconnects = V3Task::taskConnects(refp, beginp);
|
const V3TaskConnects tconnects = V3Task::taskConnects(refp, beginp);
|
||||||
|
AstVar* prevFourstateVarp = nullptr;
|
||||||
for (const auto& itr : tconnects) {
|
for (const auto& itr : tconnects) {
|
||||||
AstVar* const portp = itr.first;
|
AstVar* const portp = itr.first;
|
||||||
AstArg* const argp = itr.second;
|
AstArg* const argp = itr.second;
|
||||||
connectPort(portp, argp, namePrefix, beginp, true);
|
AstVar* varp = nullptr;
|
||||||
|
if (const AstVarScope* const vscp
|
||||||
|
= connectPort(portp, argp, namePrefix, beginp, true)) {
|
||||||
|
varp = vscp->varp();
|
||||||
|
}
|
||||||
|
UASSERT_OBJ(
|
||||||
|
itr.first->isFourstateComplement() == (prevFourstateVarp != nullptr), varp,
|
||||||
|
"Fourstate complements shall be predecessed with fourstate value part");
|
||||||
|
if (itr.first->fourstateComplementp()) {
|
||||||
|
UASSERT_OBJ(varp, itr.first, "Port not needed?");
|
||||||
|
prevFourstateVarp = varp;
|
||||||
|
} else if (prevFourstateVarp) {
|
||||||
|
prevFourstateVarp->fourstateComplementp(varp);
|
||||||
|
prevFourstateVarp = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UASSERT_OBJ(!refp->argsp(), refp, "Arg wasn't removed by above loop");
|
UASSERT_OBJ(!refp->argsp(), refp, "Arg wasn't removed by above loop");
|
||||||
|
|
|
||||||
|
|
@ -207,7 +207,11 @@ class UnknownVisitor final : public VNVisitor {
|
||||||
}
|
}
|
||||||
void visit(AstVar* nodep) override {
|
void visit(AstVar* nodep) override {
|
||||||
VL_RESTORER(m_allowXUnique);
|
VL_RESTORER(m_allowXUnique);
|
||||||
if (nodep->isParam()) m_allowXUnique = false;
|
if (nodep->isParam()) {
|
||||||
|
m_allowXUnique = false;
|
||||||
|
} else if (m_modp && m_modp->isTop() && nodep->varType() == VVarType::PORT) {
|
||||||
|
nodep->setIsTopLevelPort();
|
||||||
|
}
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
}
|
}
|
||||||
void visitEqNeqCase(AstNodeBiop* nodep) {
|
void visitEqNeqCase(AstNodeBiop* nodep) {
|
||||||
|
|
@ -551,7 +555,8 @@ public:
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
explicit UnknownVisitor(AstNetlist* nodep)
|
explicit UnknownVisitor(AstNetlist* nodep)
|
||||||
: m_lvboundNames{"__Vlvbound"}
|
: m_lvboundNames{"__Vlvbound"}
|
||||||
, m_xrandNames{std::make_unique<V3UniqueNames>(s_xrandPrefix)} {
|
, m_xrandNames{std::make_unique<V3UniqueNames>(s_xrandPrefix)}
|
||||||
|
, m_allowXUnique{!v3Global.opt.fourstate()} {
|
||||||
iterate(nodep);
|
iterate(nodep);
|
||||||
}
|
}
|
||||||
~UnknownVisitor() override { //
|
~UnknownVisitor() override { //
|
||||||
|
|
|
||||||
|
|
@ -1911,13 +1911,15 @@ class WidthVisitor final : public VNVisitor {
|
||||||
void visit(AstCExprUser* nodep) override {
|
void visit(AstCExprUser* nodep) override {
|
||||||
// Give it the size the user wants.
|
// Give it the size the user wants.
|
||||||
if (m_vup && m_vup->prelim()) {
|
if (m_vup && m_vup->prelim()) {
|
||||||
nodep->dtypeSetLogicUnsized(32, 1, VSigning::UNSIGNED); // We don't care
|
nodep->dtypeSetBitUnsized(32, 1, VSigning::UNSIGNED); // We don't care
|
||||||
// All arguments seek their natural sizes
|
// All arguments seek their natural sizes
|
||||||
userIterateChildren(nodep, WidthVP{SELF, BOTH}.p());
|
userIterateChildren(nodep, WidthVP{SELF, BOTH}.p());
|
||||||
}
|
}
|
||||||
if (m_vup->final()) {
|
if (m_vup->final()) {
|
||||||
AstNodeDType* const expDTypep = m_vup->dtypeOverridep(nodep->dtypep());
|
AstNodeDType* const expDTypep = m_vup->dtypeOverridep(nodep->dtypep());
|
||||||
nodep->dtypep(expDTypep); // Assume user knows the rules; go with the flow
|
nodep->dtypeSetBitUnsized(
|
||||||
|
expDTypep->width(), expDTypep->widthMin(),
|
||||||
|
expDTypep->numeric()); // Assume user knows the rules; go with the flow
|
||||||
if (nodep->width() > 64) {
|
if (nodep->width() > 64) {
|
||||||
nodep->v3warn(E_UNSUPPORTED, "Unsupported: $c can't generate wider than 64 bits");
|
nodep->v3warn(E_UNSUPPORTED, "Unsupported: $c can't generate wider than 64 bits");
|
||||||
}
|
}
|
||||||
|
|
@ -2049,7 +2051,7 @@ class WidthVisitor final : public VNVisitor {
|
||||||
iterateCheckSizedSelf(nodep, "FHS", nodep->fhsp(), SELF, BOTH);
|
iterateCheckSizedSelf(nodep, "FHS", nodep->fhsp(), SELF, BOTH);
|
||||||
// For widthMin, if a 32 bit number, we need a 6 bit number as we need to return '32'.
|
// For widthMin, if a 32 bit number, we need a 6 bit number as we need to return '32'.
|
||||||
const int widthMin = V3Number::log2b(nodep->lhsp()->width()) + 1;
|
const int widthMin = V3Number::log2b(nodep->lhsp()->width()) + 1;
|
||||||
nodep->dtypeSetLogicUnsized(32, widthMin, VSigning::SIGNED);
|
nodep->dtypeSetBitUnsized(32, widthMin, VSigning::SIGNED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void visit(AstCountOnes* nodep) override {
|
void visit(AstCountOnes* nodep) override {
|
||||||
|
|
@ -2057,7 +2059,7 @@ class WidthVisitor final : public VNVisitor {
|
||||||
iterateCheckSizedSelf(nodep, "LHS", nodep->lhsp(), SELF, BOTH);
|
iterateCheckSizedSelf(nodep, "LHS", nodep->lhsp(), SELF, BOTH);
|
||||||
// For widthMin, if a 32 bit number, we need a 6 bit number as we need to return '32'.
|
// For widthMin, if a 32 bit number, we need a 6 bit number as we need to return '32'.
|
||||||
const int widthMin = V3Number::log2b(nodep->lhsp()->width()) + 1;
|
const int widthMin = V3Number::log2b(nodep->lhsp()->width()) + 1;
|
||||||
nodep->dtypeSetLogicUnsized(32, widthMin, VSigning::SIGNED);
|
nodep->dtypeSetBitUnsized(32, widthMin, VSigning::SIGNED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void visit(AstCvtPackString* nodep) override {
|
void visit(AstCvtPackString* nodep) override {
|
||||||
|
|
|
||||||
|
|
@ -174,8 +174,15 @@ class WidthSelVisitor final : public VNVisitor {
|
||||||
} else {
|
} else {
|
||||||
extendp = new AstExtend{fl, indexp};
|
extendp = new AstExtend{fl, indexp};
|
||||||
}
|
}
|
||||||
extendp->dtypeSetLogicUnsized(
|
if (indexp->dtypep()->isFourstate()) {
|
||||||
32, std::max(V3Number::log2b(elwidth) + 1, indexp->widthMin()), VSigning::UNSIGNED);
|
extendp->dtypeSetLogicUnsized(
|
||||||
|
32, std::max(V3Number::log2b(elwidth) + 1, indexp->widthMin()),
|
||||||
|
VSigning::UNSIGNED);
|
||||||
|
} else {
|
||||||
|
extendp->dtypeSetBitUnsized(32,
|
||||||
|
std::max(V3Number::log2b(elwidth) + 1, indexp->widthMin()),
|
||||||
|
VSigning::UNSIGNED);
|
||||||
|
}
|
||||||
AstNodeExpr* const mulp
|
AstNodeExpr* const mulp
|
||||||
= new AstMul{fl, new AstConst{fl, AstConst::Unsized32{}, elwidth},
|
= new AstMul{fl, new AstConst{fl, AstConst::Unsized32{}, elwidth},
|
||||||
// Extend needed as index might be e.g. 3 bits but constant e.g. 5 bits
|
// Extend needed as index might be e.g. 3 bits but constant e.g. 5 bits
|
||||||
|
|
|
||||||
|
|
@ -564,6 +564,11 @@ static void process() {
|
||||||
V3Expand::expandAll(v3Global.rootp());
|
V3Expand::expandAll(v3Global.rootp());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!v3Global.opt.lintOnly() && !v3Global.opt.serializeOnly()
|
||||||
|
&& v3Global.opt.fourstate()) {
|
||||||
|
V3Fourstate::fourstateShuffleAll(v3Global.rootp());
|
||||||
|
}
|
||||||
|
|
||||||
// Propagate constants across WORDSEL arrayed temporaries
|
// Propagate constants across WORDSEL arrayed temporaries
|
||||||
if (!v3Global.opt.serializeOnly() && v3Global.opt.fSubst()) {
|
if (!v3Global.opt.serializeOnly() && v3Global.opt.fSubst()) {
|
||||||
// Constant folding of expanded stuff
|
// Constant folding of expanded stuff
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ endif
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
SCENARIOS ?= --vlt --vltmt --dist
|
SCENARIOS ?= --vlt --vltmt --dist --vlt4 --vltmt4
|
||||||
DRIVER_HASHSET ?=
|
DRIVER_HASHSET ?=
|
||||||
|
|
||||||
.PHONY: test
|
.PHONY: test
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,9 @@ All_Scenarios = {
|
||||||
'xrun': ['linter', 'simulator', 'simulator_st', 'xrun'],
|
'xrun': ['linter', 'simulator', 'simulator_st', 'xrun'],
|
||||||
'xsim': ['linter', 'simulator', 'simulator_st', 'xsim'],
|
'xsim': ['linter', 'simulator', 'simulator_st', 'xsim'],
|
||||||
'vlt': ['linter', 'simulator', 'simulator_st', 'vlt_all', 'vlt'],
|
'vlt': ['linter', 'simulator', 'simulator_st', 'vlt_all', 'vlt'],
|
||||||
|
'vlt4': ['linter', 'simulator', 'simulator_st', 'vlt_all', 'vlt'],
|
||||||
'vltmt': ['simulator', 'vlt_all', 'vltmt'],
|
'vltmt': ['simulator', 'vlt_all', 'vltmt'],
|
||||||
|
'vltmt4': ['simulator', 'vlt_all', 'vltmt'],
|
||||||
# yapf: enable
|
# yapf: enable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -731,11 +733,13 @@ class VlTest:
|
||||||
# Make e.g. self.vlt, self.vltmt etc
|
# Make e.g. self.vlt, self.vltmt etc
|
||||||
self.vlt = False # Set below also
|
self.vlt = False # Set below also
|
||||||
self.vltmt = False # Set below also
|
self.vltmt = False # Set below also
|
||||||
|
self.vlt4 = False # Set below also
|
||||||
|
self.vltmt4 = False # Set below also
|
||||||
self.xsim = False # Set below also
|
self.xsim = False # Set below also
|
||||||
for ascenario in All_Scenarios:
|
for ascenario in All_Scenarios:
|
||||||
self.__dict__[ascenario] = False
|
self.__dict__[ascenario] = False
|
||||||
self.__dict__[scenario] = True
|
self.__dict__[scenario] = True
|
||||||
self.vlt_all = self.vlt or self.vltmt # Any Verilator scenario
|
self.vlt_all = self.vlt or self.vltmt or self.vlt4 or self.vltmt4 # Any Verilator scenario
|
||||||
|
|
||||||
(self.py_filename, self.t_dir) = Runner._py_filename_adjust(self.py_filename, ".")
|
(self.py_filename, self.t_dir) = Runner._py_filename_adjust(self.py_filename, ".")
|
||||||
for tdir in Args.test_dirs: # pylint: disable=redefined-outer-name
|
for tdir in Args.test_dirs: # pylint: disable=redefined-outer-name
|
||||||
|
|
@ -895,6 +899,9 @@ class VlTest:
|
||||||
self.top_filename = re.sub(r'\.py$', '', self.py_filename) + '.' + self.v_suffix
|
self.top_filename = re.sub(r'\.py$', '', self.py_filename) + '.' + self.v_suffix
|
||||||
self.pli_filename = re.sub(r'\.py$', '', self.py_filename) + '.cpp'
|
self.pli_filename = re.sub(r'\.py$', '', self.py_filename) + '.cpp'
|
||||||
self.top_shell_filename = self.obj_dir + "/" + self.vm_prefix + "__top.v"
|
self.top_shell_filename = self.obj_dir + "/" + self.vm_prefix + "__top.v"
|
||||||
|
self.twostate_capable = True
|
||||||
|
self.fourstate_capable = True
|
||||||
|
self.fourstate_nowarn = True # This is only a temporary workaround
|
||||||
|
|
||||||
def _define_opt_calc(self) -> str:
|
def _define_opt_calc(self) -> str:
|
||||||
return "--define " if self.xsim else "+define+"
|
return "--define " if self.xsim else "+define+"
|
||||||
|
|
@ -1150,9 +1157,10 @@ class VlTest:
|
||||||
verilator_flags += ["--trace-vcd"]
|
verilator_flags += ["--trace-vcd"]
|
||||||
if Args.gdbsim or Args.rrsim:
|
if Args.gdbsim or Args.rrsim:
|
||||||
verilator_flags += ["-CFLAGS -ggdb -LDFLAGS -ggdb"]
|
verilator_flags += ["-CFLAGS -ggdb -LDFLAGS -ggdb"]
|
||||||
verilator_flags += ["--x-assign unique"] # More likely to be buggy
|
if not (param['vlt4'] or param['vltmt4']):
|
||||||
|
verilator_flags += ["--x-assign unique"] # More likely to be buggy
|
||||||
|
|
||||||
if param['vltmt']:
|
if param['vltmt'] or param['vltmt4']:
|
||||||
verilator_flags += ["--debug-partition"]
|
verilator_flags += ["--debug-partition"]
|
||||||
if param['threads'] >= 0:
|
if param['threads'] >= 0:
|
||||||
verilator_flags += ["--threads", str(param['threads'])]
|
verilator_flags += ["--threads", str(param['threads'])]
|
||||||
|
|
@ -1160,6 +1168,10 @@ class VlTest:
|
||||||
verilator_flags += ["--exe"]
|
verilator_flags += ["--exe"]
|
||||||
if param['make_main'] and param['verilator_make_gmake']:
|
if param['make_main'] and param['verilator_make_gmake']:
|
||||||
verilator_flags += ["../" + self.main_filename]
|
verilator_flags += ["../" + self.main_filename]
|
||||||
|
if param['vlt4'] or param['vltmt4']:
|
||||||
|
verilator_flags += ["--fourstate"]
|
||||||
|
if self.fourstate_nowarn:
|
||||||
|
verilator_flags += ["-Wno-FUTURE", "-Wno-CASTFOURSTATE"]
|
||||||
|
|
||||||
cmdargs = [
|
cmdargs = [
|
||||||
"--prefix",
|
"--prefix",
|
||||||
|
|
@ -1216,7 +1228,7 @@ class VlTest:
|
||||||
if re.search(r'(^|\s)-?-threads\s', checkflags):
|
if re.search(r'(^|\s)-?-threads\s', checkflags):
|
||||||
self.error("Specify threads via 'threads=' argument, not as a command line option")
|
self.error("Specify threads via 'threads=' argument, not as a command line option")
|
||||||
|
|
||||||
if param['threads'] < 0 and param['vltmt']:
|
if param['threads'] < 0 and (param['vltmt'] or param['vltmt4']):
|
||||||
param['threads'] = calc_threads(Vltmt_Threads)
|
param['threads'] = calc_threads(Vltmt_Threads)
|
||||||
if not param['context_threads']:
|
if not param['context_threads']:
|
||||||
param['context_threads'] = param['threads'] if (param['threads'] >= 1) else 1
|
param['context_threads'] = param['threads'] if (param['threads'] >= 1) else 1
|
||||||
|
|
@ -1358,6 +1370,15 @@ class VlTest:
|
||||||
self.skip("Test requires Coroutines; ignore error since not available\n")
|
self.skip("Test requires Coroutines; ignore error since not available\n")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if not self.twostate_capable and (param['vlt'] or param['vltmt']):
|
||||||
|
self.skip("Test is not twostate capable")
|
||||||
|
return
|
||||||
|
|
||||||
|
if not self.fourstate_capable and (param['vlt4'] or param['vltmt4']):
|
||||||
|
self.skip("Test is not fourstate capable - maybe verilator does not"
|
||||||
|
"support all used features")
|
||||||
|
return
|
||||||
|
|
||||||
if self.timing and self.sc and re.search(r'Ubuntu 24.04', distro.name(
|
if self.timing and self.sc and re.search(r'Ubuntu 24.04', distro.name(
|
||||||
pretty=True)) and re.search(r'clang', self.cxx_version):
|
pretty=True)) and re.search(r'clang', self.cxx_version):
|
||||||
self.skip(
|
self.skip(
|
||||||
|
|
@ -1869,6 +1890,11 @@ class VlTest:
|
||||||
tee=True,
|
tee=True,
|
||||||
verilator_run=False) -> bool: # Move gcov data to parallel area
|
verilator_run=False) -> bool: # Move gcov data to parallel area
|
||||||
|
|
||||||
|
if not self.fourstate_capable and (self.vlt4 or self.vltmt4):
|
||||||
|
self.skip("Test is not fourstate capable - maybe verilator does not"
|
||||||
|
"support all used features")
|
||||||
|
return False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
command = ' '.join(cmd)
|
command = ' '.join(cmd)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import vltest_bootstrap
|
||||||
|
|
||||||
test.priority(100)
|
test.priority(100)
|
||||||
test.scenarios('vlt')
|
test.scenarios('vlt')
|
||||||
|
test.fourstate_capable = False
|
||||||
test.top_filename = "t/t_a1_first_cc.v"
|
test.top_filename = "t/t_a1_first_cc.v"
|
||||||
|
|
||||||
test.leak_check_disable()
|
test.leak_check_disable()
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('simulator')
|
test.scenarios('simulator')
|
||||||
|
test.fourstate_capable = False
|
||||||
|
|
||||||
test.compile()
|
test.compile()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('linter')
|
test.scenarios('linter')
|
||||||
|
test.fourstate_capable = False
|
||||||
|
|
||||||
test.lint(fails=test.vlt_all, expect_filename=test.golden_filename)
|
test.lint(fails=test.vlt_all, expect_filename=test.golden_filename)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('simulator')
|
test.scenarios('simulator')
|
||||||
|
test.fourstate_capable = False
|
||||||
|
|
||||||
test.compile()
|
test.compile()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('simulator')
|
test.scenarios('simulator')
|
||||||
|
test.fourstate_capable = False
|
||||||
|
|
||||||
test.compile()
|
test.compile()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('simulator')
|
test.scenarios('simulator')
|
||||||
|
test.fourstate_capable = False
|
||||||
|
|
||||||
test.compile()
|
test.compile()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('linter')
|
test.scenarios('linter')
|
||||||
|
test.fourstate_capable = False
|
||||||
|
|
||||||
test.lint(fails=test.vlt_all, expect_filename=test.golden_filename)
|
test.lint(fails=test.vlt_all, expect_filename=test.golden_filename)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('vlt_all')
|
test.scenarios('vlt_all')
|
||||||
|
test.fourstate_capable = False
|
||||||
test.top_filename = "t/t_altera_lpm.v"
|
test.top_filename = "t/t_altera_lpm.v"
|
||||||
module = re.sub(r'.*t_altera_', '', test.name)
|
module = re.sub(r'.*t_altera_', '', test.name)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('vlt_all')
|
test.scenarios('vlt_all')
|
||||||
|
test.fourstate_capable = False
|
||||||
test.top_filename = "t/t_altera_lpm.v"
|
test.top_filename = "t/t_altera_lpm.v"
|
||||||
module = re.sub(r'.*t_altera_', '', test.name)
|
module = re.sub(r'.*t_altera_', '', test.name)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('vlt_all')
|
test.scenarios('vlt_all')
|
||||||
|
test.fourstate_capable = False
|
||||||
test.top_filename = "t/t_altera_lpm.v"
|
test.top_filename = "t/t_altera_lpm.v"
|
||||||
module = re.sub(r'.*t_altera_', '', test.name)
|
module = re.sub(r'.*t_altera_', '', test.name)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('vlt_all')
|
test.scenarios('vlt_all')
|
||||||
|
test.fourstate_capable = False
|
||||||
test.top_filename = "t/t_altera_lpm.v"
|
test.top_filename = "t/t_altera_lpm.v"
|
||||||
module = re.sub(r'.*t_altera_', '', test.name)
|
module = re.sub(r'.*t_altera_', '', test.name)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('vlt_all')
|
test.scenarios('vlt_all')
|
||||||
|
test.fourstate_capable = False
|
||||||
test.top_filename = "t/t_altera_lpm.v"
|
test.top_filename = "t/t_altera_lpm.v"
|
||||||
module = re.sub(r'.*t_altera_', '', test.name)
|
module = re.sub(r'.*t_altera_', '', test.name)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('vlt_all')
|
test.scenarios('vlt_all')
|
||||||
|
test.fourstate_capable = False
|
||||||
test.top_filename = "t/t_altera_lpm.v"
|
test.top_filename = "t/t_altera_lpm.v"
|
||||||
module = re.sub(r'.*t_altera_', '', test.name)
|
module = re.sub(r'.*t_altera_', '', test.name)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('vlt_all')
|
test.scenarios('vlt_all')
|
||||||
|
test.fourstate_capable = False
|
||||||
test.top_filename = "t/t_altera_lpm.v"
|
test.top_filename = "t/t_altera_lpm.v"
|
||||||
module = re.sub(r'.*t_altera_', '', test.name)
|
module = re.sub(r'.*t_altera_', '', test.name)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('vlt_all')
|
test.scenarios('vlt_all')
|
||||||
|
test.fourstate_capable = False
|
||||||
test.top_filename = "t/t_altera_lpm.v"
|
test.top_filename = "t/t_altera_lpm.v"
|
||||||
module = re.sub(r'.*t_altera_', '', test.name)
|
module = re.sub(r'.*t_altera_', '', test.name)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('vlt_all')
|
test.scenarios('vlt_all')
|
||||||
|
test.fourstate_capable = False
|
||||||
test.top_filename = "t/t_altera_lpm.v"
|
test.top_filename = "t/t_altera_lpm.v"
|
||||||
module = re.sub(r'.*t_altera_', '', test.name)
|
module = re.sub(r'.*t_altera_', '', test.name)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('vlt_all')
|
test.scenarios('vlt_all')
|
||||||
|
test.fourstate_capable = False
|
||||||
test.top_filename = "t/t_altera_lpm.v"
|
test.top_filename = "t/t_altera_lpm.v"
|
||||||
module = re.sub(r'.*t_altera_', '', test.name)
|
module = re.sub(r'.*t_altera_', '', test.name)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('vlt_all')
|
test.scenarios('vlt_all')
|
||||||
|
test.fourstate_capable = False
|
||||||
test.top_filename = "t/t_altera_lpm.v"
|
test.top_filename = "t/t_altera_lpm.v"
|
||||||
module = re.sub(r'.*t_altera_', '', test.name)
|
module = re.sub(r'.*t_altera_', '', test.name)
|
||||||
module = re.sub(r'_noinl', '', module)
|
module = re.sub(r'_noinl', '', module)
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('vlt_all')
|
test.scenarios('vlt_all')
|
||||||
|
test.fourstate_capable = False
|
||||||
test.top_filename = "t/t_altera_lpm.v"
|
test.top_filename = "t/t_altera_lpm.v"
|
||||||
module = re.sub(r'.*t_altera_', '', test.name)
|
module = re.sub(r'.*t_altera_', '', test.name)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('vlt_all')
|
test.scenarios('vlt_all')
|
||||||
|
test.fourstate_capable = False
|
||||||
test.top_filename = "t/t_altera_lpm.v"
|
test.top_filename = "t/t_altera_lpm.v"
|
||||||
module = re.sub(r'.*t_altera_', '', test.name)
|
module = re.sub(r'.*t_altera_', '', test.name)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('vlt_all')
|
test.scenarios('vlt_all')
|
||||||
|
test.fourstate_capable = False
|
||||||
test.top_filename = "t/t_altera_lpm.v"
|
test.top_filename = "t/t_altera_lpm.v"
|
||||||
module = re.sub(r'.*t_altera_', '', test.name)
|
module = re.sub(r'.*t_altera_', '', test.name)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('vlt_all')
|
test.scenarios('vlt_all')
|
||||||
|
test.fourstate_capable = False
|
||||||
test.top_filename = "t/t_altera_lpm.v"
|
test.top_filename = "t/t_altera_lpm.v"
|
||||||
module = re.sub(r'.*t_altera_', '', test.name)
|
module = re.sub(r'.*t_altera_', '', test.name)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('vlt_all')
|
test.scenarios('vlt_all')
|
||||||
|
test.fourstate_capable = False
|
||||||
test.top_filename = "t/t_altera_lpm.v"
|
test.top_filename = "t/t_altera_lpm.v"
|
||||||
module = re.sub(r'.*t_altera_', '', test.name)
|
module = re.sub(r'.*t_altera_', '', test.name)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('vlt_all')
|
test.scenarios('vlt_all')
|
||||||
|
test.fourstate_capable = False
|
||||||
test.top_filename = "t/t_altera_lpm.v"
|
test.top_filename = "t/t_altera_lpm.v"
|
||||||
module = re.sub(r'.*t_altera_', '', test.name)
|
module = re.sub(r'.*t_altera_', '', test.name)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('vlt_all')
|
test.scenarios('vlt_all')
|
||||||
|
test.fourstate_capable = False
|
||||||
test.top_filename = "t/t_altera_lpm.v"
|
test.top_filename = "t/t_altera_lpm.v"
|
||||||
module = re.sub(r'.*t_altera_', '', test.name)
|
module = re.sub(r'.*t_altera_', '', test.name)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('simulator')
|
test.scenarios('simulator')
|
||||||
|
test.fourstate_capable = False
|
||||||
|
|
||||||
test.compile(verilator_flags2=["--stats"])
|
test.compile(verilator_flags2=["--stats"])
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('vlt_all')
|
test.scenarios('vlt_all')
|
||||||
|
test.fourstate_capable = False
|
||||||
|
|
||||||
test.compile(verilator_flags2=["--binary"])
|
test.compile(verilator_flags2=["--binary"])
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('simulator')
|
test.scenarios('simulator')
|
||||||
|
test.fourstate_capable = False
|
||||||
|
|
||||||
test.compile(verilator_flags2=["--stats"])
|
test.compile(verilator_flags2=["--stats"])
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('simulator')
|
test.scenarios('simulator')
|
||||||
|
test.fourstate_capable = False
|
||||||
|
|
||||||
test.compile(verilator_flags2=["--stats", test.wno_unopthreads_for_few_cores])
|
test.compile(verilator_flags2=["--stats", test.wno_unopthreads_for_few_cores])
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('simulator')
|
test.scenarios('simulator')
|
||||||
|
test.fourstate_capable = False
|
||||||
|
|
||||||
test.compile(verilator_flags2=["--stats"])
|
test.compile(verilator_flags2=["--stats"])
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('simulator')
|
test.scenarios('simulator')
|
||||||
|
test.fourstate_capable = False
|
||||||
|
|
||||||
test.compile()
|
test.compile()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('simulator')
|
test.scenarios('simulator')
|
||||||
|
test.fourstate_capable = False
|
||||||
|
|
||||||
test.compile()
|
test.compile()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('simulator')
|
test.scenarios('simulator')
|
||||||
|
test.fourstate_capable = False
|
||||||
|
|
||||||
test.compile()
|
test.compile()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('simulator')
|
test.scenarios('simulator')
|
||||||
|
test.fourstate_capable = False
|
||||||
|
|
||||||
test.compile()
|
test.compile()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('simulator')
|
test.scenarios('simulator')
|
||||||
|
test.fourstate_capable = False
|
||||||
|
|
||||||
test.compile()
|
test.compile()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('simulator')
|
test.scenarios('simulator')
|
||||||
|
test.fourstate_capable = False
|
||||||
|
|
||||||
test.compile()
|
test.compile()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('simulator')
|
test.scenarios('simulator')
|
||||||
|
test.fourstate_capable = False
|
||||||
|
|
||||||
test.compile()
|
test.compile()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('simulator')
|
test.scenarios('simulator')
|
||||||
|
test.fourstate_capable = False
|
||||||
|
|
||||||
test.compile()
|
test.compile()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('simulator')
|
test.scenarios('simulator')
|
||||||
|
test.fourstate_capable = False
|
||||||
|
|
||||||
test.compile()
|
test.compile()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('simulator')
|
test.scenarios('simulator')
|
||||||
|
test.fourstate_capable = False
|
||||||
|
|
||||||
test.compile()
|
test.compile()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('simulator')
|
test.scenarios('simulator')
|
||||||
|
test.fourstate_capable = False
|
||||||
|
|
||||||
test.compile()
|
test.compile()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('simulator')
|
test.scenarios('simulator')
|
||||||
|
test.fourstate_capable = False
|
||||||
|
|
||||||
test.compile()
|
test.compile()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import vltest_bootstrap
|
import vltest_bootstrap
|
||||||
|
|
||||||
test.scenarios('simulator')
|
test.scenarios('simulator')
|
||||||
|
test.fourstate_capable = False
|
||||||
|
|
||||||
test.compile()
|
test.compile()
|
||||||
|
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue