1 /*
2 * Copyright (c) 2001-2018 Stephen Williams (steve@icarus.com)
3 * Copyright (c) 2001 Stephan Boettcher <stephan@nevis.columbia.edu>
4 *
5 * This source code is free software; you can redistribute it
6 * and/or modify it in source code form under the terms of the GNU
7 * General Public License as published by the Free Software
8 * Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20
21 /*
22 * vpiReg handles are handled here. These objects represent vectors of
23 * .var objects that can be manipulated by the VPI module.
24 */
25
26 # include "vpi_priv.h"
27 # include "vthread.h"
28 # include "config.h"
29 #ifdef CHECK_WITH_VALGRIND
30 # include "vvp_cleanup.h"
31 # include <map>
32 #endif
33 # include <cstdio>
34 # include <cstdlib>
35 # include <cassert>
36 # include "ivl_alloc.h"
37
38 /*
39 * Hex digits that represent 4-value bits of Verilog are not as
40 * trivially obvious to display as if the bits were the usual 2-value
41 * bits. So, although it is possible to write a function that
42 * generates a correct character for 4*4-value bits, it is easier to
43 * just perform the lookup in a table. This only takes 256 bytes,
44 * which is not many executable instructions:-)
45 *
46 * The table is calculated as compile time, therefore, by the
47 * draw_tt.c program.
48 */
49 extern const char hex_digits[256];
50 extern const char oct_digits[64];
51
52
53 struct __vpiVThrWord : public __vpiHandle {
54 __vpiVThrWord();
55 int get_type_code(void) const;
56 int vpi_get(int code);
57 void vpi_get_value(p_vpi_value val);
58
59 const char* name;
60 int subtype;
61 unsigned index;
62 };
63
vthr_word_get(int code,vpiHandle ref)64 static int vthr_word_get(int code, vpiHandle ref)
65 {
66 struct __vpiVThrWord*rfp = dynamic_cast<__vpiVThrWord*>(ref);
67
68 switch (code) {
69
70 case vpiConstType:
71 return rfp->subtype;
72
73 #if defined(CHECK_WITH_VALGRIND) || defined(BR916_STOPGAP_FIX)
74 case _vpiFromThr:
75 return _vpiWord;
76 #endif
77
78 default:
79 return 0;
80 }
81 }
82
vlg_round(double rval)83 static double vlg_round(double rval)
84 {
85 if (rval >= 0.0) {
86 return floor(rval + 0.5);
87 } else {
88 return ceil(rval - 0.5);
89 }
90 }
91
vthr_real_get_value(vpiHandle ref,s_vpi_value * vp)92 static void vthr_real_get_value(vpiHandle ref, s_vpi_value*vp)
93 {
94 struct __vpiVThrWord*obj = dynamic_cast<__vpiVThrWord*>(ref);
95 char *rbuf = (char *) need_result_buf(66, RBUF_VAL);
96
97 double val = 0.0;
98
99 /* Get the actual value from the index. It is possible, by the
100 way, that the vpi_get_value is called from compiletf. If
101 that's the case, there will be no current thread, and this
102 will not have access to the proper value. Punt and return a
103 0.0 value instead. */
104 if (vpip_current_vthread)
105 val = vthread_get_real_stack(vpip_current_vthread, obj->index);
106
107 switch (vp->format) {
108
109 case vpiObjTypeVal:
110 vp->format = vpiRealVal;
111 // fallthrough
112 case vpiRealVal:
113 vp->value.real = val;
114 break;
115
116 case vpiIntVal:
117 /* NaN or +/- infinity are translated as 0. */
118 if (val != val || (val && (val == 0.5*val))) {
119 val = 0.0;
120 } else {
121 val = vlg_round(val);
122 }
123 vp->value.integer = (PLI_INT32)val;
124 break;
125
126 case vpiDecStrVal:
127 if (isnan(val))
128 sprintf(rbuf, "%s", "nan");
129 else
130 sprintf(rbuf, "%0.0f", vlg_round(val));
131 vp->value.str = rbuf;
132 break;
133
134 case vpiOctStrVal:
135 sprintf(rbuf, "%" PRIo64, (uint64_t)vlg_round(val));
136 vp->value.str = rbuf;
137 break;
138
139 case vpiHexStrVal:
140 sprintf(rbuf, "%" PRIx64, (uint64_t)vlg_round(val));
141 vp->value.str = rbuf;
142 break;
143
144 case vpiBinStrVal: {
145 uint64_t vali = (uint64_t)vlg_round(val);
146 unsigned len = 0;
147
148 while (vali > 0) {
149 len += 1;
150 vali /= 2;
151 }
152
153 vali = (uint64_t)vlg_round(val);
154 for (unsigned idx = 0 ; idx < len ; idx += 1) {
155 rbuf[len-idx-1] = (vali & 1)? '1' : '0';
156 vali /= 2;
157 }
158
159 rbuf[len] = 0;
160 if (len == 0) {
161 rbuf[0] = '0';
162 rbuf[1] = 0;
163 }
164 vp->value.str = rbuf;
165 break;
166 }
167
168 default:
169 fprintf(stderr, "vvp error: get %d not supported "
170 "by vpiConstant (Real)\n", (int)vp->format);
171
172 vp->format = vpiSuppressVal;
173 break;
174 }
175 }
176
__vpiVThrWord()177 inline __vpiVThrWord::__vpiVThrWord()
178 { }
179
get_type_code(void) const180 int __vpiVThrWord::get_type_code(void) const
181 { return vpiConstant; }
182
vpi_get(int code)183 int __vpiVThrWord::vpi_get(int code)
184 { return vthr_word_get(code, this); }
185
vpi_get_value(p_vpi_value val)186 void __vpiVThrWord::vpi_get_value(p_vpi_value val)
187 { vthr_real_get_value(this, val); }
188
vpip_make_vthr_word(unsigned base,const char * type)189 vpiHandle vpip_make_vthr_word(unsigned base, const char*type)
190 {
191 struct __vpiVThrWord*obj = new __vpiVThrWord;
192
193 assert(type[0] == 'r');
194
195 obj->name = vpip_name_string("W<>");
196 obj->subtype = vpiRealConst;
197 assert(base < 65536);
198 obj->index = base;
199
200 return obj;
201 }
202
203 #ifdef CHECK_WITH_VALGRIND
204 static map<vpiHandle, bool> handle_map;
205
thread_word_delete(vpiHandle item)206 void thread_word_delete(vpiHandle item)
207 {
208 handle_map[item] = false;
209 }
210
thread_word_delete_real(vpiHandle item)211 static void thread_word_delete_real(vpiHandle item)
212 {
213 struct __vpiVThrWord*obj = dynamic_cast<__vpiVThrWord*>(item);
214 delete obj;
215 }
216 #endif
217
218 class __vpiVThrStrStack : public __vpiHandle {
219 public:
220 explicit __vpiVThrStrStack(unsigned depth);
221 int get_type_code(void) const;
222 int vpi_get(int code);
223 void vpi_get_value(p_vpi_value val);
224 private:
225 unsigned depth_;
226 };
227
__vpiVThrStrStack(unsigned d)228 __vpiVThrStrStack::__vpiVThrStrStack(unsigned d)
229 : depth_(d)
230 {
231 }
232
get_type_code(void) const233 int __vpiVThrStrStack::get_type_code(void) const
234 { return vpiConstant; }
235
vpi_get(int code)236 int __vpiVThrStrStack::vpi_get(int code)
237 {
238 switch (code) {
239 case vpiConstType:
240 return vpiStringConst;
241 #if defined(CHECK_WITH_VALGRIND) || defined(BR916_STOPGAP_FIX)
242 case _vpiFromThr:
243 return _vpiString;
244 #endif
245 default:
246 return 0;
247 }
248 }
249
vpi_get_value(p_vpi_value vp)250 void __vpiVThrStrStack::vpi_get_value(p_vpi_value vp)
251 {
252 string val;
253 char*rbuf = 0;
254
255 if (vpip_current_vthread)
256 val = vthread_get_str_stack(vpip_current_vthread, depth_);
257
258 switch (vp->format) {
259
260 case vpiObjTypeVal:
261 vp->format = vpiStringVal;
262 // fallthrough
263 case vpiStringVal:
264 rbuf = (char *) need_result_buf(val.size()+1, RBUF_VAL);
265 strcpy(rbuf, val.c_str());
266 vp->value.str = rbuf;
267 break;
268
269 default:
270 fprintf(stderr, "vvp error: get %d not supported "
271 "by vpiConstant (String)\n", (int)vp->format);
272
273 vp->format = vpiSuppressVal;
274 break;
275 }
276 }
277
278 class __vpiVThrVec4Stack : public __vpiHandle {
279 public:
280 __vpiVThrVec4Stack(unsigned depth, bool signed_flag, unsigned wid);
281 int get_type_code(void) const;
282 int vpi_get(int code);
283 char*vpi_get_str(int code);
284 void vpi_get_value(p_vpi_value val);
285 vpiHandle vpi_put_value(p_vpi_value val, int flags);
286 private:
287 void vpi_get_value_string_(p_vpi_value vp, const vvp_vector4_t&val);
288 void vpi_get_value_binstr_(p_vpi_value vp, const vvp_vector4_t&val);
289 void vpi_get_value_decstr_(p_vpi_value vp, const vvp_vector4_t&val);
290 void vpi_get_value_int_ (p_vpi_value vp, const vvp_vector4_t&val);
291 void vpi_get_value_real_ (p_vpi_value vp, const vvp_vector4_t&val);
292 void vpi_get_value_strength_(p_vpi_value vp, const vvp_vector4_t&val);
293 void vpi_get_value_octstr_(p_vpi_value vp, const vvp_vector4_t&val);
294 void vpi_get_value_hexstr_(p_vpi_value vp, const vvp_vector4_t&val);
295 void vpi_get_value_vector_(p_vpi_value vp, const vvp_vector4_t&val);
296 private:
297 unsigned depth_;
298 bool signed_flag_;
299 unsigned expect_width_;
300 const char*name;
301 };
302
__vpiVThrVec4Stack(unsigned d,bool sf,unsigned wid)303 __vpiVThrVec4Stack::__vpiVThrVec4Stack(unsigned d, bool sf, unsigned wid)
304 : depth_(d), signed_flag_(sf), expect_width_(wid)
305 {
306 name = vpip_name_string("S<,vec4,>");
307 }
308
get_type_code(void) const309 int __vpiVThrVec4Stack::get_type_code(void) const
310 { return vpiConstant; }
311
312
vpi_get(int code)313 int __vpiVThrVec4Stack::vpi_get(int code)
314 {
315 switch (code) {
316 case vpiSize:
317 return expect_width_;
318
319 case vpiSigned:
320 return signed_flag_? 1 : 0;
321
322 case vpiConstType:
323 return vpiBinaryConst;
324
325 #if defined(CHECK_WITH_VALGRIND) || defined(BR916_STOPGAP_FIX)
326 case _vpiFromThr:
327 return _vpiVThr;
328 #endif
329
330 default:
331 return 0;
332 }
333 }
334
vpi_get_str(int code)335 char*__vpiVThrVec4Stack::vpi_get_str(int code)
336 {
337 switch (code) {
338 case vpiFullName:
339 return simple_set_rbuf_str(name);
340
341 default:
342 return 0;
343 }
344 }
345
vpi_get_value(p_vpi_value vp)346 void __vpiVThrVec4Stack::vpi_get_value(p_vpi_value vp)
347 {
348 vvp_vector4_t val;
349
350 if (vpip_current_vthread)
351 val = vthread_get_vec4_stack(vpip_current_vthread, depth_);
352
353 switch (vp->format) {
354
355 case vpiBinStrVal:
356 vpi_get_value_binstr_(vp, val);
357 break;
358 case vpiDecStrVal:
359 vpi_get_value_decstr_(vp, val);
360 break;
361 case vpiOctStrVal:
362 vpi_get_value_octstr_(vp, val);
363 break;
364 case vpiHexStrVal:
365 vpi_get_value_hexstr_(vp, val);
366 break;
367 case vpiIntVal:
368 vpi_get_value_int_(vp, val);
369 break;
370 case vpiRealVal:
371 vpi_get_value_real_(vp, val);
372 break;
373 case vpiStringVal:
374 vpi_get_value_string_(vp, val);
375 break;
376 case vpiStrengthVal:
377 vpi_get_value_strength_(vp, val);
378 break;
379 case vpiObjTypeVal:
380 vp->format = vpiVectorVal;
381 // fallthrough
382 case vpiVectorVal:
383 vpi_get_value_vector_(vp, val);
384 break;
385
386 default:
387 fprintf(stderr, "internal error: vpi_get_value(<format=%d>)"
388 " not implemented for __vpiVThrVec4Stack.\n", vp->format);
389 assert(0);
390 }
391
392 }
393
vpi_get_value_binstr_(p_vpi_value vp,const vvp_vector4_t & val)394 void __vpiVThrVec4Stack::vpi_get_value_binstr_(p_vpi_value vp, const vvp_vector4_t&val)
395 {
396 unsigned wid = val.size();
397 char*rbuf = (char*) need_result_buf(wid+1, RBUF_VAL);
398 for (unsigned idx = 0 ; idx < wid ; idx += 1) {
399 rbuf[wid-idx-1] = vvp_bit4_to_ascii(val.value(idx));
400 }
401 rbuf[wid] = 0;
402 vp->value.str = rbuf;
403 }
404
vpi_get_value_decstr_(p_vpi_value vp,const vvp_vector4_t & val)405 void __vpiVThrVec4Stack::vpi_get_value_decstr_(p_vpi_value vp, const vvp_vector4_t&val)
406 {
407 unsigned wid = val.size();
408 int nbuf = (wid+2)/3 + 1;
409 char *rbuf = (char*) need_result_buf(nbuf, RBUF_VAL);
410
411 vpip_vec4_to_dec_str(val, rbuf, nbuf, signed_flag_);
412 vp->value.str = rbuf;
413 }
414
vpi_get_value_octstr_(p_vpi_value vp,const vvp_vector4_t & val)415 void __vpiVThrVec4Stack::vpi_get_value_octstr_(p_vpi_value vp, const vvp_vector4_t&val)
416 {
417 unsigned wid = val.size();
418 unsigned owid = (wid + 2) / 3;
419 char*rbuf = (char*) need_result_buf(owid+1, RBUF_VAL);
420 rbuf[owid] = 0;
421
422 unsigned oval = 0;
423 for (unsigned idx = 0; idx < wid ; idx += 1) {
424 unsigned tmp = 0;
425 switch (val.value(idx)) {
426 case BIT4_0:
427 tmp = 0;
428 break;
429 case BIT4_1:
430 tmp = 1;
431 break;
432 case BIT4_X:
433 tmp = 2;
434 break;
435 case BIT4_Z:
436 tmp = 3;
437 break;
438 }
439
440 oval = oval | (tmp << 2*(idx%3));
441
442 if (idx%3 == 2) {
443 owid -= 1;
444 rbuf[owid] = oct_digits[oval];
445 oval = 0;
446 }
447 }
448
449 if (owid > 0) {
450 owid -= 1;
451 rbuf[owid] = oct_digits[oval];
452 oval = 0;
453 }
454 vp->value.str = rbuf;
455 }
456
vpi_get_value_hexstr_(p_vpi_value vp,const vvp_vector4_t & val)457 void __vpiVThrVec4Stack::vpi_get_value_hexstr_(p_vpi_value vp, const vvp_vector4_t&val)
458 {
459 unsigned wid = val.size();
460 unsigned hwid = (wid + 3) /4;
461 char*rbuf = (char*) need_result_buf(hwid+1, RBUF_VAL);
462 rbuf[hwid] = 0;
463
464 unsigned hval = 0;
465 for (unsigned idx = 0; idx < wid ; idx += 1) {
466 unsigned tmp = 0;
467 switch (val.value(idx)) {
468 case BIT4_0:
469 tmp = 0;
470 break;
471 case BIT4_1:
472 tmp = 1;
473 break;
474 case BIT4_X:
475 tmp = 2;
476 break;
477 case BIT4_Z:
478 tmp = 3;
479 break;
480 }
481 hval = hval | (tmp << 2*(idx%4));
482
483 if (idx%4 == 3) {
484 hwid -= 1;
485 rbuf[hwid] = hex_digits[hval];
486 hval = 0;
487 }
488 }
489
490 if (hwid > 0) {
491 hwid -= 1;
492 rbuf[hwid] = hex_digits[hval];
493 hval = 0;
494 }
495 vp->value.str = rbuf;
496 }
497
vpi_get_value_int_(p_vpi_value vp,const vvp_vector4_t & val)498 void __vpiVThrVec4Stack::vpi_get_value_int_(p_vpi_value vp, const vvp_vector4_t&val)
499 {
500 int32_t vali = 0;
501 vector4_to_value(val, vali, signed_flag_, false);
502 vp->value.integer = vali;
503 }
504
vpi_get_value_real_(p_vpi_value vp,const vvp_vector4_t & val)505 void __vpiVThrVec4Stack::vpi_get_value_real_(p_vpi_value vp, const vvp_vector4_t&val)
506 {
507 unsigned wid = val.size();
508 vp->value.real = 0.0;
509
510 for (unsigned idx = wid ; idx > 0 ; idx -= 1) {
511 vp->value.real *= 2.0;
512 if (val.value(idx-1) == BIT4_1)
513 vp->value.real += 1.0;
514 }
515 }
516
vpi_get_value_string_(p_vpi_value vp,const vvp_vector4_t & val)517 void __vpiVThrVec4Stack::vpi_get_value_string_(p_vpi_value vp, const vvp_vector4_t&val)
518 {
519 char*rbuf = (char*) need_result_buf((val.size() / 8) + 1, RBUF_VAL);
520 char*cp = rbuf;
521
522 char tmp = 0;
523 for (int bitnr = val.size()-1 ; bitnr >= 0 ; bitnr -= 1) {
524 tmp <<= 1;
525 switch (val.value(bitnr)) {
526 case BIT4_1:
527 tmp |= 1;
528 break;
529 case BIT4_0:
530 default:
531 break;
532 }
533
534 if ((bitnr&7)==0) {
535 // Don't include leading nuls
536 if (tmp == 0 && cp == rbuf)
537 continue;
538
539 *cp++ = tmp? tmp : ' ';
540 tmp = 0;
541 }
542 }
543 *cp++ = 0;
544 vp->format = vpiStringVal;
545 vp->value.str = rbuf;
546 }
547
vpi_get_value_vector_(p_vpi_value vp,const vvp_vector4_t & val)548 void __vpiVThrVec4Stack::vpi_get_value_vector_(p_vpi_value vp, const vvp_vector4_t&val)
549 {
550 unsigned wid = val.size();
551
552 vp->value.vector = (s_vpi_vecval*)
553 need_result_buf((wid+31)/32*sizeof(s_vpi_vecval), RBUF_VAL);
554 assert(vp->value.vector);
555
556 for (unsigned idx = 0 ; idx < wid ; idx += 1) {
557 int word = idx/32;
558 PLI_INT32 mask = 1 << (idx%32);
559
560 switch (val.value(idx)) {
561 case BIT4_0:
562 vp->value.vector[word].aval &= ~mask;
563 vp->value.vector[word].bval &= ~mask;
564 break;
565 case BIT4_1:
566 vp->value.vector[word].aval |= mask;
567 vp->value.vector[word].bval &= ~mask;
568 break;
569 case BIT4_X:
570 vp->value.vector[word].aval |= mask;
571 vp->value.vector[word].bval |= mask;
572 break;
573 case BIT4_Z:
574 vp->value.vector[word].aval &= ~mask;
575 vp->value.vector[word].bval |= mask;
576 break;
577 }
578 }
579 }
580
vpi_get_value_strength_(p_vpi_value vp,const vvp_vector4_t & val)581 void __vpiVThrVec4Stack::vpi_get_value_strength_(p_vpi_value vp, const vvp_vector4_t&val)
582 {
583 s_vpi_strengthval*op = (s_vpi_strengthval*)
584 need_result_buf(val.size() * sizeof(s_vpi_strengthval), RBUF_VAL);
585
586 for (unsigned idx = 0 ; idx < val.size() ; idx += 1) {
587 switch (val.value(idx)) {
588 case BIT4_0:
589 op[idx].logic = vpi0;
590 op[idx].s0 = vpiStrongDrive;
591 op[idx].s1 = 0;
592 break;
593 case BIT4_1:
594 op[idx].logic = vpi1;
595 op[idx].s0 = 0;
596 op[idx].s1 = vpiStrongDrive;
597 break;
598 case BIT4_X:
599 op[idx].logic = vpiX;
600 op[idx].s0 = vpiStrongDrive;
601 op[idx].s1 = vpiStrongDrive;
602 break;
603 case BIT4_Z:
604 op[idx].logic = vpiZ;
605 op[idx].s0 = vpiHiZ;
606 op[idx].s1 = vpiHiZ;
607 break;
608 }
609 }
610
611 vp->format = vpiStrengthVal;
612 vp->value.strength = op;
613 }
614
vpi_put_value(p_vpi_value vp,int)615 vpiHandle __vpiVThrVec4Stack::vpi_put_value(p_vpi_value vp, int /*flags*/)
616 {
617 assert(vpip_current_vthread);
618
619 switch (vp->format) {
620
621 default:
622 fprintf(stderr, "internal error: vpi_put_value(<format=%d>)"
623 " not implemented for __vpiVThrVec4Stack.\n", vp->format);
624 assert(0);
625 return 0;
626 }
627 }
628
629 #ifdef CHECK_WITH_VALGRIND
thread_vthr_delete(vpiHandle item)630 void thread_vthr_delete(vpiHandle item)
631 {
632 handle_map[item] = true;
633 }
634
thread_vthr_delete_real(vpiHandle item)635 static void thread_vthr_delete_real(vpiHandle item)
636 {
637 __vpiVThrVec4Stack*obj = dynamic_cast<__vpiVThrVec4Stack*>(item);
638 delete obj;
639 }
640
vpi_handle_delete()641 void vpi_handle_delete()
642 {
643 map<vpiHandle, bool>::iterator iter;
644 for (iter = handle_map.begin(); iter != handle_map.end(); ++ iter ) {
645 if (iter->second) thread_vthr_delete_real(iter->first);
646 else thread_word_delete_real(iter->first);
647 }
648 }
649 #endif
650
651
vpip_make_vthr_str_stack(unsigned depth)652 vpiHandle vpip_make_vthr_str_stack(unsigned depth)
653 {
654 __vpiVThrStrStack*obj = new __vpiVThrStrStack(depth);
655 return obj;
656 }
657
vpip_make_vthr_vec4_stack(unsigned depth,bool signed_flag,unsigned wid)658 vpiHandle vpip_make_vthr_vec4_stack(unsigned depth, bool signed_flag, unsigned wid)
659 {
660 __vpiVThrVec4Stack*obj = new __vpiVThrVec4Stack(depth, signed_flag, wid);
661 return obj;
662 }
663
664 #ifdef CHECK_WITH_VALGRIND
665 static map<vpiHandle, bool> stack_map;
666
thread_string_delete(vpiHandle item)667 void thread_string_delete(vpiHandle item)
668 {
669 stack_map[item] = false;
670 }
671
thread_string_delete_real(vpiHandle item)672 static void thread_string_delete_real(vpiHandle item)
673 {
674 __vpiVThrStrStack*obj = dynamic_cast<__vpiVThrStrStack*>(item);
675 delete obj;
676 }
677
vpi_stack_delete()678 void vpi_stack_delete()
679 {
680 map<vpiHandle, bool>::iterator iter;
681 for (iter = stack_map.begin(); iter != stack_map.end(); ++ iter ) {
682 thread_string_delete_real(iter->first);
683 }
684 }
685 #endif
686