-
Notifications
You must be signed in to change notification settings - Fork 0
/
verilated.h
1025 lines (913 loc) · 43.8 KB
/
verilated.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Code available from: https://verilator.org
//
// Copyright 2003-2024 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
//
//*************************************************************************
///
/// \file
/// \brief Verilated common header, include for all Verilated C files
///
/// This file is included automatically by Verilator at the top of all C++
/// files it generates. It contains standard macros and classes required
/// by the Verilated code.
///
/// User wrapper code may need to include this to get appropriate
/// structures, however they would generally just include the
/// Verilated-model's header instead (which then includes this).
///
/// Those macro/function/variable starting or ending in _ are internal,
/// however many of the other function/macros here are also internal.
///
//*************************************************************************
#ifndef VERILATOR_VERILATED_H_
#define VERILATOR_VERILATED_H_
#define VERILATOR_VERILATED_H_INTERNAL_
#ifdef VERILATOR_INTERNAL_
// This file contains definition of VerilationMutex that should
// only be used by verilated code. Verilator itself should use
// mutex from V3Mutex.h. Make sure this file isn't included in
// verilator code.
#error "verilated.h should only be included in verilated code"
#endif
// clang-format off
#include "verilatedos.h"
#include "verilated_config.h"
#if VM_SC
# include "verilated_sc.h" // Get SYSTEMC_VERSION and time declarations
#endif
#include <algorithm>
#include <array>
#include <cassert>
#include <cmath>
#include <cstdarg>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <functional>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <unordered_set>
#include <vector>
// <iostream> avoided to reduce compile time
#include <atomic>
#include <mutex>
#include <thread>
// Allow user to specify their own include file
#ifdef VL_VERILATED_INCLUDE
// cppcheck-suppress preprocessorErrorDirective
# include VL_VERILATED_INCLUDE
#endif
// clang-format on
using namespace std::literals; // "<std::string literal>"s; see SF.7 core guideline
//=============================================================================
// Switches
// clang-format off
#if VM_TRACE // Verilator tracing requested
# define WAVES 1 // Set backward compatibility flag
#endif
// Version check
#if defined(SYSTEMC_VERSION) && (SYSTEMC_VERSION < 20111121)
# warning "Verilator requires SystemC 2.3.* or newer."
#endif
// clang-format on
class VerilatedContext;
class VerilatedContextImp;
class VerilatedContextImpData;
class VerilatedCovContext;
class VerilatedEvalMsgQueue;
class VerilatedFst;
class VerilatedFstC;
class VerilatedFstSc;
class VerilatedScope;
class VerilatedScopeNameMap;
template <class, class>
class VerilatedTrace;
class VerilatedTraceBaseC;
class VerilatedTraceConfig;
class VerilatedVar;
class VerilatedVarNameMap;
class VerilatedVcd;
class VerilatedVcdC;
class VerilatedVcdSc;
//=========================================================================
// Basic types
// clang-format off
// P // Packed data of bit type (C/S/I/Q/W)
using CData = uint8_t; ///< Data representing 'bit' of 1-8 packed bits
using SData = uint16_t; ///< Data representing 'bit' of 9-16 packed bits
using IData = uint32_t; ///< Data representing 'bit' of 17-32 packed bits
using QData = uint64_t; ///< Data representing 'bit' of 33-64 packed bits
using EData = uint32_t; ///< Data representing one element of WData array
using WData = EData; ///< Data representing >64 packed bits (used as pointer)
// F = float; // No typedef needed; Verilator uses float
// D = double; // No typedef needed; Verilator uses double
// N = std::string; // No typedef needed; Verilator uses string
// clang-format on
using WDataInP = const WData*; ///< 'bit' of >64 packed bits as array input to a function
using WDataOutP = WData*; ///< 'bit' of >64 packed bits as array output from a function
enum VerilatedVarType : uint8_t {
VLVT_UNKNOWN = 0,
VLVT_PTR, // Pointer to something
VLVT_UINT8, // AKA CData
VLVT_UINT16, // AKA SData
VLVT_UINT32, // AKA IData
VLVT_UINT64, // AKA QData
VLVT_WDATA, // AKA WData
VLVT_STRING, // C++ string
VLVT_REAL // AKA double
};
enum VerilatedVarFlags {
VLVD_0 = 0, // None
VLVD_IN = 1, // == vpiInput
VLVD_OUT = 2, // == vpiOutput
VLVD_INOUT = 3, // == vpiInOut
VLVD_NODIR = 5, // == vpiNoDirection
VLVF_MASK_DIR = 7, // Bit mask for above directions
// Flags
VLVF_PUB_RD = (1 << 8), // Public readable
VLVF_PUB_RW = (1 << 9), // Public writable
VLVF_DPI_CLAY = (1 << 10) // DPI compatible C standard layout
};
//=============================================================================
// Utility functions
template <size_t N>
inline constexpr size_t roundUpToMultipleOf(size_t value) {
static_assert((N & (N - 1)) == 0, "'N' must be a power of 2");
return (value + N - 1) & ~(N - 1);
}
//=========================================================================
// Mutex and threading support
// Return current thread ID (or 0), not super fast, cache if needed
extern uint32_t VL_THREAD_ID() VL_MT_SAFE;
#ifndef VL_LOCK_SPINS
#define VL_LOCK_SPINS 50000 /// Number of times to spin for a mutex before yielding
#endif
/// Mutex, wrapped to allow -fthread_safety checks
class VL_CAPABILITY("mutex") VerilatedMutex final {
private:
std::mutex m_mutex; // Mutex
public:
/// Construct mutex (without locking it)
VerilatedMutex() = default;
~VerilatedMutex() = default;
VL_UNCOPYABLE(VerilatedMutex);
const VerilatedMutex& operator!() const { return *this; } // For -fthread_safety
/// Acquire/lock mutex
void lock() VL_ACQUIRE() VL_MT_SAFE {
// Try to acquire the lock by spinning. If the wait is short,
// avoids a trap to the OS plus OS scheduler overhead.
if (VL_LIKELY(try_lock())) return; // Short circuit loop
for (int i = 0; i < VL_LOCK_SPINS; ++i) {
if (VL_LIKELY(try_lock())) return;
VL_CPU_RELAX();
}
// Spinning hasn't worked, pay the cost of blocking.
m_mutex.lock();
}
/// Release/unlock mutex
void unlock() VL_RELEASE() VL_MT_SAFE { m_mutex.unlock(); }
/// Try to acquire mutex. Returns true on success, and false on failure.
bool try_lock() VL_TRY_ACQUIRE(true) VL_MT_SAFE { return m_mutex.try_lock(); }
/// Acquire/lock mutex and check for stop request
/// It tries to lock the mutex and if it fails, it check if stop request was send.
/// It returns after locking mutex.
/// This function should be extracted to V3ThreadPool, but due to clang thread-safety
/// limitations it needs to be placed here.
void lockCheckStopRequest(std::function<void()> checkStopRequestFunction)
VL_ACQUIRE() VL_MT_SAFE {
while (true) {
checkStopRequestFunction();
if (m_mutex.try_lock()) return;
VL_CPU_RELAX();
}
}
};
/// Lock guard for mutex (ala std::unique_lock), wrapped to allow -fthread_safety checks
class VL_SCOPED_CAPABILITY VerilatedLockGuard final {
VL_UNCOPYABLE(VerilatedLockGuard);
private:
VerilatedMutex& m_mutexr;
public:
/// Construct and hold given mutex lock until destruction or unlock()
explicit VerilatedLockGuard(VerilatedMutex& mutexr) VL_ACQUIRE(mutexr) VL_MT_SAFE
: m_mutexr(mutexr) { // Need () or GCC 4.8 false warning
mutexr.lock();
}
/// Destruct and unlock the mutex
~VerilatedLockGuard() VL_RELEASE() { m_mutexr.unlock(); }
};
// Internals: Remember the calling thread at construction time, and make
// sure later calls use same thread
class VerilatedAssertOneThread final {
// MEMBERS
#ifdef VL_DEBUG
uint32_t m_threadid; // Thread that is legal
public:
// CONSTRUCTORS
// The constructor establishes the thread id for all later calls.
// If necessary, a different class could be made that inits it otherwise.
VerilatedAssertOneThread()
: m_threadid{VL_THREAD_ID()} {}
~VerilatedAssertOneThread() { check(); }
// METHODS
// Check that the current thread ID is the same as the construction thread ID
void check() VL_MT_UNSAFE_ONE {
if (VL_UNCOVERABLE(m_threadid != VL_THREAD_ID())) {
if (m_threadid == 0) {
m_threadid = VL_THREAD_ID();
} else {
fatal_different(); // LCOV_EXCL_LINE
}
}
}
static void fatal_different() VL_MT_SAFE;
#else // !VL_DEBUG
public:
void check() {}
#endif
};
//=========================================================================
/// Base class of a Verilator generated (Verilated) model.
///
/// VerilatedModel is a base class of the user facing primary class generated
/// by Verilator.
class VerilatedModel VL_NOT_FINAL {
VL_UNCOPYABLE(VerilatedModel);
VerilatedContext& m_context; // The VerilatedContext this model is instantiated under
protected:
explicit VerilatedModel(VerilatedContext& context);
virtual ~VerilatedModel() = default;
public:
/// Returns the VerilatedContext this model is instantiated under
/// Used to get to e.g. simulation time via contextp()->time()
VerilatedContext* contextp() const VL_MT_SAFE { return &m_context; }
/// Returns the hierarchical name of this module instance.
virtual const char* hierName() const = 0;
/// Returns the name of this model (the name of the generated model class).
virtual const char* modelName() const = 0;
/// Returns the thread level parallelism, this model was Verilated with. Always 1 or higher.
virtual unsigned threads() const = 0;
private:
// The following are for use by Verilator internals only
template <class, class>
friend class VerilatedTrace;
// Run-time trace configuration requested by this model
virtual std::unique_ptr<VerilatedTraceConfig> traceConfig() const;
};
//=========================================================================
/// Base class for all Verilated module classes.
class VerilatedModule VL_NOT_FINAL {
VL_UNCOPYABLE(VerilatedModule);
private:
const char* m_namep; // Module name
public:
explicit VerilatedModule(const char* namep); // Create module with given hierarchy name
~VerilatedModule();
const char* name() const VL_MT_SAFE_POSTINIT { return m_namep; } ///< Return name of module
};
//=========================================================================
// Functions overridable by user defines
// (Internals however must use VL_PRINTF_MT, which calls these.)
// clang-format off
#ifndef VL_PRINTF
# define VL_PRINTF printf ///< Print ala printf, called from main thread; redefine if desired
#endif
#ifndef VL_VPRINTF
# define VL_VPRINTF vprintf ///< Print ala vprintf, called from main thread; redefine if desired
#endif
// clang-format on
//===========================================================================
// Internal: Base class to allow virtual destruction
class VerilatedVirtualBase VL_NOT_FINAL {
public:
VerilatedVirtualBase() = default;
virtual ~VerilatedVirtualBase() = default;
};
//===========================================================================
/// Verilator simulation context
///
/// The VerilatedContext contains the information common across all models
/// that are interconnected, for example this contains the simulation time
/// and if $finish was executed.
///
/// VerilatedContexts maybe created by the user wrapper code and passed
/// when a model is created. If this is not done, then Verilator will use
/// the Verilated::defaultContextp()'s global context.
class VerilatedContext VL_NOT_FINAL {
friend class VerilatedContextImp;
protected:
// TYPES
using traceBaseModelCb_t
= std::function<void(VerilatedTraceBaseC*, int, int)>; // Type of traceBaseModel callbacks
// MEMBERS
// Slow path variables
mutable VerilatedMutex m_mutex; // Mutex for most s_s/s_ns members
struct Serialized final { // All these members serialized/deserialized
// No std::strings or pointers or will serialize badly!
// Fast path
uint64_t m_time = 0; // Current $time (unscaled), 0=at zero, or legacy
bool m_assertOn = true; // Assertions are enabled
bool m_calcUnusedSigs = false; // Waves file on, need all signals calculated
bool m_fatalOnError = true; // Fatal on $stop/non-fatal error
bool m_fatalOnVpiError = true; // Fatal on vpi error/unsupported
bool m_gotError = false; // A $finish statement executed
bool m_gotFinish = false; // A $finish or $stop statement executed
bool m_quiet = false; // Quiet, no summary report
// Slow path
int8_t m_timeunit; // Time unit as 0..15
int8_t m_timeprecision; // Time precision as 0..15
int m_errorCount = 0; // Number of errors
int m_errorLimit = 1; // Stop on error number
int m_randReset = 0; // Random reset: 0=all 0s, 1=all 1s, 2=random
int m_randSeed = 0; // Random seed: 0=random
enum { UNITS_NONE = 99 }; // Default based on precision
int m_timeFormatUnits = UNITS_NONE; // $timeformat units
int m_timeFormatPrecision = 0; // $timeformat number of decimal places
int m_timeFormatWidth = 20; // $timeformat character width
// CONSTRUCTORS
Serialized();
~Serialized() = default;
} m_s;
mutable VerilatedMutex m_timeDumpMutex; // Protect misc slow strings
std::string m_timeFormatSuffix VL_GUARDED_BY(m_timeDumpMutex); // $timeformat printf format
std::string m_dumpfile VL_GUARDED_BY(m_timeDumpMutex); // $dumpfile setting
struct NonSerialized final { // Non-serialized information
// These are reloaded from on command-line settings, so do not need to persist
// Fast path
uint64_t m_profExecStart = 1; // +prof+exec+start time
uint32_t m_profExecWindow = 2; // +prof+exec+window size
// Slow path
std::string m_coverageFilename; // +coverage+file filename
std::string m_profExecFilename; // +prof+exec+file filename
std::string m_profVltFilename; // +prof+vlt filename
std::string m_solverProgram; // SMT solver program
VlOs::DeltaCpuTime m_cpuTimeStart{false}; // CPU time, starts when create first model
VlOs::DeltaWallTime m_wallTimeStart{false}; // Wall time, starts when create first model
std::vector<traceBaseModelCb_t> m_traceBaseModelCbs; // Callbacks to traceRegisterModel
} m_ns;
mutable VerilatedMutex m_argMutex; // Protect m_argVec, m_argVecLoaded
// no need to be save-restored (serialized) the
// assumption is that the restore is allowed to pass different arguments
struct NonSerializedCommandArgs final {
// Medium speed
std::vector<std::string> m_argVec; // Argument list
bool m_argVecLoaded = false; // Ever loaded argument list
} m_args VL_GUARDED_BY(m_argMutex);
// Implementation details
const std::unique_ptr<VerilatedContextImpData> m_impdatap;
// Number of threads to use for simulation (size of m_threadPool + 1 for main thread)
unsigned m_threads = std::thread::hardware_concurrency();
// Number of threads in added models
unsigned m_threadsInModels = 0;
// The thread pool shared by all models added to this context
std::unique_ptr<VerilatedVirtualBase> m_threadPool;
// The execution profiler shared by all models added to this context
std::unique_ptr<VerilatedVirtualBase> m_executionProfiler;
// Coverage access
std::unique_ptr<VerilatedVirtualBase> m_coveragep; // Pointer for coveragep()
// File I/O
// Not serialized
mutable VerilatedMutex m_fdMutex; // Protect m_fdps, m_fdFree
std::vector<FILE*> m_fdps VL_GUARDED_BY(m_fdMutex); // File descriptors
// List of free descriptors (SLOW - FOPEN/CLOSE only)
std::vector<IData> m_fdFree VL_GUARDED_BY(m_fdMutex);
// List of free descriptors in the MCT region [4, 32)
std::vector<IData> m_fdFreeMct VL_GUARDED_BY(m_fdMutex);
// Magic to check for bad construction
static constexpr uint64_t MAGIC = 0xC35F9A6E5298EE6EULL; // SHA256 "VerilatedContext"
uint64_t m_magic = MAGIC;
private:
// CONSTRUCTORS
VL_UNCOPYABLE(VerilatedContext);
public:
/// Construct context. Also sets Verilated::threadContextp to the created context.
VerilatedContext();
~VerilatedContext();
// METHODS - User called
/// Enable assertions
void assertOn(bool flag) VL_MT_SAFE;
/// Return if assertions enabled
bool assertOn() const VL_MT_SAFE { return m_s.m_assertOn; }
/// Enable calculation of unused signals (for traces)
void calcUnusedSigs(bool flag) VL_MT_SAFE;
/// Return if calculating of unused signals (for traces)
bool calcUnusedSigs() const VL_MT_SAFE { return m_s.m_calcUnusedSigs; }
/// Record command-line arguments, for retrieval by $test$plusargs/$value$plusargs,
/// and for parsing +verilator+ run-time arguments.
/// This should be called before the first model is created.
void commandArgs(int argc, const char** argv) VL_MT_SAFE_EXCLUDES(m_argMutex);
void commandArgs(int argc, char** argv) VL_MT_SAFE {
commandArgs(argc, const_cast<const char**>(argv));
}
/// Add a command-line argument to existing arguments
void commandArgsAdd(int argc, const char** argv) VL_MT_SAFE_EXCLUDES(m_argMutex);
/// Match plusargs with a given prefix. Returns static char* valid only for a single call
const char* commandArgsPlusMatch(const char* prefixp) VL_MT_SAFE_EXCLUDES(m_argMutex);
/// Return VerilatedCovContext, allocate if needed
/// Note if get unresolved reference then likely forgot to link verilated_cov.cpp
VerilatedCovContext* coveragep() VL_MT_SAFE;
/// Set debug level
/// Debug is currently global, but for forward compatibility have a per-context method
static inline void debug(int val) VL_MT_SAFE;
/// Return debug level
static inline int debug() VL_MT_SAFE;
/// Set current number of errors/assertions
void errorCount(int val) VL_MT_SAFE;
/// Increment current number of errors/assertions
void errorCountInc() VL_MT_SAFE;
/// Return current number of errors/assertions
int errorCount() const VL_MT_SAFE { return m_s.m_errorCount; }
/// Set number of errors/assertions before stop
void errorLimit(int val) VL_MT_SAFE;
/// Return number of errors/assertions before stop
int errorLimit() const VL_MT_SAFE { return m_s.m_errorLimit; }
/// Set to throw fatal error on $stop/non-fatal error
void fatalOnError(bool flag) VL_MT_SAFE;
/// Return if to throw fatal error on $stop/non-fatal
bool fatalOnError() const VL_MT_SAFE { return m_s.m_fatalOnError; }
/// Set to throw fatal error on VPI errors
void fatalOnVpiError(bool flag) VL_MT_SAFE;
/// Return if to throw fatal error on VPI errors
bool fatalOnVpiError() const VL_MT_SAFE { return m_s.m_fatalOnVpiError; }
/// Set if got a $stop or non-fatal error
void gotError(bool flag) VL_MT_SAFE;
/// Return if got a $stop or non-fatal error
bool gotError() const VL_MT_SAFE { return m_s.m_gotError; }
/// Set if got a $finish or $stop/error
void gotFinish(bool flag) VL_MT_SAFE;
/// Return if got a $finish or $stop/error
bool gotFinish() const VL_MT_SAFE { return m_s.m_gotFinish; }
/// Enable quiet (also prevents need for OS calls to get CPU time)
void quiet(bool flag) VL_MT_SAFE;
/// Return if quiet enabled
bool quiet() const VL_MT_SAFE { return m_s.m_quiet; }
/// Select initial value of otherwise uninitialized signals.
/// 0 = Set to zeros
/// 1 = Set all bits to one
/// 2 = Randomize all bits
void randReset(int val) VL_MT_SAFE;
/// Return randReset value
int randReset() VL_MT_SAFE { return m_s.m_randReset; }
/// Return default random seed
void randSeed(int val) VL_MT_SAFE;
/// Set default random seed, 0 = seed it automatically
int randSeed() const VL_MT_SAFE { return m_s.m_randSeed; }
/// Return statistic: CPU time delta from model created until now
double statCpuTimeSinceStart() const VL_MT_SAFE_EXCLUDES(m_mutex);
/// Return statistic: Wall time delta from model created until now
double statWallTimeSinceStart() const VL_MT_SAFE_EXCLUDES(m_mutex);
/// Print statistics summary (if not quiet)
void statsPrintSummary() VL_MT_UNSAFE;
// Time handling
/// Returns current simulation time in units of timeprecision().
///
/// How Verilator runtime gets the current simulation time:
///
/// * If using SystemC, time comes from the SystemC kernel-defined
/// sc_time_stamp64(). User's wrapper must not call
/// SimulationContext::time(value) nor timeInc(value).
///
/// * Else, if SimulationContext::time(value) or
/// SimulationContext::timeInc(value) is ever called with non-zero,
/// then time will come via the context. This allows multiple contexts
/// to exist and have different simulation times. This must not be used
/// with SystemC. Note Verilated::time(value) and
/// Verilated::timeInc(value) call into SimulationContext::time and
/// timeInc, operating on the thread's context.
///
/// * Else, if VL_TIME_STAMP64 is defined, time comes from the legacy
/// 'uint64_t vl_time_stamp64()' which must a function be defined by
/// the user's wrapper.
///
/// * Else, time comes from the legacy 'double sc_time_stamp()' which
/// must be a function defined by the user's wrapper.
inline uint64_t time() const VL_MT_SAFE;
/// Set current simulation time. See time() for side effect details
void time(uint64_t value) VL_MT_SAFE { m_s.m_time = value; }
/// Advance current simulation time. See time() for side effect details
void timeInc(uint64_t add) VL_MT_UNSAFE { m_s.m_time += add; }
/// Return time units as power-of-ten
int timeunit() const VL_MT_SAFE { return -m_s.m_timeunit; }
/// Set time units as power-of-ten
void timeunit(int value) VL_MT_SAFE;
/// Return time units as IEEE-standard text
const char* timeunitString() const VL_MT_SAFE;
/// Get time precision as power-of-ten
int timeprecision() const VL_MT_SAFE { return -m_s.m_timeprecision; }
/// Return time precision as power-of-ten
inline void timeprecision(int value) VL_MT_SAFE;
/// Get time precision as IEEE-standard text
const char* timeprecisionString() const VL_MT_SAFE;
/// Get number of threads used for simulation (including the main thread)
unsigned threads() const { return m_threads; }
/// Get number of threads in added models (for statistical use only)
unsigned threadsInModels() const { return m_threadsInModels; }
/// Set number of threads used for simulation (including the main thread)
/// Can only be called before the thread pool is created (before first model is added).
void threads(unsigned n);
/// Trace signals in models within the context; called by application code
void trace(VerilatedTraceBaseC* tfp, int levels, int options = 0);
/// Allow traces to at some point be enabled (disables some optimizations)
void traceEverOn(bool flag) VL_MT_SAFE {
if (flag) calcUnusedSigs(true);
}
/// For debugging, print much of the Verilator internal state.
/// The output of this function may change in future
/// releases - contact the authors before production use.
void internalsDump() const VL_MT_SAFE;
/// For debugging, print text list of all scope names with
/// dpiImport/Export context. This function may change in future
/// releases - contact the authors before production use.
void scopesDump() const VL_MT_SAFE;
// METHODS - public but for internal use only
// Internal: access to implementation class
VerilatedContextImp* impp() VL_MT_SAFE { return reinterpret_cast<VerilatedContextImp*>(this); }
const VerilatedContextImp* impp() const VL_MT_SAFE {
return reinterpret_cast<const VerilatedContextImp*>(this);
}
// Internal: Model and thread setup
void addModel(VerilatedModel*);
VerilatedVirtualBase* threadPoolp();
void prepareClone();
VerilatedVirtualBase* threadPoolpOnClone();
VerilatedVirtualBase*
enableExecutionProfiler(VerilatedVirtualBase* (*construct)(VerilatedContext&));
// Internal: coverage
void coverageFilename(const std::string& flag) VL_MT_SAFE;
std::string coverageFilename() const VL_MT_SAFE;
// Internal: $dumpfile
void dumpfile(const std::string& flag) VL_MT_SAFE_EXCLUDES(m_timeDumpMutex);
std::string dumpfile() const VL_MT_SAFE_EXCLUDES(m_timeDumpMutex);
std::string dumpfileCheck() const VL_MT_SAFE_EXCLUDES(m_timeDumpMutex);
// Internal: --prof-exec related settings
void profExecStart(uint64_t flag) VL_MT_SAFE;
uint64_t profExecStart() const VL_MT_SAFE { return m_ns.m_profExecStart; }
void profExecWindow(uint64_t flag) VL_MT_SAFE;
uint32_t profExecWindow() const VL_MT_SAFE { return m_ns.m_profExecWindow; }
void profExecFilename(const std::string& flag) VL_MT_SAFE;
std::string profExecFilename() const VL_MT_SAFE;
void profVltFilename(const std::string& flag) VL_MT_SAFE;
std::string profVltFilename() const VL_MT_SAFE;
// Internal: SMT solver program
void solverProgram(const std::string& flag) VL_MT_SAFE;
std::string solverProgram() const VL_MT_SAFE;
// Internal: Find scope
const VerilatedScope* scopeFind(const char* namep) const VL_MT_SAFE;
const VerilatedScopeNameMap* scopeNameMap() VL_MT_SAFE;
// Internal: Serialization setup
static constexpr size_t serialized1Size() VL_PURE { return sizeof(m_s); }
void* serialized1Ptr() VL_MT_UNSAFE { return &m_s; }
// Internal: trace registration
void traceBaseModelCbAdd(traceBaseModelCb_t cb) VL_MT_SAFE;
// Internal: Check magic number
static void checkMagic(const VerilatedContext* contextp);
void selfTestClearMagic() { m_magic = 0x2; }
};
//===========================================================================
// Verilator symbol table base class
// Used for internal VPI implementation, and introspection into scopes
class VerilatedSyms VL_NOT_FINAL {
public: // But for internal use only
// MEMBERS
// Keep first so is at zero offset for fastest code
VerilatedContext* const _vm_contextp__; // Context for current model
VerilatedEvalMsgQueue* __Vm_evalMsgQp;
explicit VerilatedSyms(VerilatedContext* contextp); // Pass null for default context
~VerilatedSyms();
VL_UNCOPYABLE(VerilatedSyms);
};
//===========================================================================
// Verilator scope information class
// Used for internal VPI implementation, and introspection into scopes
class VerilatedScope final {
public:
enum Type : uint8_t {
SCOPE_MODULE,
SCOPE_OTHER,
SCOPE_PACKAGE
}; // Type of a scope, currently only module and package are interesting
private:
// Fastpath:
VerilatedSyms* m_symsp = nullptr; // Symbol table
void** m_callbacksp = nullptr; // Callback table pointer (Fastpath)
int m_funcnumMax = 0; // Maximum function number stored (Fastpath)
// 4 bytes padding (on -m64), for rent.
VerilatedVarNameMap* m_varsp = nullptr; // Variable map
const char* m_namep = nullptr; // Scope name (Slowpath)
const char* m_identifierp = nullptr; // Identifier of scope (with escapes removed)
int8_t m_timeunit = 0; // Timeunit in negative power-of-10
Type m_type = SCOPE_OTHER; // Type of the scope
public: // But internals only - called from VerilatedModule's
VerilatedScope() = default;
~VerilatedScope();
void configure(VerilatedSyms* symsp, const char* prefixp, const char* suffixp,
const char* identifier, int8_t timeunit, const Type& type) VL_MT_UNSAFE;
void exportInsert(int finalize, const char* namep, void* cb) VL_MT_UNSAFE;
void varInsert(int finalize, const char* namep, void* datap, bool isParam,
VerilatedVarType vltype, int vlflags, int dims, ...) VL_MT_UNSAFE;
// ACCESSORS
const char* name() const VL_MT_SAFE_POSTINIT { return m_namep; }
const char* identifier() const VL_MT_SAFE_POSTINIT { return m_identifierp; }
int8_t timeunit() const VL_MT_SAFE_POSTINIT { return m_timeunit; }
VerilatedSyms* symsp() const VL_MT_SAFE_POSTINIT { return m_symsp; }
VerilatedVar* varFind(const char* namep) const VL_MT_SAFE_POSTINIT;
VerilatedVarNameMap* varsp() const VL_MT_SAFE_POSTINIT { return m_varsp; }
void scopeDump() const;
void* exportFindError(int funcnum) const VL_MT_SAFE;
static void* exportFindNullError(int funcnum) VL_MT_SAFE;
static void* exportFind(const VerilatedScope* scopep, int funcnum) VL_MT_SAFE {
if (VL_UNLIKELY(!scopep)) return exportFindNullError(funcnum);
if (VL_LIKELY(funcnum < scopep->m_funcnumMax)) {
// m_callbacksp must be declared, as Max'es are > 0
return scopep->m_callbacksp[funcnum];
} else { // LCOV_EXCL_LINE
return scopep->exportFindError(funcnum); // LCOV_EXCL_LINE
}
}
Type type() const { return m_type; }
};
class VerilatedHierarchy final {
public:
static void add(VerilatedScope* fromp, VerilatedScope* top);
static void remove(VerilatedScope* fromp, VerilatedScope* top);
};
//===========================================================================
/// Verilator global static information class
class Verilated final {
// MEMBERS
// Internal Note: There should be no Serialized state in Verilated::,
// instead serialized state should all be in VerilatedContext:: as by
// definition it needs to vary per-simulation
// Internal note: Globals may multi-construct, see verilated.cpp top.
// Debug is reloaded from on command-line settings, so do not need to persist
static int s_debug; // See accessors... only when VL_DEBUG set
static VerilatedContext* s_lastContextp; // Last context constructed/attached
// Not covered by mutex, as per-thread
static thread_local struct ThreadLocal {
// No non-POD objects here due to this:
// Internal note: Globals may multi-construct, see verilated.cpp top.
// Fast path
VerilatedContext* t_contextp = nullptr; // Thread's context
uint32_t t_mtaskId = 0; // mtask# executing on this thread
// Messages maybe pending on thread, needs end-of-eval calls
uint32_t t_endOfEvalReqd = 0;
const VerilatedScope* t_dpiScopep = nullptr; // DPI context scope
const char* t_dpiFilename = nullptr; // DPI context filename
int t_dpiLineno = 0; // DPI context line number
ThreadLocal() = default;
~ThreadLocal() = default;
} t_s;
friend struct VerilatedInitializer;
// CONSTRUCTORS
VL_UNCOPYABLE(Verilated);
public:
// METHODS - User called
/// Enable debug of internal verilated code
static void debug(int level) VL_MT_SAFE;
#ifdef VL_DEBUG
/// Return debug level
/// When multithreaded this may not immediately react to another thread
/// changing the level (no mutex)
static int debug() VL_MT_SAFE { return s_debug; }
#else
/// Return constant 0 debug level, so C++'s optimizer rips up
static constexpr int debug() VL_PURE { return 0; }
#endif
/// Set the last VerilatedContext accessed
/// Generally threadContextp(value) should be called instead
static void lastContextp(VerilatedContext* contextp) VL_MT_SAFE { s_lastContextp = contextp; }
/// Return the last VerilatedContext accessed
/// Generally threadContextp() should be called instead
static VerilatedContext* lastContextp() VL_MT_SAFE {
if (!s_lastContextp) lastContextp(defaultContextp());
return s_lastContextp;
}
/// Set the VerilatedContext used by the current thread
/// If using multiple contexts, and threads are created by the user's
/// wrapper (not Verilator itself) then this must be called to set the
/// context that applies to each thread
static void threadContextp(VerilatedContext* contextp) VL_MT_SAFE {
t_s.t_contextp = contextp;
lastContextp(contextp);
}
/// Return the VerilatedContext for the current thread
static VerilatedContext* threadContextp() VL_MT_SAFE {
if (VL_UNLIKELY(!t_s.t_contextp)) t_s.t_contextp = lastContextp();
return t_s.t_contextp;
}
/// Return the global VerilatedContext, used if none created by user
static VerilatedContext* defaultContextp() VL_MT_SAFE {
static VerilatedContext s_s;
return &s_s;
}
#ifndef VL_NO_LEGACY
/// Call VerilatedContext::assertOn using current thread's VerilatedContext
static void assertOn(bool flag) VL_MT_SAFE { Verilated::threadContextp()->assertOn(flag); }
/// Return VerilatedContext::assertOn() using current thread's VerilatedContext
static bool assertOn() VL_MT_SAFE { return Verilated::threadContextp()->assertOn(); }
/// Call VerilatedContext::calcUnusedSigs using current thread's VerilatedContext
static void calcUnusedSigs(bool flag) VL_MT_SAFE {
Verilated::threadContextp()->calcUnusedSigs(flag);
}
/// Return VerilatedContext::calcUnusedSigs using current thread's VerilatedContext
static bool calcUnusedSigs() VL_MT_SAFE {
return Verilated::threadContextp()->calcUnusedSigs();
}
/// Call VerilatedContext::commandArgs using current thread's VerilatedContext
static void commandArgs(int argc, const char** argv) VL_MT_SAFE {
Verilated::threadContextp()->commandArgs(argc, argv);
}
static void commandArgs(int argc, char** argv) VL_MT_SAFE {
commandArgs(argc, const_cast<const char**>(argv));
}
/// Call VerilatedContext::commandArgsAdd using current thread's VerilatedContext
static void commandArgsAdd(int argc, const char** argv) {
Verilated::threadContextp()->commandArgsAdd(argc, argv);
}
/// Return VerilatedContext::commandArgsPlusMatch using current thread's VerilatedContext
static const char* commandArgsPlusMatch(const char* prefixp) VL_MT_SAFE {
return Verilated::threadContextp()->commandArgsPlusMatch(prefixp);
}
/// Call VerilatedContext::errorLimit using current thread's VerilatedContext
static void errorLimit(int val) VL_MT_SAFE { Verilated::threadContextp()->errorLimit(val); }
/// Return VerilatedContext::errorLimit using current thread's VerilatedContext
static int errorLimit() VL_MT_SAFE { return Verilated::threadContextp()->errorLimit(); }
/// Call VerilatedContext::fatalOnError using current thread's VerilatedContext
static void fatalOnError(bool flag) VL_MT_SAFE {
Verilated::threadContextp()->fatalOnError(flag);
}
/// Return VerilatedContext::fatalOnError using current thread's VerilatedContext
static bool fatalOnError() VL_MT_SAFE { return Verilated::threadContextp()->fatalOnError(); }
/// Call VerilatedContext::fatalOnVpiError using current thread's VerilatedContext
static void fatalOnVpiError(bool flag) VL_MT_SAFE {
Verilated::threadContextp()->fatalOnVpiError(flag);
}
/// Return VerilatedContext::fatalOnVpiError using current thread's VerilatedContext
static bool fatalOnVpiError() VL_MT_SAFE {
return Verilated::threadContextp()->fatalOnVpiError();
}
/// Call VerilatedContext::gotError using current thread's VerilatedContext
static void gotError(bool flag) VL_MT_SAFE { Verilated::threadContextp()->gotError(flag); }
/// Return VerilatedContext::gotError using current thread's VerilatedContext
static bool gotError() VL_MT_SAFE { return Verilated::threadContextp()->gotError(); }
/// Call VerilatedContext::gotFinish using current thread's VerilatedContext
static void gotFinish(bool flag) VL_MT_SAFE { Verilated::threadContextp()->gotFinish(flag); }
/// Return VerilatedContext::gotFinish using current thread's VerilatedContext
static bool gotFinish() VL_MT_SAFE { return Verilated::threadContextp()->gotFinish(); }
/// Call VerilatedContext::randReset using current thread's VerilatedContext
static void randReset(int val) VL_MT_SAFE { Verilated::threadContextp()->randReset(val); }
/// Return VerilatedContext::randReset using current thread's VerilatedContext
static int randReset() VL_MT_SAFE { return Verilated::threadContextp()->randReset(); }
/// Call VerilatedContext::randSeed using current thread's VerilatedContext
static void randSeed(int val) VL_MT_SAFE { Verilated::threadContextp()->randSeed(val); }
/// Return VerilatedContext::randSeed using current thread's VerilatedContext
static int randSeed() VL_MT_SAFE { return Verilated::threadContextp()->randSeed(); }
/// Call VerilatedContext::time using current thread's VerilatedContext
static void time(uint64_t val) VL_MT_SAFE { Verilated::threadContextp()->time(val); }
/// Return VerilatedContext::time using current thread's VerilatedContext
static uint64_t time() VL_MT_SAFE { return Verilated::threadContextp()->time(); }
/// Call VerilatedContext::timeInc using current thread's VerilatedContext
static void timeInc(uint64_t add) VL_MT_UNSAFE { Verilated::threadContextp()->timeInc(add); }
// Deprecated
static int timeunit() VL_MT_SAFE { return Verilated::threadContextp()->timeunit(); }
static int timeprecision() VL_MT_SAFE { return Verilated::threadContextp()->timeprecision(); }
/// Call VerilatedContext::tracesEverOn using current thread's VerilatedContext
static void traceEverOn(bool flag) VL_MT_SAFE {
Verilated::threadContextp()->traceEverOn(flag);
}
#endif
/// Callback typedef for addFlushCb, addExitCb
using VoidPCb = void (*)(void*);
/// Add callback to run on global flush
static void addFlushCb(VoidPCb cb, void* datap) VL_MT_SAFE;
/// Remove callback to run on global flush
static void removeFlushCb(VoidPCb cb, void* datap) VL_MT_SAFE;
/// Run flush callbacks registered with addFlushCb
static void runFlushCallbacks() VL_MT_SAFE;
#ifndef VL_NO_LEGACY
static void flushCall() VL_MT_SAFE { runFlushCallbacks(); } // Deprecated
#endif
/// Add callback to run prior to exit termination
static void addExitCb(VoidPCb cb, void* datap) VL_MT_SAFE;
/// Remove callback to run prior to exit termination
static void removeExitCb(VoidPCb cb, void* datap) VL_MT_SAFE;
/// Run exit callbacks registered with addExitCb
static void runExitCallbacks() VL_MT_SAFE;
/// Return product name for (at least) VPI
static const char* productName() VL_PURE;
/// Return product version for (at least) VPI
static const char* productVersion() VL_PURE;
/// Call OS to make a directory
static void mkdir(const char* dirname) VL_MT_UNSAFE;
/// When multithreaded, quiesce the model to prepare for trace/saves/coverage
/// This may only be called when no locks are held.
static void quiesce() VL_MT_SAFE;
#ifndef VL_NO_LEGACY
/// For debugging, print much of the Verilator internal state.
/// The output of this function may change in future
/// releases - contact the authors before production use.
static void internalsDump() VL_MT_SAFE { Verilated::threadContextp()->internalsDump(); }
/// For debugging, print text list of all scope names with
/// dpiImport/Export context. This function may change in future
/// releases - contact the authors before production use.
static void scopesDump() VL_MT_SAFE { Verilated::threadContextp()->scopesDump(); }
// Internal: Find scope
static const VerilatedScope* scopeFind(const char* namep) VL_MT_SAFE {
return Verilated::threadContextp()->scopeFind(namep);
}
static const VerilatedScopeNameMap* scopeNameMap() VL_MT_SAFE {
return Verilated::threadContextp()->scopeNameMap();
}
#endif
// METHODS - INTERNAL USE ONLY (but public due to what uses it)
// Internal: Create a new module name by concatenating two strings
// Returns pointer to thread-local static data (overwritten on next call)
static const char* catName(const char* n1, const char* n2,
const char* delimiter = ".") VL_MT_SAFE;
// Internal: Throw signal assertion
static void nullPointerError(const char* filename, int linenum) VL_ATTR_NORETURN VL_MT_SAFE;
static void overWidthError(const char* signame) VL_ATTR_NORETURN VL_MT_SAFE;
static void scTimePrecisionError(int sc_prec, int vl_prec) VL_ATTR_NORETURN VL_MT_SAFE;
static void scTraceBeforeElaborationError() VL_ATTR_NORETURN VL_MT_SAFE;
static void stackCheck(QData needSize) VL_MT_UNSAFE;
// Internal: Get and set DPI context
static const VerilatedScope* dpiScope() VL_MT_SAFE { return t_s.t_dpiScopep; }
static void dpiScope(const VerilatedScope* scopep) VL_MT_SAFE { t_s.t_dpiScopep = scopep; }
static void dpiContext(const VerilatedScope* scopep, const char* filenamep,
int lineno) VL_MT_SAFE {
t_s.t_dpiScopep = scopep;
t_s.t_dpiFilename = filenamep;
t_s.t_dpiLineno = lineno;
}
static void dpiClearContext() VL_MT_SAFE { t_s.t_dpiScopep = nullptr; }
static bool dpiInContext() VL_MT_SAFE { return t_s.t_dpiScopep != nullptr; }
static const char* dpiFilenamep() VL_MT_SAFE { return t_s.t_dpiFilename; }
static int dpiLineno() VL_MT_SAFE { return t_s.t_dpiLineno; }
static int exportFuncNum(const char* namep) VL_MT_SAFE;
// Internal: Set the mtaskId, called when an mtask starts
// Per thread, so no need to be in VerilatedContext
static void mtaskId(uint32_t id) VL_MT_SAFE { t_s.t_mtaskId = id; }
static uint32_t mtaskId() VL_MT_SAFE { return t_s.t_mtaskId; }
static void endOfEvalReqdInc() VL_MT_SAFE { ++t_s.t_endOfEvalReqd; }
static void endOfEvalReqdDec() VL_MT_SAFE { --t_s.t_endOfEvalReqd; }
// Internal: Called at end of each thread mtask, before finishing eval
static void endOfThreadMTask(VerilatedEvalMsgQueue* evalMsgQp) VL_MT_SAFE {
mtaskId(0);
if (VL_UNLIKELY(t_s.t_endOfEvalReqd)) endOfThreadMTaskGuts(evalMsgQp);
}
// Internal: Called at end of eval loop
static void endOfEval(VerilatedEvalMsgQueue* evalMsgQp) VL_MT_SAFE;
private:
static void endOfThreadMTaskGuts(VerilatedEvalMsgQueue* evalMsgQp) VL_MT_SAFE;
};
void VerilatedContext::debug(int val) VL_MT_SAFE { Verilated::debug(val); }
int VerilatedContext::debug() VL_MT_SAFE { return Verilated::debug(); }
//=========================================================================
// Data Types
#include "verilated_types.h"
//=========================================================================
// Functions
#include "verilated_funcs.h"
//======================================================================
void VerilatedContext::timeprecision(int value) VL_MT_SAFE {
if (value < 0) value = -value; // Stored as 0..15
#if VM_SC
int sc_prec = 99;
#endif
{
const VerilatedLockGuard lock{m_mutex};
m_s.m_timeprecision = value;