1 // -*- mode: C++; c-file-style: "cc-mode" -*-
2 //*************************************************************************
3 //
4 // Code available from: https://verilator.org
5 //
6 // Copyright 2009-2021 by Wilson Snyder. This program is free software; you can
7 // redistribute it and/or modify it under the terms of either the GNU
8 // Lesser General Public License Version 3 or the Perl Artistic License
9 // Version 2.0.
10 // SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
11 //
12 //=========================================================================
13 ///
14 /// \file
15 /// \brief Verilated DPI implementation code
16 ///
17 /// This file must be compiled and linked against all Verilated objects
18 /// that use the DPI.
19 ///
20 /// Declare any DPI routine inside Verilog to add this to the Makefile for
21 /// the linker.
22 ///
23 /// For documentation on the exported functions (named sv*) that are
24 /// implemented here, refer to the IEEE DPI chapter.
25 ///
26 //=========================================================================
27 
28 #define VERILATOR_VERILATED_DPI_CPP_
29 
30 #include "verilatedos.h"
31 #include "verilated_dpi.h"
32 #include "verilated_imp.h"
33 
34 // On MSVC++ we need svdpi.h to declare exports, not imports
35 #define DPI_PROTOTYPES
36 #undef XXTERN
37 #define XXTERN DPI_EXTERN DPI_DLLESPEC
38 #undef EETERN
39 #define EETERN DPI_EXTERN DPI_DLLESPEC
40 
41 #include "vltstd/svdpi.h"
42 
43 //======================================================================
44 // Internal macros
45 
46 #define VL_SVDPI_WARN_(...) VL_PRINTF_MT(__VA_ARGS__)
47 
48 // Function requires a "context" in the import declaration
49 #define VL_SVDPI_CONTEXT_WARN_() \
50     VL_SVDPI_WARN_("%%Warning: DPI C Function called by Verilog DPI import with missing " \
51                    "'context' keyword.\n")
52 
53 //======================================================================
54 //======================================================================
55 //======================================================================
56 // DPI ROUTINES
57 
svDpiVersion()58 const char* svDpiVersion() { return "1800-2005"; }
59 
60 //======================================================================
61 // Bit-select utility functions.
62 
svGetBitselBit(const svBitVecVal * sp,int bit)63 svBit svGetBitselBit(const svBitVecVal* sp, int bit) { return VL_BITRSHIFT_W(sp, bit) & 1; }
svGetBitselLogic(const svLogicVecVal * sp,int bit)64 svLogic svGetBitselLogic(const svLogicVecVal* sp, int bit) {
65     // Not VL_BITRSHIFT_W as sp is a different structure type
66     // Verilator doesn't support X/Z so only aval
67     return (((sp[VL_BITWORD_I(bit)].aval >> VL_BITBIT_I(bit)) & 1)
68             | (((sp[VL_BITWORD_I(bit)].bval >> VL_BITBIT_I(bit)) & 1) << 1));
69 }
70 
svPutBitselBit(svBitVecVal * dp,int bit,svBit s)71 void svPutBitselBit(svBitVecVal* dp, int bit, svBit s) { VL_ASSIGNBIT_WI(bit, dp, s); }
svPutBitselLogic(svLogicVecVal * dp,int bit,svLogic s)72 void svPutBitselLogic(svLogicVecVal* dp, int bit, svLogic s) {
73     // Verilator doesn't support X/Z so only aval
74     dp[VL_BITWORD_I(bit)].aval = ((dp[VL_BITWORD_I(bit)].aval & ~(VL_UL(1) << VL_BITBIT_I(bit)))
75                                   | ((s & 1) << VL_BITBIT_I(bit)));
76     dp[VL_BITWORD_I(bit)].bval = ((dp[VL_BITWORD_I(bit)].bval & ~(VL_UL(1) << VL_BITBIT_I(bit)))
77                                   | ((s & 2) >> 1 << VL_BITBIT_I(bit)));
78 }
79 
svGetPartselBit(svBitVecVal * dp,const svBitVecVal * sp,int lsb,int width)80 void svGetPartselBit(svBitVecVal* dp, const svBitVecVal* sp, int lsb, int width) {
81     // See also VL_SEL_WWI
82     const int msb = lsb + width - 1;
83     const int word_shift = VL_BITWORD_I(lsb);
84     if (VL_BITBIT_I(lsb) == 0) {
85         // Just a word extract
86         for (int i = 0; i < VL_WORDS_I(width); ++i) dp[i] = sp[i + word_shift];
87     } else {
88         const int loffset = lsb & VL_SIZEBITS_I;
89         const int nbitsfromlow = 32 - loffset;  // bits that end up in lword (know loffset!=0)
90         // Middle words
91         const int words = VL_WORDS_I(msb - lsb + 1);
92         for (int i = 0; i < words; ++i) {
93             dp[i] = sp[i + word_shift] >> loffset;
94             const int upperword = i + word_shift + 1;
95             if (upperword <= static_cast<int>(VL_BITWORD_I(msb))) {
96                 dp[i] |= sp[upperword] << nbitsfromlow;
97             }
98         }
99     }
100     // Clean result
101     dp[VL_WORDS_I(width) - 1] &= VL_MASK_I(width);
102 }
svGetPartselLogic(svLogicVecVal * dp,const svLogicVecVal * sp,int lsb,int width)103 void svGetPartselLogic(svLogicVecVal* dp, const svLogicVecVal* sp, int lsb, int width) {
104     const int msb = lsb + width - 1;
105     const int word_shift = VL_BITWORD_I(lsb);
106     if (VL_BITBIT_I(lsb) == 0) {
107         // Just a word extract
108         for (int i = 0; i < VL_WORDS_I(width); ++i) dp[i] = sp[i + word_shift];
109     } else {
110         const int loffset = lsb & VL_SIZEBITS_I;
111         const int nbitsfromlow = 32 - loffset;  // bits that end up in lword (know loffset!=0)
112         // Middle words
113         const int words = VL_WORDS_I(msb - lsb + 1);
114         for (int i = 0; i < words; ++i) {
115             dp[i].aval = sp[i + word_shift].aval >> loffset;
116             dp[i].bval = sp[i + word_shift].bval >> loffset;
117             const int upperword = i + word_shift + 1;
118             if (upperword <= static_cast<int>(VL_BITWORD_I(msb))) {
119                 dp[i].aval |= sp[upperword].aval << nbitsfromlow;
120                 dp[i].bval |= sp[upperword].bval << nbitsfromlow;
121             }
122         }
123     }
124     // Clean result
125     dp[VL_WORDS_I(width) - 1].aval &= VL_MASK_I(width);
126     dp[VL_WORDS_I(width) - 1].bval &= VL_MASK_I(width);
127 }
svPutPartselBit(svBitVecVal * dp,const svBitVecVal s,int lbit,int width)128 void svPutPartselBit(svBitVecVal* dp, const svBitVecVal s, int lbit, int width) {
129     // See also _vl_insert_WI
130     const int hbit = lbit + width - 1;
131     const int hoffset = VL_BITBIT_I(hbit);
132     const int loffset = VL_BITBIT_I(lbit);
133     if (hoffset == VL_SIZEBITS_I && loffset == 0) {
134         // Fast and common case, word based insertion
135         dp[VL_BITWORD_I(lbit)] = s;
136     } else {
137         const int hword = VL_BITWORD_I(hbit);
138         const int lword = VL_BITWORD_I(lbit);
139         if (hword == lword) {  // know < 32 bits because above checks it
140             const IData insmask = (VL_MASK_I(hoffset - loffset + 1)) << loffset;
141             dp[lword] = (dp[lword] & ~insmask) | ((s << loffset) & insmask);
142         } else {
143             const IData hinsmask = (VL_MASK_I(hoffset - 0 + 1)) << 0;
144             const IData linsmask = (VL_MASK_I(31 - loffset + 1)) << loffset;
145             const int nbitsonright = 32 - loffset;  // bits that end up in lword
146             dp[lword] = (dp[lword] & ~linsmask) | ((s << loffset) & linsmask);
147             dp[hword] = (dp[hword] & ~hinsmask) | ((s >> nbitsonright) & hinsmask);
148         }
149     }
150 }
151 // cppcheck-suppress passedByValue
svPutPartselLogic(svLogicVecVal * dp,const svLogicVecVal s,int lbit,int width)152 void svPutPartselLogic(svLogicVecVal* dp, const svLogicVecVal s, int lbit, int width) {
153     const int hbit = lbit + width - 1;
154     const int hoffset = VL_BITBIT_I(hbit);
155     const int loffset = VL_BITBIT_I(lbit);
156     if (hoffset == VL_SIZEBITS_I && loffset == 0) {
157         // Fast and common case, word based insertion
158         dp[VL_BITWORD_I(lbit)].aval = s.aval;
159         dp[VL_BITWORD_I(lbit)].bval = s.bval;
160     } else {
161         const int hword = VL_BITWORD_I(hbit);
162         const int lword = VL_BITWORD_I(lbit);
163         if (hword == lword) {  // know < 32 bits because above checks it
164             const IData insmask = (VL_MASK_I(hoffset - loffset + 1)) << loffset;
165             dp[lword].aval = (dp[lword].aval & ~insmask) | ((s.aval << loffset) & insmask);
166             dp[lword].bval = (dp[lword].bval & ~insmask) | ((s.bval << loffset) & insmask);
167         } else {
168             const IData hinsmask = (VL_MASK_I(hoffset - 0 + 1)) << 0;
169             const IData linsmask = (VL_MASK_I(31 - loffset + 1)) << loffset;
170             const int nbitsonright = 32 - loffset;  // bits that end up in lword
171             dp[lword].aval = (dp[lword].aval & ~linsmask) | ((s.aval << loffset) & linsmask);
172             dp[lword].bval = (dp[lword].bval & ~linsmask) | ((s.bval << loffset) & linsmask);
173             dp[hword].aval = (dp[hword].aval & ~hinsmask) | ((s.aval >> nbitsonright) & hinsmask);
174             dp[hword].bval = (dp[hword].bval & ~hinsmask) | ((s.bval >> nbitsonright) & hinsmask);
175         }
176     }
177 }
178 
179 //======================================================================
180 // Open array internals
181 
_vl_openhandle_varp(const svOpenArrayHandle h)182 static inline const VerilatedDpiOpenVar* _vl_openhandle_varp(const svOpenArrayHandle h) {
183     if (VL_UNLIKELY(!h)) {
184         VL_FATAL_MT(__FILE__, __LINE__, "",
185                     "%%Error: DPI svOpenArrayHandle function called with nullptr handle");
186     }
187     const VerilatedDpiOpenVar* const varp = reinterpret_cast<const VerilatedDpiOpenVar*>(h);
188     if (VL_UNLIKELY(!varp->magicOk())) {
189         VL_FATAL_MT(__FILE__, __LINE__, "",
190                     "%%Error: DPI svOpenArrayHandle function called with non-Verilator handle");
191     }
192     return varp;
193 }
194 
195 //======================================================================
196 // Open array querying functions
197 
svLeft(const svOpenArrayHandle h,int d)198 int svLeft(const svOpenArrayHandle h, int d) { return _vl_openhandle_varp(h)->left(d); }
svRight(const svOpenArrayHandle h,int d)199 int svRight(const svOpenArrayHandle h, int d) { return _vl_openhandle_varp(h)->right(d); }
svLow(const svOpenArrayHandle h,int d)200 int svLow(const svOpenArrayHandle h, int d) { return _vl_openhandle_varp(h)->low(d); }
svHigh(const svOpenArrayHandle h,int d)201 int svHigh(const svOpenArrayHandle h, int d) { return _vl_openhandle_varp(h)->high(d); }
svIncrement(const svOpenArrayHandle h,int d)202 int svIncrement(const svOpenArrayHandle h, int d) { return _vl_openhandle_varp(h)->increment(d); }
svSize(const svOpenArrayHandle h,int d)203 int svSize(const svOpenArrayHandle h, int d) { return _vl_openhandle_varp(h)->elements(d); }
svDimensions(const svOpenArrayHandle h)204 int svDimensions(const svOpenArrayHandle h) { return _vl_openhandle_varp(h)->udims(); }
205 
206 // Return pointer to open array data, or nullptr if not in IEEE standard C layout
svGetArrayPtr(const svOpenArrayHandle h)207 void* svGetArrayPtr(const svOpenArrayHandle h) {
208     const VerilatedDpiOpenVar* const varp = _vl_openhandle_varp(h);
209     if (VL_UNLIKELY(!varp->isDpiStdLayout())) return nullptr;
210     return varp->datap();
211 }
212 // Return size of open array, or 0 if not in IEEE standard C layout
svSizeOfArray(const svOpenArrayHandle h)213 int svSizeOfArray(const svOpenArrayHandle h) {
214     const VerilatedDpiOpenVar* const varp = _vl_openhandle_varp(h);
215     if (VL_UNLIKELY(!varp->isDpiStdLayout())) return 0;
216     // Truncate 64 bits to int; DPI is limited to 4GB
217     return static_cast<int>(varp->totalSize());
218 }
219 
220 //======================================================================
221 // Open array access internals
222 
_vl_sv_adjusted_datap(const VerilatedDpiOpenVar * varp,int nargs,int indx1,int indx2,int indx3)223 static void* _vl_sv_adjusted_datap(const VerilatedDpiOpenVar* varp, int nargs, int indx1,
224                                    int indx2, int indx3) {
225     void* datap = varp->datap();
226     if (VL_UNLIKELY(nargs != varp->udims())) {
227         VL_SVDPI_WARN_("%%Warning: DPI svOpenArrayHandle function called on"
228                        " %d dimensional array using %d dimensional function.\n",
229                        varp->udims(), nargs);
230         return nullptr;
231     }
232     if (nargs >= 1) {
233         datap = varp->datapAdjustIndex(datap, 1, indx1);
234         if (VL_UNLIKELY(!datap)) {
235             VL_SVDPI_WARN_("%%Warning: DPI svOpenArrayHandle function index 1 "
236                            "out of bounds; %d outside [%d:%d].\n",
237                            indx1, varp->left(1), varp->right(1));
238             return nullptr;
239         }
240     }
241     if (nargs >= 2) {
242         datap = varp->datapAdjustIndex(datap, 2, indx2);
243         if (VL_UNLIKELY(!datap)) {
244             VL_SVDPI_WARN_("%%Warning: DPI svOpenArrayHandle function index 2 "
245                            "out of bounds; %d outside [%d:%d].\n",
246                            indx2, varp->left(2), varp->right(2));
247             return nullptr;
248         }
249     }
250     if (nargs >= 3) {
251         datap = varp->datapAdjustIndex(datap, 3, indx3);
252         if (VL_UNLIKELY(!datap)) {
253             VL_SVDPI_WARN_("%%Warning: DPI svOpenArrayHandle function index 3 "
254                            "out of bounds; %d outside [%d:%d].\n",
255                            indx1, varp->left(3), varp->right(3));
256             return nullptr;
257         }
258     }
259     return datap;
260 }
261 
262 // Return pointer to simulator open array element, or nullptr if outside range
_vl_svGetArrElemPtr(const svOpenArrayHandle h,int nargs,int indx1,int indx2,int indx3)263 static void* _vl_svGetArrElemPtr(const svOpenArrayHandle h, int nargs, int indx1, int indx2,
264                                  int indx3) VL_MT_SAFE {
265     const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(h);
266     if (VL_UNLIKELY(!varp->isDpiStdLayout())) return nullptr;
267     void* const datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
268     return datap;
269 }
270 
271 // Copy to user bit array from simulator open array
_vl_svGetBitArrElemVecVal(svBitVecVal * d,const svOpenArrayHandle s,int nargs,int indx1,int indx2,int indx3)272 static void _vl_svGetBitArrElemVecVal(svBitVecVal* d, const svOpenArrayHandle s, int nargs,
273                                       int indx1, int indx2, int indx3) VL_MT_SAFE {
274     const VerilatedDpiOpenVar* const varp = _vl_openhandle_varp(s);
275     void* const datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
276     if (VL_UNLIKELY(!datap)) return;
277     switch (varp->vltype()) {  // LCOV_EXCL_BR_LINE
278     case VLVT_UINT8: d[0] = *(reinterpret_cast<CData*>(datap)); return;
279     case VLVT_UINT16: d[0] = *(reinterpret_cast<SData*>(datap)); return;
280     case VLVT_UINT32: d[0] = *(reinterpret_cast<IData*>(datap)); return;
281     case VLVT_UINT64: {
282         VlWide<2> lwp;
283         VL_SET_WQ(lwp, *(reinterpret_cast<QData*>(datap)));
284         d[0] = lwp[0];
285         d[1] = lwp[1];
286         break;
287     }
288     case VLVT_WDATA: {
289         WDataOutP wdatap = (reinterpret_cast<WDataOutP>(datap));
290         for (int i = 0; i < VL_WORDS_I(varp->packed().elements()); ++i) d[i] = wdatap[i];
291         return;
292     }
293     default:  // LCOV_EXCL_START  // Errored earlier
294         VL_SVDPI_WARN_("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
295                        varp->vltype());
296         return;  // LCOV_EXCL_STOP
297     }
298 }
299 // Copy to user logic array from simulator open array
_vl_svGetLogicArrElemVecVal(svLogicVecVal * d,const svOpenArrayHandle s,int nargs,int indx1,int indx2,int indx3)300 static void _vl_svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandle s, int nargs,
301                                         int indx1, int indx2, int indx3) VL_MT_SAFE {
302     const VerilatedDpiOpenVar* const varp = _vl_openhandle_varp(s);
303     void* const datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
304     if (VL_UNLIKELY(!datap)) return;
305     switch (varp->vltype()) {  // LCOV_EXCL_BR_LINE
306     case VLVT_UINT8:
307         d[0].aval = *(reinterpret_cast<CData*>(datap));
308         d[0].bval = 0;
309         return;
310     case VLVT_UINT16:
311         d[0].aval = *(reinterpret_cast<SData*>(datap));
312         d[0].bval = 0;
313         return;
314     case VLVT_UINT32:
315         d[0].aval = *(reinterpret_cast<IData*>(datap));
316         d[0].bval = 0;
317         return;
318     case VLVT_UINT64: {
319         VlWide<2> lwp;
320         VL_SET_WQ(lwp, *(reinterpret_cast<QData*>(datap)));
321         d[0].aval = lwp[0];
322         d[0].bval = 0;
323         d[1].aval = lwp[1];
324         d[1].bval = 0;
325         break;
326     }
327     case VLVT_WDATA: {
328         WDataOutP wdatap = (reinterpret_cast<WDataOutP>(datap));
329         for (int i = 0; i < VL_WORDS_I(varp->packed().elements()); ++i) {
330             d[i].aval = wdatap[i];
331             d[i].bval = 0;
332         }
333         return;
334     }
335     default:  // LCOV_EXCL_START  // Errored earlier
336         VL_SVDPI_WARN_("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
337                        varp->vltype());
338         return;  // LCOV_EXCL_STOP
339     }
340 }
341 
342 // Copy to simulator open array from from user bit array
_vl_svPutBitArrElemVecVal(const svOpenArrayHandle d,const svBitVecVal * s,int nargs,int indx1,int indx2,int indx3)343 static void _vl_svPutBitArrElemVecVal(const svOpenArrayHandle d, const svBitVecVal* s, int nargs,
344                                       int indx1, int indx2, int indx3) VL_MT_SAFE {
345     const VerilatedDpiOpenVar* const varp = _vl_openhandle_varp(d);
346     void* const datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
347     if (VL_UNLIKELY(!datap)) return;
348     switch (varp->vltype()) {  // LCOV_EXCL_BR_LINE
349     case VLVT_UINT8: *(reinterpret_cast<CData*>(datap)) = s[0]; return;
350     case VLVT_UINT16: *(reinterpret_cast<SData*>(datap)) = s[0]; return;
351     case VLVT_UINT32: *(reinterpret_cast<IData*>(datap)) = s[0]; return;
352     case VLVT_UINT64: *(reinterpret_cast<QData*>(datap)) = VL_SET_QII(s[1], s[0]); break;
353     case VLVT_WDATA: {
354         WDataOutP wdatap = (reinterpret_cast<WDataOutP>(datap));
355         for (int i = 0; i < VL_WORDS_I(varp->packed().elements()); ++i) wdatap[i] = s[i];
356         return;
357     }
358     default:  // LCOV_EXCL_START  // Errored earlier
359         VL_SVDPI_WARN_("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
360                        varp->vltype());
361         return;  // LCOV_EXCL_STOP
362     }
363 }
364 // Copy to simulator open array from from user logic array
_vl_svPutLogicArrElemVecVal(const svOpenArrayHandle d,const svLogicVecVal * s,int nargs,int indx1,int indx2,int indx3)365 static void _vl_svPutLogicArrElemVecVal(const svOpenArrayHandle d, const svLogicVecVal* s,
366                                         int nargs, int indx1, int indx2, int indx3) VL_MT_SAFE {
367     const VerilatedDpiOpenVar* const varp = _vl_openhandle_varp(d);
368     void* const datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
369     if (VL_UNLIKELY(!datap)) return;
370     switch (varp->vltype()) {  // LCOV_EXCL_BR_LINE
371     case VLVT_UINT8: *(reinterpret_cast<CData*>(datap)) = s[0].aval; return;
372     case VLVT_UINT16: *(reinterpret_cast<SData*>(datap)) = s[0].aval; return;
373     case VLVT_UINT32: *(reinterpret_cast<IData*>(datap)) = s[0].aval; return;
374     case VLVT_UINT64: *(reinterpret_cast<QData*>(datap)) = VL_SET_QII(s[1].aval, s[0].aval); break;
375     case VLVT_WDATA: {
376         WDataOutP wdatap = (reinterpret_cast<WDataOutP>(datap));
377         for (int i = 0; i < VL_WORDS_I(varp->packed().elements()); ++i) wdatap[i] = s[i].aval;
378         return;
379     }
380     default:  // LCOV_EXCL_START  // Errored earlier
381         VL_SVDPI_WARN_("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
382                        varp->vltype());
383         return;  // LCOV_EXCL_STOP
384     }
385 }
386 
387 // Return bit from simulator open array
_vl_svGetBitArrElem(const svOpenArrayHandle s,int nargs,int indx1,int indx2,int indx3,int)388 static svBit _vl_svGetBitArrElem(const svOpenArrayHandle s, int nargs, int indx1, int indx2,
389                                  int indx3, int) VL_MT_SAFE {
390     // One extra index supported, as need bit number
391     const VerilatedDpiOpenVar* const varp = _vl_openhandle_varp(s);
392     void* const datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
393     if (VL_UNLIKELY(!datap)) return 0;
394     switch (varp->vltype()) {  // LCOV_EXCL_BR_LINE
395     case VLVT_UINT8: return (*(reinterpret_cast<CData*>(datap))) & 1;
396     default:  // LCOV_EXCL_START  // Errored earlier
397         VL_SVDPI_WARN_("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
398                        varp->vltype());
399         return 0;  // LCOV_EXCL_STOP
400     }
401 }
402 // Update simulator open array from bit
_vl_svPutBitArrElem(const svOpenArrayHandle d,svBit value,int nargs,int indx1,int indx2,int indx3,int)403 static void _vl_svPutBitArrElem(const svOpenArrayHandle d, svBit value, int nargs, int indx1,
404                                 int indx2, int indx3, int) VL_MT_SAFE {
405     // One extra index supported, as need bit number
406     value &= 1;  // Make sure clean
407     const VerilatedDpiOpenVar* const varp = _vl_openhandle_varp(d);
408     void* const datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
409     if (VL_UNLIKELY(!datap)) return;
410     switch (varp->vltype()) {  // LCOV_EXCL_BR_LINE
411     case VLVT_UINT8: *(reinterpret_cast<CData*>(datap)) = value; return;
412     default:  // LCOV_EXCL_START  // Errored earlier
413         VL_SVDPI_WARN_("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
414                        varp->vltype());
415         return;  // LCOV_EXCL_STOP
416     }
417 }
418 
419 //======================================================================
420 // DPI accessors that simply call above functions
421 
svGetArrElemPtr(const svOpenArrayHandle h,int indx1,...)422 void* svGetArrElemPtr(const svOpenArrayHandle h, int indx1, ...) {
423     const VerilatedDpiOpenVar* const varp = _vl_openhandle_varp(h);
424     void* datap;
425     va_list ap;
426     va_start(ap, indx1);
427     // va_arg is a macro, so need temporaries as used below
428     switch (varp->udims()) {
429     case 1: datap = _vl_svGetArrElemPtr(h, 1, indx1, 0, 0); break;
430     case 2: {
431         const int indx2 = va_arg(ap, int);
432         datap = _vl_svGetArrElemPtr(h, 2, indx1, indx2, 0);
433         break;
434     }
435     case 3: {
436         const int indx2 = va_arg(ap, int);
437         const int indx3 = va_arg(ap, int);
438         datap = _vl_svGetArrElemPtr(h, 3, indx1, indx2, indx3);
439         break;
440     }
441     default: datap = _vl_svGetArrElemPtr(h, -1, 0, 0, 0); break;  // Will error
442     }
443     va_end(ap);
444     return datap;
445 }
svGetArrElemPtr1(const svOpenArrayHandle h,int indx1)446 void* svGetArrElemPtr1(const svOpenArrayHandle h, int indx1) {
447     return _vl_svGetArrElemPtr(h, 1, indx1, 0, 0);
448 }
svGetArrElemPtr2(const svOpenArrayHandle h,int indx1,int indx2)449 void* svGetArrElemPtr2(const svOpenArrayHandle h, int indx1, int indx2) {
450     return _vl_svGetArrElemPtr(h, 2, indx1, indx2, 0);
451 }
svGetArrElemPtr3(const svOpenArrayHandle h,int indx1,int indx2,int indx3)452 void* svGetArrElemPtr3(const svOpenArrayHandle h, int indx1, int indx2, int indx3) {
453     return _vl_svGetArrElemPtr(h, 3, indx1, indx2, indx3);
454 }
455 
svPutBitArrElemVecVal(const svOpenArrayHandle d,const svBitVecVal * s,int indx1,...)456 void svPutBitArrElemVecVal(const svOpenArrayHandle d, const svBitVecVal* s, int indx1, ...) {
457     const VerilatedDpiOpenVar* const varp = _vl_openhandle_varp(d);
458     va_list ap;
459     va_start(ap, indx1);
460     switch (varp->udims()) {
461     case 1: _vl_svPutBitArrElemVecVal(d, s, 1, indx1, 0, 0); break;
462     case 2: {
463         const int indx2 = va_arg(ap, int);
464         _vl_svPutBitArrElemVecVal(d, s, 2, indx1, indx2, 0);
465         break;
466     }
467     case 3: {
468         const int indx2 = va_arg(ap, int);
469         const int indx3 = va_arg(ap, int);
470         _vl_svPutBitArrElemVecVal(d, s, 3, indx1, indx2, indx3);
471         break;
472     }
473     default: _vl_svPutBitArrElemVecVal(d, s, -1, 0, 0, 0); break;  // Will error
474     }
475     va_end(ap);
476 }
svPutBitArrElem1VecVal(const svOpenArrayHandle d,const svBitVecVal * s,int indx1)477 void svPutBitArrElem1VecVal(const svOpenArrayHandle d, const svBitVecVal* s, int indx1) {
478     _vl_svPutBitArrElemVecVal(d, s, 1, indx1, 0, 0);
479 }
svPutBitArrElem2VecVal(const svOpenArrayHandle d,const svBitVecVal * s,int indx1,int indx2)480 void svPutBitArrElem2VecVal(const svOpenArrayHandle d, const svBitVecVal* s, int indx1,
481                             int indx2) {
482     _vl_svPutBitArrElemVecVal(d, s, 2, indx1, indx2, 0);
483 }
svPutBitArrElem3VecVal(const svOpenArrayHandle d,const svBitVecVal * s,int indx1,int indx2,int indx3)484 void svPutBitArrElem3VecVal(const svOpenArrayHandle d, const svBitVecVal* s, int indx1, int indx2,
485                             int indx3) {
486     _vl_svPutBitArrElemVecVal(d, s, 3, indx1, indx2, indx3);
487 }
svPutLogicArrElemVecVal(const svOpenArrayHandle d,const svLogicVecVal * s,int indx1,...)488 void svPutLogicArrElemVecVal(const svOpenArrayHandle d, const svLogicVecVal* s, int indx1, ...) {
489     const VerilatedDpiOpenVar* const varp = _vl_openhandle_varp(d);
490     va_list ap;
491     va_start(ap, indx1);
492     switch (varp->udims()) {
493     case 1: _vl_svPutLogicArrElemVecVal(d, s, 1, indx1, 0, 0); break;
494     case 2: {
495         const int indx2 = va_arg(ap, int);
496         _vl_svPutLogicArrElemVecVal(d, s, 2, indx1, indx2, 0);
497         break;
498     }
499     case 3: {
500         const int indx2 = va_arg(ap, int);
501         const int indx3 = va_arg(ap, int);
502         _vl_svPutLogicArrElemVecVal(d, s, 3, indx1, indx2, indx3);
503         break;
504     }
505     default: _vl_svPutLogicArrElemVecVal(d, s, -1, 0, 0, 0); break;  // Will error
506     }
507     va_end(ap);
508 }
svPutLogicArrElem1VecVal(const svOpenArrayHandle d,const svLogicVecVal * s,int indx1)509 void svPutLogicArrElem1VecVal(const svOpenArrayHandle d, const svLogicVecVal* s, int indx1) {
510     _vl_svPutLogicArrElemVecVal(d, s, 1, indx1, 0, 0);
511 }
svPutLogicArrElem2VecVal(const svOpenArrayHandle d,const svLogicVecVal * s,int indx1,int indx2)512 void svPutLogicArrElem2VecVal(const svOpenArrayHandle d, const svLogicVecVal* s, int indx1,
513                               int indx2) {
514     _vl_svPutLogicArrElemVecVal(d, s, 2, indx1, indx2, 0);
515 }
svPutLogicArrElem3VecVal(const svOpenArrayHandle d,const svLogicVecVal * s,int indx1,int indx2,int indx3)516 void svPutLogicArrElem3VecVal(const svOpenArrayHandle d, const svLogicVecVal* s, int indx1,
517                               int indx2, int indx3) {
518     _vl_svPutLogicArrElemVecVal(d, s, 3, indx1, indx2, indx3);
519 }
520 
521 //======================================================================
522 // From simulator storage into user space
523 
svGetBitArrElemVecVal(svBitVecVal * d,const svOpenArrayHandle s,int indx1,...)524 void svGetBitArrElemVecVal(svBitVecVal* d, const svOpenArrayHandle s, int indx1, ...) {
525     const VerilatedDpiOpenVar* const varp = _vl_openhandle_varp(s);
526     va_list ap;
527     va_start(ap, indx1);
528     switch (varp->udims()) {
529     case 1: _vl_svGetBitArrElemVecVal(d, s, 1, indx1, 0, 0); break;
530     case 2: {
531         const int indx2 = va_arg(ap, int);
532         _vl_svGetBitArrElemVecVal(d, s, 2, indx1, indx2, 0);
533         break;
534     }
535     case 3: {
536         const int indx2 = va_arg(ap, int);
537         const int indx3 = va_arg(ap, int);
538         _vl_svGetBitArrElemVecVal(d, s, 3, indx1, indx2, indx3);
539         break;
540     }
541     default: _vl_svGetBitArrElemVecVal(d, s, -1, 0, 0, 0); break;  // Will error
542     }
543     va_end(ap);
544 }
svGetBitArrElem1VecVal(svBitVecVal * d,const svOpenArrayHandle s,int indx1)545 void svGetBitArrElem1VecVal(svBitVecVal* d, const svOpenArrayHandle s, int indx1) {
546     _vl_svGetBitArrElemVecVal(d, s, 1, indx1, 0, 0);
547 }
svGetBitArrElem2VecVal(svBitVecVal * d,const svOpenArrayHandle s,int indx1,int indx2)548 void svGetBitArrElem2VecVal(svBitVecVal* d, const svOpenArrayHandle s, int indx1, int indx2) {
549     _vl_svGetBitArrElemVecVal(d, s, 2, indx1, indx2, 0);
550 }
svGetBitArrElem3VecVal(svBitVecVal * d,const svOpenArrayHandle s,int indx1,int indx2,int indx3)551 void svGetBitArrElem3VecVal(svBitVecVal* d, const svOpenArrayHandle s, int indx1, int indx2,
552                             int indx3) {
553     _vl_svGetBitArrElemVecVal(d, s, 3, indx1, indx2, indx3);
554 }
svGetLogicArrElemVecVal(svLogicVecVal * d,const svOpenArrayHandle s,int indx1,...)555 void svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandle s, int indx1, ...) {
556     const VerilatedDpiOpenVar* const varp = _vl_openhandle_varp(s);
557     va_list ap;
558     va_start(ap, indx1);
559     switch (varp->udims()) {
560     case 1: _vl_svGetLogicArrElemVecVal(d, s, 1, indx1, 0, 0); break;
561     case 2: {
562         const int indx2 = va_arg(ap, int);
563         _vl_svGetLogicArrElemVecVal(d, s, 2, indx1, indx2, 0);
564         break;
565     }
566     case 3: {
567         const int indx2 = va_arg(ap, int);
568         const int indx3 = va_arg(ap, int);
569         _vl_svGetLogicArrElemVecVal(d, s, 3, indx1, indx2, indx3);
570         break;
571     }
572     default: _vl_svGetLogicArrElemVecVal(d, s, -1, 0, 0, 0); break;  // Will error
573     }
574     va_end(ap);
575 }
svGetLogicArrElem1VecVal(svLogicVecVal * d,const svOpenArrayHandle s,int indx1)576 void svGetLogicArrElem1VecVal(svLogicVecVal* d, const svOpenArrayHandle s, int indx1) {
577     _vl_svGetLogicArrElemVecVal(d, s, 1, indx1, 0, 0);
578 }
svGetLogicArrElem2VecVal(svLogicVecVal * d,const svOpenArrayHandle s,int indx1,int indx2)579 void svGetLogicArrElem2VecVal(svLogicVecVal* d, const svOpenArrayHandle s, int indx1, int indx2) {
580     _vl_svGetLogicArrElemVecVal(d, s, 2, indx1, indx2, 0);
581 }
svGetLogicArrElem3VecVal(svLogicVecVal * d,const svOpenArrayHandle s,int indx1,int indx2,int indx3)582 void svGetLogicArrElem3VecVal(svLogicVecVal* d, const svOpenArrayHandle s, int indx1, int indx2,
583                               int indx3) {
584     _vl_svGetLogicArrElemVecVal(d, s, 3, indx1, indx2, indx3);
585 }
586 
svGetBitArrElem(const svOpenArrayHandle s,int indx1,...)587 svBit svGetBitArrElem(const svOpenArrayHandle s, int indx1, ...) {
588     const VerilatedDpiOpenVar* const varp = _vl_openhandle_varp(s);
589     svBit out;
590     va_list ap;
591     va_start(ap, indx1);
592     switch (varp->udims()) {
593     case 1: out = _vl_svGetBitArrElem(s, 1, indx1, 0, 0, 0); break;
594     case 2: {
595         const int indx2 = va_arg(ap, int);
596         out = _vl_svGetBitArrElem(s, 2, indx1, indx2, 0, 0);
597         break;
598     }
599     case 3: {
600         const int indx2 = va_arg(ap, int);
601         const int indx3 = va_arg(ap, int);
602         out = _vl_svGetBitArrElem(s, 3, indx1, indx2, indx3, 0);
603         break;
604     }
605     default: out = _vl_svGetBitArrElem(s, -1, 0, 0, 0, 0); break;  // Will error
606     }
607     va_end(ap);
608     return out;
609 }
svGetBitArrElem1(const svOpenArrayHandle s,int indx1)610 svBit svGetBitArrElem1(const svOpenArrayHandle s, int indx1) {
611     return _vl_svGetBitArrElem(s, 1, indx1, 0, 0, 0);
612 }
svGetBitArrElem2(const svOpenArrayHandle s,int indx1,int indx2)613 svBit svGetBitArrElem2(const svOpenArrayHandle s, int indx1, int indx2) {
614     return _vl_svGetBitArrElem(s, 2, indx1, indx2, 0, 0);
615 }
svGetBitArrElem3(const svOpenArrayHandle s,int indx1,int indx2,int indx3)616 svBit svGetBitArrElem3(const svOpenArrayHandle s, int indx1, int indx2, int indx3) {
617     return _vl_svGetBitArrElem(s, 3, indx1, indx2, indx3, 0);
618 }
svGetLogicArrElem(const svOpenArrayHandle s,int indx1,...)619 svLogic svGetLogicArrElem(const svOpenArrayHandle s, int indx1, ...) {
620     // Verilator doesn't support X/Z so can just call Bit version
621     const VerilatedDpiOpenVar* const varp = _vl_openhandle_varp(s);
622     svBit out;
623     va_list ap;
624     va_start(ap, indx1);
625     switch (varp->udims()) {
626     case 1: out = _vl_svGetBitArrElem(s, 1, indx1, 0, 0, 0); break;
627     case 2: {
628         const int indx2 = va_arg(ap, int);
629         out = _vl_svGetBitArrElem(s, 2, indx1, indx2, 0, 0);
630         break;
631     }
632     case 3: {
633         const int indx2 = va_arg(ap, int);
634         const int indx3 = va_arg(ap, int);
635         out = _vl_svGetBitArrElem(s, 3, indx1, indx2, indx3, 0);
636         break;
637     }
638     default: out = _vl_svGetBitArrElem(s, -1, 0, 0, 0, 0); break;  // Will error
639     }
640     va_end(ap);
641     return out;
642 }
svGetLogicArrElem1(const svOpenArrayHandle s,int indx1)643 svLogic svGetLogicArrElem1(const svOpenArrayHandle s, int indx1) {
644     // Verilator doesn't support X/Z so can just call Bit version
645     return svGetBitArrElem1(s, indx1);
646 }
svGetLogicArrElem2(const svOpenArrayHandle s,int indx1,int indx2)647 svLogic svGetLogicArrElem2(const svOpenArrayHandle s, int indx1, int indx2) {
648     // Verilator doesn't support X/Z so can just call Bit version
649     return svGetBitArrElem2(s, indx1, indx2);
650 }
svGetLogicArrElem3(const svOpenArrayHandle s,int indx1,int indx2,int indx3)651 svLogic svGetLogicArrElem3(const svOpenArrayHandle s, int indx1, int indx2, int indx3) {
652     // Verilator doesn't support X/Z so can just call Bit version
653     return svGetBitArrElem3(s, indx1, indx2, indx3);
654 }
655 
svPutBitArrElem(const svOpenArrayHandle d,svBit value,int indx1,...)656 void svPutBitArrElem(const svOpenArrayHandle d, svBit value, int indx1, ...) {
657     const VerilatedDpiOpenVar* const varp = _vl_openhandle_varp(d);
658     va_list ap;
659     va_start(ap, indx1);
660     switch (varp->udims()) {
661     case 1: _vl_svPutBitArrElem(d, value, 1, indx1, 0, 0, 0); break;
662     case 2: {
663         const int indx2 = va_arg(ap, int);
664         _vl_svPutBitArrElem(d, value, 2, indx1, indx2, 0, 0);
665         break;
666     }
667     case 3: {
668         const int indx2 = va_arg(ap, int);
669         const int indx3 = va_arg(ap, int);
670         _vl_svPutBitArrElem(d, value, 3, indx1, indx2, indx3, 0);
671         break;
672     }
673     default: _vl_svPutBitArrElem(d, value, -1, 0, 0, 0, 0); break;  // Will error
674     }
675     va_end(ap);
676 }
svPutBitArrElem1(const svOpenArrayHandle d,svBit value,int indx1)677 void svPutBitArrElem1(const svOpenArrayHandle d, svBit value, int indx1) {
678     _vl_svPutBitArrElem(d, value, 1, indx1, 0, 0, 0);
679 }
svPutBitArrElem2(const svOpenArrayHandle d,svBit value,int indx1,int indx2)680 void svPutBitArrElem2(const svOpenArrayHandle d, svBit value, int indx1, int indx2) {
681     _vl_svPutBitArrElem(d, value, 2, indx1, indx2, 0, 0);
682 }
svPutBitArrElem3(const svOpenArrayHandle d,svBit value,int indx1,int indx2,int indx3)683 void svPutBitArrElem3(const svOpenArrayHandle d, svBit value, int indx1, int indx2, int indx3) {
684     _vl_svPutBitArrElem(d, value, 3, indx1, indx2, indx3, 0);
685 }
svPutLogicArrElem(const svOpenArrayHandle d,svLogic value,int indx1,...)686 void svPutLogicArrElem(const svOpenArrayHandle d, svLogic value, int indx1, ...) {
687     // Verilator doesn't support X/Z so can just call Bit version
688     const VerilatedDpiOpenVar* const varp = _vl_openhandle_varp(d);
689     va_list ap;
690     va_start(ap, indx1);
691     switch (varp->udims()) {
692     case 1: _vl_svPutBitArrElem(d, value, 1, indx1, 0, 0, 0); break;
693     case 2: {
694         const int indx2 = va_arg(ap, int);
695         _vl_svPutBitArrElem(d, value, 2, indx1, indx2, 0, 0);
696         break;
697     }
698     case 3: {
699         const int indx2 = va_arg(ap, int);
700         const int indx3 = va_arg(ap, int);
701         _vl_svPutBitArrElem(d, value, 3, indx1, indx2, indx3, 0);
702         break;
703     }
704     default: _vl_svPutBitArrElem(d, value, -1, 0, 0, 0, 0); break;  // Will error
705     }
706     va_end(ap);
707 }
svPutLogicArrElem1(const svOpenArrayHandle d,svLogic value,int indx1)708 void svPutLogicArrElem1(const svOpenArrayHandle d, svLogic value, int indx1) {
709     // Verilator doesn't support X/Z so can just call Bit version
710     svPutBitArrElem1(d, value, indx1);
711 }
svPutLogicArrElem2(const svOpenArrayHandle d,svLogic value,int indx1,int indx2)712 void svPutLogicArrElem2(const svOpenArrayHandle d, svLogic value, int indx1, int indx2) {
713     // Verilator doesn't support X/Z so can just call Bit version
714     svPutBitArrElem2(d, value, indx1, indx2);
715 }
svPutLogicArrElem3(const svOpenArrayHandle d,svLogic value,int indx1,int indx2,int indx3)716 void svPutLogicArrElem3(const svOpenArrayHandle d, svLogic value, int indx1, int indx2,
717                         int indx3) {
718     // Verilator doesn't support X/Z so can just call Bit version
719     svPutBitArrElem3(d, value, indx1, indx2, indx3);
720 }
721 
722 //======================================================================
723 // Functions for working with DPI context
724 
svGetScope()725 svScope svGetScope() {
726     if (VL_UNLIKELY(!Verilated::dpiInContext())) {
727         VL_SVDPI_CONTEXT_WARN_();
728         return nullptr;
729     }
730     // NOLINTNEXTLINE(google-readability-casting)
731     return (svScope)(Verilated::dpiScope());
732 }
733 
svSetScope(const svScope scope)734 svScope svSetScope(const svScope scope) {
735     const VerilatedScope* const prevScopep = Verilated::dpiScope();
736     const VerilatedScope* const vscopep = reinterpret_cast<const VerilatedScope*>(scope);
737     Verilated::dpiScope(vscopep);
738     // NOLINTNEXTLINE(google-readability-casting)
739     return (svScope)(prevScopep);
740 }
741 
svGetNameFromScope(const svScope scope)742 const char* svGetNameFromScope(const svScope scope) {
743     const VerilatedScope* const vscopep = reinterpret_cast<const VerilatedScope*>(scope);
744     return vscopep->name();
745 }
746 
svGetScopeFromName(const char * scopeName)747 svScope svGetScopeFromName(const char* scopeName) {
748     // NOLINTNEXTLINE(google-readability-casting)
749     return (svScope)(Verilated::threadContextp()->scopeFind(scopeName));
750 }
751 
svPutUserData(const svScope scope,void * userKey,void * userData)752 int svPutUserData(const svScope scope, void* userKey, void* userData) {
753     VerilatedImp::userInsert(scope, userKey, userData);
754     return 0;
755 }
756 
svGetUserData(const svScope scope,void * userKey)757 void* svGetUserData(const svScope scope, void* userKey) {
758     return VerilatedImp::userFind(scope, userKey);
759 }
760 
svGetCallerInfo(const char ** fileNamepp,int * lineNumberp)761 int svGetCallerInfo(const char** fileNamepp, int* lineNumberp) {
762     if (VL_UNLIKELY(!Verilated::dpiInContext())) {
763         VL_SVDPI_CONTEXT_WARN_();
764         return false;
765     }
766     if (VL_LIKELY(fileNamepp)) *fileNamepp = Verilated::dpiFilenamep();  // thread local
767     if (VL_LIKELY(lineNumberp)) *lineNumberp = Verilated::dpiLineno();  // thread local
768     return true;
769 }
770 
771 //======================================================================
772 // Disables
773 
svIsDisabledState()774 int svIsDisabledState() {
775     return 0;  // Disables not implemented
776 }
777 
svAckDisabledState()778 void svAckDisabledState() {
779     // Disables not implemented
780 }
781