Verilator

Форк
0
/
verilated.cpp 
3440 строк · 136.5 Кб
1
// -*- mode: C++; c-file-style: "cc-mode" -*-
2
//*************************************************************************
3
//
4
// Code available from: https://verilator.org
5
//
6
// Copyright 2003-2024 by Wilson Snyder. This program is free software; you can
7
// redistribute it and/or modify it under the terms of either the GNU
8
// Lesser General Public License Version 3 or the Perl Artistic License
9
// Version 2.0.
10
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
11
//
12
//=========================================================================
13
///
14
/// \file
15
/// \brief Verilated general routine implementation code
16
///
17
/// This file must be compiled and linked against all Verilated objects
18
/// (all code created from Verilator).
19
///
20
/// Verilator always adds this file to the Makefile for the linker.
21
///
22
/// Those macro/function/variable starting or ending in _ are internal,
23
/// however many of the other function/macros here are also internal.
24
///
25
//=========================================================================
26
// Internal note:
27
//
28
// verilated.o may exist both in --lib-create (incrementally linked .a/.so)
29
// and the main module.  Both refer the same instance of static
30
// variables/thread_local in verilated.o such as Verilated, or
31
// VerilatedImpData.  This is important to share that state, but the
32
// sharing may cause a double-free error when shutting down because the
33
// loader will insert a constructor/destructor at each reference to
34
// verilated.o, resulting in at runtime constructors/destructors being
35
// called multiple times.
36
//
37
// To avoid the trouble:
38
//   * Statics declared inside functions. The compiler will wrap
39
//     the construction in must-be-one-time checks.
40
//   * Or, use only C++20 constinit types. (TODO: Make a VL_CONSTINIT).
41
//   * Or, use types that are multi-constructor safe.
42
//   * Or, the static should be of a union, which will avoid compiler
43
//     construction, and appropriately check for duplicate construction.
44
//   * Or, code is not linked in protected library. e.g. the VPI
45
//     and DPI libraries are not needed there.
46
//=========================================================================
47

48
#define VERILATOR_VERILATED_CPP_
49

50
#include "verilated_config.h"
51
#include "verilatedos.h"
52

53
#include "verilated_imp.h"
54

55
#include <algorithm>
56
#include <cctype>
57
#include <cerrno>
58
#include <cstdlib>
59
#include <limits>
60
#include <list>
61
#include <sstream>
62
#include <utility>
63

64
#include <sys/stat.h>  // mkdir
65

66
// clang-format off
67
#if defined(_WIN32) || defined(__MINGW32__)
68
# include <direct.h>  // mkdir
69
#endif
70
#ifdef __GLIBC__
71
# include <execinfo.h>
72
# define _VL_HAVE_STACKTRACE
73
#endif
74
#if defined(__linux) || (defined(__APPLE__) && defined(__MACH__))
75
# include <sys/time.h>
76
# include <sys/resource.h>
77
# define _VL_HAVE_GETRLIMIT
78
#endif
79

80
#include "verilated_threads.h"
81
// clang-format on
82

83
#include "verilated_trace.h"
84

85
#ifdef VM_SOLVER_DEFAULT
86
#define VL_SOLVER_DEFAULT VM_SOLVER_DEFAULT
87
#else
88
#define VL_SOLVER_DEFAULT "z3 --in"
89
#endif
90

91
// Max characters in static char string for VL_VALUE_STRING
92
constexpr unsigned VL_VALUE_STRING_MAX_WIDTH = 8192;
93

94
//===========================================================================
95
// Static sanity checks
96

97
static_assert(sizeof(uint8_t) == 1, "uint8_t is missized");
98
static_assert(sizeof(uint16_t) == 2, "uint8_t is missized");
99
static_assert(sizeof(uint32_t) == 4, "uint8_t is missized");
100
static_assert(sizeof(uint64_t) == 8, "uint8_t is missized");
101

102
//===========================================================================
103
// Global variables
104
// Internal note: Globals may multi-construct, see verilated.cpp top.
105

106
// Fast path, keep together
107
int Verilated::s_debug = 0;
108
VerilatedContext* Verilated::s_lastContextp = nullptr;
109

110
// Keep below together in one cache line
111
// Internal note: Globals may multi-construct, see verilated.cpp top.
112
thread_local Verilated::ThreadLocal Verilated::t_s;
113

114
//===========================================================================
115
// User definable functions
116
// Note a TODO is a future version of the API will pass a structure so that
117
// the calling arguments allow for extension
118

119
#ifndef VL_USER_FINISH  ///< Define this to override the vl_finish function
120
void vl_finish(const char* filename, int linenum, const char* hier) VL_MT_UNSAFE {
121
    // hier is unused in the default implementation.
122
    (void)hier;
123
    VL_PRINTF(  // Not VL_PRINTF_MT, already on main thread
124
        "- %s:%d: Verilog $finish\n", filename, linenum);
125
    Verilated::threadContextp()->gotFinish(true);
126
}
127
#endif
128

129
#ifndef VL_USER_STOP  ///< Define this to override the vl_stop function
130
void vl_stop(const char* filename, int linenum, const char* hier) VL_MT_UNSAFE {
131
    const char* const msg = "Verilog $stop";
132
    Verilated::threadContextp()->gotError(true);
133
    Verilated::threadContextp()->gotFinish(true);
134
    if (Verilated::threadContextp()->fatalOnError()) {
135
        vl_fatal(filename, linenum, hier, msg);
136
    } else {
137
        if (filename && filename[0]) {
138
            // Not VL_PRINTF_MT, already on main thread
139
            VL_PRINTF("%%Error: %s:%d: %s\n", filename, linenum, msg);
140
        } else {
141
            VL_PRINTF("%%Error: %s\n", msg);
142
        }
143
        Verilated::runFlushCallbacks();
144
    }
145
}
146
#endif
147

148
#ifndef VL_USER_FATAL  ///< Define this to override the vl_fatal function
149
void vl_fatal(const char* filename, int linenum, const char* hier, const char* msg) VL_MT_UNSAFE {
150
    // hier is unused in the default implementation.
151
    (void)hier;
152
    Verilated::threadContextp()->gotError(true);
153
    Verilated::threadContextp()->gotFinish(true);
154
    if (filename && filename[0]) {
155
        // Not VL_PRINTF_MT, already on main thread
156
        VL_PRINTF("%%Error: %s:%d: %s\n", filename, linenum, msg);
157
    } else {
158
        VL_PRINTF("%%Error: %s\n", msg);
159
    }
160
    Verilated::runFlushCallbacks();
161

162
    VL_PRINTF("Aborting...\n");  // Not VL_PRINTF_MT, already on main thread
163

164
    // Second flush in case VL_PRINTF does something needing a flush
165
    Verilated::runFlushCallbacks();
166

167
    // Callbacks prior to termination
168
    Verilated::runExitCallbacks();
169
    std::abort();
170
}
171
#endif
172

173
#ifndef VL_USER_STOP_MAYBE  ///< Define this to override the vl_stop_maybe function
174
void vl_stop_maybe(const char* filename, int linenum, const char* hier, bool maybe) VL_MT_UNSAFE {
175
    Verilated::threadContextp()->errorCountInc();
176
    if (maybe
177
        && Verilated::threadContextp()->errorCount() < Verilated::threadContextp()->errorLimit()) {
178
        // Do just once when cross error limit
179
        if (Verilated::threadContextp()->errorCount() == 1) {
180
            VL_PRINTF(  // Not VL_PRINTF_MT, already on main thread
181
                "-Info: %s:%d: %s\n", filename, linenum,
182
                "Verilog $stop, ignored due to +verilator+error+limit");
183
        }
184
    } else {
185
        vl_stop(filename, linenum, hier);
186
    }
187
}
188
#endif
189

190
#ifndef VL_USER_WARN  ///< Define this to override the vl_warn function
191
void vl_warn(const char* filename, int linenum, const char* hier, const char* msg) VL_MT_UNSAFE {
192
    // hier is unused in the default implementation.
193
    (void)hier;
194
    if (filename && filename[0]) {
195
        // Not VL_PRINTF_MT, already on main thread
196
        VL_PRINTF("%%Warning: %s:%d: %s\n", filename, linenum, msg);
197
    } else {
198
        VL_PRINTF("%%Warning: %s\n", msg);
199
    }
200
    Verilated::runFlushCallbacks();
201
}
202
#endif
203

204
//===========================================================================
205
// Wrapper to call certain functions via messages when multithreaded
206

207
void VL_FINISH_MT(const char* filename, int linenum, const char* hier) VL_MT_SAFE {
208
    VerilatedThreadMsgQueue::post(VerilatedMsg{[=]() {  //
209
        vl_finish(filename, linenum, hier);
210
    }});
211
}
212

213
void VL_STOP_MT(const char* filename, int linenum, const char* hier, bool maybe) VL_MT_SAFE {
214
    VerilatedThreadMsgQueue::post(VerilatedMsg{[=]() {  //
215
        vl_stop_maybe(filename, linenum, hier, maybe);
216
    }});
217
}
218

219
void VL_FATAL_MT(const char* filename, int linenum, const char* hier, const char* msg) VL_MT_SAFE {
220
    VerilatedThreadMsgQueue::post(VerilatedMsg{[=]() {  //
221
        vl_fatal(filename, linenum, hier, msg);
222
    }});
223
}
224

225
void VL_WARN_MT(const char* filename, int linenum, const char* hier, const char* msg) VL_MT_SAFE {
226
    VerilatedThreadMsgQueue::post(VerilatedMsg{[=]() {  //
227
        vl_warn(filename, linenum, hier, msg);
228
    }});
229
}
230

231
//===========================================================================
232
// Debug prints
233

234
// sprintf but return as string (this isn't fast, for print messages only)
235
std::string _vl_string_vprintf(const char* formatp, va_list ap) VL_MT_SAFE {
236
    va_list aq;
237
    va_copy(aq, ap);
238
    const size_t len = VL_VSNPRINTF(nullptr, 0, formatp, aq);
239
    va_end(aq);
240
    if (VL_UNLIKELY(len < 1)) return "";
241

242
    char* const bufp = new char[len + 1];
243
    VL_VSNPRINTF(bufp, len + 1, formatp, ap);
244

245
    std::string result{bufp, len};  // Not const to allow move optimization
246
    delete[] bufp;
247
    return result;
248
}
249

250
uint64_t _vl_dbg_sequence_number() VL_MT_SAFE {
251
    static std::atomic<uint64_t> sequence;
252
    return ++sequence;
253
}
254

255
uint32_t VL_THREAD_ID() VL_MT_SAFE {
256
    // Alternative is to use std::this_thread::get_id, but that returns a
257
    // hard-to-read number and is very slow
258
    static std::atomic<uint32_t> s_nextId(0);
259
    static thread_local uint32_t t_myId = ++s_nextId;
260
    return t_myId;
261
}
262

263
void VL_DBG_MSGF(const char* formatp, ...) VL_MT_SAFE {
264
    // We're still using c printf formats instead of operator<< so we can avoid the heavy
265
    // includes that otherwise would be required in every Verilated module
266
    va_list ap;
267
    va_start(ap, formatp);
268
    const std::string result = _vl_string_vprintf(formatp, ap);
269
    va_end(ap);
270
    // printf("-imm-V{t%d,%" PRId64 "}%s", VL_THREAD_ID(), _vl_dbg_sequence_number(),
271
    // result.c_str());
272

273
    // Using VL_PRINTF not VL_PRINTF_MT so that we can call VL_DBG_MSGF
274
    // from within the guts of the thread execution machinery (and it goes
275
    // to the screen and not into the queues we're debugging)
276
    VL_PRINTF("-V{t%u,%" PRIu64 "}%s", VL_THREAD_ID(), _vl_dbg_sequence_number(), result.c_str());
277
}
278

279
void VL_PRINTF_MT(const char* formatp, ...) VL_MT_SAFE {
280
    va_list ap;
281
    va_start(ap, formatp);
282
    const std::string result = _vl_string_vprintf(formatp, ap);
283
    va_end(ap);
284
    VerilatedThreadMsgQueue::post(VerilatedMsg{[=]() {  //
285
        VL_PRINTF("%s", result.c_str());
286
    }});
287
}
288

289
//===========================================================================
290
// Random -- Mostly called at init time, so not inline.
291

292
VlRNG::VlRNG() VL_MT_SAFE {
293
    // Starting point for this new class comes from the global RNG
294
    VlRNG& fromr = vl_thread_rng();
295
    m_state = fromr.m_state;
296
    // Advance the *source* so it can later generate a new number
297
    // Xoroshiro128+ algorithm
298
    fromr.m_state[1] ^= fromr.m_state[0];
299
    fromr.m_state[0] = (((fromr.m_state[0] << 55) | (fromr.m_state[0] >> 9)) ^ fromr.m_state[1]
300
                        ^ (fromr.m_state[1] << 14));
301
    fromr.m_state[1] = (fromr.m_state[1] << 36) | (fromr.m_state[1] >> 28);
302
}
303
uint64_t VlRNG::rand64() VL_MT_UNSAFE {
304
    // Xoroshiro128+ algorithm
305
    const uint64_t result = m_state[0] + m_state[1];
306
    m_state[1] ^= m_state[0];
307
    m_state[0] = (((m_state[0] << 55) | (m_state[0] >> 9)) ^ m_state[1] ^ (m_state[1] << 14));
308
    m_state[1] = (m_state[1] << 36) | (m_state[1] >> 28);
309
    return result;
310
}
311
uint64_t VlRNG::vl_thread_rng_rand64() VL_MT_SAFE {
312
    VlRNG& fromr = vl_thread_rng();
313
    const uint64_t result = fromr.m_state[0] + fromr.m_state[1];
314
    fromr.m_state[1] ^= fromr.m_state[0];
315
    fromr.m_state[0] = (((fromr.m_state[0] << 55) | (fromr.m_state[0] >> 9)) ^ fromr.m_state[1]
316
                        ^ (fromr.m_state[1] << 14));
317
    fromr.m_state[1] = (fromr.m_state[1] << 36) | (fromr.m_state[1] >> 28);
318
    return result;
319
}
320
void VlRNG::srandom(uint64_t n) VL_MT_UNSAFE {
321
    m_state[0] = n;
322
    m_state[1] = m_state[0];
323
    // Fix state as algorithm is slow to randomize if many zeros
324
    // This causes a loss of ~ 1 bit of seed entropy, no big deal
325
    if (VL_COUNTONES_I(m_state[0]) < 10) m_state[0] = ~m_state[0];
326
    if (VL_COUNTONES_I(m_state[1]) < 10) m_state[1] = ~m_state[1];
327
}
328
std::string VlRNG::get_randstate() const VL_MT_UNSAFE {
329
    // Though not stated in IEEE, assumption is the string must be printable
330
    const char* const stateCharsp = reinterpret_cast<const char*>(&m_state);
331
    static_assert(sizeof(m_state) == 16, "");
332
    std::string result{"R00112233445566770011223344556677"};
333
    for (size_t i = 0; i < sizeof(m_state); ++i) {
334
        result[1 + i * 2] = 'a' + ((stateCharsp[i] >> 4) & 15);
335
        result[1 + i * 2 + 1] = 'a' + (stateCharsp[i] & 15);
336
    }
337
    return result;
338
}
339
void VlRNG::set_randstate(const std::string& state) VL_MT_UNSAFE {
340
    if (VL_UNLIKELY((state.length() != 1 + 2 * sizeof(m_state)) || (state[0] != 'R'))) {
341
        VL_PRINTF_MT("%%Warning: set_randstate ignored as state string not from get_randstate\n");
342
        return;
343
    }
344
    char* const stateCharsp = reinterpret_cast<char*>(&m_state);
345
    for (size_t i = 0; i < sizeof(m_state); ++i) {
346
        stateCharsp[i]
347
            = (((state[1 + i * 2] - 'a') & 15) << 4) | ((state[1 + i * 2 + 1] - 'a') & 15);
348
    }
349
}
350

351
static uint32_t vl_sys_rand32() VL_MT_SAFE {
352
    // Return random 32-bits using system library.
353
    // Used only to construct seed for Verilator's PRNG.
354
    static VerilatedMutex s_mutex;
355
    const VerilatedLockGuard lock{s_mutex};  // Otherwise rand is unsafe
356
#if defined(_WIN32) && !defined(__CYGWIN__)
357
    // Windows doesn't have lrand48(), although Cygwin does.
358
    return (std::rand() << 16) ^ std::rand();
359
#else
360
    return (lrand48() << 16) ^ lrand48();
361
#endif
362
}
363

364
VlRNG& VlRNG::vl_thread_rng() VL_MT_SAFE {
365
    static thread_local VlRNG t_rng{0};
366
    static thread_local uint32_t t_seedEpoch = 0;
367
    // For speed, we use a thread-local epoch number to know when to reseed
368
    // A thread always belongs to a single context, so this works out ok
369
    if (VL_UNLIKELY(t_seedEpoch != VerilatedContextImp::randSeedEpoch())) {
370
        // Set epoch before state, to avoid race case with new seeding
371
        t_seedEpoch = VerilatedContextImp::randSeedEpoch();
372
        // Same as srandom() but here as needs to be VL_MT_SAFE
373
        t_rng.m_state[0] = Verilated::threadContextp()->impp()->randSeedDefault64();
374
        t_rng.m_state[1] = t_rng.m_state[0];
375
        // Fix state as algorithm is slow to randomize if many zeros
376
        // This causes a loss of ~ 1 bit of seed entropy, no big deal
377
        if (VL_COUNTONES_I(t_rng.m_state[0]) < 10) t_rng.m_state[0] = ~t_rng.m_state[0];
378
        if (VL_COUNTONES_I(t_rng.m_state[1]) < 10) t_rng.m_state[1] = ~t_rng.m_state[1];
379
    }
380
    return t_rng;
381
}
382

383
WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp) VL_MT_SAFE {
384
    for (int i = 0; i < VL_WORDS_I(obits); ++i) outwp[i] = vl_rand64();
385
    // Last word is unclean
386
    return outwp;
387
}
388

389
WDataOutP VL_RANDOM_RNG_W(VlRNG& rngr, int obits, WDataOutP outwp) VL_MT_UNSAFE {
390
    for (int i = 0; i < VL_WORDS_I(obits); ++i) outwp[i] = rngr.rand64();
391
    // Last word is unclean
392
    return outwp;
393
}
394

395
IData VL_RANDOM_SEEDED_II(IData& seedr) VL_MT_SAFE {
396
    // $random - seed is a new seed to apply, then we return new seed
397
    Verilated::threadContextp()->randSeed(static_cast<int>(seedr));
398
    seedr = VL_RANDOM_I();
399
    return VL_RANDOM_I();
400
}
401
IData VL_URANDOM_SEEDED_II(IData seed) VL_MT_SAFE {
402
    // $urandom - seed is a new seed to apply
403
    Verilated::threadContextp()->randSeed(static_cast<int>(seed));
404
    return VL_RANDOM_I();
405
}
406
IData VL_RAND_RESET_I(int obits) VL_MT_SAFE {
407
    if (Verilated::threadContextp()->randReset() == 0) return 0;
408
    IData data = ~0;
409
    if (Verilated::threadContextp()->randReset() != 1) {  // if 2, randomize
410
        data = VL_RANDOM_I();
411
    }
412
    data &= VL_MASK_I(obits);
413
    return data;
414
}
415
QData VL_RAND_RESET_Q(int obits) VL_MT_SAFE {
416
    if (Verilated::threadContextp()->randReset() == 0) return 0;
417
    QData data = ~0ULL;
418
    if (Verilated::threadContextp()->randReset() != 1) {  // if 2, randomize
419
        data = VL_RANDOM_Q();
420
    }
421
    data &= VL_MASK_Q(obits);
422
    return data;
423
}
424
WDataOutP VL_RAND_RESET_W(int obits, WDataOutP outwp) VL_MT_SAFE {
425
    for (int i = 0; i < VL_WORDS_I(obits) - 1; ++i) outwp[i] = VL_RAND_RESET_I(32);
426
    outwp[VL_WORDS_I(obits) - 1] = VL_RAND_RESET_I(32) & VL_MASK_E(obits);
427
    return outwp;
428
}
429
WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp) VL_MT_SAFE {
430
    // Not inlined to speed up compilation of slowpath code
431
    return VL_ZERO_W(obits, outwp);
432
}
433

434
//===========================================================================
435
// Debug
436

437
void _vl_debug_print_w(int lbits, const WDataInP iwp) VL_MT_SAFE {
438
    VL_PRINTF_MT("  Data: w%d: ", lbits);
439
    for (int i = VL_WORDS_I(lbits) - 1; i >= 0; --i) VL_PRINTF_MT("%08x ", iwp[i]);
440
    VL_PRINTF_MT("\n");
441
}
442

443
//===========================================================================
444
// Slow expressions
445

