48
#define VERILATOR_VERILATED_CPP_
50
#include "verilated_config.h"
51
#include "verilatedos.h"
53
#include "verilated_imp.h"
67
#if defined(_WIN32) || defined(__MINGW32__)
72
# define _VL_HAVE_STACKTRACE
74
#if defined(__linux) || (defined(__APPLE__) && defined(__MACH__))
76
# include <sys/resource.h>
77
# define _VL_HAVE_GETRLIMIT
80
#include "verilated_threads.h"
83
#include "verilated_trace.h"
85
#ifdef VM_SOLVER_DEFAULT
86
#define VL_SOLVER_DEFAULT VM_SOLVER_DEFAULT
88
#define VL_SOLVER_DEFAULT "z3 --in"
92
constexpr unsigned VL_VALUE_STRING_MAX_WIDTH = 8192;
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");
107
int Verilated::s_debug = 0;
108
VerilatedContext* Verilated::s_lastContextp = nullptr;
112
thread_local Verilated::ThreadLocal Verilated::t_s;
119
#ifndef VL_USER_FINISH
120
void vl_finish(const char* filename, int linenum, const char* hier) VL_MT_UNSAFE {
124
"- %s:%d: Verilog $finish\n", filename, linenum);
125
Verilated::threadContextp()->gotFinish(true);
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);
137
if (filename && filename[0]) {
139
VL_PRINTF("%%Error: %s:%d: %s\n", filename, linenum, msg);
141
VL_PRINTF("%%Error: %s\n", msg);
143
Verilated::runFlushCallbacks();
149
void vl_fatal(const char* filename, int linenum, const char* hier, const char* msg) VL_MT_UNSAFE {
152
Verilated::threadContextp()->gotError(true);
153
Verilated::threadContextp()->gotFinish(true);
154
if (filename && filename[0]) {
156
VL_PRINTF("%%Error: %s:%d: %s\n", filename, linenum, msg);
158
VL_PRINTF("%%Error: %s\n", msg);
160
Verilated::runFlushCallbacks();
162
VL_PRINTF("Aborting...\n");
165
Verilated::runFlushCallbacks();
168
Verilated::runExitCallbacks();
173
#ifndef VL_USER_STOP_MAYBE
174
void vl_stop_maybe(const char* filename, int linenum, const char* hier, bool maybe) VL_MT_UNSAFE {
175
Verilated::threadContextp()->errorCountInc();
177
&& Verilated::threadContextp()->errorCount() < Verilated::threadContextp()->errorLimit()) {
179
if (Verilated::threadContextp()->errorCount() == 1) {
181
"-Info: %s:%d: %s\n", filename, linenum,
182
"Verilog $stop, ignored due to +verilator+error+limit");
185
vl_stop(filename, linenum, hier);
191
void vl_warn(const char* filename, int linenum, const char* hier, const char* msg) VL_MT_UNSAFE {
194
if (filename && filename[0]) {
196
VL_PRINTF("%%Warning: %s:%d: %s\n", filename, linenum, msg);
198
VL_PRINTF("%%Warning: %s\n", msg);
200
Verilated::runFlushCallbacks();
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);
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);
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);
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);
235
std::string _vl_string_vprintf(const char* formatp, va_list ap) VL_MT_SAFE {
238
const size_t len = VL_VSNPRINTF(nullptr, 0, formatp, aq);
240
if (VL_UNLIKELY(len < 1)) return "";
242
char* const bufp = new char[len + 1];
243
VL_VSNPRINTF(bufp, len + 1, formatp, ap);
245
std::string result{bufp, len};
250
uint64_t _vl_dbg_sequence_number() VL_MT_SAFE {
251
static std::atomic<uint64_t> sequence;
255
uint32_t VL_THREAD_ID() VL_MT_SAFE {
258
static std::atomic<uint32_t> s_nextId(0);
259
static thread_local uint32_t t_myId = ++s_nextId;
263
void VL_DBG_MSGF(const char* formatp, ...) VL_MT_SAFE {
267
va_start(ap, formatp);
268
const std::string result = _vl_string_vprintf(formatp, ap);
276
VL_PRINTF("-V{t%u,%" PRIu64 "}%s", VL_THREAD_ID(), _vl_dbg_sequence_number(), result.c_str());
279
void VL_PRINTF_MT(const char* formatp, ...) VL_MT_SAFE {
281
va_start(ap, formatp);
282
const std::string result = _vl_string_vprintf(formatp, ap);
284
VerilatedThreadMsgQueue::post(VerilatedMsg{[=]() {
285
VL_PRINTF("%s", result.c_str());
292
VlRNG::VlRNG() VL_MT_SAFE {
294
VlRNG& fromr = vl_thread_rng();
295
m_state = fromr.m_state;
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);
303
uint64_t VlRNG::rand64() VL_MT_UNSAFE {
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);
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);
320
void VlRNG::srandom(uint64_t n) VL_MT_UNSAFE {
322
m_state[1] = m_state[0];
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];
328
std::string VlRNG::get_randstate() const VL_MT_UNSAFE {
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);
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");
344
char* const stateCharsp = reinterpret_cast<char*>(&m_state);
345
for (size_t i = 0; i < sizeof(m_state); ++i) {
347
= (((state[1 + i * 2] - 'a') & 15) << 4) | ((state[1 + i * 2 + 1] - 'a') & 15);
351
static uint32_t vl_sys_rand32() VL_MT_SAFE {
354
static VerilatedMutex s_mutex;
355
const VerilatedLockGuard lock{s_mutex};
356
#if defined(_WIN32) && !defined(__CYGWIN__)
358
return (std::rand() << 16) ^ std::rand();
360
return (lrand48() << 16) ^ lrand48();
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;
369
if (VL_UNLIKELY(t_seedEpoch != VerilatedContextImp::randSeedEpoch())) {
371
t_seedEpoch = VerilatedContextImp::randSeedEpoch();
373
t_rng.m_state[0] = Verilated::threadContextp()->impp()->randSeedDefault64();
374
t_rng.m_state[1] = t_rng.m_state[0];
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];
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();
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();
395
IData VL_RANDOM_SEEDED_II(IData& seedr) VL_MT_SAFE {
397
Verilated::threadContextp()->randSeed(static_cast<int>(seedr));
398
seedr = VL_RANDOM_I();
399
return VL_RANDOM_I();
401
IData VL_URANDOM_SEEDED_II(IData seed) VL_MT_SAFE {
403
Verilated::threadContextp()->randSeed(static_cast<int>(seed));
404
return VL_RANDOM_I();
406
IData VL_RAND_RESET_I(int obits) VL_MT_SAFE {
407
if (Verilated::threadContextp()->randReset() == 0) return 0;
409
if (Verilated::threadContextp()->randReset() != 1) {
410
data = VL_RANDOM_I();
412
data &= VL_MASK_I(obits);
415
QData VL_RAND_RESET_Q(int obits) VL_MT_SAFE {
416
if (Verilated::threadContextp()->randReset() == 0) return 0;
418
if (Verilated::threadContextp()->randReset() != 1) {
419
data = VL_RANDOM_Q();
421
data &= VL_MASK_Q(obits);
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);
429
WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp) VL_MT_SAFE {
431
return VL_ZERO_W(obits, outwp);
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]);
446
WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, const WDataInP lwp, const WDataInP rwp,
447
bool is_modulus) VL_MT_SAFE {
452
const int words = VL_WORDS_I(lbits);
453
for (int i = 0; i < words; ++i) owp[i] = 0;
455
const int umsbp1 = VL_MOSTSETBITP1_W(words, lwp);
456
const int vmsbp1 = VL_MOSTSETBITP1_W(words, rwp);
457
if (VL_UNLIKELY(vmsbp1 == 0)
458
|| VL_UNLIKELY(umsbp1 == 0)) {
462
const int uw = VL_WORDS_I(umsbp1);
463
const int vw = VL_WORDS_I(vmsbp1);
464
VL_DEBUG_IFDEF(assert(uw <= VL_MULS_MAX_WORDS););
465
VL_DEBUG_IFDEF(assert(vw <= VL_MULS_MAX_WORDS););
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]);
476
for (int i = 1; i < words; ++i) owp[i] = 0;
482
uint32_t un[VL_MULS_MAX_WORDS + 1];
483
uint32_t vn[VL_MULS_MAX_WORDS + 1];
487
for (int i = 0; i < words + 1; ++i) un[i] = vn[i] = 0;
491
const int s = 31 - VL_BITBIT_I(vmsbp1 - 1);
494
for (int i = vw - 1; i > 0; --i) vn[i] = (rwp[i] << s) | (rwp[i - 1] >> (32 - 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));
500
for (int i = vw - 1; i > 0; --i) vn[i] = rwp[i];
503
for (int i = uw - 1; i > 0; --i) un[i] = lwp[i];
508
for (int j = uw - vw; j >= 0; --j) {
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]);
516
if (qhat >= 0x100000000ULL || ((qhat * vn[vw - 2]) > ((rhat << 32ULL) + un[j + vw - 2]))) {
518
rhat = rhat + vn[vw - 1];
519
if (rhat < 0x100000000ULL) goto again;
524
for (int i = 0; i < vw; ++i) {
525
const uint64_t p = qhat * vn[i];
526
t = un[i + j] - k - (p & 0xFFFFFFFFULL);
528
k = (p >> 32ULL) - (t >> 32ULL);
538
for (int i = 0; i < vw; ++i) {
539
t = static_cast<uint64_t>(un[i + j]) + static_cast<uint64_t>(vn[i]) + k;
543
un[j + vw] = un[j + vw] + k;
550
for (int i = 0; i < vw; ++i) owp[i] = (un[i] >> s) | (un[i + 1] << (32 - s));
552
for (int i = 0; i < vw; ++i) owp[i] = un[i];
554
for (int i = vw; i < words; ++i) owp[i] = 0;
561
WDataOutP VL_POW_WWW(int obits, int, int rbits, WDataOutP owp, const WDataInP lwp,
562
const WDataInP rwp) VL_MT_SAFE {
564
const int owords = VL_WORDS_I(obits);
565
VL_DEBUG_IFDEF(assert(owords <= VL_MULS_MAX_WORDS););
567
for (int i = 1; i < VL_WORDS_I(obits); i++) owp[i] = 0;
569
VlWide<VL_MULS_MAX_WORDS> powstore;
570
VlWide<VL_MULS_MAX_WORDS> lastpowstore;
571
VlWide<VL_MULS_MAX_WORDS> lastoutstore;
573
VL_ASSIGN_W(obits, powstore, lwp);
574
for (int bit = 0; bit < rbits; bit++) {
576
VL_ASSIGN_W(obits, lastpowstore, powstore);
577
VL_MUL_W(owords, powstore, lastpowstore, lastpowstore);
579
if (VL_BITISSET_W(rwp, bit)) {
580
VL_ASSIGN_W(obits, lastoutstore, owp);
581
VL_MUL_W(owords, owp, lastoutstore, powstore);
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);
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);
595
for (int w = 1; w < rwords; ++w) rnz |= rwp[w];
597
if (VL_UNLIKELY(lhs == 0)) return 0;
600
for (int bit = 0; bit < rbits; ++bit) {
601
if (bit > 0) power = power * power;
602
if (VL_BITISSET_W(rwp, bit)) result *= power;
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 {
610
if (rsign && VL_SIGN_W(rbits, rwp)) {
611
const int words = VL_WORDS_I(obits);
612
VL_ZERO_W(obits, owp);
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) {
618
} else if (lor == 0 && lwp[0] == 1) {
621
} else if (lsign && lor == ~VL_EUL(0) && lwp[0] == ~VL_EUL(0)) {
623
return VL_ALLONES_W(obits, owp);
631
return VL_POW_WWW(obits, rbits, rbits, owp, lwp, rwp);
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);
639
QData VL_POWSS_QQW(int obits, int, int rbits, QData lhs, const WDataInP rwp, bool lsign,
640
bool rsign) VL_MT_SAFE {
642
if (rsign && VL_SIGN_W(rbits, rwp)) {
645
} else if (lhs == 1) {
647
} else if (lsign && lhs == VL_MASK_Q(obits)) {
649
return VL_MASK_Q(obits);
656
return VL_POW_QQW(obits, rbits, rbits, lhs, rwp);
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));
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));
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];
680
VL_NEGATE_W(words, pos, lwp);
681
_vl_clean_inplace_w(lbits, pos);
682
return -VL_ITOR_D_W(lbits, pos);
689
std::string VL_DECIMAL_NW(int width, const WDataInP lwp) VL_MT_SAFE {
690
const int maxdecwidth = (width + 3) * 4 / 3;
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;
698
for (; from_bit >= 0 && !(VL_BITRSHIFT_W(lwp, from_bit) & 1); --from_bit) {}
700
for (; from_bit >= 0; --from_bit) {
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);
711
VL_ASSIGN_W(maxdecwidth, tmp, bcd);
712
VL_SHIFTL_WWI(maxdecwidth, maxdecwidth, 32, bcd, tmp, 1);
714
if (VL_BITISSET_W(lwp, from_bit)) bcd[0] |= 1;
717
int lsb = (maxdecwidth - 1) & ~3;
718
for (; lsb > 0; lsb -= 4) {
719
if (VL_BITRSHIFT_W(bcd, lsb) & 0xf) break;
721
for (; lsb >= 0; lsb -= 4) {
722
output += ('0' + (VL_BITRSHIFT_W(bcd, lsb) & 0xf));
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();
732
const int fracDigits = ctxImpp->timeFormatPrecision();
733
const int shift = -userUnits + fracDigits + timeunit;
735
if (std::numeric_limits<T>::is_integer) {
736
constexpr int b = 128;
737
constexpr int w = VL_WORDS_I(b);
743
WDataInP shifted = VL_EXTEND_WQ(b, 0, tmp0, static_cast<QData>(ld));
745
const WDataInP pow10 = VL_EXTEND_WQ(b, 0, tmp1, vl_time_pow10(-shift));
746
shifted = VL_DIV_WWW(b, tmp2, shifted, pow10);
748
const WDataInP pow10 = VL_EXTEND_WQ(b, 0, tmp1, vl_time_pow10(shift));
749
shifted = VL_MUL_W(w, tmp2, shifted, pow10);
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());
757
if (VL_GT_W(w, integer, max64Bit)) {
758
WDataOutP v = VL_ASSIGN_W(b, tmp3, integer);
762
VL_EXTEND_WI(b, 0, ten, 10);
764
char* ptr = buf + sizeof(buf) - 1;
766
while (VL_GT_W(w, v, zero)) {
768
const WDataInP mod = VL_MODDIV_WWW(b, tmp2, v, ten);
769
*ptr = "0123456789"[VL_SET_QW(mod)];
771
VL_DIV_WWW(b, divided, v, ten);
772
VL_ASSIGN_W(b, v, divided);
775
digits = VL_SNPRINTF(tmp, VL_VALUE_STRING_MAX_WIDTH, "%s%s", ptr, suffix.c_str());
777
digits = VL_SNPRINTF(tmp, VL_VALUE_STRING_MAX_WIDTH, "%s.%0*" PRIu64 "%s", ptr,
778
fracDigits, VL_SET_QW(frac), suffix.c_str());
781
const uint64_t integer64 = VL_SET_QW(integer);
783
digits = VL_SNPRINTF(tmp, VL_VALUE_STRING_MAX_WIDTH, "%" PRIu64 "%s", integer64,
786
digits = VL_SNPRINTF(tmp, VL_VALUE_STRING_MAX_WIDTH, "%" PRIu64 ".%0*" PRIu64 "%s",
787
integer64, fracDigits, VL_SET_QW(frac), suffix.c_str());
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;
796
digits = VL_SNPRINTF(tmp, VL_VALUE_STRING_MAX_WIDTH, "%.0f%s", whole, suffix.c_str());
798
digits = VL_SNPRINTF(tmp, VL_VALUE_STRING_MAX_WIDTH, "%.*f%s", fracDigits, whole,
803
const int needmore = static_cast<int>(width) - digits;
805
if (needmore > 0) padding.append(needmore, ' ');
806
return left ? (tmp + padding) : (padding + tmp);
810
#define VL_VA_ARG_Q_(ap, bits) (((bits) <= VL_IDATASIZE) ? va_arg(ap, IData) : va_arg(ap, QData))
812
void _vl_vsformat(std::string& output, const std::string& format, va_list ap) VL_MT_SAFE {
820
static thread_local char t_tmp[VL_VALUE_STRING_MAX_WIDTH];
821
std::string::const_iterator pctit = format.end();
823
bool widthSet = false;
826
for (std::string::const_iterator pos = format.cbegin(); pos != format.cend(); ++pos) {
827
if (!inPct && pos[0] == '%') {
834
std::string::const_iterator ep = pos;
835
while (ep != format.end() && ep[0] != '%') ++ep;
837
output.append(pos, ep);
842
const char fmt = pos[0];
856
width = width * 10 + (fmt - '0');
869
const char* const cstrp = va_arg(ap, const char*);
870
if (VL_LIKELY(*cstrp)) {
877
const char* const cstrp = va_arg(ap, const char*);
883
const std::string* const cstrp = va_arg(ap, const std::string*);
885
if (width > cstrp->size()) padding.append(width - cstrp->size(), ' ');
886
output += left ? (*cstrp + padding) : (padding + *cstrp);
893
const int lbits = va_arg(ap, int);
894
const double d = va_arg(ap, double);
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);
901
const std::string fmts{pctit, pos + 1};
902
VL_SNPRINTF(t_tmp, VL_VALUE_STRING_MAX_WIDTH, fmts.c_str(), d);
909
const int lbits = va_arg(ap, int);
911
VlWide<VL_WQ_WORDS_E> qlwp;
912
WDataInP lwp = nullptr;
913
if (lbits <= VL_QUADSIZE) {
914
ld = VL_VA_ARG_Q_(ap, lbits);
918
lwp = va_arg(ap, WDataInP);
922
if (widthSet && width == 0) {
923
while (lsb && !VL_BITISSET_W(lwp, lsb)) --lsb;
927
const IData charval = ld & 0xff;
928
output += static_cast<char>(charval);
933
for (; lsb >= 0; --lsb) {
935
const IData charval = VL_BITRSHIFT_W(lwp, lsb) & 0xff;
936
field += (charval == 0) ? ' ' : charval;
939
if (width > field.size()) padding.append(width - field.size(), ' ');
940
output += left ? (field + padding) : (padding + field);
946
if (lbits <= VL_QUADSIZE) {
948
= VL_SNPRINTF(t_tmp, VL_VALUE_STRING_MAX_WIDTH, "%" PRId64,
949
static_cast<int64_t>(VL_EXTENDS_QQ(lbits, lbits, ld)));
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);
957
append = VL_DECIMAL_NW(lbits, lwp);
959
digits = static_cast<int>(append.length());
961
const int needmore = static_cast<int>(width) - digits;
965
padding.append(needmore, ' ');
966
output += append + padding;
968
if (pctit != format.end() && pctit[0] && pctit[1] == '0') {
969
padding.append(needmore, '0');
971
padding.append(needmore, ' ');
973
output += padding + append;
983
if (lbits <= VL_QUADSIZE) {
984
digits = VL_SNPRINTF(t_tmp, VL_VALUE_STRING_MAX_WIDTH, "%" PRIu64, ld);
987
append = VL_DECIMAL_NW(lbits, lwp);
988
digits = static_cast<int>(append.length());
990
const int needmore = static_cast<int>(width) - digits;
994
padding.append(needmore, ' ');
995
output += append + padding;
997
if (pctit != format.end() && pctit[0] && pctit[1] == '0') {
998
padding.append(needmore, '0');
1000
padding.append(needmore, ' ');
1002
output += padding + append;
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);
1018
if (widthSet || left) {
1019
lsb = VL_MOSTSETBITP1_W(VL_WORDS_I(lbits), lwp);
1020
lsb = (lsb < 1) ? 0 : (lsb - 1);
1028
for (; lsb >= 0; --lsb) append += (VL_BITRSHIFT_W(lwp, lsb) & 1) + '0';
1032
digits = (lsb + 1 + 2) / 3;
1033
for (; lsb >= 0; --lsb) {
1034
lsb = (lsb / 3) * 3;
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));
1046
digits = (lsb + 1 + 3) / 4;
1047
for (; lsb >= 0; --lsb) {
1048
lsb = (lsb / 4) * 4;
1049
const IData charval = VL_BITRSHIFT_W(lwp, lsb) & 0xf;
1050
append += "0123456789abcdef"[charval];
1056
const int needmore = static_cast<int>(width) - digits;
1058
std::string padding;
1060
padding.append(needmore, ' ');
1061
output += append + padding;
1063
padding.append(needmore, '0');
1064
output += padding + append;
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);
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;
1088
for (lsb = lbits - 1; lsb >= 0; --lsb) {
1089
if (VL_BITRSHIFT_W(lwp, lsb) & 1) {
1097
const std::string msg = "Unknown _vl_vsformat code: "s + pos[0];
1098
VL_FATAL_MT(__FILE__, __LINE__, "", msg.c_str());
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;
1115
static void _vl_vsss_advance(FILE* fp, int& floc) VL_MT_SAFE {
1116
if (VL_LIKELY(fp)) {
1122
static int _vl_vsss_peek(FILE* fp, int& floc, const WDataInP fromp,
1123
const std::string& fstr) VL_MT_SAFE {
1125
if (VL_LIKELY(fp)) {
1126
const int data = std::fgetc(fp);
1127
if (data == EOF) return EOF;
1131
if (floc < 0) return EOF;
1133
if (fromp == nullptr) {
1134
return fstr[fstr.length() - 1 - (floc >> 3)];
1136
return VL_BITRSHIFT_W(fromp, floc) & 0xff;
1140
static void _vl_vsss_skipspace(FILE* fp, int& floc, const WDataInP fromp,
1141
const std::string& fstr) VL_MT_SAFE {
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);
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 {
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;
1156
if (acceptp) c = std::tolower(c);
1158
_vl_vsss_advance(fp, floc);
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 {
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);
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);
1180
void _vl_vsss_based(WDataOutP owp, int obits, int baseLog2, const char* strp, size_t posstart,
1181
size_t posend) VL_MT_SAFE {
1183
VL_ZERO_W(obits, owp);
1185
for (int i = 0, pos = static_cast<int>(posend) - 1;
1186
i < obits && pos >= static_cast<int>(posstart); --pos) {
1188
switch (tolower (strp[pos])) {
1189
case 'x': case 'z': case '?':
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;
1212
IData _vl_vsscanf(FILE* fp,
1213
int fbits, const WDataInP fromp,
1214
const std::string& fstr,
1215
const std::string& format, va_list ap) VL_MT_SAFE {
1219
static thread_local char t_tmp[VL_VALUE_STRING_MAX_WIDTH];
1220
int floc = fbits - 1;
1223
bool inIgnore = false;
1224
std::string::const_iterator pos = format.cbegin();
1225
for (; pos != format.cend() && !_vl_vsss_eof(fp, floc); ++pos) {
1228
if (!inPct && pos[0] == '%') {
1231
} else if (!inPct && std::isspace(pos[0])) {
1232
while (std::isspace(pos[1])) ++pos;
1233
_vl_vsss_skipspace(fp, floc, fromp, fstr);
1234
} else if (!inPct) {
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);
1242
const char fmt = pos[0];
1245
const int c = _vl_vsss_peek(fp, floc, fromp, fstr);
1246
if (c != '%') goto done;
1247
_vl_vsss_advance(fp, floc);
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;
1263
if (VL_UNCOVERABLE(fmt != 's')) {
1265
__FILE__, __LINE__, "",
1266
"Internal: format other than %s is passed to string");
1268
} else if (obits > VL_QUADSIZE) {
1269
owp = va_arg(ap, WDataOutP);
1272
for (int i = 0; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
1275
const int c = _vl_vsss_peek(fp, floc, fromp, fstr);
1276
if (c == EOF) goto done;
1277
_vl_vsss_advance(fp, floc);
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;
1286
int lpos = (static_cast<int>(std::strlen(t_tmp))) - 1;
1288
for (int i = 0; i < obits && lpos >= 0; --lpos) {
1289
_vl_vsss_setbit(owp, obits, lsb, 8, t_tmp[lpos]);
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;
1300
std::sscanf(t_tmp, "%30" PRId64, &ld);
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;
1315
u.r = std::strtod(t_tmp, nullptr);
1316
VL_SET_WQ(owp, u.ld);
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;
1325
std::sscanf(t_tmp, "%30" PRIu64, &ld);
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));
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));
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));
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;
1358
&& !_vl_vsss_read_bin(fp, floc, fromp, fstr, out, 4 - last, true))
1364
char* out = reinterpret_cast<char*>(owp);
1365
int bytes = VL_BYTES_I(obits);
1367
const int abytes = std::min(4, bytes);
1369
out = _vl_vsss_read_bin(fp, floc, fromp, fstr, out, abytes);
1370
if (!out) goto done;
1372
out = _vl_vsss_read_bin(fp, floc, fromp, fstr, out, 8 - abytes, true);
1373
if (!out) goto done;
1379
const std::string msg = "Unknown _vl_vsscanf code: "s + pos[0];
1380
VL_FATAL_MT(__FILE__, __LINE__, "", msg.c_str());
1386
if (!inIgnore) ++got;
1389
} else if (obits == -1) {
1390
std::string* const p = va_arg(ap, std::string*);
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));
1405
_vl_clean_inplace_w(obits, owp);
1418
FILE* VL_CVT_I_FP(IData lhs) VL_MT_SAFE {
1420
return Verilated::threadContextp()->impp()->fdToFp(lhs);
1423
void _vl_vint_to_string(int obits, char* destoutp, const WDataInP sourcep) VL_MT_SAFE {
1425
int lsb = obits - 1;
1427
char* destp = destoutp;
1428
for (; lsb >= 0; --lsb) {
1429
lsb = (lsb / 8) * 8;
1430
const IData charval = VL_BITRSHIFT_W(sourcep, lsb) & 0xff;
1431
if (!start || charval) {
1432
*destp++ = (charval == 0) ? ' ' : charval;
1438
while (std::isspace(*(destp - 1)) && destp > destoutp) *--destp = '\0';
1442
void _vl_string_to_vint(int obits, void* destp, size_t srclen, const char* srcp) VL_MT_SAFE {
1444
const size_t bytes = VL_BYTES_I(obits);
1445
char* op = reinterpret_cast<char*>(destp);
1446
if (srclen > bytes) srclen = bytes;
1448
for (i = 0; i < srclen; ++i) *op++ = srcp[srclen - 1 - i];
1449
for (; i < bytes; ++i) *op++ = 0;
1452
static IData getLine(std::string& str, IData fpi, size_t maxLen) VL_MT_SAFE {
1456
FILE* const fp = VL_CVT_I_FP(fpi);
1457
if (VL_UNLIKELY(!fp)) return 0;
1460
while (str.size() < maxLen) {
1461
const int c = getc(fp);
1462
if (c == EOF) break;
1464
if (c == '\n') break;
1466
return static_cast<IData>(str.size());
1469
IData VL_FGETS_IXI(int obits, void* destp, IData fpi) VL_MT_SAFE {
1471
const IData bytes = VL_BYTES_I(obits);
1472
const IData got = getLine(str, fpi, bytes);
1474
if (VL_UNLIKELY(str.empty())) return 0;
1477
if (VL_UNCOVERABLE(bytes < str.size())) {
1478
VL_FATAL_MT(__FILE__, __LINE__, "", "Internal: fgets buffer overrun");
1481
_vl_string_to_vint(obits, destp, got, str.data());
1485
IData VL_FGETS_NI(std::string& dest, IData fpi) VL_MT_SAFE {
1486
return getLine(dest, fpi, std::numeric_limits<size_t>::max());
1489
IData VL_FERROR_IN(IData, std::string& outputr) VL_MT_SAFE {
1491
const IData ret = errno;
1492
outputr = std::string{::std::strerror(ret)};
1495
IData VL_FERROR_IW(IData fpi, int obits, WDataOutP outwp) VL_MT_SAFE {
1497
const IData ret = VL_FERROR_IN(fpi, output );
1498
_vl_string_to_vint(obits, outwp, output.length(), output.c_str());
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());
1505
IData VL_FOPEN_MCD_N(const std::string& filename) VL_MT_SAFE {
1506
return Verilated::threadContextp()->impp()->fdNewMcd(filename.c_str());
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);
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 {
1516
Verilated::threadContextp()->impp()->fdClose(fdi);
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;
1524
_vl_vsformat(t_output, format, ap);
1527
_vl_string_to_vint(obits, &destr, t_output.length(), t_output.c_str());
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;
1535
_vl_vsformat(t_output, format, ap);
1538
_vl_string_to_vint(obits, &destr, t_output.length(), t_output.c_str());
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;
1546
_vl_vsformat(t_output, format, ap);
1549
_vl_string_to_vint(obits, &destr, t_output.length(), t_output.c_str());
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;
1557
_vl_vsformat(t_output, format, ap);
1560
_vl_string_to_vint(obits, &destr, t_output.length(), t_output.c_str());
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;
1568
_vl_vsformat(t_output, format, ap);
1571
_vl_string_to_vint(obits, destp, t_output.length(), t_output.c_str());
1574
void VL_SFORMAT_NX(int obits_ignored, std::string& output, const std::string& format, int argc,
1576
(void)obits_ignored;
1577
std::string temp_output;
1580
_vl_vsformat(temp_output, format, ap);
1582
output = temp_output;
1585
std::string VL_SFORMATF_N_NX(const std::string& format, int argc, ...) VL_MT_SAFE {
1586
static thread_local std::string t_output;
1590
_vl_vsformat(t_output, format, ap);
1596
void VL_WRITEF_NX(const std::string& format, int argc, ...) VL_MT_SAFE {
1597
static thread_local std::string t_output;
1601
_vl_vsformat(t_output, format, ap);
1604
VL_PRINTF_MT("%s", t_output.c_str());
1607
void VL_FWRITEF_NX(IData fpi, const std::string& format, int argc, ...) VL_MT_SAFE {
1609
static thread_local std::string t_output;
1614
_vl_vsformat(t_output, format, ap);
1617
Verilated::threadContextp()->impp()->fdWrite(fpi, t_output);
1620
IData VL_FSCANF_INX(IData fpi, const std::string& format, int argc, ...) VL_MT_SAFE {
1622
FILE* const fp = VL_CVT_I_FP(fpi);
1623
if (VL_UNLIKELY(!fp)) return ~0U;
1627
const IData got = _vl_vsscanf(fp, 0, nullptr, "", format, ap);
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;
1638
const IData got = _vl_vsscanf(nullptr, lbits, fnw, "", format, ap);
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;
1648
const IData got = _vl_vsscanf(nullptr, lbits, fnw, "", format, ap);
1652
IData VL_SSCANF_IWNX(int lbits, const WDataInP lwp, const std::string& format, int argc,
1656
const IData got = _vl_vsscanf(nullptr, lbits, lwp, "", format, ap);
1660
IData VL_SSCANF_INNX(int, const std::string& ld, const std::string& format, int argc,
1665
= _vl_vsscanf(nullptr, static_cast<int>(ld.length() * 8), nullptr, ld, format, ap);
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 {
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);
1677
IData read_count = 0;
1678
IData read_elements = 0;
1679
const int start_shift = (width - 1) & ~7;
1680
int shift = start_shift;
1685
const int c = std::fgetc(fp);
1686
if (VL_UNLIKELY(c == EOF)) break;
1688
const IData entry = read_elements + start - array_lsb;
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));
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));
1714
shift = start_shift;
1716
if (VL_UNLIKELY(read_elements >= count)) break;
1722
std::string VL_STACKTRACE_N() VL_MT_SAFE {
1723
static VerilatedMutex s_stackTraceMutex;
1724
const VerilatedLockGuard lock{s_stackTraceMutex};
1727
char** strings = nullptr;
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);
1737
if (!strings) return "Unable to backtrace\n";
1739
std::string result = "Backtrace:\n";
1740
for (int j = 0; j < nptrs; j++) result += std::string{strings[j]} + "\n"s;
1745
void VL_STACKTRACE() VL_MT_SAFE {
1746
const std::string result = VL_STACKTRACE_N();
1747
VL_PRINTF("%s", result.c_str());
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);
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);
1760
IData VL_SYSTEM_IN(const std::string& lhs) VL_MT_SAFE {
1761
const int code = std::system(lhs.c_str());
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;
1770
IData VL_VALUEPLUSARGS_INW(int rbits, const std::string& ld, WDataOutP rwp) VL_MT_SAFE {
1775
for (const char* posp = ld.c_str(); !done && *posp; ++posp) {
1776
if (!inPct && posp[0] == '%') {
1778
} else if (!inPct) {
1780
} else if (*posp == '0') {
1782
switch (std::tolower(*posp)) {
1795
const std::string& match = Verilated::threadContextp()->impp()->argPlusMatch(prefix.c_str());
1796
const char* const dp = match.c_str() + 1 + prefix.length();
1797
if (match.empty()) return 0;
1799
VL_ZERO_W(rbits, rwp);
1800
switch (std::tolower(fmt)) {
1803
std::sscanf(dp, "%30" PRId64, &lld);
1804
VL_SET_WQ(rwp, lld);
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;
1810
case 'x': _vl_vsss_based(rwp, rbits, 4, dp, 0, std::strlen(dp)); break;
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]);
1821
std::sscanf(dp, "%le", &temp);
1822
VL_SET_WQ(rwp, VL_CVT_Q_D(temp));
1827
std::sscanf(dp, "%lf", &temp);
1828
VL_SET_WQ(rwp, VL_CVT_Q_D(temp));
1833
std::sscanf(dp, "%lg", &temp);
1834
VL_SET_WQ(rwp, VL_CVT_Q_D(temp));
1840
_vl_clean_inplace_w(rbits, rwp);
1843
IData VL_VALUEPLUSARGS_INN(int, const std::string& ld, std::string& rdr) VL_MT_SAFE {
1847
for (const char* posp = ld.c_str(); !done && *posp; ++posp) {
1848
if (!inPct && posp[0] == '%') {
1850
} else if (!inPct) {
1853
switch (std::tolower(*posp)) {
1864
const std::string& match = Verilated::threadContextp()->impp()->argPlusMatch(prefix.c_str());
1865
const char* const dp = match.c_str() + 1 + prefix.length();
1866
if (match.empty()) return 0;
1867
rdr = std::string{dp};
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;
1877
*sp && (dp - t_outstr) < (VL_VALUE_STRING_MAX_WIDTH - 2);)
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);
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);
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);
1906
std::string VL_CVT_PACK_STR_NW(int lwords, const WDataInP lwp) VL_PURE {
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;
1913
for (; lsb >= 0; --lsb) {
1914
lsb = (lsb / 8) * 8;
1915
const IData charval = VL_BITRSHIFT_W(lwp, lsb) & 0xff;
1917
*destp++ = static_cast<char>(charval);
1921
return std::string{destout, len};
1924
std::string VL_CVT_PACK_STR_ND(const VlQueue<std::string>& q) VL_PURE {
1926
for (const std::string& s : q) output += s;
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;
1934
if (0 <= rhs_s && rhs < lhs.length() && ths != 0) lstring[rhs] = ths;
1938
CData VL_GETC_N(const std::string& lhs, IData rhs) VL_PURE {
1940
const int32_t rhs_s = rhs;
1942
if (0 <= rhs_s && rhs < lhs.length()) v = lhs[rhs];
1946
std::string VL_SUBSTR_N(const std::string& lhs, IData rhs, IData ths) VL_PURE {
1947
const int32_t rhs_s = rhs;
1948
const int32_t ths_s = ths;
1950
if (rhs_s < 0 || ths_s < rhs_s || ths >= lhs.length()) return "";
1952
return lhs.substr(rhs, ths - rhs + 1);
1955
IData VL_ATOI_N(const std::string& str, int base) VL_PURE {
1956
std::string str_mod = str;
1958
str_mod.erase(std::remove(str_mod.begin(), str_mod.end(), '_'), str_mod.end());
1961
auto v = std::strtol(str_mod.c_str(), nullptr, base);
1962
if (errno != 0) v = 0;
1963
return static_cast<IData>(v);
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 {
1968
const char* const datap = str.data();
1969
int pos = static_cast<int>(str.length()) - 1;
1971
while (bit < obits && pos >= 0) {
1972
out |= static_cast<QData>(datap[pos]) << VL_BITBIT_Q(bit);
1976
return out & VL_MASK_Q(obits);
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;
1984
while (bit < obits && pos >= 0) {
1985
owp[VL_BITWORD_I(bit)] |= static_cast<EData>(datap[pos]) << VL_BITBIT_I(bit);
1989
owp[words - 1] &= VL_MASK_E(obits);
1995
static const char* memhFormat(int nBits) {
1996
assert((nBits >= 1) && (nBits <= 32));
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;
2013
static const char* formatBinary(int nBits, uint32_t bits) {
2014
assert((nBits >= 1) && (nBits <= 32));
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');
2021
t_buf[nBits] = '\0';
2025
VlReadMem::VlReadMem(bool hex, int bits, const std::string& filename, QData start, QData end)
2028
, m_filename(filename)
2031
m_fp = std::fopen(filename.c_str(), "r");
2032
if (VL_UNLIKELY(!m_fp)) {
2034
VL_WARN_MT(filename.c_str(), 0, "", "$readmem file not found");
2039
VlReadMem::~VlReadMem() {
2045
bool VlReadMem::get(QData& addrr, std::string& valuer) {
2046
if (VL_UNLIKELY(!m_fp)) return false;
2049
bool inData = false;
2050
bool ignoreToEol = false;
2051
bool ignoreToComment = false;
2052
bool readingAddress = false;
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;
2067
if (c == '_') continue;
2068
if (inData && !chIs4StateHex) {
2078
ignoreToEol = false;
2079
readingAddress = false;
2080
} else if (c == '\t' || c == ' ' || c == '\r' || c == '\f') {
2081
readingAddress = false;
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 == '/') {
2092
} else if (c == '/') {
2093
} else if (c == '#') {
2095
} else if (c == '@') {
2096
readingAddress = true;
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) {
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");
2114
VL_FATAL_MT(m_filename.c_str(), m_linenum, "", "$readmem file syntax error");
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)");
2128
void VlReadMem::setData(void* valuep, const std::string& rhs) {
2129
const QData shift = m_hex ? 4ULL : 1ULL;
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)
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);
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));
2164
VlWriteMem::VlWriteMem(bool hex, int bits, const std::string& filename, QData start, QData end)
2167
if (VL_UNLIKELY(start > end)) {
2168
VL_FATAL_MT(filename.c_str(), 0, "", "$writemem invalid address range");
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");
2179
VlWriteMem::~VlWriteMem() {
2185
void VlWriteMem::print(QData addr, bool addrstamp, const void* valuep) {
2186
if (VL_UNLIKELY(!m_fp)) return;
2187
if (addr != m_addr && addrstamp) {
2188
fprintf(m_fp, "@%" PRIx64 "\n", addr);
2192
const CData* const datap = reinterpret_cast<const CData*>(valuep);
2194
fprintf(m_fp, memhFormat(m_bits), VL_MASK_I(m_bits) & *datap);
2195
fprintf(m_fp, "\n");
2197
fprintf(m_fp, "%s\n", formatBinary(m_bits, *datap));
2199
} else if (m_bits <= 16) {
2200
const SData* const datap = reinterpret_cast<const SData*>(valuep);
2202
fprintf(m_fp, memhFormat(m_bits), VL_MASK_I(m_bits) & *datap);
2203
fprintf(m_fp, "\n");
2205
fprintf(m_fp, "%s\n", formatBinary(m_bits, *datap));
2207
} else if (m_bits <= 32) {
2208
const IData* const datap = reinterpret_cast<const IData*>(valuep);
2210
fprintf(m_fp, memhFormat(m_bits), VL_MASK_I(m_bits) & *datap);
2211
fprintf(m_fp, "\n");
2213
fprintf(m_fp, "%s\n", formatBinary(m_bits, *datap));
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;
2221
fprintf(m_fp, memhFormat(m_bits - 32), hi);
2222
fprintf(m_fp, "%08x\n", lo);
2224
fprintf(m_fp, "%s", formatBinary(m_bits - 32, hi));
2225
fprintf(m_fp, "%s\n", formatBinary(32, lo));
2228
const WDataInP datap = reinterpret_cast<WDataInP>(valuep);
2232
int word_idx = ((m_bits - 1) / VL_EDATASIZE);
2234
while (word_idx >= 0) {
2235
EData data = datap[word_idx];
2237
data &= VL_MASK_E(m_bits);
2238
const int top_word_nbits = VL_BITBIT_E(m_bits - 1) + 1;
2240
fprintf(m_fp, memhFormat(top_word_nbits), data);
2242
fprintf(m_fp, "%s", formatBinary(top_word_nbits, data));
2246
fprintf(m_fp, "%08x", data);
2248
fprintf(m_fp, "%s", formatBinary(32, data));
2254
fprintf(m_fp, "\n");
2258
void VL_READMEM_N(bool hex,
2263
const std::string& filename,
2268
if (start < static_cast<QData>(array_lsb)) start = array_lsb;
2270
VlReadMem rmem{hex, bits, filename, start, end};
2271
if (VL_UNLIKELY(!rmem.isOpen())) return;
2275
if (rmem.get(addr , value )) {
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");
2282
const QData entry = addr - array_lsb;
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);
2297
= &(reinterpret_cast<WDataOutP>(memp))[entry * VL_WORDS_I(bits)];
2298
rmem.setData(datap, value);
2307
void VL_WRITEMEM_N(bool hex,
2312
const std::string& filename,
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;
2321
VlWriteMem wmem{hex, bits, filename, start, end};
2322
if (VL_UNLIKELY(!wmem.isOpen())) return;
2324
for (QData addr = start; addr <= end; ++addr) {
2325
const QData row_offset = addr - array_lsb;
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);
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);
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];
2356
double vl_time_multiplier(int scale) VL_PURE {
2361
static const double neg10[] = {1.0,
2378
0.00000000000000001,
2379
0.000000000000000001};
2381
return neg10[-scale];
2383
static const double pow10[] = {1.0,
2399
10000000000000000.0,
2400
100000000000000000.0,
2401
1000000000000000000.0};
2403
return pow10[scale];
2406
uint64_t vl_time_pow10(int n) {
2407
static const uint64_t pow10[20] = {
2423
1000000000000000ULL,
2424
10000000000000000ULL,
2425
100000000000000000ULL,
2426
1000000000000000000ULL,
2431
std::string vl_timescaled_double(double value, const char* format) VL_PURE {
2432
const char* suffixp = "s";
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; }
2443
VL_SNPRINTF(valuestr, 100, format, value, suffixp);
2444
return std::string{valuestr};
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());
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);
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);
2472
std::fill(m_fdps.begin(), m_fdps.end(), static_cast<FILE*>(nullptr));
2473
m_fdFreeMct.resize(30);
2475
for (std::size_t i = 0; i < m_fdFreeMct.size(); ++i, ++id) m_fdFreeMct[i] = id;
2479
VerilatedContext::~VerilatedContext() {
2484
void VerilatedContext::checkMagic(const VerilatedContext* contextp) {
2485
if (VL_UNLIKELY(!contextp || contextp->m_magic != MAGIC)) {
2486
VL_FATAL_MT("", 0, "",
2487
"Attempt to create model using a bad/deleted VerilatedContext pointer");
2491
VerilatedContext::Serialized::Serialized() {
2492
constexpr int8_t picosecond = -12;
2493
m_timeunit = picosecond;
2494
m_timeprecision = picosecond;
2497
void VerilatedContext::assertOn(bool flag) VL_MT_SAFE {
2498
const VerilatedLockGuard lock{m_mutex};
2499
m_s.m_assertOn = flag;
2501
void VerilatedContext::calcUnusedSigs(bool flag) VL_MT_SAFE {
2502
const VerilatedLockGuard lock{m_mutex};
2503
m_s.m_calcUnusedSigs = flag;
2505
void VerilatedContext::coverageFilename(const std::string& flag) VL_MT_SAFE {
2506
const VerilatedLockGuard lock{m_mutex};
2507
m_ns.m_coverageFilename = flag;
2509
std::string VerilatedContext::coverageFilename() const VL_MT_SAFE {
2510
const VerilatedLockGuard lock{m_mutex};
2511
return m_ns.m_coverageFilename;
2513
void VerilatedContext::dumpfile(const std::string& flag) VL_MT_SAFE_EXCLUDES(m_timeDumpMutex) {
2514
const VerilatedLockGuard lock{m_timeDumpMutex};
2517
std::string VerilatedContext::dumpfile() const VL_MT_SAFE_EXCLUDES(m_timeDumpMutex) {
2518
const VerilatedLockGuard lock{m_timeDumpMutex};
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");
2529
void VerilatedContext::errorCount(int val) VL_MT_SAFE {
2530
const VerilatedLockGuard lock{m_mutex};
2531
m_s.m_errorCount = val;
2533
void VerilatedContext::errorCountInc() VL_MT_SAFE {
2534
const VerilatedLockGuard lock{m_mutex};
2537
void VerilatedContext::errorLimit(int val) VL_MT_SAFE {
2538
const VerilatedLockGuard lock{m_mutex};
2539
m_s.m_errorLimit = val;
2541
void VerilatedContext::fatalOnError(bool flag) VL_MT_SAFE {
2542
const VerilatedLockGuard lock{m_mutex};
2543
m_s.m_fatalOnError = flag;
2545
void VerilatedContext::fatalOnVpiError(bool flag) VL_MT_SAFE {
2546
const VerilatedLockGuard lock{m_mutex};
2547
m_s.m_fatalOnVpiError = flag;
2549
void VerilatedContext::gotError(bool flag) VL_MT_SAFE {
2550
const VerilatedLockGuard lock{m_mutex};
2551
m_s.m_gotError = flag;
2553
void VerilatedContext::gotFinish(bool flag) VL_MT_SAFE {
2554
const VerilatedLockGuard lock{m_mutex};
2555
m_s.m_gotFinish = flag;
2557
void VerilatedContext::profExecStart(uint64_t flag) VL_MT_SAFE {
2558
const VerilatedLockGuard lock{m_mutex};
2559
m_ns.m_profExecStart = flag;
2561
void VerilatedContext::profExecWindow(uint64_t flag) VL_MT_SAFE {
2562
const VerilatedLockGuard lock{m_mutex};
2563
m_ns.m_profExecWindow = flag;
2565
void VerilatedContext::profExecFilename(const std::string& flag) VL_MT_SAFE {
2566
const VerilatedLockGuard lock{m_mutex};
2567
m_ns.m_profExecFilename = flag;
2569
std::string VerilatedContext::profExecFilename() const VL_MT_SAFE {
2570
const VerilatedLockGuard lock{m_mutex};
2571
return m_ns.m_profExecFilename;
2573
void VerilatedContext::profVltFilename(const std::string& flag) VL_MT_SAFE {
2574
const VerilatedLockGuard lock{m_mutex};
2575
m_ns.m_profVltFilename = flag;
2577
std::string VerilatedContext::profVltFilename() const VL_MT_SAFE {
2578
const VerilatedLockGuard lock{m_mutex};
2579
return m_ns.m_profVltFilename;
2581
void VerilatedContext::solverProgram(const std::string& flag) VL_MT_SAFE {
2582
const VerilatedLockGuard lock{m_mutex};
2583
m_ns.m_solverProgram = flag;
2585
std::string VerilatedContext::solverProgram() const VL_MT_SAFE {
2586
const VerilatedLockGuard lock{m_mutex};
2587
return m_ns.m_solverProgram;
2589
void VerilatedContext::quiet(bool flag) VL_MT_SAFE {
2590
const VerilatedLockGuard lock{m_mutex};
2593
void VerilatedContext::randReset(int val) VL_MT_SAFE {
2594
const VerilatedLockGuard lock{m_mutex};
2595
m_s.m_randReset = val;
2597
void VerilatedContext::timeunit(int value) VL_MT_SAFE {
2598
if (value < 0) value = -value;
2599
const VerilatedLockGuard lock{m_mutex};
2600
m_s.m_timeunit = value;
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());
2607
void VerilatedContext::threads(unsigned n) {
2608
if (n == 0) VL_FATAL_MT(__FILE__, __LINE__, "", "%Error: Simulation threads must be >= 1");
2612
__FILE__, __LINE__, "",
2613
"%Error: Cannot set simulation threads after the thread pool has been created.");
2616
if (m_threads == n) return;
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);
2626
void VerilatedContext::commandArgs(int argc, const char** argv) VL_MT_SAFE_EXCLUDES(m_argMutex) {
2630
impp()->commandArgsGuts(argc, argv);
2632
void VerilatedContext::commandArgsAdd(int argc, const char** argv)
2633
VL_MT_SAFE_EXCLUDES(m_argMutex) {
2637
impp()->commandArgsAddGutsLock(argc, argv);
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);)
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();
2659
void VerilatedContext::addModel(VerilatedModel* modelp) {
2663
const VerilatedLockGuard lock{m_mutex};
2664
m_ns.m_cpuTimeStart.start();
2665
m_ns.m_wallTimeStart.start();
2670
if (VL_UNLIKELY(time()))
2673
"Adding model when time is non-zero. ... Suggest check time(), or for restarting"
2674
" model use a new VerilatedContext");
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());
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();
2694
void VerilatedContext::prepareClone() { delete m_threadPool.release(); }
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();
2702
VerilatedVirtualBase*
2703
VerilatedContext::enableExecutionProfiler(VerilatedVirtualBase* (*construct)(VerilatedContext&)) {
2704
if (!m_executionProfiler) m_executionProfiler.reset(construct(*this));
2705
return m_executionProfiler.get();
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();
2715
commandArgsAddGuts(argc, argv);
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);
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]);
2730
m_args.m_argVecLoaded = true;
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());
2738
std::string VerilatedContextImp::argPlusMatch(const char* prefixp)
2739
VL_MT_SAFE_EXCLUDES(m_argMutex) {
2740
const VerilatedLockGuard lock{m_argMutex};
2742
const size_t len = std::strlen(prefixp);
2743
if (VL_UNLIKELY(!m_args.m_argVecLoaded)) {
2744
m_args.m_argVecLoaded = true;
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).");
2749
for (const auto& i : m_args.m_argVec) {
2751
if (0 == std::strncmp(prefixp, i.c_str() + 1, len)) return i;
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)) {
2765
s_argc = static_cast<int>(m_args.m_argVec.size());
2766
s_argvp = new char*[s_argc + 1];
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);
2773
s_argvp[s_argc] = nullptr;
2775
return std::make_pair(s_argc, s_argvp);
2778
void VerilatedContextImp::commandArgVl(const std::string& arg) {
2779
if (0 == std::strncmp(arg.c_str(), "+verilator+", std::strlen("+verilator+"))) {
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") {
2799
} else if (commandArgVlUint64(arg, "+verilator+prof+exec+start+", 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") {
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();
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)");
2823
const std::string msg = "Unknown runtime argument: " + arg;
2824
VL_FATAL_MT("COMMAND_LINE", 0, "", msg.c_str());
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);
2840
bool VerilatedContextImp::commandArgVlUint64(const std::string& arg, const std::string& prefix,
2841
uint64_t& valuer, uint64_t min, uint64_t max) {
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());
2854
if (std::any_of(str.cbegin(), str.cend(), [](int c) { return !std::isdigit(c); })) fail();
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();
2867
void VerilatedContext::randSeed(int val) VL_MT_SAFE {
2870
const VerilatedLockGuard lock{VerilatedContextImp::s().s_randMutex};
2871
m_s.m_randSeed = val;
2872
const uint64_t newEpoch = VerilatedContextImp::s().s_randSeedEpoch + 1;
2874
std::atomic_signal_fence(std::memory_order_release);
2875
VerilatedContextImp::s().s_randSeedEpoch = newEpoch;
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())));
2881
return ((static_cast<uint64_t>(vl_sys_rand32()) << 32)
2882
^ (static_cast<uint64_t>(vl_sys_rand32())));
2889
double VerilatedContext::statCpuTimeSinceStart() const VL_MT_SAFE_EXCLUDES(m_mutex) {
2890
const VerilatedLockGuard lock{m_mutex};
2891
return m_ns.m_cpuTimeStart.deltaTime();
2893
double VerilatedContext::statWallTimeSinceStart() const VL_MT_SAFE_EXCLUDES(m_mutex) {
2894
const VerilatedLockGuard lock{m_mutex};
2895
return m_ns.m_wallTimeStart.deltaTime();
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);
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();
2929
void VerilatedContextImp::scopeInsert(const VerilatedScope* scopep) VL_MT_SAFE {
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);
2935
void VerilatedContextImp::scopeErase(const VerilatedScope* scopep) VL_MT_SAFE {
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);
2942
const VerilatedScope* VerilatedContext::scopeFind(const char* namep) const VL_MT_SAFE {
2944
const VerilatedLockGuard lock{m_impdatap->m_nameMutex};
2946
const auto& it = m_impdatap->m_nameMap.find(namep);
2947
if (VL_UNLIKELY(it == m_impdatap->m_nameMap.end())) return nullptr;
2950
const VerilatedScopeNameMap* VerilatedContext::scopeNameMap() VL_MT_SAFE {
2951
return &(impp()->m_impdatap->m_nameMap);
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");
2967
if (tfp->modelConnected()) return;
2968
tfp->modelConnected(true);
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);
2978
void VerilatedContext::traceBaseModelCbAdd(traceBaseModelCb_t cb) VL_MT_SAFE {
2980
const VerilatedLockGuard lock{m_mutex};
2981
m_ns.m_traceBaseModelCbs.push_back(cb);
2987
VerilatedSyms::VerilatedSyms(VerilatedContext* contextp)
2988
: _vm_contextp__(contextp ? contextp : Verilated::threadContextp()) {
2989
VerilatedContext::checkMagic(_vm_contextp__);
2990
Verilated::threadContextp(_vm_contextp__);
2992
__Vm_evalMsgQp = new VerilatedEvalMsgQueue;
2995
VerilatedSyms::~VerilatedSyms() {
2996
VerilatedContext::checkMagic(_vm_contextp__);
2997
delete __Vm_evalMsgQp;
3003
void Verilated::debug(int level) VL_MT_SAFE {
3007
VL_DEBUG_IF(VL_DBG_MSGF("- Verilated::debug is on."
3008
" Message prefix indicates {<thread>,<sequence_number>}.\n"););
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");
3017
const char* Verilated::catName(const char* n1, const char* n2, const char* delimiter) VL_MT_SAFE {
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];
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++;
3040
using VoidPCbList = std::list<std::pair<Verilated::VoidPCb, void*>>;
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);
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);
3053
VlCbStatic.s_flushCbs.push_back(pair);
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);
3060
VlCbStatic.s_exitCbs.push_back(pair);
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);
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);
3074
static void runCallbacks(const VoidPCbList& cbs) VL_MT_SAFE {
3075
for (const auto& i : cbs) i.first(i.second);
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 {
3082
static std::atomic<int> s_recursing;
3083
if (!s_recursing++) {
3084
const VerilatedLockGuard lock{VlCbStatic.s_flushMutex};
3085
runCallbacks(VlCbStatic.s_flushCbs);
3088
std::fflush(stderr);
3089
std::fflush(stdout);
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);
3107
const char* Verilated::productName() VL_PURE { return VERILATOR_PRODUCT; }
3108
const char* Verilated::productVersion() VL_PURE { return VERILATOR_VERSION; }
3110
void Verilated::nullPointerError(const char* filename, int linenum) VL_MT_SAFE {
3112
VL_FATAL_MT(filename, linenum, "", "Null pointer dereferenced");
3116
void Verilated::overWidthError(const char* signame) VL_MT_SAFE {
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());
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());
3136
void Verilated::scTraceBeforeElaborationError() VL_MT_SAFE {
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.");
3144
void Verilated::stackCheck(QData needSize) VL_MT_UNSAFE {
3146
#ifdef _VL_HAVE_GETRLIMIT
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;
3156
QData requestSize = needSize + needSize / 2;
3157
if (VL_UNLIKELY(haveSize && needSize && haveSize < requestSize)) {
3159
rlim.rlim_cur = requestSize;
3161
#ifdef _VL_TEST_RLIMIT_FAIL
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);
3176
void Verilated::mkdir(const char* dirname) VL_MT_UNSAFE {
3177
#if defined(_WIN32) || defined(__MINGW32__)
3180
::mkdir(dirname, 0777);
3184
void Verilated::quiesce() VL_MT_SAFE {
3189
int Verilated::exportFuncNum(const char* namep) VL_MT_SAFE {
3190
return VerilatedImp::exportFind(namep);
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);
3198
void Verilated::endOfEval(VerilatedEvalMsgQueue* evalMsgQp) VL_MT_SAFE {
3203
VL_DEBUG_IF(VL_DBG_MSGF("End-of-eval cleanup\n"););
3204
VerilatedThreadMsgQueue::flush(evalMsgQp);
3205
evalMsgQp->process();
3211
void VerilatedImp::versionDump() VL_MT_SAFE {
3212
VL_PRINTF_MT(" Version: %s %s\n", Verilated::productName(), Verilated::productVersion());
3218
VerilatedModel::VerilatedModel(VerilatedContext& context)
3219
: m_context{context} {}
3221
std::unique_ptr<VerilatedTraceConfig> VerilatedModel::traceConfig() const { return nullptr; }
3226
VerilatedModule::VerilatedModule(const char* namep)
3227
: m_namep{strdup(namep)} {}
3229
VerilatedModule::~VerilatedModule() {
3232
if (m_namep) VL_DO_CLEAR(free((void*)(m_namep)), m_namep = nullptr);
3239
uint32_t VerilatedVarProps::entSize() const VL_MT_SAFE {
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;
3253
size_t VerilatedVarProps::totalSize() const {
3254
size_t size = entSize();
3255
for (int udim = 0; udim < udims(); ++udim) size *= m_unpacked[udim].elements();
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);
3265
size_t slicesz = entSize();
3266
for (int d = dim + 1; d <= m_udims; ++d) slicesz *= elements(d);
3267
bytep += indxAdj * slicesz;
3274
VerilatedScope::~VerilatedScope() {
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);
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 {
3290
m_timeunit = timeunit;
3292
char* const namep = new char[std::strlen(prefixp) + std::strlen(suffixp) + 2];
3294
for (const char* sp = prefixp; *sp;) *dp++ = *sp++;
3295
if (*prefixp && *suffixp) *dp++ = '.';
3296
for (const char* sp = suffixp; *sp;) *dp++ = *sp++;
3300
m_identifierp = identifier;
3301
Verilated::threadContextp()->impp()->scopeInsert(this);
3304
void VerilatedScope::exportInsert(int finalize, const char* namep, void* cb) VL_MT_UNSAFE {
3307
const int funcnum = VerilatedImp::exportInsert(namep);
3311
if (funcnum >= m_funcnumMax) m_funcnumMax = funcnum + 1;
3313
if (VL_UNCOVERABLE(funcnum >= m_funcnumMax)) {
3314
VL_FATAL_MT(__FILE__, __LINE__, "",
3315
"Internal: Bad funcnum vs. pre-finalize maximum");
3317
if (VL_UNLIKELY(!m_callbacksp)) {
3318
m_callbacksp = new void*[m_funcnumMax];
3319
std::memset(m_callbacksp, 0, m_funcnumMax * sizeof(void*));
3321
m_callbacksp[funcnum] = cb;
3325
void VerilatedScope::varInsert(int finalize, const char* namep, void* datap, bool isParam,
3326
VerilatedVarType vltype, int vlflags, int dims, ...) VL_MT_UNSAFE {
3330
if (!finalize) return;
3332
if (!m_varsp) m_varsp = new VerilatedVarNameMap;
3333
VerilatedVar var(namep, datap, vltype, static_cast<VerilatedVarFlags>(vlflags), dims, isParam);
3337
for (int i = 0; i < dims; ++i) {
3338
const int msb = va_arg(ap, int);
3339
const int lsb = va_arg(ap, int);
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;
3349
const std::string msg = "Unsupported multi-dimensional public varInsert: "s + namep;
3350
VL_FATAL_MT(__FILE__, __LINE__, "", msg.c_str());
3355
m_varsp->emplace(namep, var);
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);
3367
void* VerilatedScope::exportFindNullError(int funcnum) VL_MT_SAFE {
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());
3376
void* VerilatedScope::exportFindError(int funcnum) const VL_MT_SAFE {
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()
3382
VL_FATAL_MT("unknown", 0, "", msg.c_str());
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));
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);
3399
void VerilatedHierarchy::add(VerilatedScope* fromp, VerilatedScope* top) {
3400
VerilatedImp::hierarchyAdd(fromp, top);
3403
void VerilatedHierarchy::remove(VerilatedScope* fromp, VerilatedScope* top) {
3404
VerilatedImp::hierarchyRemove(fromp, top);
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");
3421
void VlDeleter::deleteAll() VL_EXCLUDES(m_mutex) VL_EXCLUDES(m_deleteMutex) VL_MT_SAFE {
3424
VerilatedLockGuard lock{m_mutex};
3425
if (m_newGarbage.empty()) break;
3426
m_deleteMutex.lock();
3427
std::swap(m_newGarbage, m_deleteNow);
3430
for (VlDeletable* const objp : m_deleteNow) delete objp;
3431
m_deleteNow.clear();
3432
m_deleteMutex.unlock();
3439
#define VL_ALLOW_VERILATEDOS_C
3440
#include "verilatedos_c.h"