Add support of Events for VCD/FST traces (#3759)

This commit is contained in:
Yves Mathieu 2022-11-23 10:07:14 +01:00 committed by GitHub
parent e97e6c2213
commit 06fdf7be58
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 218 additions and 31 deletions

View File

@ -221,6 +221,10 @@ void VerilatedFst::declare(uint32_t code, const char* name, int dtypenum, fstVar
}
}
void VerilatedFst::declEvent(uint32_t code, const char* name, int dtypenum, fstVarDir vardir,
fstVarType vartype, bool array, int arraynum) {
declare(code, name, dtypenum, vardir, vartype, array, arraynum, false, 0, 0);
}
void VerilatedFst::declBit(uint32_t code, const char* name, int dtypenum, fstVarDir vardir,
fstVarType vartype, bool array, int arraynum) {
declare(code, name, dtypenum, vardir, vartype, array, arraynum, false, 0, 0);
@ -279,6 +283,12 @@ void VerilatedFst::configure(const VerilatedTraceConfig& config) {
// verilated_trace_imp.h, which is included in this file at the top),
// so always inline them.
VL_ATTR_ALWINLINE
void VerilatedFstBuffer::emitEvent(uint32_t code, VlEvent newval) {
VL_DEBUG_IFDEF(assert(m_symbolp[code]););
fstWriterEmitValueChange(m_fst, m_symbolp[code], "1");
}
VL_ATTR_ALWINLINE
void VerilatedFstBuffer::emitBit(uint32_t code, CData newval) {
VL_DEBUG_IFDEF(assert(m_symbolp[code]););

View File

@ -101,6 +101,8 @@ public:
//=========================================================================
// Internal interface to Verilator generated code
void declEvent(uint32_t code, const char* name, int dtypenum, fstVarDir vardir,
fstVarType vartype, bool array, int arraynum);
void declBit(uint32_t code, const char* name, int dtypenum, fstVarDir vardir,
fstVarType vartype, bool array, int arraynum);
void declBus(uint32_t code, const char* name, int dtypenum, fstVarDir vardir,
@ -161,6 +163,7 @@ class VerilatedFstBuffer VL_NOT_FINAL {
// Implementations of duck-typed methods for VerilatedTraceBuffer. These are
// called from only one place (the full* methods), so always inline them.
VL_ATTR_ALWINLINE void emitEvent(uint32_t code, VlEvent newval);
VL_ATTR_ALWINLINE void emitBit(uint32_t code, CData newval);
VL_ATTR_ALWINLINE void emitCData(uint32_t code, CData newval, int bits);
VL_ATTR_ALWINLINE void emitSData(uint32_t code, SData newval, int bits);

View File

@ -107,6 +107,7 @@ public:
CHG_QDATA = 0x5,
CHG_WDATA = 0x6,
CHG_DOUBLE = 0x8,
CHG_EVENT = 0x9,
// TODO: full..
TIME_CHANGE = 0xc,
TRACE_BUFFER = 0xd,
@ -422,6 +423,7 @@ public:
void fullQData(uint32_t* oldp, QData newval, int bits);
void fullWData(uint32_t* oldp, const WData* newvalp, int bits);
void fullDouble(uint32_t* oldp, double newval);
void fullEvent(uint32_t* oldp, VlEvent newval);
// In non-offload mode, these are called directly by the trace callbacks,
// and are called chg*. In offload mode, they are called by the worker
@ -456,6 +458,9 @@ public:
}
}
}
VL_ATTR_ALWINLINE void chgEvent(uint32_t* oldp, VlEvent newval) {
fullEvent(oldp, newval);
}
VL_ATTR_ALWINLINE void chgDouble(uint32_t* oldp, double newval) {
// cppcheck-suppress invalidPointerCast
if (VL_UNLIKELY(*reinterpret_cast<double*>(oldp) != newval)) fullDouble(oldp, newval);
@ -533,6 +538,12 @@ public:
m_offloadBufferWritep += 4;
VL_DEBUG_IF(assert(m_offloadBufferWritep <= m_offloadBufferEndp););
}
void chgEvent(uint32_t code, VlEvent newval) {
m_offloadBufferWritep[0] = VerilatedTraceOffloadCommand::CHG_EVENT ;
m_offloadBufferWritep[1] = code;
m_offloadBufferWritep += 2;
VL_DEBUG_IF(assert(m_offloadBufferWritep <= m_offloadBufferEndp););
}
};
#endif // guard

View File

@ -183,6 +183,10 @@ void VerilatedTrace<VL_SUB_T, VL_BUF_T>::offloadWorkerThreadMain() {
traceBufp->chgDouble(oldp, *reinterpret_cast<const double*>(readp));
readp += 2;
continue;
case VerilatedTraceOffloadCommand::CHG_EVENT:
VL_TRACE_OFFLOAD_DEBUG("Command CHG_EVENT " << top);
traceBufp->chgEvent(oldp, *reinterpret_cast<const VlEvent*>(readp));
continue;
//===
// Rare commands
@ -834,6 +838,13 @@ void VerilatedTraceBuffer<VL_BUF_T>::fullBit(uint32_t* oldp, CData newval) {
emitBit(code, newval);
}
template <>
void VerilatedTraceBuffer<VL_BUF_T>::fullEvent(uint32_t* oldp, VlEvent newval) {
const uint32_t code = oldp - m_sigs_oldvalp;
*oldp = 1; // Do we really store an "event" ?
emitEvent(code, newval);
}
template <>
void VerilatedTraceBuffer<VL_BUF_T>::fullCData(uint32_t* oldp, CData newval, int bits) {
const uint32_t code = oldp - m_sigs_oldvalp;

View File

@ -548,6 +548,9 @@ void VerilatedVcd::declare(uint32_t code, const char* name, const char* wirep, b
m_namemapp->emplace(hiername, decl);
}
void VerilatedVcd::declEvent(uint32_t code, const char* name, bool array, int arraynum) {
declare(code, name, "event", array, arraynum, false, false, 0, 0);
}
void VerilatedVcd::declBit(uint32_t code, const char* name, bool array, int arraynum) {
declare(code, name, "wire", array, arraynum, false, false, 0, 0);
}
@ -694,6 +697,19 @@ void VerilatedVcdBuffer::finishLine(uint32_t code, char* writep) {
// verilated_trace_imp.h, which is included in this file at the top),
// so always inline them.
VL_ATTR_ALWINLINE
void VerilatedVcdBuffer::emitEvent(uint32_t code, VlEvent newval) {
const bool triggered = newval.isTriggered();
// TODO : It seems that untriggerd events are not filtered
// should be tested before this last step
if(triggered) {
// Don't prefetch suffix as it's a bit too late;
char* wp = m_writep;
*wp++ = '1' ;
finishLine(code, wp);
}
}
VL_ATTR_ALWINLINE
void VerilatedVcdBuffer::emitBit(uint32_t code, CData newval) {
// Don't prefetch suffix as it's a bit too late;

View File

@ -140,6 +140,7 @@ public:
//=========================================================================
// Internal interface to Verilator generated code
void declEvent(uint32_t code, const char* name, bool array, int arraynum);
void declBit(uint32_t code, const char* name, bool array, int arraynum);
void declBus(uint32_t code, const char* name, bool array, int arraynum, int msb, int lsb);
void declQuad(uint32_t code, const char* name, bool array, int arraynum, int msb, int lsb);
@ -206,6 +207,7 @@ class VerilatedVcdBuffer VL_NOT_FINAL {
// Implementation of VerilatedTraceBuffer interface
// Implementations of duck-typed methods for VerilatedTraceBuffer. These are
// called from only one place (the full* methods), so always inline them.
VL_ATTR_ALWINLINE void emitEvent(uint32_t code, VlEvent newval);
VL_ATTR_ALWINLINE void emitBit(uint32_t code, CData newval);
VL_ATTR_ALWINLINE void emitCData(uint32_t code, CData newval, int bits);
VL_ATTR_ALWINLINE void emitSData(uint32_t code, SData newval, int bits);

View File

@ -637,6 +637,8 @@ class EmitCTrace final : EmitCFunc {
puts("tracep->declQuad");
} else if (nodep->bitRange().ranged()) {
puts("tracep->declBus");
} else if (nodep->dtypep()->basicp()->isEvent()) {
puts("tracep->declEvent");
} else {
puts("tracep->declBit");
}
@ -689,11 +691,11 @@ class EmitCTrace final : EmitCFunc {
else if (kwd == VBasicDTypeKwd::SHORTINT) { fstvt = "FST_VT_SV_SHORTINT"; }
else if (kwd == VBasicDTypeKwd::LONGINT) { fstvt = "FST_VT_SV_LONGINT"; }
else if (kwd == VBasicDTypeKwd::BYTE) { fstvt = "FST_VT_SV_BYTE"; }
else if (kwd == VBasicDTypeKwd::EVENT) { fstvt = "FST_VT_VCD_EVENT"; }
else { fstvt = "FST_VT_SV_BIT"; }
// clang-format on
//
// Not currently supported
// FST_VT_VCD_EVENT
// FST_VT_VCD_PORT
// FST_VT_VCD_SHORTREAL
// FST_VT_VCD_REALTIME
@ -779,6 +781,9 @@ class EmitCTrace final : EmitCFunc {
puts("bufp->" + func + "SData");
} else if (nodep->declp()->widthMin() > 1) {
puts("bufp->" + func + "CData");
} else if (nodep->dtypep()->basicp()->isEvent()) {
puts("bufp->" + func + "Event");
emitWidth = false;
} else {
puts("bufp->" + func + "Bit");
emitWidth = false;

View File

@ -1,16 +1,17 @@
$version Generated by VerilatedVcd $end
$date Thu Oct 20 09:56:59 2022 $end
$date Tue Nov 22 16:48:14 2022 $end
$timescale 1ps $end
$scope module TOP $end
$scope module t $end
$var wire 32 * CLK_HALF_PERIOD [31:0] $end
$var wire 32 ) CLK_PERIOD [31:0] $end
$var wire 32 + CLK_HALF_PERIOD [31:0] $end
$var wire 32 * CLK_PERIOD [31:0] $end
$var wire 1 $ a $end
$var wire 1 % b $end
$var wire 1 & c $end
$var wire 1 ( clk $end
$var wire 1 ) clk $end
$var wire 1 ' d $end
$var event 1 ( ev $end
$var wire 1 # rst $end
$upscope $end
$upscope $end
@ -23,54 +24,57 @@ $enddefinitions $end
0%
0&
0'
0(
b00000000000000000000000000001010 )
b00000000000000000000000000000101 *
0)
b00000000000000000000000000001010 *
b00000000000000000000000000000101 +
#5
1(
1)
#10
0#
1%
0(
1(
0)
#15
1(
1)
#20
0(
1(
0)
#25
1(
1)
#30
0(
0)
#35
1(
1)
#40
0(
0)
#45
1(
1)
#50
0(
0)
#55
1(
1)
#60
0(
0)
#65
1(
1)
#70
0(
0)
#75
1(
1)
#80
0(
0)
#85
1(
1)
#90
0(
0)
#95
1(
1)
#100
0(
0)
#105
1(
1)
#110
1#
0%
0(
1(
0)

View File

@ -16,6 +16,7 @@ module t;
logic b;
logic c;
logic d;
event ev;
initial begin
$dumpfile(`STRINGIFY(`TEST_DUMPFILE));
@ -34,10 +35,15 @@ module t;
#CLK_PERIOD;
rst = 0;
b = 1;
-> ev ;
#CLK_PERIOD;
-> ev ;
#(10 * CLK_PERIOD);
#(9 * CLK_PERIOD);
-> ev ;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,87 @@
$date
Tue Nov 22 18:14:18 2022
$end
$version
fstWriter
$end
$timescale
1ps
$end
$scope module TOP $end
$scope module t $end
$var parameter 32 ! CLK_PERIOD [31:0] $end
$var parameter 32 " CLK_HALF_PERIOD [31:0] $end
$var logic 1 # rst $end
$var logic 1 $ clk $end
$var logic 1 % a $end
$var logic 1 & b $end
$var logic 1 ' c $end
$var logic 1 ( d $end
$var event 1 ) ev $end
$upscope $end
$upscope $end
$enddefinitions $end
#0
$dumpvars
1)
0(
0'
0&
0%
0$
1#
b00000000000000000000000000000101 "
b00000000000000000000000000001010 !
$end
#5
1$
#10
0$
0#
1&
1)
#15
1$
#20
0$
1)
#25
1$
#30
0$
#35
1$
#40
0$
#45
1$
#50
0$
#55
1$
#60
0$
#65
1$
#70
0$
#75
1$
#80
0$
#85
1$
#90
0$
#95
1$
#100
0$
#105
1$
#110
0$
1)
0&
1#

View File

@ -0,0 +1,32 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2022 Yves Mathieu. 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-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(simulator => 1);
top_filename("t/t_timing_trace.v");
if (!$Self->have_coroutines) {
skip("No coroutine support");
}
else {
compile(
verilator_flags2 => ["--exe --main --timing --trace-fst -Wno-MINTYPMAXDLY"],
make_main => 0,
);
execute(
check_finished => 1,
);
fst_identical($Self->trace_filename, $Self->{golden_filename});
}
ok(1);
1;