446
WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, const WDataInP lwp, const WDataInP rwp,
447
                       bool is_modulus) VL_MT_SAFE {
448
    // See Knuth Algorithm D.  Computes u/v = q.r
449
    // This isn't massively tuned, as wide division is rare
450
    // for debug see V3Number version
451
    // Requires clean input
452
    const int words = VL_WORDS_I(lbits);
453
    for (int i = 0; i < words; ++i) owp[i] = 0;
454
    // Find MSB and check for zero.
455
    const int umsbp1 = VL_MOSTSETBITP1_W(words, lwp);  // dividend
456
    const int vmsbp1 = VL_MOSTSETBITP1_W(words, rwp);  // divisor
457
    if (VL_UNLIKELY(vmsbp1 == 0)  // rwp==0 so division by zero.  Return 0.
458
        || VL_UNLIKELY(umsbp1 == 0)) {  // 0/x so short circuit and return 0
459
        return owp;
460
    }
461

462
    const int uw = VL_WORDS_I(umsbp1);  // aka "m" in the algorithm
463
    const int vw = VL_WORDS_I(vmsbp1);  // aka "n" in the algorithm
464
    VL_DEBUG_IFDEF(assert(uw <= VL_MULS_MAX_WORDS););
465
    VL_DEBUG_IFDEF(assert(vw <= VL_MULS_MAX_WORDS););
466

467
    if (vw == 1) {  // Single divisor word breaks rest of algorithm
468
        uint64_t k = 0;
469
        for (int j = uw - 1; j >= 0; --j) {
470
            const uint64_t unw64 = ((k << 32ULL) + static_cast<uint64_t>(lwp[j]));
471
            owp[j] = unw64 / static_cast<uint64_t>(rwp[0]);
472
            k = unw64 - static_cast<uint64_t>(owp[j]) * static_cast<uint64_t>(rwp[0]);
473
        }
474
        if (is_modulus) {
475
            owp[0] = k;
476
            for (int i = 1; i < words; ++i) owp[i] = 0;
477
        }
478
        return owp;
479
    }
480

481
    // +1 word as we may shift during normalization
482
    uint32_t un[VL_MULS_MAX_WORDS + 1];  // Fixed size, as MSVC++ doesn't allow [words] here
483
    uint32_t vn[VL_MULS_MAX_WORDS + 1];  // v normalized
484

485
    // Zero for ease of debugging and to save having to zero for shifts
486
    // Note +1 as loop will use extra word
487
    for (int i = 0; i < words + 1; ++i) un[i] = vn[i] = 0;
488

489
    // Algorithm requires divisor MSB to be set
490
    // Copy and shift to normalize divisor so MSB of vn[vw-1] is set
491
    const int s = 31 - VL_BITBIT_I(vmsbp1 - 1);  // shift amount (0...31)
492
    // Copy and shift dividend by same amount; may set new upper word
493
    if (s) {
494
        for (int i = vw - 1; i > 0; --i) vn[i] = (rwp[i] << s) | (rwp[i - 1] >> (32 - s));
495
        vn[0] = rwp[0] << s;
496
        un[uw] = lwp[uw - 1] >> (32 - s);
497
        for (int i = uw - 1; i > 0; --i) un[i] = (lwp[i] << s) | (lwp[i - 1] >> (32 - s));
498
        un[0] = lwp[0] << s;
499
    } else {
500
        for (int i = vw - 1; i > 0; --i) vn[i] = rwp[i];
501
        vn[0] = rwp[0];
502
        un[uw] = 0;
503
        for (int i = uw - 1; i > 0; --i) un[i] = lwp[i];
504
        un[0] = lwp[0];
505
    }
506

507
    // Main loop
508
    for (int j = uw - vw; j >= 0; --j) {
509
        // Estimate
510
        const uint64_t unw64
511
            = (static_cast<uint64_t>(un[j + vw]) << 32ULL | static_cast<uint64_t>(un[j + vw - 1]));
512
        uint64_t qhat = unw64 / static_cast<uint64_t>(vn[vw - 1]);
513
        uint64_t rhat = unw64 - qhat * static_cast<uint64_t>(vn[vw - 1]);
514

515
    again:
516
        if (qhat >= 0x100000000ULL || ((qhat * vn[vw - 2]) > ((rhat << 32ULL) + un[j + vw - 2]))) {
517
            qhat = qhat - 1;
518
            rhat = rhat + vn[vw - 1];
519
            if (rhat < 0x100000000ULL) goto again;
520
        }
521

522
        int64_t t = 0;  // Must be signed
523
        uint64_t k = 0;
524
        for (int i = 0; i < vw; ++i) {
525
            const uint64_t p = qhat * vn[i];  // Multiply by estimate
526
            t = un[i + j] - k - (p & 0xFFFFFFFFULL);  // Subtract
527
            un[i + j] = t;
528
            k = (p >> 32ULL) - (t >> 32ULL);
529
        }
530
        t = un[j + vw] - k;
531
        un[j + vw] = t;
532
        owp[j] = qhat;  // Save quotient digit
533

534
        if (t < 0) {
535
            // Over subtracted; correct by adding back
536
            owp[j]--;
537
            k = 0;
538
            for (int i = 0; i < vw; ++i) {
539
                t = static_cast<uint64_t>(un[i + j]) + static_cast<uint64_t>(vn[i]) + k;
540
                un[i + j] = t;
541
                k = t >> 32ULL;
542
            }
543
            un[j + vw] = un[j + vw] + k;
544
        }
545
    }
546

547
    if (is_modulus) {  // modulus
548
        // Need to reverse normalization on copy to output
549
        if (s) {
550
            for (int i = 0; i < vw; ++i) owp[i] = (un[i] >> s) | (un[i + 1] << (32 - s));
551
        } else {
552
            for (int i = 0; i < vw; ++i) owp[i] = un[i];
553
        }
554
        for (int i = vw; i < words; ++i) owp[i] = 0;
555
        return owp;
556
    } else {  // division
557
        return owp;
558
    }
559
}
560

561
WDataOutP VL_POW_WWW(int obits, int, int rbits, WDataOutP owp, const WDataInP lwp,
562
                     const WDataInP rwp) VL_MT_SAFE {
563
    // obits==lbits, rbits can be different
564
    const int owords = VL_WORDS_I(obits);
565
    VL_DEBUG_IFDEF(assert(owords <= VL_MULS_MAX_WORDS););
566
    owp[0] = 1;
567
    for (int i = 1; i < VL_WORDS_I(obits); i++) owp[i] = 0;
568
    // cppcheck-has-bug-suppress variableScope
569
    VlWide<VL_MULS_MAX_WORDS> powstore;  // Fixed size, as MSVC++ doesn't allow [words] here
570
    VlWide<VL_MULS_MAX_WORDS> lastpowstore;  // Fixed size, as MSVC++ doesn't allow [words] here
571
    VlWide<VL_MULS_MAX_WORDS> lastoutstore;  // Fixed size, as MSVC++ doesn't allow [words] here
572
    // cppcheck-has-bug-suppress variableScope
573
    VL_ASSIGN_W(obits, powstore, lwp);
574
    for (int bit = 0; bit < rbits; bit++) {
575
        if (bit > 0) {  // power = power*power
576
            VL_ASSIGN_W(obits, lastpowstore, powstore);
577
            VL_MUL_W(owords, powstore, lastpowstore, lastpowstore);
578
        }
579
        if (VL_BITISSET_W(rwp, bit)) {  // out *= power
580
            VL_ASSIGN_W(obits, lastoutstore, owp);
581
            VL_MUL_W(owords, owp, lastoutstore, powstore);
582
        }
583
    }
584
    return owp;
585
}
586
WDataOutP VL_POW_WWQ(int obits, int lbits, int rbits, WDataOutP owp, const WDataInP lwp,
587
                     QData rhs) VL_MT_SAFE {
588
    VlWide<VL_WQ_WORDS_E> rhsw;
589
    VL_SET_WQ(rhsw, rhs);
590
    return VL_POW_WWW(obits, lbits, rbits, owp, lwp, rhsw);
591
}
592
QData VL_POW_QQW(int, int, int rbits, QData lhs, const WDataInP rwp) VL_MT_SAFE {
593
    const int rwords = VL_WORDS_I(rbits);
594
    EData rnz = rwp[0];
595
    for (int w = 1; w < rwords; ++w) rnz |= rwp[w];
596
    if (!rnz) return 1;  // rwp == 0
597
    if (VL_UNLIKELY(lhs == 0)) return 0;
598
    QData power = lhs;
599
    QData result = 1ULL;
600
    for (int bit = 0; bit < rbits; ++bit) {
601
        if (bit > 0) power = power * power;
602
        if (VL_BITISSET_W(rwp, bit)) result *= power;
603
    }
604
    return result;
605
}
606

607
WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, const WDataInP lwp,
608
                       const WDataInP rwp, bool lsign, bool rsign) VL_MT_SAFE {
609
    // obits==lbits, rbits can be different
610
    if (rsign && VL_SIGN_W(rbits, rwp)) {
611
        const int words = VL_WORDS_I(obits);
612
        VL_ZERO_W(obits, owp);
613
        EData lor = 0;  // 0=all zeros, ~0=all ones, else mix
614
        for (int i = 1; i < (words - 1); ++i) lor |= lwp[i];
615
        lor |= ((lwp[words - 1] == VL_MASK_E(rbits)) ? ~VL_EUL(0) : 0);
616
        if (lor == 0 && lwp[0] == 0) {  // "X" so return 0
617
            return owp;
618
        } else if (lor == 0 && lwp[0] == 1) {  // 1
619
            owp[0] = 1;
620
            return owp;
621
        } else if (lsign && lor == ~VL_EUL(0) && lwp[0] == ~VL_EUL(0)) {  // -1
622
            if (rwp[0] & 1) {  // -1^odd=-1
623
                return VL_ALLONES_W(obits, owp);
624
            } else {  // -1^even=1
625
                owp[0] = 1;
626
                return owp;
627
            }
628
        }
629
        return owp;
630
    }
631
    return VL_POW_WWW(obits, rbits, rbits, owp, lwp, rwp);
632
}
633
WDataOutP VL_POWSS_WWQ(int obits, int lbits, int rbits, WDataOutP owp, const WDataInP lwp,
634
                       QData rhs, bool lsign, bool rsign) VL_MT_SAFE {
635
    VlWide<VL_WQ_WORDS_E> rhsw;
636
    VL_SET_WQ(rhsw, rhs);
637
    return VL_POWSS_WWW(obits, lbits, rbits, owp, lwp, rhsw, lsign, rsign);
638
}
639
QData VL_POWSS_QQW(int obits, int, int rbits, QData lhs, const WDataInP rwp, bool lsign,
640
                   bool rsign) VL_MT_SAFE {
641
    // Skip check for rhs == 0, as short-circuit doesn't save time
642
    if (rsign && VL_SIGN_W(rbits, rwp)) {
643
        if (lhs == 0) {
644
            return 0;  // "X"
645
        } else if (lhs == 1) {
646
            return 1;
647
        } else if (lsign && lhs == VL_MASK_Q(obits)) {  // -1
648
            if (rwp[0] & 1) {
649
                return VL_MASK_Q(obits);  // -1^odd=-1
650
            } else {
651
                return 1;  // -1^even=1
652
            }
653
        }
654
        return 0;
655
    }
656
    return VL_POW_QQW(obits, rbits, rbits, lhs, rwp);
657
}
658

659
double VL_ITOR_D_W(int lbits, const WDataInP lwp) VL_PURE {
660
    int ms_word = VL_WORDS_I(lbits) - 1;
661
    for (; !lwp[ms_word] && ms_word > 0;) --ms_word;
662
    if (ms_word == 0) return static_cast<double>(lwp[0]);
663
    if (ms_word == 1) return static_cast<double>(VL_SET_QW(lwp));
664
    // We need 53 bits of mantissa, which might mean looking at 3 words
665
    // namely ms_word, ms_word-1 and ms_word-2
666
    const EData ihi = lwp[ms_word];
667
    const EData imid = lwp[ms_word - 1];
668
    const EData ilo = lwp[ms_word - 2];
669
    const double hi = static_cast<double>(ihi) * std::exp2(2 * VL_EDATASIZE);
670
    const double mid = static_cast<double>(imid) * std::exp2(VL_EDATASIZE);
671
    const double lo = static_cast<double>(ilo);
672
    const double d = (hi + mid + lo) * std::exp2(VL_EDATASIZE * (ms_word - 2));
673
    return d;
674
}
675
double VL_ISTOR_D_W(int lbits, const WDataInP lwp) VL_MT_SAFE {
676
    if (!VL_SIGN_W(lbits, lwp)) return VL_ITOR_D_W(lbits, lwp);
677
    const int words = VL_WORDS_I(lbits);
678
    VL_DEBUG_IFDEF(assert(words <= VL_MULS_MAX_WORDS););
679
    uint32_t pos[VL_MULS_MAX_WORDS + 1];  // Fixed size, as MSVC++ doesn't allow [words] here
680
    VL_NEGATE_W(words, pos, lwp);
681
    _vl_clean_inplace_w(lbits, pos);
682
    return -VL_ITOR_D_W(lbits, pos);
683
}
684

685
//===========================================================================
686
// Formatting
687

688
// Output a string representation of a wide number
689
std::string VL_DECIMAL_NW(int width, const WDataInP lwp) VL_MT_SAFE {
690
    const int maxdecwidth = (width + 3) * 4 / 3;
691
    // Or (maxdecwidth+7)/8], but can't have more than 4 BCD bits per word
692
    VlWide<VL_VALUE_STRING_MAX_WIDTH / 4 + 2> bcd;
693
    VL_ZERO_W(maxdecwidth, bcd);
694
    VlWide<VL_VALUE_STRING_MAX_WIDTH / 4 + 2> tmp;
695
    VlWide<VL_VALUE_STRING_MAX_WIDTH / 4 + 2> tmp2;
696
    int from_bit = width - 1;
697
    // Skip all leading zeros
698
    for (; from_bit >= 0 && !(VL_BITRSHIFT_W(lwp, from_bit) & 1); --from_bit) {}
699
    // Double-dabble algorithm
700
    for (; from_bit >= 0; --from_bit) {
701
        // Any digits >= 5 need an add 3 (via tmp)
702
        for (int nibble_bit = 0; nibble_bit < maxdecwidth; nibble_bit += 4) {
703
            if ((VL_BITRSHIFT_W(bcd, nibble_bit) & 0xf) >= 5) {
704
                VL_ZERO_W(maxdecwidth, tmp2);
705
                tmp2[VL_BITWORD_E(nibble_bit)] |= VL_EUL(0x3) << VL_BITBIT_E(nibble_bit);
706
                VL_ASSIGN_W(maxdecwidth, tmp, bcd);
707
                VL_ADD_W(VL_WORDS_I(maxdecwidth), bcd, tmp, tmp2);
708
            }
709
        }
710
        // Shift; bcd = bcd << 1
711
        VL_ASSIGN_W(maxdecwidth, tmp, bcd);
712
        VL_SHIFTL_WWI(maxdecwidth, maxdecwidth, 32, bcd, tmp, 1);
713
        // bcd[0] = lwp[from_bit]
714
        if (VL_BITISSET_W(lwp, from_bit)) bcd[0] |= 1;
715
    }
716
    std::string output;
717
    int lsb = (maxdecwidth - 1) & ~3;
718
    for (; lsb > 0; lsb -= 4) {  // Skip leading zeros
719
        if (VL_BITRSHIFT_W(bcd, lsb) & 0xf) break;
720
    }
721
    for (; lsb >= 0; lsb -= 4) {
722
        output += ('0' + (VL_BITRSHIFT_W(bcd, lsb) & 0xf));  // 0..9
723
    }
724
    return output;
725
}
726

727
template <typename T>
728
std::string _vl_vsformat_time(char* tmp, T ld, int timeunit, bool left, size_t width) VL_MT_SAFE {
729
    const VerilatedContextImp* const ctxImpp = Verilated::threadContextp()->impp();
730
    const std::string suffix = ctxImpp->timeFormatSuffix();
731
    const int userUnits = ctxImpp->timeFormatUnits();  // 0..-15
732
    const int fracDigits = ctxImpp->timeFormatPrecision();  // 0..N
733
    const int shift = -userUnits + fracDigits + timeunit;  // 0..-15
734
    int digits = 0;
735
    if (std::numeric_limits<T>::is_integer) {
736
        constexpr int b = 128;
737
        constexpr int w = VL_WORDS_I(b);
738
        VlWide<w> tmp0;
739
        VlWide<w> tmp1;
740
        VlWide<w> tmp2;
741
        VlWide<w> tmp3;
742

743
        WDataInP shifted = VL_EXTEND_WQ(b, 0, tmp0, static_cast<QData>(ld));
744
        if (shift < 0) {
745
            const WDataInP pow10 = VL_EXTEND_WQ(b, 0, tmp1, vl_time_pow10(-shift));
746
            shifted = VL_DIV_WWW(b, tmp2, shifted, pow10);
747
        } else {
748
            const WDataInP pow10 = VL_EXTEND_WQ(b, 0, tmp1, vl_time_pow10(shift));
749
            shifted = VL_MUL_W(w, tmp2, shifted, pow10);
750
        }
751

752
        const WDataInP fracDigitsPow10 = VL_EXTEND_WQ(b, 0, tmp3, vl_time_pow10(fracDigits));
753
        const WDataInP integer = VL_DIV_WWW(b, tmp0, shifted, fracDigitsPow10);
754
        const WDataInP frac = VL_MODDIV_WWW(b, tmp1, shifted, fracDigitsPow10);
755
        const WDataInP max64Bit
756
            = VL_EXTEND_WQ(b, 0, tmp2, std::numeric_limits<uint64_t>::max());  // breaks shifted
757
        if (VL_GT_W(w, integer, max64Bit)) {
758
            WDataOutP v = VL_ASSIGN_W(b, tmp3, integer);  // breaks fracDigitsPow10
759
            VlWide<w> zero;
760
            VlWide<w> ten;
761
            VL_ZERO_W(b, zero);
762
            VL_EXTEND_WI(b, 0, ten, 10);
763
            char buf[128];  // 128B is obviously long enough to represent 128bit integer in decimal
764
            char* ptr = buf + sizeof(buf) - 1;
765
            *ptr = '\0';
766
            while (VL_GT_W(w, v, zero)) {
767
                --ptr;
768
                const WDataInP mod = VL_MODDIV_WWW(b, tmp2, v, ten);  // breaks max64Bit
769
                *ptr = "0123456789"[VL_SET_QW(mod)];
770
                VlWide<w> divided;
771
                VL_DIV_WWW(b, divided, v, ten);
772
                VL_ASSIGN_W(b, v, divided);
773
            }
774
            if (!fracDigits) {
775
                digits = VL_SNPRINTF(tmp, VL_VALUE_STRING_MAX_WIDTH, "%s%s", ptr, suffix.c_str());
776
            } else {
777
                digits = VL_SNPRINTF(tmp, VL_VALUE_STRING_MAX_WIDTH, "%s.%0*" PRIu64 "%s", ptr,
778
                                     fracDigits, VL_SET_QW(frac), suffix.c_str());
779
            }
780
        } else {
781
            const uint64_t integer64 = VL_SET_QW(integer);
782
            if (!fracDigits) {
783
                digits = VL_SNPRINTF(tmp, VL_VALUE_STRING_MAX_WIDTH, "%" PRIu64 "%s", integer64,
784
                                     suffix.c_str());
785
            } else {
786
                digits = VL_SNPRINTF(tmp, VL_VALUE_STRING_MAX_WIDTH, "%" PRIu64 ".%0*" PRIu64 "%s",
787
                                     integer64, fracDigits, VL_SET_QW(frac), suffix.c_str());
788
            }
789
        }
790
    } else {
791
        const double shiftd = vl_time_multiplier(shift);
792
        const double scaled = ld * shiftd;
793
        const double fracDiv = vl_time_multiplier(fracDigits);
794
        const double whole = scaled / fracDiv;
795
        if (!fracDigits) {
796
            digits = VL_SNPRINTF(tmp, VL_VALUE_STRING_MAX_WIDTH, "%.0f%s", whole, suffix.c_str());
797
        } else {
798
            digits = VL_SNPRINTF(tmp, VL_VALUE_STRING_MAX_WIDTH, "%.*f%s", fracDigits, whole,
799
                                 suffix.c_str());
800
        }
801
    }
802

803
    const int needmore = static_cast<int>(width) - digits;
804
    std::string padding;
805
    if (needmore > 0) padding.append(needmore, ' ');  // Pad with spaces
806
    return left ? (tmp + padding) : (padding + tmp);
807
}
808

809
// Do a va_arg returning a quad, assuming input argument is anything less than wide
810
#define VL_VA_ARG_Q_(ap, bits) (((bits) <= VL_IDATASIZE) ? va_arg(ap, IData) : va_arg(ap, QData))
811

