Optimize VCD vector zero trimming
This commit is contained in:
parent
eb258d7df7
commit
b7362d7017
|
|
@ -635,50 +635,118 @@ void VerilatedVcdBuffer::emitBit(uint32_t code, CData newval) {
|
||||||
finishLine(code, wp);
|
finishLine(code, wp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int vlVcdClz32(uint32_t value) {
|
||||||
|
VL_DEBUG_IFDEF(assert(value););
|
||||||
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
|
return __builtin_clz(value);
|
||||||
|
#else
|
||||||
|
int zeros = 0;
|
||||||
|
uint32_t bit = 1U << 31;
|
||||||
|
while (!(value & bit)) {
|
||||||
|
++zeros;
|
||||||
|
bit >>= 1;
|
||||||
|
}
|
||||||
|
return zeros;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int vlVcdClz64(uint64_t value) {
|
||||||
|
VL_DEBUG_IFDEF(assert(value););
|
||||||
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
|
return __builtin_clzll(value);
|
||||||
|
#else
|
||||||
|
const uint32_t upper = static_cast<uint32_t>(value >> 32);
|
||||||
|
return upper ? vlVcdClz32(upper) : 32 + vlVcdClz32(static_cast<uint32_t>(value));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
VL_ATTR_ALWINLINE
|
VL_ATTR_ALWINLINE
|
||||||
void VerilatedVcdBuffer::emitCData(uint32_t code, CData newval, int bits) {
|
void VerilatedVcdBuffer::emitCData(uint32_t code, CData newval, int bits) {
|
||||||
char* wp = m_writep;
|
char* wp = m_writep;
|
||||||
*wp++ = 'b';
|
*wp++ = 'b';
|
||||||
cvtCDataToStr(wp, newval << (VL_BYTESIZE - bits));
|
CData value = newval << (VL_BYTESIZE - bits);
|
||||||
finishLine(code, wp + bits);
|
if (VL_UNLIKELY(!value)) {
|
||||||
|
*wp++ = '0';
|
||||||
|
finishLine(code, wp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const int skip = vlVcdClz32(value) - (VL_IDATASIZE - VL_BYTESIZE);
|
||||||
|
cvtCDataToStr(wp, value << skip);
|
||||||
|
finishLine(code, wp + bits - skip);
|
||||||
}
|
}
|
||||||
|
|
||||||
VL_ATTR_ALWINLINE
|
VL_ATTR_ALWINLINE
|
||||||
void VerilatedVcdBuffer::emitSData(uint32_t code, SData newval, int bits) {
|
void VerilatedVcdBuffer::emitSData(uint32_t code, SData newval, int bits) {
|
||||||
char* wp = m_writep;
|
char* wp = m_writep;
|
||||||
*wp++ = 'b';
|
*wp++ = 'b';
|
||||||
cvtSDataToStr(wp, newval << (VL_SHORTSIZE - bits));
|
SData value = newval << (VL_SHORTSIZE - bits);
|
||||||
finishLine(code, wp + bits);
|
if (VL_UNLIKELY(!value)) {
|
||||||
|
*wp++ = '0';
|
||||||
|
finishLine(code, wp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const int skip = vlVcdClz32(value) - (VL_IDATASIZE - VL_SHORTSIZE);
|
||||||
|
cvtSDataToStr(wp, value << skip);
|
||||||
|
finishLine(code, wp + bits - skip);
|
||||||
}
|
}
|
||||||
|
|
||||||
VL_ATTR_ALWINLINE
|
VL_ATTR_ALWINLINE
|
||||||
void VerilatedVcdBuffer::emitIData(uint32_t code, IData newval, int bits) {
|
void VerilatedVcdBuffer::emitIData(uint32_t code, IData newval, int bits) {
|
||||||
char* wp = m_writep;
|
char* wp = m_writep;
|
||||||
*wp++ = 'b';
|
*wp++ = 'b';
|
||||||
cvtIDataToStr(wp, newval << (VL_IDATASIZE - bits));
|
IData value = newval << (VL_IDATASIZE - bits);
|
||||||
finishLine(code, wp + bits);
|
if (VL_UNLIKELY(!value)) {
|
||||||
|
*wp++ = '0';
|
||||||
|
finishLine(code, wp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const int skip = vlVcdClz32(value);
|
||||||
|
cvtIDataToStr(wp, value << skip);
|
||||||
|
finishLine(code, wp + bits - skip);
|
||||||
}
|
}
|
||||||
|
|
||||||
VL_ATTR_ALWINLINE
|
VL_ATTR_ALWINLINE
|
||||||
void VerilatedVcdBuffer::emitQData(uint32_t code, QData newval, int bits) {
|
void VerilatedVcdBuffer::emitQData(uint32_t code, QData newval, int bits) {
|
||||||
char* wp = m_writep;
|
char* wp = m_writep;
|
||||||
*wp++ = 'b';
|
*wp++ = 'b';
|
||||||
cvtQDataToStr(wp, newval << (VL_QUADSIZE - bits));
|
QData value = newval << (VL_QUADSIZE - bits);
|
||||||
finishLine(code, wp + bits);
|
if (VL_UNLIKELY(!value)) {
|
||||||
|
*wp++ = '0';
|
||||||
|
finishLine(code, wp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const int skip = vlVcdClz64(value);
|
||||||
|
cvtQDataToStr(wp, value << skip);
|
||||||
|
finishLine(code, wp + bits - skip);
|
||||||
}
|
}
|
||||||
|
|
||||||
VL_ATTR_ALWINLINE
|
VL_ATTR_ALWINLINE
|
||||||
void VerilatedVcdBuffer::emitWData(uint32_t code, const WData* newvalp, int bits) {
|
void VerilatedVcdBuffer::emitWData(uint32_t code, const WData* newvalp, int bits) {
|
||||||
int words = VL_WORDS_I(bits);
|
|
||||||
char* wp = m_writep;
|
char* wp = m_writep;
|
||||||
*wp++ = 'b';
|
*wp++ = 'b';
|
||||||
// Handle the most significant word
|
|
||||||
|
int word = VL_WORDS_I(bits) - 1;
|
||||||
const int bitsInMSW = VL_BITBIT_E(bits) ? VL_BITBIT_E(bits) : VL_EDATASIZE;
|
const int bitsInMSW = VL_BITBIT_E(bits) ? VL_BITBIT_E(bits) : VL_EDATASIZE;
|
||||||
cvtEDataToStr(wp, newvalp[--words] << (VL_EDATASIZE - bitsInMSW));
|
int bitsInWord = bitsInMSW;
|
||||||
wp += bitsInMSW;
|
EData value = newvalp[word] & VL_MASK_E(bitsInMSW);
|
||||||
// Handle the remaining words
|
|
||||||
while (words > 0) {
|
while (!value && word > 0) {
|
||||||
cvtEDataToStr(wp, newvalp[--words]);
|
value = newvalp[--word];
|
||||||
|
bitsInWord = VL_EDATASIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VL_UNLIKELY(!value)) {
|
||||||
|
*wp++ = '0';
|
||||||
|
finishLine(code, wp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int skip = vlVcdClz32(value) - (VL_EDATASIZE - bitsInWord);
|
||||||
|
cvtEDataToStr(wp, value << (VL_EDATASIZE - bitsInWord + skip));
|
||||||
|
wp += bitsInWord - skip;
|
||||||
|
|
||||||
|
while (word > 0) {
|
||||||
|
cvtEDataToStr(wp, newvalp[--word]);
|
||||||
wp += VL_EDATASIZE;
|
wp += VL_EDATASIZE;
|
||||||
}
|
}
|
||||||
finishLine(code, wp);
|
finishLine(code, wp);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify it
|
||||||
|
# under the terms of either the GNU Lesser General Public License Version 3
|
||||||
|
# or the Perl Artistic License Version 2.0.
|
||||||
|
# SPDX-FileCopyrightText: 2026 Wilson Snyder
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
|
import vltest_bootstrap
|
||||||
|
|
||||||
|
import os
|
||||||
|
import platform
|
||||||
|
|
||||||
|
test.scenarios('vlt')
|
||||||
|
|
||||||
|
if platform.machine().lower() not in ("amd64", "x86_64"):
|
||||||
|
test.skip("Test requires x86-64 AVX2/LZCNT")
|
||||||
|
|
||||||
|
if os.path.exists("/proc/cpuinfo"):
|
||||||
|
with open("/proc/cpuinfo", encoding="utf-8") as fh:
|
||||||
|
cpuinfo = " " + fh.read().lower() + " "
|
||||||
|
if " avx2 " not in cpuinfo or (" lzcnt " not in cpuinfo and " abm " not in cpuinfo):
|
||||||
|
test.skip("Test requires x86-64 AVX2/LZCNT")
|
||||||
|
|
||||||
|
test.compile(verilator_flags2=[
|
||||||
|
"--binary", "--trace-vcd", "-CFLAGS", "\"-mavx2 -mlzcnt\""
|
||||||
|
])
|
||||||
|
|
||||||
|
test.execute()
|
||||||
|
|
||||||
|
code = r"[!-~]+"
|
||||||
|
|
||||||
|
test.file_grep(test.trace_filename, rf"^b0 {code}$")
|
||||||
|
test.file_grep(test.trace_filename, rf"^b10 {code}$")
|
||||||
|
test.file_grep(test.trace_filename, rf"^b1 {code}$")
|
||||||
|
test.file_grep(test.trace_filename, rf"^b1000000000000000 {code}$")
|
||||||
|
test.file_grep(test.trace_filename, rf"^b10100101 {code}$")
|
||||||
|
test.file_grep(test.trace_filename, rf"^b1{'0' * 63} {code}$")
|
||||||
|
test.file_grep(test.trace_filename, rf"^b1{'0' * 32} {code}$")
|
||||||
|
test.file_grep(test.trace_filename, rf"^b1{'0' * 65} {code}$")
|
||||||
|
|
||||||
|
test.file_grep_not(test.trace_filename, rf"^b0[01]+ {code}$")
|
||||||
|
|
||||||
|
test.passes()
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||||
|
// SPDX-FileCopyrightText: 2026 Wilson Snyder
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
`define STRINGIFY(x) `"x`"
|
||||||
|
|
||||||
|
module t;
|
||||||
|
logic [3:0] zero4 = 4'b0;
|
||||||
|
logic [3:0] small4 = 4'b0010;
|
||||||
|
logic [7:0] small8 = 8'h01;
|
||||||
|
logic [15:0] msb16 = 16'h8000;
|
||||||
|
logic [31:0] mid32 = 32'h0000_00a5;
|
||||||
|
logic [63:0] msb64 = 64'h8000_0000_0000_0000;
|
||||||
|
logic [99:0] wide_skip = 100'h1_0000_0000;
|
||||||
|
logic [67:0] wide_partial = 68'h2_0000_0000_0000_0000;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$dumpfile(`STRINGIFY(`TEST_DUMPFILE));
|
||||||
|
$dumpvars(0, t);
|
||||||
|
#1;
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify it
|
||||||
|
# under the terms of either the GNU Lesser General Public License Version 3
|
||||||
|
# or the Perl Artistic License Version 2.0.
|
||||||
|
# SPDX-FileCopyrightText: 2026 Wilson Snyder
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
|
import vltest_bootstrap
|
||||||
|
|
||||||
|
test.scenarios('vlt')
|
||||||
|
test.top_filename = "t/t_trace_vcd_shortened.v"
|
||||||
|
|
||||||
|
test.compile(verilator_flags2=[
|
||||||
|
"--binary", "--trace-vcd", "-CFLAGS", "-DVL_PORTABLE_ONLY"
|
||||||
|
])
|
||||||
|
|
||||||
|
test.execute()
|
||||||
|
|
||||||
|
code = r"[!-~]+"
|
||||||
|
|
||||||
|
test.file_grep(test.trace_filename, rf"^b0 {code}$")
|
||||||
|
test.file_grep(test.trace_filename, rf"^b10 {code}$")
|
||||||
|
test.file_grep(test.trace_filename, rf"^b1 {code}$")
|
||||||
|
test.file_grep(test.trace_filename, rf"^b1000000000000000 {code}$")
|
||||||
|
test.file_grep(test.trace_filename, rf"^b10100101 {code}$")
|
||||||
|
test.file_grep(test.trace_filename, rf"^b1{'0' * 63} {code}$")
|
||||||
|
test.file_grep(test.trace_filename, rf"^b1{'0' * 32} {code}$")
|
||||||
|
test.file_grep(test.trace_filename, rf"^b1{'0' * 65} {code}$")
|
||||||
|
|
||||||
|
test.file_grep_not(test.trace_filename, rf"^b0[01]+ {code}$")
|
||||||
|
|
||||||
|
test.passes()
|
||||||
Loading…
Reference in New Issue