1 // -*- mode: C++; c-file-style: "cc-mode" -*-
2 //=============================================================================
3 //
4 // Code available from: https://verilator.org
5 //
6 // Copyright 2001-2021 by Wilson Snyder. This program is free software; you
7 // can redistribute it and/or modify it under the terms of either the GNU
8 // Lesser General Public License Version 3 or the Perl Artistic License
9 // Version 2.0.
10 // SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
11 //
12 //=============================================================================
13 ///
14 /// \file
15 /// \brief Verilated tracing in FST format header
16 ///
17 /// User wrapper code should use this header when creating FST traces.
18 ///
19 //=============================================================================
20 
21 #ifndef VERILATOR_VERILATED_FST_C_H_
22 #define VERILATOR_VERILATED_FST_C_H_
23 
24 #include "verilated.h"
25 #include "verilated_trace.h"
26 
27 #include "gtkwave/fstapi.h"
28 
29 #include <list>
30 #include <map>
31 #include <string>
32 #include <vector>
33 
34 //=============================================================================
35 // VerilatedFst
36 // Base class to create a Verilator FST dump
37 // This is an internally used class - see VerilatedFstC for what to call from applications
38 
39 class VerilatedFst final : public VerilatedTrace<VerilatedFst> {
40 private:
41     // Give the superclass access to private bits (to avoid virtual functions)
42     friend class VerilatedTrace<VerilatedFst>;
43 
44     //=========================================================================
45     // FST specific internals
46 
47     void* m_fst;
48     std::map<vluint32_t, fstHandle> m_code2symbol;
49     std::map<int, fstEnumHandle> m_local2fstdtype;
50     std::list<std::string> m_curScope;
51     fstHandle* m_symbolp = nullptr;  // same as m_code2symbol, but as an array
52     char* m_strbuf = nullptr;  // String buffer long enough to hold maxBits() chars
53 
54     // CONSTRUCTORS
55     VL_UNCOPYABLE(VerilatedFst);
56     void declare(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
57                  fstVarType vartype, bool array, int arraynum, int msb, int lsb);
58 
59 protected:
60     //=========================================================================
61     // Implementation of VerilatedTrace interface
62 
63     // Implementations of protected virtual methods for VerilatedTrace
64     virtual void emitTimeChange(vluint64_t timeui) override;
65 
66     // Hooks called from VerilatedTrace
preFullDump()67     virtual bool preFullDump() override { return isOpen(); }
preChangeDump()68     virtual bool preChangeDump() override { return isOpen(); }
69 
70     // Implementations of duck-typed methods for VerilatedTrace. These are
71     // called from only one place (namely full*) so always inline them.
72     inline void emitBit(vluint32_t code, CData newval);
73     inline void emitCData(vluint32_t code, CData newval, int bits);
74     inline void emitSData(vluint32_t code, SData newval, int bits);
75     inline void emitIData(vluint32_t code, IData newval, int bits);
76     inline void emitQData(vluint32_t code, QData newval, int bits);
77     inline void emitWData(vluint32_t code, const WData* newvalp, int bits);
78     inline void emitDouble(vluint32_t code, double newval);
79 
80 public:
81     //=========================================================================
82     // External interface to client code
83     // (All must be threadsafe)
84 
85     explicit VerilatedFst(void* fst = nullptr);
86     ~VerilatedFst();
87 
88     // Open the file; call isOpen() to see if errors
89     void open(const char* filename) VL_MT_SAFE_EXCLUDES(m_mutex);
90     // Close the file
91     void close() VL_MT_SAFE_EXCLUDES(m_mutex);
92     // Flush any remaining data to this file
93     void flush() VL_MT_SAFE_EXCLUDES(m_mutex);
94     // Return if file is open
isOpen()95     bool isOpen() const VL_MT_SAFE { return m_fst != nullptr; }
96 
97     //=========================================================================
98     // Internal interface to Verilator generated code
99 
100     // Inside dumping routines, declare a data type
101     void declDTypeEnum(int dtypenum, const char* name, vluint32_t elements,
102                        unsigned int minValbits, const char** itemNamesp, const char** itemValuesp);
103 
104     // Inside dumping routines, declare a signal
105     void declBit(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
106                  fstVarType vartype, bool array, int arraynum);
107     void declBus(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
108                  fstVarType vartype, bool array, int arraynum, int msb, int lsb);
109     void declQuad(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
110                   fstVarType vartype, bool array, int arraynum, int msb, int lsb);
111     void declArray(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
112                    fstVarType vartype, bool array, int arraynum, int msb, int lsb);
113     void declDouble(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
114                     fstVarType vartype, bool array, int arraynum);
115 };
116 
117 #ifndef DOXYGEN
118 // Declare specialization here as it's used in VerilatedFstC just below
119 template <> void VerilatedTrace<VerilatedFst>::dump(vluint64_t timeui);
120 template <> void VerilatedTrace<VerilatedFst>::set_time_unit(const char* unitp);
121 template <> void VerilatedTrace<VerilatedFst>::set_time_unit(const std::string& unit);
122 template <> void VerilatedTrace<VerilatedFst>::set_time_resolution(const char* unitp);
123 template <> void VerilatedTrace<VerilatedFst>::set_time_resolution(const std::string& unit);
124 #endif
125 
126 //=============================================================================
127 // VerilatedFstC
128 /// Create a FST dump file in C standalone (no SystemC) simulations.
129 /// Also derived for use in SystemC simulations.
130 
131 class VerilatedFstC VL_NOT_FINAL {
132     VerilatedFst m_sptrace;  // Trace file being created
133 
134     // CONSTRUCTORS
135     VL_UNCOPYABLE(VerilatedFstC);
136 
137 public:
138     /// Construct the dump. Optional argument is ignored.
139     explicit VerilatedFstC(void* filep = nullptr)
140         : m_sptrace{filep} {}
141     /// Destruct, flush, and close the dump
~VerilatedFstC()142     ~VerilatedFstC() { close(); }
143 
144     // METHODS - User called
145 
146     /// Return if file is open
isOpen()147     bool isOpen() const VL_MT_SAFE { return m_sptrace.isOpen(); }
148     /// Open a new FST file
open(const char * filename)149     void open(const char* filename) VL_MT_SAFE { m_sptrace.open(filename); }
150     /// Close dump
close()151     void close() VL_MT_SAFE { m_sptrace.close(); }
152     /// Flush dump
flush()153     void flush() VL_MT_SAFE { m_sptrace.flush(); }
154     /// Write one cycle of dump data
155     /// Call with the current context's time just after eval'ed,
156     /// e.g. ->dump(contextp->time())
dump(vluint64_t timeui)157     void dump(vluint64_t timeui) { m_sptrace.dump(timeui); }
158     /// Write one cycle of dump data - backward compatible and to reduce
159     /// conversion warnings.  It's better to use a vluint64_t time instead.
dump(double timestamp)160     void dump(double timestamp) { dump(static_cast<vluint64_t>(timestamp)); }
dump(vluint32_t timestamp)161     void dump(vluint32_t timestamp) { dump(static_cast<vluint64_t>(timestamp)); }
dump(int timestamp)162     void dump(int timestamp) { dump(static_cast<vluint64_t>(timestamp)); }
163 
164     // METHODS - Internal/backward compatible
165     // \protectedsection
166 
167     // Set time units (s/ms, defaults to ns)
168     // Users should not need to call this, as for Verilated models, these
169     // propage from the Verilated default timeunit
set_time_unit(const char * unitp)170     void set_time_unit(const char* unitp) VL_MT_SAFE { m_sptrace.set_time_unit(unitp); }
set_time_unit(const std::string & unit)171     void set_time_unit(const std::string& unit) VL_MT_SAFE { m_sptrace.set_time_unit(unit); }
172     // Set time resolution (s/ms, defaults to ns)
173     // Users should not need to call this, as for Verilated models, these
174     // propage from the Verilated default timeprecision
set_time_resolution(const char * unitp)175     void set_time_resolution(const char* unitp) VL_MT_SAFE {
176         m_sptrace.set_time_resolution(unitp);
177     }
set_time_resolution(const std::string & unit)178     void set_time_resolution(const std::string& unit) VL_MT_SAFE {
179         m_sptrace.set_time_resolution(unit);
180     }
181 
182     // Internal class access
spTrace()183     inline VerilatedFst* spTrace() { return &m_sptrace; };
184 };
185 
186 #endif  // guard
187