812
void _vl_vsformat(std::string& output, const std::string& format, va_list ap) VL_MT_SAFE {
813
    // Format a Verilog $write style format into the output list
814
    // The format must be pre-processed (and lower cased) by Verilator
815
    // Arguments are in "width, arg-value (or WDataIn* if wide)" form
816
    //
817
    // Note uses a single buffer internally; presumes only one usage per printf
818
    // Note also assumes variables < 64 are not wide, this assumption is
819
    // sometimes not true in low-level routines written here in verilated.cpp
820
    static thread_local char t_tmp[VL_VALUE_STRING_MAX_WIDTH];
821
    std::string::const_iterator pctit = format.end();  // Most recent %##.##g format
822
    bool inPct = false;
823
    bool widthSet = false;
824
    bool left = false;
825
    size_t width = 0;
826
    for (std::string::const_iterator pos = format.cbegin(); pos != format.cend(); ++pos) {
827
        if (!inPct && pos[0] == '%') {
828
            pctit = pos;
829
            inPct = true;
830
            widthSet = false;
831
            width = 0;
832
        } else if (!inPct) {  // Normal text
833
            // Fast-forward to next escape and add to output
834
            std::string::const_iterator ep = pos;
835
            while (ep != format.end() && ep[0] != '%') ++ep;
836
            if (ep != pos) {
837
                output.append(pos, ep);
838
                pos = ep - 1;
839
            }
840
        } else {  // Format character
841
            inPct = false;
842
            const char fmt = pos[0];
843
            switch (fmt) {
844
            case '0':  // FALLTHRU
845
            case '1':  // FALLTHRU
846
            case '2':  // FALLTHRU
847
            case '3':  // FALLTHRU
848
            case '4':  // FALLTHRU
849
            case '5':  // FALLTHRU
850
            case '6':  // FALLTHRU
851
            case '7':  // FALLTHRU
852
            case '8':  // FALLTHRU
853
            case '9':
854
                inPct = true;  // Get more digits
855
                widthSet = true;
856
                width = width * 10 + (fmt - '0');
857
                break;
858
            case '-':
859
                left = true;
860
                inPct = true;  // Get more digits
861
                break;
862
            case '.':
863
                inPct = true;  // Get more digits
864
                break;
865
            case '%':  //
866
                output += '%';
867
                break;
868
            case 'N': {  // "C" string with name of module, add . if needed
869
                const char* const cstrp = va_arg(ap, const char*);
870
                if (VL_LIKELY(*cstrp)) {
871
                    output += cstrp;
872
                    output += '.';
873
                }
874
                break;
875
            }
876
            case 'S': {  // "C" string
877
                const char* const cstrp = va_arg(ap, const char*);
878
                output += cstrp;
879
                break;
880
            }
881
            case '@': {  // Verilog/C++ string
882
                va_arg(ap, int);  // # bits is ignored
883
                const std::string* const cstrp = va_arg(ap, const std::string*);
884
                std::string padding;
885
                if (width > cstrp->size()) padding.append(width - cstrp->size(), ' ');
886
                output += left ? (*cstrp + padding) : (padding + *cstrp);
887
                break;
888
            }
889
            case 'e':
890
            case 'f':
891
            case 'g':
892
            case '^': {  // Realtime
893
                const int lbits = va_arg(ap, int);
894
                const double d = va_arg(ap, double);
895
                (void)lbits;  // UNUSED - always 64
896
                if (fmt == '^') {  // Realtime
897
                    if (!widthSet) width = Verilated::threadContextp()->impp()->timeFormatWidth();
898
                    const int timeunit = va_arg(ap, int);
899
                    output += _vl_vsformat_time(t_tmp, d, timeunit, left, width);
900
                } else {
901
                    const std::string fmts{pctit, pos + 1};
902
                    VL_SNPRINTF(t_tmp, VL_VALUE_STRING_MAX_WIDTH, fmts.c_str(), d);
903
                    output += t_tmp;
904
                }
905
                break;
906
            }
907
            default: {
908
                // Deal with all read-and-print somethings
909
                const int lbits = va_arg(ap, int);
910
                QData ld = 0;
911
                VlWide<VL_WQ_WORDS_E> qlwp;
912
                WDataInP lwp = nullptr;
913
                if (lbits <= VL_QUADSIZE) {
914
                    ld = VL_VA_ARG_Q_(ap, lbits);
915
                    VL_SET_WQ(qlwp, ld);
916
                    lwp = qlwp;
917
                } else {
918
                    lwp = va_arg(ap, WDataInP);
919
                    ld = lwp[0];
920
                }
921
                int lsb = lbits - 1;
922
                if (widthSet && width == 0) {
923
                    while (lsb && !VL_BITISSET_W(lwp, lsb)) --lsb;
924
                }
925
                switch (fmt) {
926
                case 'c': {
927
                    const IData charval = ld & 0xff;
928
                    output += static_cast<char>(charval);
929
                    break;
930
                }
931
                case 's': {
932
                    std::string field;
933
                    for (; lsb >= 0; --lsb) {
934
                        lsb = (lsb / 8) * 8;  // Next digit
935
                        const IData charval = VL_BITRSHIFT_W(lwp, lsb) & 0xff;
936
                        field += (charval == 0) ? ' ' : charval;
937
                    }
938
                    std::string padding;
939
                    if (width > field.size()) padding.append(width - field.size(), ' ');
940
                    output += left ? (field + padding) : (padding + field);
941
                    break;
942
                }
943
                case 'd': {  // Signed decimal
944
                    int digits = 0;
945
                    std::string append;
946
                    if (lbits <= VL_QUADSIZE) {
947
                        digits
948
                            = VL_SNPRINTF(t_tmp, VL_VALUE_STRING_MAX_WIDTH, "%" PRId64,
949
                                          static_cast<int64_t>(VL_EXTENDS_QQ(lbits, lbits, ld)));
950
                        append = t_tmp;
951
                    } else {
952
                        if (VL_SIGN_E(lbits, lwp[VL_WORDS_I(lbits) - 1])) {
953
                            VlWide<VL_VALUE_STRING_MAX_WIDTH / 4 + 2> neg;
954
                            VL_NEGATE_W(VL_WORDS_I(lbits), neg, lwp);
955
                            append = "-"s + VL_DECIMAL_NW(lbits, neg);
956
                        } else {
957
                            append = VL_DECIMAL_NW(lbits, lwp);
958
                        }
959
                        digits = static_cast<int>(append.length());
960
                    }
961
                    const int needmore = static_cast<int>(width) - digits;
962
                    if (needmore > 0) {
963
                        std::string padding;
964
                        if (left) {
965
                            padding.append(needmore, ' ');  // Pre-pad spaces
966
                            output += append + padding;
967
                        } else {
968
                            if (pctit != format.end() && pctit[0] && pctit[1] == '0') {  // %0
969
                                padding.append(needmore, '0');  // Pre-pad zero
970
                            } else {
971
                                padding.append(needmore, ' ');  // Pre-pad spaces
972
                            }
973
                            output += padding + append;
974
                        }
975
                    } else {
976
                        output += append;
977
                    }
978
                    break;
979
                }
980
                case '#': {  // Unsigned decimal
981
                    int digits = 0;
982
                    std::string append;
983
                    if (lbits <= VL_QUADSIZE) {
984
                        digits = VL_SNPRINTF(t_tmp, VL_VALUE_STRING_MAX_WIDTH, "%" PRIu64, ld);
985
                        append = t_tmp;
986
                    } else {
987
                        append = VL_DECIMAL_NW(lbits, lwp);
988
                        digits = static_cast<int>(append.length());
989
                    }
990
                    const int needmore = static_cast<int>(width) - digits;
991
                    if (needmore > 0) {
992
                        std::string padding;
993
                        if (left) {
994
                            padding.append(needmore, ' ');  // Pre-pad spaces
995
                            output += append + padding;
996
                        } else {
997
                            if (pctit != format.end() && pctit[0] && pctit[1] == '0') {  // %0
998
                                padding.append(needmore, '0');  // Pre-pad zero
999
                            } else {
1000
                                padding.append(needmore, ' ');  // Pre-pad spaces
1001
                            }
1002
                            output += padding + append;
1003
                        }
1004
                    } else {
1005
                        output += append;
1006
                    }
1007
                    break;
1008
                }
1009
                case 't': {  // Time
1010
                    if (!widthSet) width = Verilated::threadContextp()->impp()->timeFormatWidth();
1011
                    const int timeunit = va_arg(ap, int);
1012
                    output += _vl_vsformat_time(t_tmp, ld, timeunit, left, width);
1013
                    break;
1014
                }
1015
                case 'b':  // FALLTHRU
1016
                case 'o':  // FALLTHRU
1017
                case 'x': {
1018
                    if (widthSet || left) {
1019
                        lsb = VL_MOSTSETBITP1_W(VL_WORDS_I(lbits), lwp);
1020
                        lsb = (lsb < 1) ? 0 : (lsb - 1);
1021
                    }
1022

1023
                    std::string append;
1024
                    int digits;
1025
                    switch (fmt) {
1026
                    case 'b': {
1027
                        digits = lsb + 1;
1028
                        for (; lsb >= 0; --lsb) append += (VL_BITRSHIFT_W(lwp, lsb) & 1) + '0';
1029
                        break;
1030
                    }
1031
                    case 'o': {
1032
                        digits = (lsb + 1 + 2) / 3;
1033
                        for (; lsb >= 0; --lsb) {
1034
                            lsb = (lsb / 3) * 3;  // Next digit
1035
                            // Octal numbers may span more than one wide word,
1036
                            // so we need to grab each bit separately and check for overrun
1037
                            // Octal is rare, so we'll do it a slow simple way
1038
                            append += static_cast<char>(
1039
                                '0' + ((VL_BITISSETLIMIT_W(lwp, lbits, lsb + 0)) ? 1 : 0)
1040
                                + ((VL_BITISSETLIMIT_W(lwp, lbits, lsb + 1)) ? 2 : 0)
1041
                                + ((VL_BITISSETLIMIT_W(lwp, lbits, lsb + 2)) ? 4 : 0));
1042
                        }
1043
                        break;
1044
                    }
1045
                    default: {  // 'x'
1046
                        digits = (lsb + 1 + 3) / 4;
1047
                        for (; lsb >= 0; --lsb) {
1048
                            lsb = (lsb / 4) * 4;  // Next digit
1049
                            const IData charval = VL_BITRSHIFT_W(lwp, lsb) & 0xf;
1050
                            append += "0123456789abcdef"[charval];
1051
                        }
1052
                        break;
1053
                    }
1054
                    }  // switch
1055

1056
                    const int needmore = static_cast<int>(width) - digits;
1057
                    if (needmore > 0) {
1058
                        std::string padding;
1059
                        if (left) {
1060
                            padding.append(needmore, ' ');  // Pre-pad spaces
1061
                            output += append + padding;
1062
                        } else {
1063
                            padding.append(needmore, '0');  // Pre-pad zero
1064
                            output += padding + append;
1065
                        }
1066
                    } else {
1067
                        output += append;
1068
                    }
1069
                    break;
1070
                }  // b / o / x
1071
                case 'u':
1072
                case 'z': {  // Packed 4-state
1073
                    const bool is_4_state = (fmt == 'z');
1074
                    output.reserve(output.size() + ((is_4_state ? 2 : 1) * VL_WORDS_I(lbits)));
1075
                    int bytes_to_go = VL_BYTES_I(lbits);
1076
                    int bit = 0;
1077
                    while (bytes_to_go > 0) {
1078
                        const int wr_bytes = std::min(4, bytes_to_go);
1079
                        for (int byte = 0; byte < wr_bytes; byte++, bit += 8)
1080
                            output += static_cast<char>(VL_BITRSHIFT_W(lwp, bit) & 0xff);
1081
                        output.append(4 - wr_bytes, static_cast<char>(0));
1082
                        if (is_4_state) output.append(4, static_cast<char>(0));
1083
                        bytes_to_go -= wr_bytes;
1084
                    }
1085
                    break;
1086
                }
1087
                case 'v':  // Strength; assume always strong
1088
                    for (lsb = lbits - 1; lsb >= 0; --lsb) {
1089
                        if (VL_BITRSHIFT_W(lwp, lsb) & 1) {
1090
                            output += "St1 ";
1091
                        } else {
1092
                            output += "St0 ";
1093
                        }
1094
                    }
1095
                    break;
1096
                default: {  // LCOV_EXCL_START
1097
                    const std::string msg = "Unknown _vl_vsformat code: "s + pos[0];
1098
                    VL_FATAL_MT(__FILE__, __LINE__, "", msg.c_str());
1099
                    break;
1100
                }  // LCOV_EXCL_STOP
1101
                }  // switch
1102
            }
1103
            }  // switch
1104
        }
1105
    }
1106
}
1107

1108
static bool _vl_vsss_eof(FILE* fp, int floc) VL_MT_SAFE {
1109
    if (VL_LIKELY(fp)) {
1110
        return std::feof(fp) ? true : false;  // true : false to prevent MSVC++ warning
1111
    } else {
1112
        return floc < 0;
1113
    }
1114
}
1115
static void _vl_vsss_advance(FILE* fp, int& floc) VL_MT_SAFE {
1116
    if (VL_LIKELY(fp)) {
1117
        std::fgetc(fp);
1118
    } else {
1119
        floc -= 8;
1120
    }
1121
}
1122
static int _vl_vsss_peek(FILE* fp, int& floc, const WDataInP fromp,
1123
                         const std::string& fstr) VL_MT_SAFE {
1124
    // Get a character without advancing
1125
    if (VL_LIKELY(fp)) {
1126
        const int data = std::fgetc(fp);
1127
        if (data == EOF) return EOF;
1128
        ungetc(data, fp);
1129
        return data;
1130
    } else {
1131
        if (floc < 0) return EOF;
1132
        floc = floc & ~7;  // Align to closest character
1133
        if (fromp == nullptr) {
1134
            return fstr[fstr.length() - 1 - (floc >> 3)];
1135
        } else {
1136
            return VL_BITRSHIFT_W(fromp, floc) & 0xff;
1137
        }
1138
    }
1139
}
1140
static void _vl_vsss_skipspace(FILE* fp, int& floc, const WDataInP fromp,
1141
                               const std::string& fstr) VL_MT_SAFE {
1142
    while (true) {
1143
        const int c = _vl_vsss_peek(fp, floc, fromp, fstr);
1144
        if (c == EOF || !std::isspace(c)) return;
1145
        _vl_vsss_advance(fp, floc);
1146
    }
1147
}
1148
static void _vl_vsss_read_str(FILE* fp, int& floc, const WDataInP fromp, const std::string& fstr,
1149
                              char* tmpp, const char* acceptp) VL_MT_SAFE {
1150
    // Read into tmp, consisting of characters from acceptp list
1151
    char* cp = tmpp;
1152
    while (true) {
1153
        int c = _vl_vsss_peek(fp, floc, fromp, fstr);
1154
        if (c == EOF || std::isspace(c)) break;
1155
        if (acceptp && nullptr == std::strchr(acceptp, c)) break;  // String - allow anything
1156
        if (acceptp) c = std::tolower(c);  // Non-strings we'll simplify
1157
        *cp++ = c;
1158
        _vl_vsss_advance(fp, floc);
1159
    }
1160
    *cp++ = '\0';
1161
    // VL_DBG_MSGF(" _read got='"<<tmpp<<"'\n");
1162
}
1163
static char* _vl_vsss_read_bin(FILE* fp, int& floc, const WDataInP fromp, const std::string& fstr,
1164
                               char* beginp, std::size_t n,
1165
                               const bool inhibit = false) VL_MT_SAFE {
1166
    // Variant of _vl_vsss_read_str using the same underlying I/O functions but optimized
1167
    // specifically for block reads of N bytes (read operations are not demarcated by
1168
    // whitespace). In the fp case, except descriptor to have been opened in binary mode.
1169
    while (n-- > 0) {
1170
        const int c = _vl_vsss_peek(fp, floc, fromp, fstr);
1171
        if (c == EOF) return nullptr;
1172
        if (!inhibit) *beginp++ = c;
1173
        _vl_vsss_advance(fp, floc);
1174
    }
1175
    return beginp;
1176
}
1177
static void _vl_vsss_setbit(WDataOutP iowp, int obits, int lsb, int nbits, IData ld) VL_MT_SAFE {
1178
    for (; nbits && lsb < obits; nbits--, lsb++, ld >>= 1) VL_ASSIGNBIT_WI(lsb, iowp, ld & 1);
1179
}
1180
void _vl_vsss_based(WDataOutP owp, int obits, int baseLog2, const char* strp, size_t posstart,
1181
                    size_t posend) VL_MT_SAFE {
1182
    // Read in base "2^^baseLog2" digits from strp[posstart..posend-1] into owp of size obits.
1183
    VL_ZERO_W(obits, owp);
1184
    int lsb = 0;
1185
    for (int i = 0, pos = static_cast<int>(posend) - 1;
1186
         i < obits && pos >= static_cast<int>(posstart); --pos) {
1187
        // clang-format off
1188
        switch (tolower (strp[pos])) {
1189
        case 'x': case 'z': case '?':  // FALLTHRU
1190
        case '0': lsb += baseLog2; break;
1191
        case '1': _vl_vsss_setbit(owp, obits, lsb, baseLog2,  1); lsb += baseLog2; break;
1192
        case '2': _vl_vsss_setbit(owp, obits, lsb, baseLog2,  2); lsb += baseLog2; break;
1193
        case '3': _vl_vsss_setbit(owp, obits, lsb, baseLog2,  3); lsb += baseLog2; break;
1194
        case '4': _vl_vsss_setbit(owp, obits, lsb, baseLog2,  4); lsb += baseLog2; break;
1195
        case '5': _vl_vsss_setbit(owp, obits, lsb, baseLog2,  5); lsb += baseLog2; break;
1196
        case '6': _vl_vsss_setbit(owp, obits, lsb, baseLog2,  6); lsb += baseLog2; break;
1197
        case '7': _vl_vsss_setbit(owp, obits, lsb, baseLog2,  7); lsb += baseLog2; break;
1198
        case '8': _vl_vsss_setbit(owp, obits, lsb, baseLog2,  8); lsb += baseLog2; break;
1199
        case '9': _vl_vsss_setbit(owp, obits, lsb, baseLog2,  9); lsb += baseLog2; break;
1200
        case 'a': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 10); lsb += baseLog2; break;
1201
        case 'b': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 11); lsb += baseLog2; break;
1202
        case 'c': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 12); lsb += baseLog2; break;
1203
        case 'd': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 13); lsb += baseLog2; break;
1204
        case 'e': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 14); lsb += baseLog2; break;
1205
        case 'f': _vl_vsss_setbit(owp, obits, lsb, baseLog2, 15); lsb += baseLog2; break;
1206
        case '_': break;
1207
        }
1208
        // clang-format on
1209
    }
1210
}
1211

