30 SignalNameRef(uint64_t signalIndex, uint64_t nameOffset)
31 : signalIndex(signalIndex), nameOffset(nameOffset) {}
36 std::string_view getStringView(
const char *nameBlob)
const {
37 return std::string_view(nameBlob + nameOffset);
44 const uint8_t *data) {
45 const auto *sigStr = signal.
id.
cStr();
48 for (
unsigned n = signal.
numBits; n > 0; --n)
49 *(dest++) = (
data[(n - 1) / 8] & (1 << ((n - 1) % 8)) ?
'1' :
'0');
53 *(dest++) = *(sigStr++);
58 std::string &dest,
const uint8_t *data) {
59 auto strOffset = dest.size();
61 dumpSignal(signal, &dest[strOffset], data);
64static void writeVCDHeader(std::basic_ostream<char> &os) {
67 os <<
"$version\n Some cryptic ArcRuntime magic\n$end\n";
68 os <<
"$timescale 1ns $end\n";
78 const char base = (
'~' -
'!') + 1;
80 assert(pos < (
sizeof(
raw) - 1) &&
"Signal ID out of range");
81 raw[pos] =
'!' +
static_cast<char>(index % base);
90 const std::filesystem::path &outFilePath,
93 outFilePath(outFilePath) {}
98 for (uint64_t i = 0; i < info->numTraceTaps; ++i)
99 signalTable.emplace_back(i, info->traceTaps[i].stateOffset,
100 info->traceTaps[i].typeBits);
104 const std::string_view &name) {
106 buffer.append(
"<EMPTY>");
109 for (
auto c : name) {
112 buffer.push_back(
'_');
113 else if (std::isprint(c))
122 const char *sigNameBlob = info->traceTapNames;
123 auto nameRefVector = std::vector<SignalNameRef>();
125 uint64_t sigOffset = 0;
127 uint64_t sigOffsetNext = info->traceTaps[0].nameOffset + 1;
128 uint64_t signalIndex = 0;
129 while (signalIndex < info->numTraceTaps) {
130 nameRefVector.emplace_back(signalIndex, sigOffset);
131 auto nameLen = nameRefVector.back().getStringView(sigNameBlob).length();
133 sigOffset += nameLen + 1;
134 if (sigOffset >= sigOffsetNext) {
136 assert(sigOffset == sigOffsetNext);
139 if (signalIndex < info->numTraceTaps)
140 sigOffsetNext = info->traceTaps[signalIndex].nameOffset + 1;
146 nameRefVector.begin(), nameRefVector.end(),
147 [sigNameBlob](
const SignalNameRef &a,
const SignalNameRef &b) {
148 return a.getStringView(sigNameBlob) < b.getStringView(sigNameBlob);
151 std::vector<std::string_view> currentScope;
152 for (
auto &name : nameRefVector) {
153 auto nameStr = name.getStringView(sigNameBlob);
154 std::vector<std::string_view> sigScope;
155 size_t charOffset = 0;
157 auto newOffset = std::string::npos;
158 while ((newOffset = nameStr.find(
'/', charOffset)) != std::string::npos) {
159 sigScope.push_back(nameStr.substr(charOffset, newOffset - charOffset));
160 charOffset = newOffset + 1;
163 unsigned commonScopes = 0;
164 for (
size_t i = 0; i < std::min(currentScope.size(), sigScope.size());
166 if (sigScope[i] == currentScope[i])
172 while (commonScopes < currentScope.size()) {
173 currentScope.pop_back();
174 vcdHdr.append(currentScope.size() + 1,
' ');
175 vcdHdr.append(
"$upscope $end\n");
178 while (sigScope.size() > currentScope.size()) {
179 vcdHdr.append(currentScope.size() + 1,
' ');
180 vcdHdr.append(
"$scope module ");
182 vcdHdr.append(
" $end\n");
183 currentScope.push_back(sigScope[currentScope.size()]);
186 vcdHdr.append(currentScope.size() + 1,
' ');
187 vcdHdr.append(
"$var wire ");
188 vcdHdr.append(std::to_string(
signalTable[name.signalIndex].numBits));
190 vcdHdr.append(
signalTable[name.signalIndex].id.cStr());
193 vcdHdr.append(
" $end\n");
201 std::vector<char> &buf) {
203 auto stepStr = std::to_string(currentStep);
204 std::copy(&stepStr.c_str()[0], &stepStr.c_str()[stepStr.size()],
205 std::back_inserter(buf));
211 const size_t fileBufferCapacity = 32 * 1024;
212 fileBuffer = std::unique_ptr<char[]>(
new char[fileBufferCapacity]);
216 std::cerr <<
"[ArcRuntime] WARNING: Unable to open VCD trace file "
217 <<
outFilePath <<
" for writing. No trace will be produced."
222 std::cout <<
"[ArcRuntime] Created VCD trace file: " <<
outFilePath
233 outFile <<
"$enddefinitions $end\n";
236 std::string outstring;
239 dumpSignalToString(sig, outstring, &state->
modelState[sig.stateOffset]);
258 const uint64_t *basePtr = work.
getData();
260 while (offset < work.
size) {
262 auto idx = basePtr[offset];
265 const void *voidPtr =
static_cast<const void *
>(basePtr + offset);
271 static_cast<const uint8_t *
>(voidPtr));
275 if (stepIter != work.
stepMarkers.end() && stepIter->offset == offset) {
assert(baseType &&"element must be base type")
Abstract TraceEncoder managing trace buffers and the encoder thread.
const ArcRuntimeModelInfo *const modelInfo
Metadata of the traced model.
void startUpWorker() override
Called by the worker thread before entering the encode loop.
std::ofstream outFile
Output file stream.
std::vector< char > workerOutBuffer
Concatenation buffer of the worker thread.
std::unique_ptr< char[]> fileBuffer
Internal buffer of the output stream.
void windDownWorker() override
Called by the worker thread after leaving the encode loop.
void createHierarchy()
Build and dump the signal hierarchy.
const std::filesystem::path outFilePath
Path to the output file.
void encode(TraceBuffer &work) override
Encode the given trace buffer. Called by the worker thread.
std::vector< VCDSignalTableEntry > signalTable
Table of signals: The index matches their Trace Tap ID.
bool initialize(const ArcState *state) override
Set-up the encoder before starting the worker thread.
int64_t workerStep
Current time step of the worker thread.
void initSignalTable()
Create the table of signals.
VCDTraceEncoder(const ArcRuntimeModelInfo *modelInfo, ArcState *state, const std::filesystem::path &outFilePath, bool debug)
void finalize(const ArcState *state) override
Finish trace encoding. Called by the simulation thread.
static void appendLegalizedName(std::string &buffer, const std::string_view &name)
static void writeTimestepToBuffer(int64_t currentStep, std::vector< char > &buf)
Static information for a compiled hardware model, generated by the MLIR lowering.
struct ArcModelTraceInfo * traceInfo
Signal tracing information. NULL iff the model is not trace instrumented.
uint64_t numStateBytes
Number of bytes required for the model's state.
const char * modelName
Name of the compiled model.
Combined runtime and model state for a hardware model instance.
A heap allocated buffer containing raw trace data and time step markers.
int64_t firstStep
Time step of the buffer's first entry.
std::vector< TraceBufferMarker > stepMarkers
Time step markers.
uint32_t size
Number of valid elements, set on dispatch.
uint64_t * getData() const
Get the pointer to the buffer's storage.
const char * cStr() const
Get the ID as null terminated string.
std::array< char, 16 > raw
unsigned getNumChars() const
Get the number of characters in the ID.
A traced signal in the VCD file.
VCDSignalId id
VCD signal ID.
unsigned getDumpSize() const
Get the number of characters required to dump this signal's ID and value.
uint32_t numBits
Bit width of the signal.