1212
IData _vl_vsscanf(FILE* fp,  // If a fscanf
1213
                  int fbits, const WDataInP fromp,  // Else if a sscanf
1214
                  const std::string& fstr,  // if a sscanf to string
1215
                  const std::string& format, va_list ap) VL_MT_SAFE {
1216
    // Read a Verilog $sscanf/$fscanf style format into the output list
1217
    // The format must be pre-processed (and lower cased) by Verilator
1218
    // Arguments are in "width, arg-value (or WDataIn* if wide)" form
1219
    static thread_local char t_tmp[VL_VALUE_STRING_MAX_WIDTH];
1220
    int floc = fbits - 1;
1221
    IData got = 0;
1222
    bool inPct = false;
1223
    bool inIgnore = false;
1224
    std::string::const_iterator pos = format.cbegin();
1225
    for (; pos != format.cend() && !_vl_vsss_eof(fp, floc); ++pos) {
1226
        // VL_DBG_MSGF("_vlscan fmt='"<<pos[0]<<"' floc="<<floc<<" file='"<<_vl_vsss_peek(fp, floc,
1227
        // fromp, fstr)<<"'\n");
1228
        if (!inPct && pos[0] == '%') {
1229
            inPct = true;
1230
            inIgnore = false;
1231
        } else if (!inPct && std::isspace(pos[0])) {  // Format spaces
1232
            while (std::isspace(pos[1])) ++pos;
1233
            _vl_vsss_skipspace(fp, floc, fromp, fstr);
1234
        } else if (!inPct) {  // Expected Format
1235
            _vl_vsss_skipspace(fp, floc, fromp, fstr);
1236
            const int c = _vl_vsss_peek(fp, floc, fromp, fstr);
1237
            if (c != pos[0]) goto done;
1238
            _vl_vsss_advance(fp, floc);
1239
        } else {  // Format character
1240
            // Skip loading spaces
1241
            inPct = false;
1242
            const char fmt = pos[0];
1243
            switch (fmt) {
1244
            case '%': {
1245
                const int c = _vl_vsss_peek(fp, floc, fromp, fstr);
1246
                if (c != '%') goto done;
1247
                _vl_vsss_advance(fp, floc);
1248
                break;
1249
            }
1250
            case '*':
1251
                inPct = true;
1252
                inIgnore = true;
1253
                break;
1254
            default: {
1255
                // Deal with all read-and-scan somethings
1256
                // Note LSBs are preserved if there's an overflow
1257
                const int obits = inIgnore ? 0 : va_arg(ap, int);
1258
                VlWide<VL_WQ_WORDS_E> qowp;
1259
                VL_SET_WQ(qowp, 0ULL);
1260
                WDataOutP owp = qowp;
1261
                if (obits == -1) {  // string
1262
                    owp = nullptr;
1263
                    if (VL_UNCOVERABLE(fmt != 's')) {
1264
                        VL_FATAL_MT(
1265
                            __FILE__, __LINE__, "",
1266
                            "Internal: format other than %s is passed to string");  // LCOV_EXCL_LINE
1267
                    }
1268
                } else if (obits > VL_QUADSIZE) {
1269
                    owp = va_arg(ap, WDataOutP);
1270
                }
1271

1272
                for (int i = 0; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
1273
                switch (fmt) {
1274
                case 'c': {
1275
                    const int c = _vl_vsss_peek(fp, floc, fromp, fstr);
1276
                    if (c == EOF) goto done;
1277
                    _vl_vsss_advance(fp, floc);
1278
                    owp[0] = c;
1279
                    break;
1280
                }
1281
                case 's': {
1282
                    _vl_vsss_skipspace(fp, floc, fromp, fstr);
1283
                    _vl_vsss_read_str(fp, floc, fromp, fstr, t_tmp, nullptr);
1284
                    if (!t_tmp[0]) goto done;
1285
                    if (owp) {
1286
                        int lpos = (static_cast<int>(std::strlen(t_tmp))) - 1;
1287
                        int lsb = 0;
1288
                        for (int i = 0; i < obits && lpos >= 0; --lpos) {
1289
                            _vl_vsss_setbit(owp, obits, lsb, 8, t_tmp[lpos]);
1290
                            lsb += 8;
1291
                        }
1292
                    }
1293
                    break;
1294
                }
1295
                case 'd': {  // Signed decimal
1296
                    _vl_vsss_skipspace(fp, floc, fromp, fstr);
1297
                    _vl_vsss_read_str(fp, floc, fromp, fstr, t_tmp, "0123456789+-xXzZ?_");
1298
                    if (!t_tmp[0]) goto done;
1299
                    int64_t ld = 0;
1300
                    std::sscanf(t_tmp, "%30" PRId64, &ld);
1301
                    VL_SET_WQ(owp, ld);
1302
                    break;
1303
                }
1304
                case 'f':
1305
                case 'e':
1306
                case 'g': {  // Real number
1307
                    _vl_vsss_skipspace(fp, floc, fromp, fstr);
1308
                    _vl_vsss_read_str(fp, floc, fromp, fstr, t_tmp, "+-.0123456789eE");
1309
                    if (!t_tmp[0]) goto done;
1310
                    // cppcheck-has-bug-suppress unusedStructMember, unreadVariable
1311
                    union {
1312
                        double r;
1313
                        int64_t ld;
1314
                    } u;
1315
                    u.r = std::strtod(t_tmp, nullptr);
1316
                    VL_SET_WQ(owp, u.ld);
1317
                    break;
1318
                }
1319
                case 't':  // FALLTHRU  // Time
1320
                case '#': {  // Unsigned decimal
1321
                    _vl_vsss_skipspace(fp, floc, fromp, fstr);
1322
                    _vl_vsss_read_str(fp, floc, fromp, fstr, t_tmp, "0123456789+-xXzZ?_");
1323
                    if (!t_tmp[0]) goto done;
1324
                    QData ld = 0;
1325
                    std::sscanf(t_tmp, "%30" PRIu64, &ld);
1326
                    VL_SET_WQ(owp, ld);
1327
                    break;
1328
                }
1329
                case 'b': {
1330
                    _vl_vsss_skipspace(fp, floc, fromp, fstr);
1331
                    _vl_vsss_read_str(fp, floc, fromp, fstr, t_tmp, "01xXzZ?_");
1332
                    if (!t_tmp[0]) goto done;
1333
                    _vl_vsss_based(owp, obits, 1, t_tmp, 0, std::strlen(t_tmp));
1334
                    break;
1335
                }
1336
                case 'o': {
1337
                    _vl_vsss_skipspace(fp, floc, fromp, fstr);
1338
                    _vl_vsss_read_str(fp, floc, fromp, fstr, t_tmp, "01234567xXzZ?_");
1339
                    if (!t_tmp[0]) goto done;
1340
                    _vl_vsss_based(owp, obits, 3, t_tmp, 0, std::strlen(t_tmp));
1341
                    break;
1342
                }
1343
                case 'x': {
1344
                    _vl_vsss_skipspace(fp, floc, fromp, fstr);
1345
                    _vl_vsss_read_str(fp, floc, fromp, fstr, t_tmp,
1346
                                      "0123456789abcdefABCDEFxXzZ?_");
1347
                    if (!t_tmp[0]) goto done;
1348
                    _vl_vsss_based(owp, obits, 4, t_tmp, 0, std::strlen(t_tmp));
1349
                    break;
1350
                }
1351
                case 'u': {
1352
                    // Read packed 2-value binary data
1353
                    const int bytes = VL_BYTES_I(obits);
1354
                    char* const out = reinterpret_cast<char*>(owp);
1355
                    if (!_vl_vsss_read_bin(fp, floc, fromp, fstr, out, bytes)) goto done;
1356
                    const int last = bytes % 4;
1357
                    if (last != 0
1358
                        && !_vl_vsss_read_bin(fp, floc, fromp, fstr, out, 4 - last, true))
1359
                        goto done;
1360
                    break;
1361
                }
1362
                case 'z': {
1363
                    // Read packed 4-value binary data
1364
                    char* out = reinterpret_cast<char*>(owp);
1365
                    int bytes = VL_BYTES_I(obits);
1366
                    while (bytes > 0) {
1367
                        const int abytes = std::min(4, bytes);
1368
                        // aval (4B) read {0, 1} state
1369
                        out = _vl_vsss_read_bin(fp, floc, fromp, fstr, out, abytes);
1370
                        if (!out) goto done;
1371
                        // bval (4B) disregard {X, Z} state and align to new 8B boundary.
1372
                        out = _vl_vsss_read_bin(fp, floc, fromp, fstr, out, 8 - abytes, true);
1373
                        if (!out) goto done;
1374
                        bytes -= abytes;
1375
                    }
1376
                    break;
1377
                }
1378
                default: {  // LCOV_EXCL_START
1379
                    const std::string msg = "Unknown _vl_vsscanf code: "s + pos[0];
1380
                    VL_FATAL_MT(__FILE__, __LINE__, "", msg.c_str());
1381
                    break;
1382
                }  // LCOV_EXCL_STOP
1383

1384
                }  // switch
1385

1386
                if (!inIgnore) ++got;
1387
                // Reload data if non-wide (if wide, we put it in the right place directly)
1388
                if (obits == 0) {  // Due to inIgnore
1389
                } else if (obits == -1) {  // string
1390
                    std::string* const p = va_arg(ap, std::string*);
1391
                    *p = t_tmp;
1392
                } else if (obits <= VL_BYTESIZE) {
1393
                    CData* const p = va_arg(ap, CData*);
1394
                    *p = VL_CLEAN_II(obits, obits, owp[0]);
1395
                } else if (obits <= VL_SHORTSIZE) {
1396
                    SData* const p = va_arg(ap, SData*);
1397
                    *p = VL_CLEAN_II(obits, obits, owp[0]);
1398
                } else if (obits <= VL_IDATASIZE) {
1399
                    IData* const p = va_arg(ap, IData*);
1400
                    *p = VL_CLEAN_II(obits, obits, owp[0]);
1401
                } else if (obits <= VL_QUADSIZE) {
1402
                    QData* const p = va_arg(ap, QData*);
1403
                    *p = VL_CLEAN_QQ(obits, obits, VL_SET_QW(owp));
1404
                } else {
1405
                    _vl_clean_inplace_w(obits, owp);
1406
                }
1407
            }
1408
            }  // switch
1409
        }
1410
    }
1411
done:
1412
    return got;
1413
}
1414

1415
//===========================================================================
1416
// File I/O
1417

1418
FILE* VL_CVT_I_FP(IData lhs) VL_MT_SAFE {
1419
    // Expected non-MCD case; returns null on MCD descriptors.
1420
    return Verilated::threadContextp()->impp()->fdToFp(lhs);
1421
}
1422

1423
void _vl_vint_to_string(int obits, char* destoutp, const WDataInP sourcep) VL_MT_SAFE {
1424
    // See also VL_DATA_TO_STRING_NW
1425
    int lsb = obits - 1;
1426
    bool start = true;
1427
    char* destp = destoutp;
1428
    for (; lsb >= 0; --lsb) {
1429
        lsb = (lsb / 8) * 8;  // Next digit
1430
        const IData charval = VL_BITRSHIFT_W(sourcep, lsb) & 0xff;
1431
        if (!start || charval) {
1432
            *destp++ = (charval == 0) ? ' ' : charval;
1433
            start = false;  // Drop leading 0s
1434
        }
1435
    }
1436
    *destp = '\0';  // Terminate
1437
    if (!start) {  // Drop trailing spaces
1438
        while (std::isspace(*(destp - 1)) && destp > destoutp) *--destp = '\0';
1439
    }
1440
}
1441

1442
void _vl_string_to_vint(int obits, void* destp, size_t srclen, const char* srcp) VL_MT_SAFE {
1443
    // Convert C string to Verilog format
1444
    const size_t bytes = VL_BYTES_I(obits);
1445
    char* op = reinterpret_cast<char*>(destp);
1446
    if (srclen > bytes) srclen = bytes;  // Don't overflow destination
1447
    size_t i = 0;
1448
    for (i = 0; i < srclen; ++i) *op++ = srcp[srclen - 1 - i];
1449
    for (; i < bytes; ++i) *op++ = 0;
1450
}
1451

1452
static IData getLine(std::string& str, IData fpi, size_t maxLen) VL_MT_SAFE {
1453
    str.clear();
1454

1455
    // While threadsafe, each thread can only access different file handles
1456
    FILE* const fp = VL_CVT_I_FP(fpi);
1457
    if (VL_UNLIKELY(!fp)) return 0;
1458

1459
    // We don't use fgets, as we must read \0s.
1460
    while (str.size() < maxLen) {
1461
        const int c = getc(fp);  // getc() is threadsafe
1462
        if (c == EOF) break;
1463
        str.push_back(c);
1464
        if (c == '\n') break;
1465
    }
1466
    return static_cast<IData>(str.size());
1467
}
1468

1469
IData VL_FGETS_IXI(int obits, void* destp, IData fpi) VL_MT_SAFE {
1470
    std::string str;
1471
    const IData bytes = VL_BYTES_I(obits);
1472
    const IData got = getLine(str, fpi, bytes);
1473

1474
    if (VL_UNLIKELY(str.empty())) return 0;
1475

1476
    // V3Emit has static check that bytes < VL_VALUE_STRING_MAX_WORDS, but be safe
1477
    if (VL_UNCOVERABLE(bytes < str.size())) {
1478
        VL_FATAL_MT(__FILE__, __LINE__, "", "Internal: fgets buffer overrun");  // LCOV_EXCL_LINE
1479
    }
1480

1481
    _vl_string_to_vint(obits, destp, got, str.data());
1482
    return got;
1483
}
1484

1485
IData VL_FGETS_NI(std::string& dest, IData fpi) VL_MT_SAFE {
1486
    return getLine(dest, fpi, std::numeric_limits<size_t>::max());
1487
}
1488

1489
IData VL_FERROR_IN(IData, std::string& outputr) VL_MT_SAFE {
1490
    // We ignore lhs/fpi - IEEE says "most recent error" so probably good enough
1491
    const IData ret = errno;
1492
    outputr = std::string{::std::strerror(ret)};
1493
    return ret;
1494
}
1495
IData VL_FERROR_IW(IData fpi, int obits, WDataOutP outwp) VL_MT_SAFE {
1496
    std::string output;
1497
    const IData ret = VL_FERROR_IN(fpi, output /*ref*/);
1498
    _vl_string_to_vint(obits, outwp, output.length(), output.c_str());
1499
    return ret;
1500
}
1501

1502
IData VL_FOPEN_NN(const std::string& filename, const std::string& mode) {
1503
    return Verilated::threadContextp()->impp()->fdNew(filename.c_str(), mode.c_str());
1504
}
1505
IData VL_FOPEN_MCD_N(const std::string& filename) VL_MT_SAFE {
1506
    return Verilated::threadContextp()->impp()->fdNewMcd(filename.c_str());
1507
}
1508

1509
void VL_FFLUSH_I(IData fdi) VL_MT_SAFE { Verilated::threadContextp()->impp()->fdFlush(fdi); }
1510
IData VL_FSEEK_I(IData fdi, IData offset, IData origin) VL_MT_SAFE {
1511
    return Verilated::threadContextp()->impp()->fdSeek(fdi, offset, origin);
1512
}
1513
IData VL_FTELL_I(IData fdi) VL_MT_SAFE { return Verilated::threadContextp()->impp()->fdTell(fdi); }
1514
void VL_FCLOSE_I(IData fdi) VL_MT_SAFE {
1515
    // While threadsafe, each thread can only access different file handles
1516
    Verilated::threadContextp()->impp()->fdClose(fdi);
1517
}
1518

1519
void VL_SFORMAT_NX(int obits, CData& destr, const std::string& format, int argc, ...) VL_MT_SAFE {
1520
    static thread_local std::string t_output;  // static only for speed
1521
    t_output = "";
1522
    va_list ap;
1523
    va_start(ap, argc);
1524
    _vl_vsformat(t_output, format, ap);
1525
    va_end(ap);
1526

1527
    _vl_string_to_vint(obits, &destr, t_output.length(), t_output.c_str());
1528
}
1529

1530
void VL_SFORMAT_NX(int obits, SData& destr, const std::string& format, int argc, ...) VL_MT_SAFE {
1531
    static thread_local std::string t_output;  // static only for speed
1532
    t_output = "";
1533
    va_list ap;
1534
    va_start(ap, argc);
1535
    _vl_vsformat(t_output, format, ap);
1536
    va_end(ap);
1537

1538
    _vl_string_to_vint(obits, &destr, t_output.length(), t_output.c_str());
1539
}
1540

1541
void VL_SFORMAT_NX(int obits, IData& destr, const std::string& format, int argc, ...) VL_MT_SAFE {
1542
    static thread_local std::string t_output;  // static only for speed
1543
    t_output = "";
1544
    va_list ap;
1545
    va_start(ap, argc);
1546
    _vl_vsformat(t_output, format, ap);
1547
    va_end(ap);
1548

1549
    _vl_string_to_vint(obits, &destr, t_output.length(), t_output.c_str());
1550
}
1551

1552
void VL_SFORMAT_NX(int obits, QData& destr, const std::string& format, int argc, ...) VL_MT_SAFE {
1553
    static thread_local std::string t_output;  // static only for speed
1554
    t_output = "";
1555
    va_list ap;
1556
    va_start(ap, argc);
1557
    _vl_vsformat(t_output, format, ap);
1558
    va_end(ap);
1559

1560
    _vl_string_to_vint(obits, &destr, t_output.length(), t_output.c_str());
1561
}
1562

1563
void VL_SFORMAT_NX(int obits, void* destp, const std::string& format, int argc, ...) VL_MT_SAFE {
1564
    static thread_local std::string t_output;  // static only for speed
1565
    t_output = "";
1566
    va_list ap;
1567
    va_start(ap, argc);
1568
    _vl_vsformat(t_output, format, ap);
1569
    va_end(ap);
1570

1571
    _vl_string_to_vint(obits, destp, t_output.length(), t_output.c_str());
1572
}
1573

1574
void VL_SFORMAT_NX(int obits_ignored, std::string& output, const std::string& format, int argc,
1575
                   ...) VL_MT_SAFE {
1576
    (void)obits_ignored;  // So VL_SFORMAT_NNX function signatures all match
1577
    std::string temp_output;
1578
    va_list ap;
1579
    va_start(ap, argc);
1580
    _vl_vsformat(temp_output, format, ap);
1581
    va_end(ap);
1582
    output = temp_output;
1583
}
1584

1585
std::string VL_SFORMATF_N_NX(const std::string& format, int argc, ...) VL_MT_SAFE {
1586
    static thread_local std::string t_output;  // static only for speed
1587
    t_output = "";
1588
    va_list ap;
1589
    va_start(ap, argc);
1590
    _vl_vsformat(t_output, format, ap);
1591
    va_end(ap);
1592

1593
    return t_output;
1594
}
1595

1596
void VL_WRITEF_NX(const std::string& format, int argc, ...) VL_MT_SAFE {
1597
    static thread_local std::string t_output;  // static only for speed
1598
    t_output = "";
1599
    va_list ap;
1600
    va_start(ap, argc);
1601
    _vl_vsformat(t_output, format, ap);
1602
    va_end(ap);
1603

1604
    VL_PRINTF_MT("%s", t_output.c_str());
1605
}
1606

1607
void VL_FWRITEF_NX(IData fpi, const std::string& format, int argc, ...) VL_MT_SAFE {
1608
    // While threadsafe, each thread can only access different file handles
1609
    static thread_local std::string t_output;  // static only for speed
1610
    t_output = "";
1611

1612
    va_list ap;
1613
    va_start(ap, argc);
1614
    _vl_vsformat(t_output, format, ap);
1615
    va_end(ap);
1616

1617
    Verilated::threadContextp()->impp()->fdWrite(fpi, t_output);
1618
}
1619

1620
IData VL_FSCANF_INX(IData fpi, const std::string& format, int argc, ...) VL_MT_SAFE {
1621
    // While threadsafe, each thread can only access different file handles
1622
    FILE* const fp = VL_CVT_I_FP(fpi);
1623
    if (VL_UNLIKELY(!fp)) return ~0U;  // -1
1624

1625
    va_list ap;
1626
    va_start(ap, argc);
1627
    const IData got = _vl_vsscanf(fp, 0, nullptr, "", format, ap);
1628
    va_end(ap);
1629
    return got;
1630
}
1631

1632
IData VL_SSCANF_IINX(int lbits, IData ld, const std::string& format, int argc, ...) VL_MT_SAFE {
1633
    VlWide<VL_WQ_WORDS_E> fnw;
1634
    VL_SET_WI(fnw, ld);
1635

1636
    va_list ap;
1637
    va_start(ap, argc);
1638
    const IData got = _vl_vsscanf(nullptr, lbits, fnw, "", format, ap);
1639
    va_end(ap);
1640
    return got;
1641
}
1642
IData VL_SSCANF_IQNX(int lbits, QData ld, const std::string& format, int argc, ...) VL_MT_SAFE {
1643
    VlWide<VL_WQ_WORDS_E> fnw;
1644
    VL_SET_WQ(fnw, ld);
1645

1646
    va_list ap;
1647
    va_start(ap, argc);
1648
    const IData got = _vl_vsscanf(nullptr, lbits, fnw, "", format, ap);
1649
    va_end(ap);
1650
    return got;
1651
}
1652
IData VL_SSCANF_IWNX(int lbits, const WDataInP lwp, const std::string& format, int argc,
1653
                     ...) VL_MT_SAFE {
1654
    va_list ap;
1655
    va_start(ap, argc);
1656
    const IData got = _vl_vsscanf(nullptr, lbits, lwp, "", format, ap);
1657
    va_end(ap);
1658
    return got;
1659
}
1660
IData VL_SSCANF_INNX(int, const std::string& ld, const std::string& format, int argc,
1661
                     ...) VL_MT_SAFE {
1662
    va_list ap;
1663
    va_start(ap, argc);
1664
    const IData got
1665
        = _vl_vsscanf(nullptr, static_cast<int>(ld.length() * 8), nullptr, ld, format, ap);
1666
    va_end(ap);
1667
    return got;
1668
}
1669

1670
IData VL_FREAD_I(int width, int array_lsb, int array_size, void* memp, IData fpi, IData start,
1671
                 IData count) VL_MT_SAFE {
1672
    // While threadsafe, each thread can only access different file handles
1673
    FILE* const fp = VL_CVT_I_FP(fpi);
1674
    if (VL_UNLIKELY(!fp)) return 0;
1675
    if (count > (array_size - (start - array_lsb))) count = array_size - (start - array_lsb);
1676
    // Prep for reading
1677
    IData read_count = 0;
1678
    IData read_elements = 0;
1679
    const int start_shift = (width - 1) & ~7;  // bit+7:bit gets first character
1680
    int shift = start_shift;
1681
    // Read the data
1682
    // We process a character at a time, as then we don't need to deal
1683
    // with changing buffer sizes dynamically, etc.
1684
    while (true) {
1685
        const int c = std::fgetc(fp);
1686
        if (VL_UNLIKELY(c == EOF)) break;
1687
        // Shift value in
1688
        const IData entry = read_elements + start - array_lsb;
1689
        if (width <= 8) {
1690
            CData* const datap = &(reinterpret_cast<CData*>(memp))[entry];
1691
            if (shift == start_shift) *datap = 0;
1692
            *datap |= (c << shift) & VL_MASK_I(width);
1693
        } else if (width <= 16) {
1694
            SData* const datap = &(reinterpret_cast<SData*>(memp))[entry];
1695
            if (shift == start_shift) *datap = 0;
1696
            *datap |= (c << shift) & VL_MASK_I(width);
1697
        } else if (width <= VL_IDATASIZE) {
1698
            IData* const datap = &(reinterpret_cast<IData*>(memp))[entry];
1699
            if (shift == start_shift) *datap = 0;
1700
            *datap |= (c << shift) & VL_MASK_I(width);
1701
        } else if (width <= VL_QUADSIZE) {
1702
            QData* const datap = &(reinterpret_cast<QData*>(memp))[entry];
1703
            if (shift == start_shift) *datap = 0;
1704
            *datap |= ((static_cast<QData>(c) << static_cast<QData>(shift)) & VL_MASK_Q(width));
1705
        } else {
1706
            WDataOutP datap = &(reinterpret_cast<WDataOutP>(memp))[entry * VL_WORDS_I(width)];
1707
            if (shift == start_shift) VL_ZERO_W(width, datap);
1708
            datap[VL_BITWORD_E(shift)] |= (static_cast<EData>(c) << VL_BITBIT_E(shift));
1709
        }
1710
        // Prep for next
1711
        ++read_count;
1712
        shift -= 8;
1713
        if (shift < 0) {
1714
            shift = start_shift;
1715
            ++read_elements;
1716
            if (VL_UNLIKELY(read_elements >= count)) break;
1717
        }
1718
    }
1719
    return read_count;
1720
}
1721

1722
std::string VL_STACKTRACE_N() VL_MT_SAFE {
1723
    static VerilatedMutex s_stackTraceMutex;
1724
    const VerilatedLockGuard lock{s_stackTraceMutex};
1725

1726
    int nptrs = 0;
1727
    char** strings = nullptr;
1728

1729
#ifdef _VL_HAVE_STACKTRACE
1730
    constexpr int BT_BUF_SIZE = 100;
1731
    void* buffer[BT_BUF_SIZE];
1732
    nptrs = backtrace(buffer, BT_BUF_SIZE);
1733
    strings = backtrace_symbols(buffer, nptrs);
1734
#endif
1735

1736
    // cppcheck-suppress knownConditionTrueFalse
1737
    if (!strings) return "Unable to backtrace\n";
1738

1739
    std::string result = "Backtrace:\n";
1740
    for (int j = 0; j < nptrs; j++) result += std::string{strings[j]} + "\n"s;
1741
    free(strings);
1742
    return result;
1743
}
1744

1745
void VL_STACKTRACE() VL_MT_SAFE {
1746
    const std::string result = VL_STACKTRACE_N();
1747
    VL_PRINTF("%s", result.c_str());
1748
}
1749

1750
IData VL_SYSTEM_IQ(QData lhs) VL_MT_SAFE {
1751
    VlWide<VL_WQ_WORDS_E> lhsw;
1752
    VL_SET_WQ(lhsw, lhs);
1753
    return VL_SYSTEM_IW(VL_WQ_WORDS_E, lhsw);
1754
}
1755
IData VL_SYSTEM_IW(int lhswords, const WDataInP lhsp) VL_MT_SAFE {
1756
    char filenamez[VL_VALUE_STRING_MAX_CHARS + 1];
1757
    _vl_vint_to_string(lhswords * VL_EDATASIZE, filenamez, lhsp);
1758
    return VL_SYSTEM_IN(filenamez);
1759
}
1760
IData VL_SYSTEM_IN(const std::string& lhs) VL_MT_SAFE {
1761
    const int code = std::system(lhs.c_str());  // Yes, std::system() is threadsafe
1762
    return code >> 8;  // Want exit status
1763
}
1764

1765
IData VL_TESTPLUSARGS_I(const std::string& format) VL_MT_SAFE {
1766
    const std::string& match = Verilated::threadContextp()->impp()->argPlusMatch(format.c_str());
1767
    return match.empty() ? 0 : 1;
1768
}
1769

1770
IData VL_VALUEPLUSARGS_INW(int rbits, const std::string& ld, WDataOutP rwp) VL_MT_SAFE {
1771
    std::string prefix;
1772
    bool inPct = false;
1773
    bool done = false;
1774
    char fmt = ' ';
1775
    for (const char* posp = ld.c_str(); !done && *posp; ++posp) {
1776
        if (!inPct && posp[0] == '%') {
1777
            inPct = true;
1778
        } else if (!inPct) {  // Normal text
1779
            prefix += *posp;
1780
        } else if (*posp == '0') {  // %0
1781
        } else {  // Format character
1782
            switch (std::tolower(*posp)) {
1783
            case '%':
1784
                prefix += *posp;
1785
                inPct = false;
1786
                break;
1787
            default:
1788
                fmt = *posp;
1789
                done = true;
1790
                break;
1791
            }
1792
        }
1793
    }
1794

1795
    const std::string& match = Verilated::threadContextp()->impp()->argPlusMatch(prefix.c_str());
1796
    const char* const dp = match.c_str() + 1 /*leading + */ + prefix.length();
1797
    if (match.empty()) return 0;
1798

1799
    VL_ZERO_W(rbits, rwp);
1800
    switch (std::tolower(fmt)) {
1801
    case 'd': {
1802
        int64_t lld = 0;
1803
        std::sscanf(dp, "%30" PRId64, &lld);
1804
        VL_SET_WQ(rwp, lld);
1805
        break;
1806
    }
1807
    case 'b': _vl_vsss_based(rwp, rbits, 1, dp, 0, std::strlen(dp)); break;
1808
    case 'o': _vl_vsss_based(rwp, rbits, 3, dp, 0, std::strlen(dp)); break;
1809
    case 'h':  // FALLTHRU
1810
    case 'x': _vl_vsss_based(rwp, rbits, 4, dp, 0, std::strlen(dp)); break;
1811
    case 's': {  // string/no conversion
1812
        for (int i = 0, lsb = 0, posp = static_cast<int>(std::strlen(dp)) - 1;
1813
             i < rbits && posp >= 0; --posp) {
1814
            _vl_vsss_setbit(rwp, rbits, lsb, 8, dp[posp]);
1815
            lsb += 8;
1816
        }
1817
        break;
1818
    }
1819
    case 'e': {
1820
        double temp = 0.F;
1821
        std::sscanf(dp, "%le", &temp);
1822
        VL_SET_WQ(rwp, VL_CVT_Q_D(temp));
1823
        break;
1824
    }
1825
    case 'f': {
1826
        double temp = 0.F;
1827
        std::sscanf(dp, "%lf", &temp);
1828
        VL_SET_WQ(rwp, VL_CVT_Q_D(temp));
1829
        break;
1830
    }
1831
    case 'g': {
1832
        double temp = 0.F;
1833
        std::sscanf(dp, "%lg", &temp);
1834
        VL_SET_WQ(rwp, VL_CVT_Q_D(temp));
1835
        break;
1836
    }
1837
    default:  // Other simulators return 0 in these cases and don't error out
1838
        return 0;
1839
    }
1840
    _vl_clean_inplace_w(rbits, rwp);
1841
    return 1;
1842
}
1843
IData VL_VALUEPLUSARGS_INN(int, const std::string& ld, std::string& rdr) VL_MT_SAFE {
1844
    std::string prefix;
1845
    bool inPct = false;
1846
    bool done = false;
1847
    for (const char* posp = ld.c_str(); !done && *posp; ++posp) {
1848
        if (!inPct && posp[0] == '%') {
1849
            inPct = true;
1850
        } else if (!inPct) {  // Normal text
1851
            prefix += *posp;
1852
        } else {  // Format character
1853
            switch (std::tolower(*posp)) {
1854
            case '%':
1855
                prefix += *posp;
1856
                inPct = false;
1857
                break;
1858
            default:  //
1859
                done = true;
1860
                break;
1861
            }
1862
        }
1863
    }
1864
    const std::string& match = Verilated::threadContextp()->impp()->argPlusMatch(prefix.c_str());
1865
    const char* const dp = match.c_str() + 1 /*leading + */ + prefix.length();
1866
    if (match.empty()) return 0;
1867
    rdr = std::string{dp};
1868
    return 1;
1869
}
1870

1871
const char* vl_mc_scan_plusargs(const char* prefixp) VL_MT_SAFE {
1872
    const std::string& match = Verilated::threadContextp()->impp()->argPlusMatch(prefixp);
1873
    static thread_local char t_outstr[VL_VALUE_STRING_MAX_WIDTH];
1874
    if (match.empty()) return nullptr;
1875
    char* dp = t_outstr;
1876
    for (const char* sp = match.c_str() + std::strlen(prefixp) + 1;  // +1 to skip the "+"
1877
         *sp && (dp - t_outstr) < (VL_VALUE_STRING_MAX_WIDTH - 2);)
1878
        *dp++ = *sp++;
1879
    *dp++ = '\0';
1880
    return t_outstr;
1881
}
1882

1883
//===========================================================================
1884
// Heavy string functions
1885

1886
std::string VL_TO_STRING(CData lhs) { return VL_SFORMATF_N_NX("'h%0x", 0, 8, lhs); }
1887
std::string VL_TO_STRING(SData lhs) { return VL_SFORMATF_N_NX("'h%0x", 0, 16, lhs); }
1888
std::string VL_TO_STRING(IData lhs) { return VL_SFORMATF_N_NX("'h%0x", 0, 32, lhs); }
1889
std::string VL_TO_STRING(QData lhs) { return VL_SFORMATF_N_NX("'h%0x", 0, 64, lhs); }
1890
std::string VL_TO_STRING(double lhs) { return VL_SFORMATF_N_NX("%d", 0, 64, lhs); }
1891
std::string VL_TO_STRING_W(int words, const WDataInP obj) {
1892
    return VL_SFORMATF_N_NX("'h%0x", 0, words * VL_EDATASIZE, obj);
1893
}
1894

1895
std::string VL_TOLOWER_NN(const std::string& ld) VL_PURE {
1896
    std::string result = ld;
1897
    for (auto& cr : result) cr = std::tolower(cr);
1898
    return result;
1899
}
1900
std::string VL_TOUPPER_NN(const std::string& ld) VL_PURE {
1901
    std::string result = ld;
1902
    for (auto& cr : result) cr = std::toupper(cr);
1903
    return result;
1904
}
1905

1906
std::string VL_CVT_PACK_STR_NW(int lwords, const WDataInP lwp) VL_PURE {
1907
    // See also _vl_vint_to_string
1908
    char destout[VL_VALUE_STRING_MAX_CHARS + 1];
1909
    const int obits = lwords * VL_EDATASIZE;
1910
    int lsb = obits - 1;
1911
    char* destp = destout;
1912
    size_t len = 0;
1913
    for (; lsb >= 0; --lsb) {
1914
        lsb = (lsb / 8) * 8;  // Next digit
1915
        const IData charval = VL_BITRSHIFT_W(lwp, lsb) & 0xff;
1916
        if (charval) {
1917
            *destp++ = static_cast<char>(charval);
1918
            ++len;
1919
        }
1920
    }
1921
    return std::string{destout, len};
1922
}
1923

1924
std::string VL_CVT_PACK_STR_ND(const VlQueue<std::string>& q) VL_PURE {
1925
    std::string output;
1926
    for (const std::string& s : q) output += s;
1927
    return output;
1928
}
1929

1930
std::string VL_PUTC_N(const std::string& lhs, IData rhs, CData ths) VL_PURE {
1931
    std::string lstring = lhs;
1932
    const int32_t rhs_s = rhs;  // To signed value
1933
    // 6.16.2:str.putc(i, c) does not change the value when i < 0 || i >= str.len() || c == 0
1934
    if (0 <= rhs_s && rhs < lhs.length() && ths != 0) lstring[rhs] = ths;
1935
    return lstring;
1936
}
1937

1938
CData VL_GETC_N(const std::string& lhs, IData rhs) VL_PURE {
1939
    CData v = 0;
1940
    const int32_t rhs_s = rhs;  // To signed value
1941
    // 6.16.3:str.getc(i) returns 0 if i < 0 || i >= str.len()
1942
    if (0 <= rhs_s && rhs < lhs.length()) v = lhs[rhs];
1943
    return v;
1944
}
1945

1946
std::string VL_SUBSTR_N(const std::string& lhs, IData rhs, IData ths) VL_PURE {
1947
    const int32_t rhs_s = rhs;  // To signed value
1948
    const int32_t ths_s = ths;  // To signed value
1949
    // 6.16.8:str.substr(i, j) returns an empty string when i < 0 || j < i || j >= str.len()
1950
    if (rhs_s < 0 || ths_s < rhs_s || ths >= lhs.length()) return "";
1951
    // Second parameter of std::string::substr(i, n) is length, not position as in SystemVerilog
1952
    return lhs.substr(rhs, ths - rhs + 1);
1953
}
1954

1955
IData VL_ATOI_N(const std::string& str, int base) VL_PURE {
1956
    std::string str_mod = str;
1957
    // IEEE 1800-2023 6.16.9 says '_' may exist.
1958
    str_mod.erase(std::remove(str_mod.begin(), str_mod.end(), '_'), str_mod.end());
1959

1960
    errno = 0;
1961
    auto v = std::strtol(str_mod.c_str(), nullptr, base);
1962
    if (errno != 0) v = 0;
1963
    return static_cast<IData>(v);
1964
}
1965
IData VL_NTOI_I(int obits, const std::string& str) VL_PURE { return VL_NTOI_Q(obits, str); }
1966
QData VL_NTOI_Q(int obits, const std::string& str) VL_PURE {
1967
    QData out = 0;
1968
    const char* const datap = str.data();
1969
    int pos = static_cast<int>(str.length()) - 1;
1970
    int bit = 0;
1971
    while (bit < obits && pos >= 0) {
1972
        out |= static_cast<QData>(datap[pos]) << VL_BITBIT_Q(bit);
1973
        bit += 8;
1974
        --pos;
1975
    }
1976
    return out & VL_MASK_Q(obits);
1977
}
1978
void VL_NTOI_W(int obits, WDataOutP owp, const std::string& str) VL_PURE {
1979
    const int words = VL_WORDS_I(obits);
1980
    for (int i = 0; i < words; ++i) owp[i] = 0;
1981
    const char* const datap = str.data();
1982
    int pos = static_cast<int>(str.length()) - 1;
1983
    int bit = 0;
1984
    while (bit < obits && pos >= 0) {
1985
        owp[VL_BITWORD_I(bit)] |= static_cast<EData>(datap[pos]) << VL_BITBIT_I(bit);
1986
        bit += 8;
1987
        --pos;
1988
    }
1989
    owp[words - 1] &= VL_MASK_E(obits);
1990
}
1991

1992
//===========================================================================
1993
// Readmem/writemem
1994

1995
static const char* memhFormat(int nBits) {
1996
    assert((nBits >= 1) && (nBits <= 32));
1997

1998
    static thread_local char t_buf[32];
1999
    switch ((nBits - 1) / 4) {
2000
    case 0: VL_SNPRINTF(t_buf, 32, "%%01x"); break;
2001
    case 1: VL_SNPRINTF(t_buf, 32, "%%02x"); break;
2002
    case 2: VL_SNPRINTF(t_buf, 32, "%%03x"); break;
2003
    case 3: VL_SNPRINTF(t_buf, 32, "%%04x"); break;
2004
    case 4: VL_SNPRINTF(t_buf, 32, "%%05x"); break;
2005
    case 5: VL_SNPRINTF(t_buf, 32, "%%06x"); break;
2006
    case 6: VL_SNPRINTF(t_buf, 32, "%%07x"); break;
2007
    case 7: VL_SNPRINTF(t_buf, 32, "%%08x"); break;
2008
    default: assert(false); break;  // LCOV_EXCL_LINE
2009
    }
2010
    return t_buf;
2011
}
2012

2013
static const char* formatBinary(int nBits, uint32_t bits) {
2014
    assert((nBits >= 1) && (nBits <= 32));
2015

2016
    static thread_local char t_buf[64];
2017
    for (int i = 0; i < nBits; i++) {
2018
        const bool isOne = bits & (1 << (nBits - 1 - i));
2019
        t_buf[i] = (isOne ? '1' : '0');
2020
    }
2021
    t_buf[nBits] = '\0';
2022
    return t_buf;
2023
}
2024

2025
VlReadMem::VlReadMem(bool hex, int bits, const std::string& filename, QData start, QData end)
2026
    : m_hex{hex}
2027
    , m_bits{bits}
2028
    , m_filename(filename)  // Need () or GCC 4.8 false warning
2029
    , m_end{end}
2030
    , m_addr{start} {
2031
    m_fp = std::fopen(filename.c_str(), "r");
2032
    if (VL_UNLIKELY(!m_fp)) {
2033
        // We don't report the Verilog source filename as it slow to have to pass it down
2034
        VL_WARN_MT(filename.c_str(), 0, "", "$readmem file not found");
2035
        // cppcheck-has-bug-suppress resourceLeak  // m_fp is nullptr
2036
        return;
2037
    }
2038
}
2039
VlReadMem::~VlReadMem() {
2040
    if (m_fp) {
2041
        std::fclose(m_fp);
2042
        m_fp = nullptr;
2043
    }
2044
}
2045
bool VlReadMem::get(QData& addrr, std::string& valuer) {
2046
    if (VL_UNLIKELY(!m_fp)) return false;
2047
    valuer = "";
2048
    // Prep for reading
2049
    bool inData = false;
2050
    bool ignoreToEol = false;
2051
    bool ignoreToComment = false;
2052
    bool readingAddress = false;
2053
    int lastCh = ' ';
2054
    // Read the data
2055
    // We process a character at a time, as then we don't need to deal
2056
    // with changing buffer sizes dynamically, etc.
2057
    while (true) {
2058
        int c = std::fgetc(m_fp);
2059
        if (VL_UNLIKELY(c == EOF)) break;
2060
        const bool chIs4StateBin
2061
            = c == '0' || c == '1' || c == 'x' || c == 'X' || c == 'z' || c == 'Z';
2062
        const bool chIs2StateHex = std::isxdigit(c);
2063
        const bool chIs4StateHex = std::isxdigit(c) || chIs4StateBin;
2064
        // printf("%d: Got '%c' Addr%lx IN%d IgE%d IgC%d\n",
2065
        //        m_linenum, c, m_addr, inData, ignoreToEol, ignoreToComment);
2066
        // See if previous data value has completed, and if so return
2067
        if (c == '_') continue;  // Ignore _ e.g. inside a number
2068
        if (inData && !chIs4StateHex) {
2069
            // printf("Got data @%lx = %s\n", m_addr, valuer.c_str());
2070
            ungetc(c, m_fp);
2071
            addrr = m_addr;
2072
            ++m_addr;
2073
            return true;
2074
        }
2075
        // Parse line
2076
        if (c == '\n') {
2077
            ++m_linenum;
2078
            ignoreToEol = false;
2079
            readingAddress = false;
2080
        } else if (c == '\t' || c == ' ' || c == '\r' || c == '\f') {
2081
            readingAddress = false;
2082
        }
2083
        // Skip // comments and detect /* comments
2084
        else if (ignoreToComment && lastCh == '*' && c == '/') {
2085
            ignoreToComment = false;
2086
            readingAddress = false;
2087
        } else if (!ignoreToEol && !ignoreToComment) {
2088
            if (lastCh == '/' && c == '*') {
2089
                ignoreToComment = true;
2090
            } else if (lastCh == '/' && c == '/') {
2091
                ignoreToEol = true;
2092
            } else if (c == '/') {  // Part of /* or //
2093
            } else if (c == '#') {
2094
                ignoreToEol = true;
2095
            } else if (c == '@') {
2096
                readingAddress = true;
2097
                m_anyAddr = true;
2098
                m_addr = 0;
2099
            } else if (readingAddress && chIs2StateHex) {
2100
                c = std::tolower(c);
2101
                const int addressValue = (c >= 'a') ? (c - 'a' + 10) : (c - '0');
2102
                m_addr = (m_addr << 4) + addressValue;
2103
            } else if (readingAddress && chIs4StateHex) {
2104
                VL_FATAL_MT(m_filename.c_str(), m_linenum, "",
2105
                            "$readmem address contains 4-state characters");
2106
            } else if (chIs4StateHex) {
2107
                inData = true;
2108
                valuer += static_cast<char>(c);
2109
                if (VL_UNLIKELY(!m_hex && !chIs4StateBin)) {
2110
                    VL_FATAL_MT(m_filename.c_str(), m_linenum, "",
2111
                                "$readmemb (binary) file contains hex characters");
2112
                }
2113
            } else {
2114
                VL_FATAL_MT(m_filename.c_str(), m_linenum, "", "$readmem file syntax error");
2115
            }
2116
        }
2117
        lastCh = c;
2118
    }
2119

2120
    if (VL_UNLIKELY(m_end != ~0ULL && m_addr <= m_end && !m_anyAddr)) {
2121
        VL_WARN_MT(m_filename.c_str(), m_linenum, "",
2122
                   "$readmem file ended before specified final address (IEEE 1800-2023 21.4)");
2123
    }
2124

2125
    addrr = m_addr;
2126
    return inData;  // EOF
2127
}
2128
void VlReadMem::setData(void* valuep, const std::string& rhs) {
2129
    const QData shift = m_hex ? 4ULL : 1ULL;
2130
    bool innum = false;
2131
    // Shift value in
2132
    for (const auto& i : rhs) {
2133
        const char c = std::tolower(i);
2134
        const int value = (c == 'x' || c == 'z') ? VL_RAND_RESET_I(m_hex ? 4 : 1)
2135
                          : (c >= 'a')           ? (c - 'a' + 10)
2136
                                                 : (c - '0');
2137
        if (m_bits <= 8) {
2138
            CData* const datap = reinterpret_cast<CData*>(valuep);
2139
            if (!innum) *datap = 0;
2140
            *datap = ((*datap << shift) + value) & VL_MASK_I(m_bits);
2141
        } else if (m_bits <= 16) {
2142
            SData* const datap = reinterpret_cast<SData*>(valuep);
2143
            if (!innum) *datap = 0;
2144
            *datap = ((*datap << shift) + value) & VL_MASK_I(m_bits);
2145
        } else if (m_bits <= VL_IDATASIZE) {
2146
            IData* const datap = reinterpret_cast<IData*>(valuep);
2147
            if (!innum) *datap = 0;
2148
            *datap = ((*datap << shift) + value) & VL_MASK_I(m_bits);
2149
        } else if (m_bits <= VL_QUADSIZE) {
2150
            QData* const datap = reinterpret_cast<QData*>(valuep);
2151
            if (!innum) *datap = 0;
2152
            *datap = ((*datap << static_cast<QData>(shift)) + static_cast<QData>(value))
2153
                     & VL_MASK_Q(m_bits);
2154
        } else {
2155
            WDataOutP datap = reinterpret_cast<WDataOutP>(valuep);
2156
            if (!innum) VL_ZERO_W(m_bits, datap);
2157
            _vl_shiftl_inplace_w(m_bits, datap, static_cast<IData>(shift));
2158
            datap[0] |= value;
2159
        }
2160
        innum = true;
2161
    }
2162
}
2163

2164
VlWriteMem::VlWriteMem(bool hex, int bits, const std::string& filename, QData start, QData end)
2165
    : m_hex{hex}
2166
    , m_bits{bits} {
2167
    if (VL_UNLIKELY(start > end)) {
2168
        VL_FATAL_MT(filename.c_str(), 0, "", "$writemem invalid address range");
2169
        return;
2170
    }
2171

2172
    m_fp = std::fopen(filename.c_str(), "w");
2173
    if (VL_UNLIKELY(!m_fp)) {
2174
        VL_FATAL_MT(filename.c_str(), 0, "", "$writemem file not found");
2175
        // cppcheck-has-bug-suppress resourceLeak  // m_fp is nullptr
2176
        return;
2177
    }
2178
}
2179
VlWriteMem::~VlWriteMem() {
2180
    if (m_fp) {
2181
        std::fclose(m_fp);
2182
        m_fp = nullptr;
2183
    }
2184
}
2185
void VlWriteMem::print(QData addr, bool addrstamp, const void* valuep) {
2186
    if (VL_UNLIKELY(!m_fp)) return;
2187
    if (addr != m_addr && addrstamp) {  // Only assoc has time stamps
2188
        fprintf(m_fp, "@%" PRIx64 "\n", addr);
2189
    }
2190
    m_addr = addr + 1;
2191
    if (m_bits <= 8) {
2192
        const CData* const datap = reinterpret_cast<const CData*>(valuep);
2193
        if (m_hex) {
2194
            fprintf(m_fp, memhFormat(m_bits), VL_MASK_I(m_bits) & *datap);
2195
            fprintf(m_fp, "\n");
2196
        } else {
2197
            fprintf(m_fp, "%s\n", formatBinary(m_bits, *datap));
2198
        }
2199
    } else if (m_bits <= 16) {
2200
        const SData* const datap = reinterpret_cast<const SData*>(valuep);
2201
        if (m_hex) {
2202
            fprintf(m_fp, memhFormat(m_bits), VL_MASK_I(m_bits) & *datap);
2203
            fprintf(m_fp, "\n");
2204
        } else {
2205
            fprintf(m_fp, "%s\n", formatBinary(m_bits, *datap));
2206
        }
2207
    } else if (m_bits <= 32) {
2208
        const IData* const datap = reinterpret_cast<const IData*>(valuep);
2209
        if (m_hex) {
2210
            fprintf(m_fp, memhFormat(m_bits), VL_MASK_I(m_bits) & *datap);
2211
            fprintf(m_fp, "\n");
2212
        } else {
2213
            fprintf(m_fp, "%s\n", formatBinary(m_bits, *datap));
2214
        }
2215
    } else if (m_bits <= 64) {
2216
        const QData* const datap = reinterpret_cast<const QData*>(valuep);
2217
        const uint64_t value = VL_MASK_Q(m_bits) & *datap;
2218
        const uint32_t lo = value & 0xffffffff;
2219
        const uint32_t hi = value >> 32;
2220
        if (m_hex) {
2221
            fprintf(m_fp, memhFormat(m_bits - 32), hi);
2222
            fprintf(m_fp, "%08x\n", lo);
2223
        } else {
2224
            fprintf(m_fp, "%s", formatBinary(m_bits - 32, hi));
2225
            fprintf(m_fp, "%s\n", formatBinary(32, lo));
2226
        }
2227
    } else {
2228
        const WDataInP datap = reinterpret_cast<WDataInP>(valuep);
2229
        // output as a sequence of VL_EDATASIZE'd words
2230
        // from MSB to LSB. Mask off the MSB word which could
2231
        // contain junk above the top of valid data.
2232
        int word_idx = ((m_bits - 1) / VL_EDATASIZE);
2233
        bool first = true;
2234
        while (word_idx >= 0) {
2235
            EData data = datap[word_idx];
2236
            if (first) {
2237
                data &= VL_MASK_E(m_bits);
2238
                const int top_word_nbits = VL_BITBIT_E(m_bits - 1) + 1;
2239
                if (m_hex) {
2240
                    fprintf(m_fp, memhFormat(top_word_nbits), data);
2241
                } else {
2242
                    fprintf(m_fp, "%s", formatBinary(top_word_nbits, data));
2243
                }
2244
            } else {
2245
                if (m_hex) {
2246
                    fprintf(m_fp, "%08x", data);
2247
                } else {
2248
                    fprintf(m_fp, "%s", formatBinary(32, data));
2249
                }
2250
            }
2251
            --word_idx;
2252
            first = false;
2253
        }
2254
        fprintf(m_fp, "\n");
2255
    }
2256
}
2257

2258
void VL_READMEM_N(bool hex,  // Hex format, else binary
2259
                  int bits,  // M_Bits of each array row
2260
                  QData depth,  // Number of rows
2261
                  int array_lsb,  // Index of first row. Valid row addresses
2262
                  //              //  range from array_lsb up to (array_lsb + depth - 1)
2263
                  const std::string& filename,  // Input file name
2264
                  void* memp,  // Array state
2265
                  QData start,  // First array row address to read
2266
                  QData end  // Last row address to read
2267
                  ) VL_MT_SAFE {
2268
    if (start < static_cast<QData>(array_lsb)) start = array_lsb;
2269

2270
    VlReadMem rmem{hex, bits, filename, start, end};
2271
    if (VL_UNLIKELY(!rmem.isOpen())) return;
2272
    while (true) {
2273
        QData addr = 0;
2274
        std::string value;
2275
        if (rmem.get(addr /*ref*/, value /*ref*/)) {
2276
            // printf("readmem.get [%" PRIu64 "]=%s\n", addr, value.c_str());
2277
            if (VL_UNLIKELY(addr < static_cast<QData>(array_lsb)
2278
                            || addr >= static_cast<QData>(array_lsb + depth))) {
2279
                VL_FATAL_MT(filename.c_str(), rmem.linenum(), "",
2280
                            "$readmem file address beyond bounds of array");
2281
            } else {
2282
                const QData entry = addr - array_lsb;
2283
                if (bits <= 8) {
2284
                    CData* const datap = &(reinterpret_cast<CData*>(memp))[entry];
2285
                    rmem.setData(datap, value);
2286
                } else if (bits <= 16) {
2287
                    SData* const datap = &(reinterpret_cast<SData*>(memp))[entry];
2288
                    rmem.setData(datap, value);
2289
                } else if (bits <= VL_IDATASIZE) {
2290
                    IData* const datap = &(reinterpret_cast<IData*>(memp))[entry];
2291
                    rmem.setData(datap, value);
2292
                } else if (bits <= VL_QUADSIZE) {
2293
                    QData* const datap = &(reinterpret_cast<QData*>(memp))[entry];
2294
                    rmem.setData(datap, value);
2295
                } else {
2296
                    WDataOutP datap
2297
                        = &(reinterpret_cast<WDataOutP>(memp))[entry * VL_WORDS_I(bits)];
2298
                    rmem.setData(datap, value);
2299
                }
2300
            }
2301
        } else {
2302
            break;
2303
        }
2304
    }
2305
}
2306

2307
void VL_WRITEMEM_N(bool hex,  // Hex format, else binary
2308
                   int bits,  // Width of each array row
2309
                   QData depth,  // Number of rows
2310
                   int array_lsb,  // Index of first row. Valid row addresses
2311
                   //              //  range from array_lsb up to (array_lsb + depth - 1)
2312
                   const std::string& filename,  // Output file name
2313
                   const void* memp,  // Array state
2314
                   QData start,  // First array row address to write
2315
                   QData end  // Last address to write, or ~0 when not specified
2316
                   ) VL_MT_SAFE {
2317
    const QData addr_max = array_lsb + depth - 1;
2318
    if (start < static_cast<QData>(array_lsb)) start = array_lsb;
2319
    if (end > addr_max) end = addr_max;
2320

2321
    VlWriteMem wmem{hex, bits, filename, start, end};
2322
    if (VL_UNLIKELY(!wmem.isOpen())) return;
2323

2324
    for (QData addr = start; addr <= end; ++addr) {
2325
        const QData row_offset = addr - array_lsb;
2326
        if (bits <= 8) {
2327
            const CData* const datap = &(reinterpret_cast<const CData*>(memp))[row_offset];
2328
            wmem.print(addr, false, datap);
2329
        } else if (bits <= 16) {
2330
            const SData* const datap = &(reinterpret_cast<const SData*>(memp))[row_offset];
2331
            wmem.print(addr, false, datap);
2332
        } else if (bits <= 32) {
2333
            const IData* const datap = &(reinterpret_cast<const IData*>(memp))[row_offset];
2334
            wmem.print(addr, false, datap);
2335
        } else if (bits <= 64) {
2336
            const QData* const datap = &(reinterpret_cast<const QData*>(memp))[row_offset];
2337
            wmem.print(addr, false, datap);
2338
        } else {
2339
            const WDataInP memDatap = reinterpret_cast<WDataInP>(memp);
2340
            const WDataInP datap = &memDatap[row_offset * VL_WORDS_I(bits)];
2341
            wmem.print(addr, false, datap);
2342
        }
2343
    }
2344
}
2345

2346
//===========================================================================
2347
// Timescale conversion
2348

2349
static const char* vl_time_str(int scale) VL_PURE {
2350
    static const char* const names[]
2351
        = {"100s",  "10s",  "1s",  "100ms", "10ms", "1ms", "100us", "10us", "1us",
2352
           "100ns", "10ns", "1ns", "100ps", "10ps", "1ps", "100fs", "10fs", "1fs"};
2353
    if (VL_UNLIKELY(scale > 2 || scale < -15)) scale = 0;
2354
    return names[2 - scale];
2355
}
2356
double vl_time_multiplier(int scale) VL_PURE {
2357
    // Return timescale multiplier -18 to +18
2358
    // For speed, this does not check for illegal values
2359
    // cppcheck-has-bug-suppress arrayIndexOutOfBoundsCond
2360
    if (scale < 0) {
2361
        static const double neg10[] = {1.0,
2362
                                       0.1,
2363
                                       0.01,
2364
                                       0.001,
2365
                                       0.0001,
2366
                                       0.00001,
2367
                                       0.000001,
2368
                                       0.0000001,
2369
                                       0.00000001,
2370
                                       0.000000001,
2371
                                       0.0000000001,
2372
                                       0.00000000001,
2373
                                       0.000000000001,
2374
                                       0.0000000000001,
2375
                                       0.00000000000001,
2376
                                       0.000000000000001,
2377
                                       0.0000000000000001,
2378
                                       0.00000000000000001,
2379
                                       0.000000000000000001};
2380
        // cppcheck-has-bug-suppress arrayIndexOutOfBoundsCond
2381
        return neg10[-scale];
2382
    } else {
2383
        static const double pow10[] = {1.0,
2384
                                       10.0,
2385
                                       100.0,
2386
                                       1000.0,
2387
                                       10000.0,
2388
                                       100000.0,
2389
                                       1000000.0,
2390
                                       10000000.0,
2391
                                       100000000.0,
2392
                                       1000000000.0,
2393
                                       10000000000.0,
2394
                                       100000000000.0,
2395
                                       1000000000000.0,
2396
                                       10000000000000.0,
2397
                                       100000000000000.0,
2398
                                       1000000000000000.0,
2399
                                       10000000000000000.0,
2400
                                       100000000000000000.0,
2401
                                       1000000000000000000.0};
2402
        // cppcheck-has-bug-suppress arrayIndexOutOfBoundsCond
2403
        return pow10[scale];
2404
    }
2405
}
2406
uint64_t vl_time_pow10(int n) {
2407
    static const uint64_t pow10[20] = {
2408
        1ULL,
2409
        10ULL,
2410
        100ULL,
2411
        1000ULL,
2412
        10000ULL,
2413
        100000ULL,
2414
        1000000ULL,
2415
        10000000ULL,
2416
        100000000ULL,
2417
        1000000000ULL,
2418
        10000000000ULL,
2419
        100000000000ULL,
2420
        1000000000000ULL,
2421
        10000000000000ULL,
2422
        100000000000000ULL,
2423
        1000000000000000ULL,
2424
        10000000000000000ULL,
2425
        100000000000000000ULL,
2426
        1000000000000000000ULL,
2427
    };
2428
    return pow10[n];
2429
}
2430

2431
std::string vl_timescaled_double(double value, const char* format) VL_PURE {
2432
    const char* suffixp = "s";
2433
    // clang-format off
2434
    if      (value >= 1e0)   { suffixp = "s"; value *= 1e0; }
2435
    else if (value >= 1e-3)  { suffixp = "ms"; value *= 1e3; }
2436
    else if (value >= 1e-6)  { suffixp = "us"; value *= 1e6; }
2437
    else if (value >= 1e-9)  { suffixp = "ns"; value *= 1e9; }
2438
    else if (value >= 1e-12) { suffixp = "ps"; value *= 1e12; }
2439
    else if (value >= 1e-15) { suffixp = "fs"; value *= 1e15; }
2440
    else if (value >= 1e-18) { suffixp = "as"; value *= 1e18; }
2441
    // clang-format on
2442
    char valuestr[100];
2443
    VL_SNPRINTF(valuestr, 100, format, value, suffixp);
2444
    return std::string{valuestr};  // Gets converted to string, so no ref to stack
2445
}
2446

2447
void VL_PRINTTIMESCALE(const char* namep, const char* timeunitp,
2448
                       const VerilatedContext* contextp) VL_MT_SAFE {
2449
    VL_PRINTF_MT("Time scale of %s is %s / %s\n", namep, timeunitp,
2450
                 contextp->timeprecisionString());
2451
}
2452
void VL_TIMEFORMAT_IINI(int units, int precision, const std::string& suffix, int width,
2453
                        VerilatedContext* contextp) VL_MT_SAFE {
2454
    contextp->impp()->timeFormatUnits(units);
2455
    contextp->impp()->timeFormatPrecision(precision);
2456
    contextp->impp()->timeFormatSuffix(suffix);
2457
    contextp->impp()->timeFormatWidth(width);
2458
}
2459

2460
//======================================================================
2461
// VerilatedContext:: Methods
2462

2463
VerilatedContext::VerilatedContext()
2464
    : m_impdatap{new VerilatedContextImpData} {
2465
    Verilated::lastContextp(this);
2466
    Verilated::threadContextp(this);
2467
    m_ns.m_coverageFilename = "coverage.dat";
2468
    m_ns.m_profExecFilename = "profile_exec.dat";
2469
    m_ns.m_profVltFilename = "profile.vlt";
2470
    m_ns.m_solverProgram = VlOs::getenvStr("VERILATOR_SOLVER", VL_SOLVER_DEFAULT);
2471
    m_fdps.resize(31);
2472
    std::fill(m_fdps.begin(), m_fdps.end(), static_cast<FILE*>(nullptr));
2473
    m_fdFreeMct.resize(30);
2474
    IData id = 1;
2475
    for (std::size_t i = 0; i < m_fdFreeMct.size(); ++i, ++id) m_fdFreeMct[i] = id;
2476
}
2477

2478
// Must declare here not in interface, as otherwise forward declarations not known
2479
VerilatedContext::~VerilatedContext() {
2480
    checkMagic(this);
2481
    m_magic = 0x1;  // Arbitrary but 0x1 is what Verilator src uses for a deleted pointer
2482
}
2483

2484
void VerilatedContext::checkMagic(const VerilatedContext* contextp) {
2485
    if (VL_UNLIKELY(!contextp || contextp->m_magic != MAGIC)) {
2486
        VL_FATAL_MT("", 0, "",  // LCOV_EXCL_LINE
2487
                    "Attempt to create model using a bad/deleted VerilatedContext pointer");
2488
    }
2489
}
2490

2491
VerilatedContext::Serialized::Serialized() {
2492
    constexpr int8_t picosecond = -12;
2493
    m_timeunit = picosecond;  // Initial value until overridden by _Vconfigure
2494
    m_timeprecision = picosecond;  // Initial value until overridden by _Vconfigure
2495
}
2496

2497
void VerilatedContext::assertOn(bool flag) VL_MT_SAFE {
2498
    const VerilatedLockGuard lock{m_mutex};
2499
    m_s.m_assertOn = flag;
2500
}
2501
void VerilatedContext::calcUnusedSigs(bool flag) VL_MT_SAFE {
2502
    const VerilatedLockGuard lock{m_mutex};
2503
    m_s.m_calcUnusedSigs = flag;
2504
}
2505
void VerilatedContext::coverageFilename(const std::string& flag) VL_MT_SAFE {
2506
    const VerilatedLockGuard lock{m_mutex};
2507
    m_ns.m_coverageFilename = flag;
2508
}
2509
std::string VerilatedContext::coverageFilename() const VL_MT_SAFE {
2510
    const VerilatedLockGuard lock{m_mutex};
2511
    return m_ns.m_coverageFilename;
2512
}
2513
void VerilatedContext::dumpfile(const std::string& flag) VL_MT_SAFE_EXCLUDES(m_timeDumpMutex) {
2514
    const VerilatedLockGuard lock{m_timeDumpMutex};
2515
    m_dumpfile = flag;
2516
}
2517
std::string VerilatedContext::dumpfile() const VL_MT_SAFE_EXCLUDES(m_timeDumpMutex) {
2518
    const VerilatedLockGuard lock{m_timeDumpMutex};
2519
    return m_dumpfile;
2520
}
2521
std::string VerilatedContext::dumpfileCheck() const VL_MT_SAFE_EXCLUDES(m_timeDumpMutex) {
2522
    std::string out = dumpfile();
2523
    if (VL_UNLIKELY(out.empty())) {
2524
        VL_PRINTF_MT("%%Warning: $dumpvar ignored as not preceded by $dumpfile\n");
2525
        return "";
2526
    }
2527
    return out;
2528
}
2529
void VerilatedContext::errorCount(int val) VL_MT_SAFE {
2530
    const VerilatedLockGuard lock{m_mutex};
2531
    m_s.m_errorCount = val;
2532
}
2533
void VerilatedContext::errorCountInc() VL_MT_SAFE {
2534
    const VerilatedLockGuard lock{m_mutex};
2535
    ++m_s.m_errorCount;
2536
}
2537
void VerilatedContext::errorLimit(int val) VL_MT_SAFE {
2538
    const VerilatedLockGuard lock{m_mutex};
2539
    m_s.m_errorLimit = val;
2540
}
2541
void VerilatedContext::fatalOnError(bool flag) VL_MT_SAFE {
2542
    const VerilatedLockGuard lock{m_mutex};
2543
    m_s.m_fatalOnError = flag;
2544
}
2545
void VerilatedContext::fatalOnVpiError(bool flag) VL_MT_SAFE {
2546
    const VerilatedLockGuard lock{m_mutex};
2547
    m_s.m_fatalOnVpiError = flag;
2548
}
2549
void VerilatedContext::gotError(bool flag) VL_MT_SAFE {
2550
    const VerilatedLockGuard lock{m_mutex};
2551
    m_s.m_gotError = flag;
2552
}
2553
void VerilatedContext::gotFinish(bool flag) VL_MT_SAFE {
2554
    const VerilatedLockGuard lock{m_mutex};
2555
    m_s.m_gotFinish = flag;
2556
}
2557
void VerilatedContext::profExecStart(uint64_t flag) VL_MT_SAFE {
2558
    const VerilatedLockGuard lock{m_mutex};
2559
    m_ns.m_profExecStart = flag;
2560
}
2561
void VerilatedContext::profExecWindow(uint64_t flag) VL_MT_SAFE {
2562
    const VerilatedLockGuard lock{m_mutex};
2563
    m_ns.m_profExecWindow = flag;
2564
}
2565
void VerilatedContext::profExecFilename(const std::string& flag) VL_MT_SAFE {
2566
    const VerilatedLockGuard lock{m_mutex};
2567
    m_ns.m_profExecFilename = flag;
2568
}
2569
std::string VerilatedContext::profExecFilename() const VL_MT_SAFE {
2570
    const VerilatedLockGuard lock{m_mutex};
2571
    return m_ns.m_profExecFilename;
2572
}
2573
void VerilatedContext::profVltFilename(const std::string& flag) VL_MT_SAFE {
2574
    const VerilatedLockGuard lock{m_mutex};
2575
    m_ns.m_profVltFilename = flag;
2576
}
2577
std::string VerilatedContext::profVltFilename() const VL_MT_SAFE {
2578
    const VerilatedLockGuard lock{m_mutex};
2579
    return m_ns.m_profVltFilename;
2580
}
2581
void VerilatedContext::solverProgram(const std::string& flag) VL_MT_SAFE {
2582
    const VerilatedLockGuard lock{m_mutex};
2583
    m_ns.m_solverProgram = flag;
2584
}
2585
std::string VerilatedContext::solverProgram() const VL_MT_SAFE {
2586
    const VerilatedLockGuard lock{m_mutex};
2587
    return m_ns.m_solverProgram;
2588
}
2589
void VerilatedContext::quiet(bool flag) VL_MT_SAFE {
2590
    const VerilatedLockGuard lock{m_mutex};
2591
    m_s.m_quiet = flag;
2592
}
2593
void VerilatedContext::randReset(int val) VL_MT_SAFE {
2594
    const VerilatedLockGuard lock{m_mutex};
2595
    m_s.m_randReset = val;
2596
}
2597
void VerilatedContext::timeunit(int value) VL_MT_SAFE {
2598
    if (value < 0) value = -value;  // Stored as 0..15
2599
    const VerilatedLockGuard lock{m_mutex};
2600
    m_s.m_timeunit = value;
2601
}
2602
const char* VerilatedContext::timeunitString() const VL_MT_SAFE { return vl_time_str(timeunit()); }
2603
const char* VerilatedContext::timeprecisionString() const VL_MT_SAFE {
2604
    return vl_time_str(timeprecision());
2605
}
2606

2607
void VerilatedContext::threads(unsigned n) {
2608
    if (n == 0) VL_FATAL_MT(__FILE__, __LINE__, "", "%Error: Simulation threads must be >= 1");
2609

2610
    if (m_threadPool) {
2611
        VL_FATAL_MT(
2612
            __FILE__, __LINE__, "",
2613
            "%Error: Cannot set simulation threads after the thread pool has been created.");
2614
    }
2615

2616
    if (m_threads == n) return;  // To avoid unnecessary warnings
2617
    m_threads = n;
2618
    const unsigned hardwareThreadsAvailable = std::thread::hardware_concurrency();
2619
    if (m_threads > hardwareThreadsAvailable) {
2620
        VL_PRINTF_MT("%%Warning: System has %u hardware threads but simulation thread count set "
2621
                     "to %u. This will likely cause significant slowdown.\n",
2622
                     hardwareThreadsAvailable, m_threads);
2623
    }
2624
}
2625

2626
void VerilatedContext::commandArgs(int argc, const char** argv) VL_MT_SAFE_EXCLUDES(m_argMutex) {
2627
    // Not locking m_argMutex here, it is done in impp()->commandArgsAddGuts
2628
    // m_argMutex here is the same as in impp()->commandArgsAddGuts;
2629
    // due to clang limitations, it doesn't properly check it
2630
    impp()->commandArgsGuts(argc, argv);
2631
}
2632
void VerilatedContext::commandArgsAdd(int argc, const char** argv)
2633
    VL_MT_SAFE_EXCLUDES(m_argMutex) {
2634
    // Not locking m_argMutex here, it is done in impp()->commandArgsAddGuts
2635
    // m_argMutex here is the same as in impp()->commandArgsAddGuts;
2636
    // due to clang limitations, it doesn't properly check it
2637
    impp()->commandArgsAddGutsLock(argc, argv);
2638
}
2639
const char* VerilatedContext::commandArgsPlusMatch(const char* prefixp)
2640
    VL_MT_SAFE_EXCLUDES(m_argMutex) {
2641
    const std::string& match = impp()->argPlusMatch(prefixp);
2642
    static thread_local char t_outstr[VL_VALUE_STRING_MAX_WIDTH];
2643
    if (match.empty()) return "";
2644
    char* dp = t_outstr;
2645
    for (const char* sp = match.c_str(); *sp && (dp - t_outstr) < (VL_VALUE_STRING_MAX_WIDTH - 2);)
2646
        *dp++ = *sp++;
2647
    *dp++ = '\0';
2648
    return t_outstr;
2649
}
2650
void VerilatedContext::internalsDump() const VL_MT_SAFE {
2651
    VL_PRINTF_MT("internalsDump:\n");
2652
    VerilatedImp::versionDump();
2653
    impp()->commandArgDump();
2654
    impp()->scopesDump();
2655
    VerilatedImp::exportsDump();
2656
    VerilatedImp::userDump();
2657
}
2658

2659
void VerilatedContext::addModel(VerilatedModel* modelp) {
2660
    if (!quiet()) {
2661
        // CPU time isn't read as starting point until model creation, so that quiet() is set
2662
        // Thus if quiet(), avoids slow OS read affecting some usages that make many models
2663
        const VerilatedLockGuard lock{m_mutex};
2664
        m_ns.m_cpuTimeStart.start();
2665
        m_ns.m_wallTimeStart.start();
2666
    }
2667

2668
    // We look for time passing, as opposed to post-eval(), as embedded
2669
    // models might get added inside initial blocks.
2670
    if (VL_UNLIKELY(time()))
2671
        VL_FATAL_MT(
2672
            "", 0, "",
2673
            "Adding model when time is non-zero. ... Suggest check time(), or for restarting"
2674
            " model use a new VerilatedContext");
2675

2676
    threadPoolp();  // Ensure thread pool is created, so m_threads cannot change any more
2677
    m_threadsInModels += modelp->threads();
2678
    if (VL_UNLIKELY(modelp->threads() > m_threads)) {
2679
        std::ostringstream msg;
2680
        msg << "VerilatedContext has " << m_threads << " threads but model '"
2681
            << modelp->modelName() << "' (instantiated as '" << modelp->hierName()
2682
            << "') was Verilated with --threads " << modelp->threads() << ".\n";
2683
        const std::string str = msg.str();
2684
        VL_FATAL_MT(__FILE__, __LINE__, modelp->hierName(), str.c_str());
2685
    }
2686
}
2687

2688
VerilatedVirtualBase* VerilatedContext::threadPoolp() {
2689
    if (m_threads == 1) return nullptr;
2690
    if (!m_threadPool) m_threadPool.reset(new VlThreadPool{this, m_threads - 1});
2691
    return m_threadPool.get();
2692
}
2693

2694
void VerilatedContext::prepareClone() { delete m_threadPool.release(); }
2695

2696
VerilatedVirtualBase* VerilatedContext::threadPoolpOnClone() {
2697
    if (VL_UNLIKELY(m_threadPool)) m_threadPool.release();
2698
    m_threadPool = std::unique_ptr<VlThreadPool>(new VlThreadPool{this, m_threads - 1});
2699
    return m_threadPool.get();
2700
}
2701

2702
VerilatedVirtualBase*
2703
VerilatedContext::enableExecutionProfiler(VerilatedVirtualBase* (*construct)(VerilatedContext&)) {
2704
    if (!m_executionProfiler) m_executionProfiler.reset(construct(*this));
2705
    return m_executionProfiler.get();
2706
}
2707

2708
//======================================================================
2709
// VerilatedContextImp:: Methods - command line
2710

2711
void VerilatedContextImp::commandArgsGuts(int argc, const char** argv)
2712
    VL_MT_SAFE_EXCLUDES(m_argMutex) {
2713
    const VerilatedLockGuard lock{m_argMutex};
2714
    m_args.m_argVec.clear();  // Empty first, then add
2715
    commandArgsAddGuts(argc, argv);
2716
}
2717

2718
void VerilatedContextImp::commandArgsAddGutsLock(int argc, const char** argv)
2719
    VL_MT_SAFE_EXCLUDES(m_argMutex) {
2720
    const VerilatedLockGuard lock{m_argMutex};
2721
    commandArgsAddGuts(argc, argv);
2722
}
2723

2724
void VerilatedContextImp::commandArgsAddGuts(int argc, const char** argv) VL_REQUIRES(m_argMutex) {
2725
    if (!m_args.m_argVecLoaded) m_args.m_argVec.clear();
2726
    for (int i = 0; i < argc; ++i) {
2727
        m_args.m_argVec.emplace_back(argv[i]);
2728
        commandArgVl(argv[i]);
2729
    }
2730
    m_args.m_argVecLoaded = true;  // Can't just test later for empty vector, no arguments is ok
2731
}
2732
void VerilatedContextImp::commandArgDump() const VL_MT_SAFE_EXCLUDES(m_argMutex) {
2733
    const VerilatedLockGuard lock{m_argMutex};
2734
    VL_PRINTF_MT("  Argv:");
2735
    for (const auto& i : m_args.m_argVec) VL_PRINTF_MT(" %s", i.c_str());
2736
    VL_PRINTF_MT("\n");
2737
}
2738
std::string VerilatedContextImp::argPlusMatch(const char* prefixp)
2739
    VL_MT_SAFE_EXCLUDES(m_argMutex) {
2740
    const VerilatedLockGuard lock{m_argMutex};
2741
    // Note prefixp does not include the leading "+"
2742
    const size_t len = std::strlen(prefixp);
2743
    if (VL_UNLIKELY(!m_args.m_argVecLoaded)) {
2744
        m_args.m_argVecLoaded = true;  // Complain only once
2745
        VL_FATAL_MT("unknown", 0, "",
2746
                    "%Error: Verilog called $test$plusargs or $value$plusargs without"
2747
                    " testbench C first calling Verilated::commandArgs(argc,argv).");
2748
    }
2749
    for (const auto& i : m_args.m_argVec) {
2750
        if (i[0] == '+') {
2751
            if (0 == std::strncmp(prefixp, i.c_str() + 1, len)) return i;
2752
        }
2753
    }
2754
    return "";
2755
}
2756
// Return string representing current argv
2757
// Only used by VPI so uses static storage, only supports most recent called context
2758
std::pair<int, char**> VerilatedContextImp::argc_argv() VL_MT_SAFE_EXCLUDES(m_argMutex) {
2759
    const VerilatedLockGuard lock{m_argMutex};
2760
    static bool s_loaded = false;
2761
    static int s_argc = 0;
2762
    static char** s_argvp = nullptr;
2763
    if (VL_UNLIKELY(!s_loaded)) {
2764
        s_loaded = true;
2765
        s_argc = static_cast<int>(m_args.m_argVec.size());
2766
        s_argvp = new char*[s_argc + 1];
2767
        int in = 0;
2768
        for (const auto& i : m_args.m_argVec) {
2769
            s_argvp[in] = new char[i.length() + 1];
2770
            std::memcpy(s_argvp[in], i.c_str(), i.length() + 1);
2771
            ++in;
2772
        }
2773
        s_argvp[s_argc] = nullptr;
2774
    }
2775
    return std::make_pair(s_argc, s_argvp);
2776
}
2777

2778
void VerilatedContextImp::commandArgVl(const std::string& arg) {
2779
    if (0 == std::strncmp(arg.c_str(), "+verilator+", std::strlen("+verilator+"))) {
2780
        std::string str;
2781
        uint64_t u64;
2782
        if (commandArgVlString(arg, "+verilator+coverage+file+", str)) {
2783
            coverageFilename(str);
2784
        } else if (arg == "+verilator+debug") {
2785
            Verilated::debug(4);
2786
        } else if (commandArgVlUint64(arg, "+verilator+debugi+", u64, 0,
2787
                                      std::numeric_limits<int>::max())) {
2788
            Verilated::debug(static_cast<int>(u64));
2789
        } else if (commandArgVlUint64(arg, "+verilator+error+limit+", u64, 0,
2790
                                      std::numeric_limits<int>::max())) {
2791
            errorLimit(static_cast<int>(u64));
2792
        } else if (arg == "+verilator+help") {
2793
            VerilatedImp::versionDump();
2794
            VL_PRINTF_MT("For help, please see 'verilator --help'\n");
2795
            VL_FATAL_MT("COMMAND_LINE", 0, "",
2796
                        "Exiting due to command line argument (not an error)");
2797
        } else if (arg == "+verilator+noassert") {
2798
            assertOn(false);
2799
        } else if (commandArgVlUint64(arg, "+verilator+prof+exec+start+", u64)) {
2800
            profExecStart(u64);
2801
        } else if (commandArgVlUint64(arg, "+verilator+prof+exec+window+", u64, 1)) {
2802
            profExecWindow(u64);
2803
        } else if (commandArgVlString(arg, "+verilator+prof+exec+file+", str)) {
2804
            profExecFilename(str);
2805
        } else if (commandArgVlString(arg, "+verilator+prof+vlt+file+", str)) {
2806
            profVltFilename(str);
2807
        } else if (arg == "+verilator+quiet") {
2808
            quiet(true);
2809
        } else if (commandArgVlUint64(arg, "+verilator+rand+reset+", u64, 0, 2)) {
2810
            randReset(static_cast<int>(u64));
2811
        } else if (commandArgVlUint64(arg, "+verilator+seed+", u64, 1,
2812
                                      std::numeric_limits<int>::max())) {
2813
            randSeed(static_cast<int>(u64));
2814
        } else if (arg == "+verilator+V") {
2815
            VerilatedImp::versionDump();  // Someday more info too
2816
            VL_FATAL_MT("COMMAND_LINE", 0, "",
2817
                        "Exiting due to command line argument (not an error)");
2818
        } else if (arg == "+verilator+version") {
2819
            VerilatedImp::versionDump();
2820
            VL_FATAL_MT("COMMAND_LINE", 0, "",
2821
                        "Exiting due to command line argument (not an error)");
2822
        } else {
2823
            const std::string msg = "Unknown runtime argument: " + arg;
2824
            VL_FATAL_MT("COMMAND_LINE", 0, "", msg.c_str());
2825
        }
2826
    }
2827
}
2828

2829
bool VerilatedContextImp::commandArgVlString(const std::string& arg, const std::string& prefix,
2830
                                             std::string& valuer) {
2831
    const size_t len = prefix.length();
2832
    if (0 == std::strncmp(prefix.c_str(), arg.c_str(), len)) {
2833
        valuer = arg.substr(len);
2834
        return true;
2835
    } else {
2836
        return false;
2837
    }
2838
}
2839

2840
bool VerilatedContextImp::commandArgVlUint64(const std::string& arg, const std::string& prefix,
2841
                                             uint64_t& valuer, uint64_t min, uint64_t max) {
2842
    std::string str;
2843
    if (commandArgVlString(arg, prefix, str)) {
2844
        const auto fail = [&](const std::string& extra = "") {
2845
            std::stringstream ss;
2846
            ss << "Argument '" << prefix << "' must be an unsigned integer";
2847
            if (min != std::numeric_limits<uint64_t>::min()) ss << ", greater than " << min - 1;
2848
            if (max != std::numeric_limits<uint64_t>::max()) ss << ", less than " << max + 1;
2849
            if (!extra.empty()) ss << ". " << extra;
2850
            const std::string& msg = ss.str();
2851
            VL_FATAL_MT("COMMAND_LINE", 0, "", msg.c_str());
2852
        };
2853

2854
        if (std::any_of(str.cbegin(), str.cend(), [](int c) { return !std::isdigit(c); })) fail();
2855
        char* end;
2856
        valuer = std::strtoull(str.c_str(), &end, 10);
2857
        if (errno == ERANGE) fail("Value out of range of uint64_t");
2858
        if (valuer < min || valuer > max) fail();
2859
        return true;
2860
    }
2861
    return false;
2862
}
2863

2864
//======================================================================
2865
// VerilatedContext:: + VerilatedContextImp:: Methods - random
2866

2867
void VerilatedContext::randSeed(int val) VL_MT_SAFE {
2868
    // As we have per-thread state, the epoch must be static,
2869
    // and so the rand seed's mutex must also be static
2870
    const VerilatedLockGuard lock{VerilatedContextImp::s().s_randMutex};
2871
    m_s.m_randSeed = val;
2872
    const uint64_t newEpoch = VerilatedContextImp::s().s_randSeedEpoch + 1;
2873
    // Observers must see new epoch AFTER seed updated
2874
    std::atomic_signal_fence(std::memory_order_release);
2875
    VerilatedContextImp::s().s_randSeedEpoch = newEpoch;
2876
}
2877
uint64_t VerilatedContextImp::randSeedDefault64() const VL_MT_SAFE {
2878
    if (randSeed() != 0) {
2879
        return ((static_cast<uint64_t>(randSeed()) << 32) ^ (static_cast<uint64_t>(randSeed())));
2880
    } else {
2881
        return ((static_cast<uint64_t>(vl_sys_rand32()) << 32)
2882
                ^ (static_cast<uint64_t>(vl_sys_rand32())));
2883
    }
2884
}
2885

2886
//======================================================================
2887
// VerilatedContext:: Statistics
2888

2889
double VerilatedContext::statCpuTimeSinceStart() const VL_MT_SAFE_EXCLUDES(m_mutex) {
2890
    const VerilatedLockGuard lock{m_mutex};
2891
    return m_ns.m_cpuTimeStart.deltaTime();
2892
}
2893
double VerilatedContext::statWallTimeSinceStart() const VL_MT_SAFE_EXCLUDES(m_mutex) {
2894
    const VerilatedLockGuard lock{m_mutex};
2895
    return m_ns.m_wallTimeStart.deltaTime();
2896
}
2897
void VerilatedContext::statsPrintSummary() VL_MT_UNSAFE {
2898
    if (quiet()) return;
2899
    VL_PRINTF("- S i m u l a t i o n   R e p o r t: %s %s\n", Verilated::productName(),
2900
              Verilated::productVersion());
2901
    const std::string endwhy = gotError() ? "$stop" : gotFinish() ? "$finish" : "end";
2902
    const double simtimeInUnits = VL_TIME_Q() * vl_time_multiplier(timeunit())
2903
                                  * vl_time_multiplier(timeprecision() - timeunit());
2904
    const std::string simtime = vl_timescaled_double(simtimeInUnits);
2905
    const double walltime = statWallTimeSinceStart();
2906
    const double cputime = statCpuTimeSinceStart();
2907
    const std::string simtimePerf
2908
        = vl_timescaled_double((cputime != 0.0) ? (simtimeInUnits / cputime) : 0, "%0.3f %s");
2909
    VL_PRINTF("- Verilator: %s at %s; walltime %0.3f s; speed %s/s\n", endwhy.c_str(),
2910
              simtime.c_str(), walltime, simtimePerf.c_str());
2911
    const double modelMB = VlOs::memUsageBytes() / 1024.0 / 1024.0;
2912
    VL_PRINTF("- Verilator: cpu %0.3f s on %u threads; alloced %0.0f MB\n", cputime,
2913
              threadsInModels(), modelMB);
2914
}
2915

2916
//======================================================================
2917
// VerilatedContext:: Methods - scopes
2918

2919
void VerilatedContext::scopesDump() const VL_MT_SAFE {
2920
    const VerilatedLockGuard lock{m_impdatap->m_nameMutex};
2921
    VL_PRINTF_MT("  scopesDump:\n");
2922
    for (const auto& i : m_impdatap->m_nameMap) {
2923
        const VerilatedScope* const scopep = i.second;
2924
        scopep->scopeDump();
2925
    }
2926
    VL_PRINTF_MT("\n");
2927
}
2928

2929
void VerilatedContextImp::scopeInsert(const VerilatedScope* scopep) VL_MT_SAFE {
2930
    // Slow ok - called once/scope at construction
2931
    const VerilatedLockGuard lock{m_impdatap->m_nameMutex};
2932
    const auto it = m_impdatap->m_nameMap.find(scopep->name());
2933
    if (it == m_impdatap->m_nameMap.end()) m_impdatap->m_nameMap.emplace(scopep->name(), scopep);
2934
}
2935
void VerilatedContextImp::scopeErase(const VerilatedScope* scopep) VL_MT_SAFE {
2936
    // Slow ok - called once/scope at destruction
2937
    const VerilatedLockGuard lock{m_impdatap->m_nameMutex};
2938
    VerilatedImp::userEraseScope(scopep);
2939
    const auto it = m_impdatap->m_nameMap.find(scopep->name());
2940
    if (it != m_impdatap->m_nameMap.end()) m_impdatap->m_nameMap.erase(it);
2941
}
2942
const VerilatedScope* VerilatedContext::scopeFind(const char* namep) const VL_MT_SAFE {
2943
    // Thread save only assuming this is called only after model construction completed
2944
    const VerilatedLockGuard lock{m_impdatap->m_nameMutex};
2945
    // If too slow, can assume this is only VL_MT_SAFE_POSINIT
2946
    const auto& it = m_impdatap->m_nameMap.find(namep);
2947
    if (VL_UNLIKELY(it == m_impdatap->m_nameMap.end())) return nullptr;
2948
    return it->second;
2949
}
2950
const VerilatedScopeNameMap* VerilatedContext::scopeNameMap() VL_MT_SAFE {
2951
    return &(impp()->m_impdatap->m_nameMap);
2952
}
2953

2954
//======================================================================
2955
// VerilatedContext:: Methods - trace
2956

2957
void VerilatedContext::trace(VerilatedTraceBaseC* tfp, int levels, int options) VL_MT_SAFE {
2958
    VL_DEBUG_IF(VL_DBG_MSGF("+ VerilatedContext::trace\n"););
2959
    if (tfp->isOpen()) {
2960
        VL_FATAL_MT("", 0, "",
2961
                    "Testbench C call to 'VerilatedContext::trace()' must not be called"
2962
                    " after 'VerilatedTrace*::open()'\n");
2963
    }
2964
    {
2965
        // Legacy usage may call {modela}->trace(...) then {modelb}->trace(...)
2966
        // So check for and suppress second and later calls
2967
        if (tfp->modelConnected()) return;
2968
        tfp->modelConnected(true);
2969
    }
2970
    // We rely on m_ns.m_traceBaseModelCbs being stable when trace() is called
2971
    // nope: const VerilatedLockGuard lock{m_mutex};
2972
    if (m_ns.m_traceBaseModelCbs.empty())
2973
        VL_FATAL_MT("", 0, "",
2974
                    "Testbench C call to 'VerilatedContext::trace()' requires model(s) Verilated"
2975
                    " with --trace or --trace-vcd option");
2976
    for (auto& cbr : m_ns.m_traceBaseModelCbs) cbr(tfp, levels, options);
2977
}
2978
void VerilatedContext::traceBaseModelCbAdd(traceBaseModelCb_t cb) VL_MT_SAFE {
2979
    // Model creation registering a callback for when Verilated::trace() called
2980
    const VerilatedLockGuard lock{m_mutex};
2981
    m_ns.m_traceBaseModelCbs.push_back(cb);
2982
}
2983

2984
//======================================================================
2985
// VerilatedSyms:: Methods
2986

2987
VerilatedSyms::VerilatedSyms(VerilatedContext* contextp)
2988
    : _vm_contextp__(contextp ? contextp : Verilated::threadContextp()) {
2989
    VerilatedContext::checkMagic(_vm_contextp__);
2990
    Verilated::threadContextp(_vm_contextp__);
2991
    // cppcheck-has-bug-suppress noCopyConstructor
2992
    __Vm_evalMsgQp = new VerilatedEvalMsgQueue;
2993
}
2994

2995
VerilatedSyms::~VerilatedSyms() {
2996
    VerilatedContext::checkMagic(_vm_contextp__);
2997
    delete __Vm_evalMsgQp;
2998
}
2999

3000
//===========================================================================
3001
// Verilated:: Methods
3002

3003
void Verilated::debug(int level) VL_MT_SAFE {
3004
    s_debug = level;
3005
    if (level) {
3006
#ifdef VL_DEBUG
3007
        VL_DEBUG_IF(VL_DBG_MSGF("- Verilated::debug is on."
3008
                                " Message prefix indicates {<thread>,<sequence_number>}.\n"););
3009
#else
3010
        VL_PRINTF_MT("- Verilated::debug attempted,"
3011
                     " but compiled without VL_DEBUG, so messages suppressed.\n"
3012
                     "- Suggest remake using 'make ... CPPFLAGS=-DVL_DEBUG'\n");
3013
#endif
3014
    }
3015
}
3016

3017
const char* Verilated::catName(const char* n1, const char* n2, const char* delimiter) VL_MT_SAFE {
3018
    // Used by symbol table creation to make module names
3019
    static thread_local char* t_strp = nullptr;
3020
    static thread_local size_t t_len = 0;
3021
    const size_t newlen = std::strlen(n1) + std::strlen(n2) + std::strlen(delimiter) + 1;
3022
    if (VL_UNLIKELY(!t_strp || newlen > t_len)) {
3023
        if (t_strp) delete[] t_strp;
3024
        t_strp = new char[newlen];
3025
        t_len = newlen;
3026
    }
3027
    char* dp = t_strp;
3028
    for (const char* sp = n1; *sp;) *dp++ = *sp++;
3029
    for (const char* sp = delimiter; *sp;) *dp++ = *sp++;
3030
    for (const char* sp = n2; *sp;) *dp++ = *sp++;
3031
    *dp++ = '\0';
3032
    return t_strp;
3033
}
3034

3035
//=========================================================================
3036
// Flush and exit callbacks
3037

3038
// Keeping these out of class Verilated to avoid having to include <list>
3039
// in verilated.h (for compilation speed)
3040
using VoidPCbList = std::list<std::pair<Verilated::VoidPCb, void*>>;
3041
static struct {
3042
    VerilatedMutex s_flushMutex;
3043
    VoidPCbList s_flushCbs VL_GUARDED_BY(s_flushMutex);
3044
    VerilatedMutex s_exitMutex;
3045
    VoidPCbList s_exitCbs VL_GUARDED_BY(s_exitMutex);
3046
} VlCbStatic;
3047

3048
static void addCbFlush(Verilated::VoidPCb cb, void* datap)
3049
    VL_MT_SAFE_EXCLUDES(VlCbStatic.s_flushMutex) {
3050
    const VerilatedLockGuard lock{VlCbStatic.s_flushMutex};
3051
    std::pair<Verilated::VoidPCb, void*> pair(cb, datap);
3052
    VlCbStatic.s_flushCbs.remove(pair);  // Just in case it's a duplicate
3053
    VlCbStatic.s_flushCbs.push_back(pair);
3054
}
3055
static void addCbExit(Verilated::VoidPCb cb, void* datap)
3056
    VL_MT_SAFE_EXCLUDES(VlCbStatic.s_exitMutex) {
3057
    const VerilatedLockGuard lock{VlCbStatic.s_exitMutex};
3058
    std::pair<Verilated::VoidPCb, void*> pair(cb, datap);
3059
    VlCbStatic.s_exitCbs.remove(pair);  // Just in case it's a duplicate
3060
    VlCbStatic.s_exitCbs.push_back(pair);
3061
}
3062
static void removeCbFlush(Verilated::VoidPCb cb, void* datap)
3063
    VL_MT_SAFE_EXCLUDES(VlCbStatic.s_flushMutex) {
3064
    const VerilatedLockGuard lock{VlCbStatic.s_flushMutex};
3065
    std::pair<Verilated::VoidPCb, void*> pair(cb, datap);
3066
    VlCbStatic.s_flushCbs.remove(pair);
3067
}
3068
static void removeCbExit(Verilated::VoidPCb cb, void* datap)
3069
    VL_MT_SAFE_EXCLUDES(VlCbStatic.s_exitMutex) {
3070
    const VerilatedLockGuard lock{VlCbStatic.s_exitMutex};
3071
    std::pair<Verilated::VoidPCb, void*> pair(cb, datap);
3072
    VlCbStatic.s_exitCbs.remove(pair);
3073
}
3074
static void runCallbacks(const VoidPCbList& cbs) VL_MT_SAFE {
3075
    for (const auto& i : cbs) i.first(i.second);
3076
}
3077

3078
void Verilated::addFlushCb(VoidPCb cb, void* datap) VL_MT_SAFE { addCbFlush(cb, datap); }
3079
void Verilated::removeFlushCb(VoidPCb cb, void* datap) VL_MT_SAFE { removeCbFlush(cb, datap); }
3080
void Verilated::runFlushCallbacks() VL_MT_SAFE {
3081
    // Flush routines may call flush, so avoid mutex deadlock
3082
    static std::atomic<int> s_recursing;
3083
    if (!s_recursing++) {
3084
        const VerilatedLockGuard lock{VlCbStatic.s_flushMutex};
3085
        runCallbacks(VlCbStatic.s_flushCbs);
3086
    }
3087
    --s_recursing;
3088
    std::fflush(stderr);
3089
    std::fflush(stdout);
3090
    // When running internal code coverage (gcc --coverage, as opposed to
3091
    // verilator --coverage), dump coverage data to properly cover failing
3092
    // tests.
3093
    VL_GCOV_DUMP();
3094
}
3095

3096
void Verilated::addExitCb(VoidPCb cb, void* datap) VL_MT_SAFE { addCbExit(cb, datap); }
3097
void Verilated::removeExitCb(VoidPCb cb, void* datap) VL_MT_SAFE { removeCbExit(cb, datap); }
3098
void Verilated::runExitCallbacks() VL_MT_SAFE {
3099
    static std::atomic<int> s_recursing;
3100
    if (!s_recursing++) {
3101
        const VerilatedLockGuard lock{VlCbStatic.s_exitMutex};
3102
        runCallbacks(VlCbStatic.s_exitCbs);
3103
    }
3104
    --s_recursing;
3105
}
3106

3107
const char* Verilated::productName() VL_PURE { return VERILATOR_PRODUCT; }
3108
const char* Verilated::productVersion() VL_PURE { return VERILATOR_VERSION; }
3109

3110
void Verilated::nullPointerError(const char* filename, int linenum) VL_MT_SAFE {
3111
    // Slowpath - Called only on error
3112
    VL_FATAL_MT(filename, linenum, "", "Null pointer dereferenced");
3113
    VL_UNREACHABLE;
3114
}
3115

3116
void Verilated::overWidthError(const char* signame) VL_MT_SAFE {
3117
    // Slowpath - Called only when signal sets too high of a bit
3118
    const std::string msg = ("Testbench C set input '"s + signame
3119
                             + "' to value that overflows what the signal's width can fit");
3120
    VL_FATAL_MT("unknown", 0, "", msg.c_str());
3121
    VL_UNREACHABLE;
3122
}
3123

3124
void Verilated::scTimePrecisionError(int sc_prec, int vl_prec) VL_MT_SAFE {
3125
    std::ostringstream msg;
3126
    msg << "SystemC's sc_set_time_resolution is 10^-" << sc_prec
3127
        << ", which does not match Verilog timeprecision 10^-" << vl_prec
3128
        << ". Suggest use 'sc_set_time_resolution(" << vl_time_str(vl_prec)
3129
        << ")', or Verilator '--timescale-override " << vl_time_str(sc_prec) << "/"
3130
        << vl_time_str(sc_prec) << "'";
3131
    const std::string msgs = msg.str();
3132
    VL_FATAL_MT("", 0, "", msgs.c_str());
3133
    VL_UNREACHABLE;
3134
}
3135

3136
void Verilated::scTraceBeforeElaborationError() VL_MT_SAFE {
3137
    // Slowpath - Called only when trace file opened before SystemC elaboration
3138
    VL_FATAL_MT("unknown", 0, "",
3139
                "%Error: Verilated*Sc::open(...) was called before sc_core::sc_start(). "
3140
                "Run sc_core::sc_start(sc_core::SC_ZERO_TIME) before opening a wave file.");
3141
    VL_UNREACHABLE;
3142
}
3143

3144
void Verilated::stackCheck(QData needSize) VL_MT_UNSAFE {
3145
    // Slowpath - Called only when constructing
3146
#ifdef _VL_HAVE_GETRLIMIT
3147
    QData haveSize = 0;
3148
    rlimit rlim;
3149
    if (0 == getrlimit(RLIMIT_STACK, &rlim)) {
3150
        haveSize = rlim.rlim_cur;
3151
        if (haveSize == RLIM_INFINITY) haveSize = rlim.rlim_max;
3152
        if (haveSize == RLIM_INFINITY) haveSize = 0;
3153
    }
3154
    // VL_PRINTF_MT("-Info: stackCheck(%" PRIu64 ") have %" PRIu64 "\n", needSize, haveSize);
3155
    // Check and request for 1.5x need. This is automated so the user doesn't need to do anything.
3156
    QData requestSize = needSize + needSize / 2;
3157
    if (VL_UNLIKELY(haveSize && needSize && haveSize < requestSize)) {
3158
        // Try to increase the stack limit to the requested size
3159
        rlim.rlim_cur = requestSize;
3160
        if (
3161
#ifdef _VL_TEST_RLIMIT_FAIL
3162
            true ||
3163
#endif
3164
            setrlimit(RLIMIT_STACK, &rlim)) {
3165
            VL_PRINTF_MT("%%Warning: System has stack size %" PRIu64 " kb"
3166
                         " which may be too small; failed to request more"
3167
                         " using 'ulimit -s %" PRIu64 "'\n",
3168
                         haveSize / 1024, requestSize);
3169
        }
3170
    }
3171
#else
3172
    (void)needSize;  // Unused argument
3173
#endif
3174
}
3175

3176
void Verilated::mkdir(const char* dirname) VL_MT_UNSAFE {
3177
#if defined(_WIN32) || defined(__MINGW32__)
3178
    ::mkdir(dirname);
3179
#else
3180
    ::mkdir(dirname, 0777);
3181
#endif
3182
}
3183

3184
void Verilated::quiesce() VL_MT_SAFE {
3185
    // Wait until all threads under this evaluation are quiet
3186
    // THREADED-TODO
3187
}
3188

3189
int Verilated::exportFuncNum(const char* namep) VL_MT_SAFE {
3190
    return VerilatedImp::exportFind(namep);
3191
}
3192

3193
void Verilated::endOfThreadMTaskGuts(VerilatedEvalMsgQueue* evalMsgQp) VL_MT_SAFE {
3194
    VL_DEBUG_IF(VL_DBG_MSGF("End of thread mtask\n"););
3195
    VerilatedThreadMsgQueue::flush(evalMsgQp);
3196
}
3197

3198
void Verilated::endOfEval(VerilatedEvalMsgQueue* evalMsgQp) VL_MT_SAFE {
3199
    // It doesn't work to set endOfEvalReqd on the threadpool thread
3200
    // and then check it on the eval thread since it's thread local.
3201
    // It should be ok to call into endOfEvalGuts, it returns immediately
3202
    // if there are no transactions.
3203
    VL_DEBUG_IF(VL_DBG_MSGF("End-of-eval cleanup\n"););
3204
    VerilatedThreadMsgQueue::flush(evalMsgQp);
3205
    evalMsgQp->process();
3206
}
3207

3208
//===========================================================================
3209
// VerilatedImp:: Methods
3210

3211
void VerilatedImp::versionDump() VL_MT_SAFE {
3212
    VL_PRINTF_MT("  Version: %s %s\n", Verilated::productName(), Verilated::productVersion());
3213
}
3214

3215
//===========================================================================
3216
// VerilatedModel:: Methods
3217

3218
VerilatedModel::VerilatedModel(VerilatedContext& context)
3219
    : m_context{context} {}
3220

3221
std::unique_ptr<VerilatedTraceConfig> VerilatedModel::traceConfig() const { return nullptr; }
3222

3223
//===========================================================================
3224
// VerilatedModule:: Methods
3225

3226
VerilatedModule::VerilatedModule(const char* namep)
3227
    : m_namep{strdup(namep)} {}
3228

3229
VerilatedModule::~VerilatedModule() {
3230
    // Memory cleanup - not called during normal operation
3231
    // NOLINTNEXTLINE(google-readability-casting)
3232
    if (m_namep) VL_DO_CLEAR(free((void*)(m_namep)), m_namep = nullptr);
3233
}
3234

3235
//======================================================================
3236
// VerilatedVar:: Methods
3237

3238
// cppcheck-suppress unusedFunction  // Used by applications
3239
uint32_t VerilatedVarProps::entSize() const VL_MT_SAFE {
3240
    uint32_t size = 1;
3241
    switch (vltype()) {
3242
    case VLVT_PTR: size = sizeof(void*); break;
3243
    case VLVT_UINT8: size = sizeof(CData); break;
3244
    case VLVT_UINT16: size = sizeof(SData); break;
3245
    case VLVT_UINT32: size = sizeof(IData); break;
3246
    case VLVT_UINT64: size = sizeof(QData); break;
3247
    case VLVT_WDATA: size = VL_WORDS_I(packed().elements()) * sizeof(IData); break;
3248
    default: size = 0; break;  // LCOV_EXCL_LINE
3249
    }
3250
    return size;
3251
}
3252

3253
size_t VerilatedVarProps::totalSize() const {
3254
    size_t size = entSize();
3255
    for (int udim = 0; udim < udims(); ++udim) size *= m_unpacked[udim].elements();
3256
    return size;
3257
}
3258

3259
void* VerilatedVarProps::datapAdjustIndex(void* datap, int dim, int indx) const VL_MT_SAFE {
3260
    if (VL_UNLIKELY(dim <= 0 || dim > udims())) return nullptr;
3261
    if (VL_UNLIKELY(indx < low(dim) || indx > high(dim))) return nullptr;
3262
    const int indxAdj = indx - low(dim);
3263
    uint8_t* bytep = reinterpret_cast<uint8_t*>(datap);
3264
    // If on index 1 of a 2 index array, then each index 1 is index2sz*entsz
3265
    size_t slicesz = entSize();
3266
    for (int d = dim + 1; d <= m_udims; ++d) slicesz *= elements(d);
3267
    bytep += indxAdj * slicesz;
3268
    return bytep;
3269
}
3270

3271
//======================================================================
3272
// VerilatedScope:: Methods
3273

3274
VerilatedScope::~VerilatedScope() {
3275
    // Memory cleanup - not called during normal operation
3276
    Verilated::threadContextp()->impp()->scopeErase(this);
3277
    if (m_namep) VL_DO_CLEAR(delete[] m_namep, m_namep = nullptr);
3278
    if (m_callbacksp) VL_DO_CLEAR(delete[] m_callbacksp, m_callbacksp = nullptr);
3279
    if (m_varsp) VL_DO_CLEAR(delete m_varsp, m_varsp = nullptr);
3280
    m_funcnumMax = 0;  // Force callback table to empty
3281
}
3282

3283
void VerilatedScope::configure(VerilatedSyms* symsp, const char* prefixp, const char* suffixp,
3284
                               const char* identifier, int8_t timeunit,
3285
                               const Type& type) VL_MT_UNSAFE {
3286
    // Slowpath - called once/scope at construction
3287
    // We don't want the space and reference-count access overhead of strings.
3288
    m_symsp = symsp;
3289
    m_type = type;
3290
    m_timeunit = timeunit;
3291
    {
3292
        char* const namep = new char[std::strlen(prefixp) + std::strlen(suffixp) + 2];
3293
        char* dp = namep;
3294
        for (const char* sp = prefixp; *sp;) *dp++ = *sp++;
3295
        if (*prefixp && *suffixp) *dp++ = '.';
3296
        for (const char* sp = suffixp; *sp;) *dp++ = *sp++;
3297
        *dp++ = '\0';
3298
        m_namep = namep;
3299
    }
3300
    m_identifierp = identifier;
3301
    Verilated::threadContextp()->impp()->scopeInsert(this);
3302
}
3303

3304
void VerilatedScope::exportInsert(int finalize, const char* namep, void* cb) VL_MT_UNSAFE {
3305
    // Slowpath - called once/scope*export at construction
3306
    // Insert a exported function into scope table
3307
    const int funcnum = VerilatedImp::exportInsert(namep);
3308
    if (!finalize) {
3309
        // Need two passes so we know array size to create
3310
        // Alternative is to dynamically stretch the array, which is more code, and slower.
3311
        if (funcnum >= m_funcnumMax) m_funcnumMax = funcnum + 1;
3312
    } else {
3313
        if (VL_UNCOVERABLE(funcnum >= m_funcnumMax)) {
3314
            VL_FATAL_MT(__FILE__, __LINE__, "",  // LCOV_EXCL_LINE
3315
                        "Internal: Bad funcnum vs. pre-finalize maximum");
3316
        }
3317
        if (VL_UNLIKELY(!m_callbacksp)) {  // First allocation
3318
            m_callbacksp = new void*[m_funcnumMax];
3319
            std::memset(m_callbacksp, 0, m_funcnumMax * sizeof(void*));
3320
        }
3321
        m_callbacksp[funcnum] = cb;
3322
    }
3323
}
3324

3325
void VerilatedScope::varInsert(int finalize, const char* namep, void* datap, bool isParam,
3326
                               VerilatedVarType vltype, int vlflags, int dims, ...) VL_MT_UNSAFE {
3327
    // Grab dimensions
3328
    // In the future we may just create a large table at emit time and
3329
    // statically construct from that.
3330
    if (!finalize) return;
3331

3332
    if (!m_varsp) m_varsp = new VerilatedVarNameMap;
3333
    VerilatedVar var(namep, datap, vltype, static_cast<VerilatedVarFlags>(vlflags), dims, isParam);
3334

3335
    va_list ap;
3336
    va_start(ap, dims);
3337
    for (int i = 0; i < dims; ++i) {
3338
        const int msb = va_arg(ap, int);
3339
        const int lsb = va_arg(ap, int);
3340
        if (i == 0) {
3341
            var.m_packed.m_left = msb;
3342
            var.m_packed.m_right = lsb;
3343
        } else if (i >= 1 && i <= var.udims()) {
3344
            var.m_unpacked[i - 1].m_left = msb;
3345
            var.m_unpacked[i - 1].m_right = lsb;
3346
        } else {
3347
            // We could have a linked list of ranges, but really this whole thing needs
3348
            // to be generalized to support structs and unions, etc.
3349
            const std::string msg = "Unsupported multi-dimensional public varInsert: "s + namep;
3350
            VL_FATAL_MT(__FILE__, __LINE__, "", msg.c_str());
3351
        }
3352
    }
3353
    va_end(ap);
3354

3355
    m_varsp->emplace(namep, var);
3356
}
3357

3358
// cppcheck-suppress unusedFunction  // Used by applications
3359
VerilatedVar* VerilatedScope::varFind(const char* namep) const VL_MT_SAFE_POSTINIT {
3360
    if (VL_LIKELY(m_varsp)) {
3361
        const auto it = m_varsp->find(namep);
3362
        if (VL_LIKELY(it != m_varsp->end())) return &(it->second);
3363
    }
3364
    return nullptr;
3365
}
3366

3367
void* VerilatedScope::exportFindNullError(int funcnum) VL_MT_SAFE {
3368
    // Slowpath - Called only when find has failed
3369
    const std::string msg = ("Testbench C called '"s + VerilatedImp::exportName(funcnum)
3370
                             + "' but scope wasn't set, perhaps due to dpi import call without "
3371
                             + "'context', or missing svSetScope. See IEEE 1800-2023 35.5.3.");
3372
    VL_FATAL_MT("unknown", 0, "", msg.c_str());
3373
    return nullptr;
3374
}
3375

3376
void* VerilatedScope::exportFindError(int funcnum) const VL_MT_SAFE {
3377
    // Slowpath - Called only when find has failed
3378
    const std::string msg
3379
        = ("Testbench C called '"s + VerilatedImp::exportName(funcnum)
3380
           + "' but this DPI export function exists only in other scopes, not scope '" + name()
3381
           + "'");
3382
    VL_FATAL_MT("unknown", 0, "", msg.c_str());
3383
    return nullptr;
3384
}
3385

3386
void VerilatedScope::scopeDump() const {
3387
    VL_PRINTF_MT("    SCOPE %p: %s\n", this, name());
3388
    for (int i = 0; i < m_funcnumMax; ++i) {
3389
        if (m_callbacksp && m_callbacksp[i]) {
3390
            VL_PRINTF_MT("       DPI-EXPORT %p: %s\n", m_callbacksp[i],
3391
                         VerilatedImp::exportName(i));
3392
        }
3393
    }
3394
    if (const VerilatedVarNameMap* const varsp = this->varsp()) {
3395
        for (const auto& i : *varsp) VL_PRINTF_MT("       VAR %p: %s\n", &(i.second), i.first);
3396
    }
3397
}
3398

3399
void VerilatedHierarchy::add(VerilatedScope* fromp, VerilatedScope* top) {
3400
    VerilatedImp::hierarchyAdd(fromp, top);
3401
}
3402

3403
void VerilatedHierarchy::remove(VerilatedScope* fromp, VerilatedScope* top) {
3404
    VerilatedImp::hierarchyRemove(fromp, top);
3405
}
3406

3407
//===========================================================================
3408
// VerilatedOneThreaded:: Methods
3409

3410
#ifdef VL_DEBUG
3411
void VerilatedAssertOneThread::fatal_different() VL_MT_SAFE {
3412
    VL_FATAL_MT(__FILE__, __LINE__, "",
3413
                "Routine called that is single threaded, but called from"
3414
                " a different thread then the expected constructing thread");
3415
}
3416
#endif
3417

3418
//===========================================================================
3419
// VlDeleter:: Methods
3420

3421
void VlDeleter::deleteAll() VL_EXCLUDES(m_mutex) VL_EXCLUDES(m_deleteMutex) VL_MT_SAFE {
3422
    while (true) {
3423
        {
3424
            VerilatedLockGuard lock{m_mutex};
3425
            if (m_newGarbage.empty()) break;
3426
            m_deleteMutex.lock();
3427
            std::swap(m_newGarbage, m_deleteNow);
3428
            // m_mutex is unlocked here, so destructors can enqueue new objects
3429
        }
3430
        for (VlDeletable* const objp : m_deleteNow) delete objp;
3431
        m_deleteNow.clear();
3432
        m_deleteMutex.unlock();
3433
    }
3434
}
3435

3436
//===========================================================================
3437
// OS functions (last, so we have minimal OS dependencies above)
3438

3439
#define VL_ALLOW_VERILATEDOS_C
3440
#include "verilatedos_c.h"
3441

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.