1 /*
2 * Copyright (c) 2001-2018 Stephen Williams (steve@icarus.com)
3 *
4 * This source code is free software; you can redistribute it
5 * and/or modify it in source code form under the terms of the GNU
6 * General Public License as published by the Free Software
7 * Foundation; either version 2 of the License, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19
20 # include "vpi_priv.h"
21 # include "compile.h"
22 # include "config.h"
23 #ifdef CHECK_WITH_VALGRIND
24 # include "vvp_cleanup.h"
25 #endif
26 # include <cstdio>
27 # include <cstdlib>
28 # include <cstring>
29 # include <cassert>
30 # include "ivl_alloc.h"
31
32 class __vpiStringConst : public __vpiHandle {
33 public:
34 explicit __vpiStringConst(char*val);
35 ~__vpiStringConst();
36 int get_type_code(void) const;
37 int vpi_get(int code);
38 void vpi_get_value(p_vpi_value val);
39
40 private:
41 void process_string_();
42 private:
43 char*value_;
44 size_t value_len_;
45 };
46
__vpiStringConst(char * v)47 inline __vpiStringConst::__vpiStringConst(char*v)
48 : value_(v)
49 {
50 process_string_();
51 }
52
53 /*
54 * Strings are described at the level of the vvp source as a string
55 * with literal characters or octal escapes. No other escapes are
56 * included, they are processed already by the compiler that generated
57 * the vvp source.
58 */
process_string_(void)59 void __vpiStringConst::process_string_(void)
60 {
61 char*chr = value_;
62 char*dp = value_;
63
64 while (*chr) {
65 char next_char = *chr;
66
67 /* Process octal escapes that I might find. */
68 if (*chr == '\\') {
69 for (int idx = 1 ; idx <= 3 ; idx += 1) {
70 assert(chr[idx] != 0);
71 assert(chr[idx] < '8');
72 assert(chr[idx] >= '0');
73 next_char = next_char*8 + chr[idx] - '0';
74 }
75 chr += 3;
76 }
77 *dp++ = next_char;
78 chr += 1;
79 }
80 *dp = 0;
81 value_len_ = dp - value_;
82 }
83
~__vpiStringConst()84 __vpiStringConst::~__vpiStringConst()
85 {
86 delete[] value_;
87 }
88
get_type_code(void) const89 int __vpiStringConst::get_type_code(void) const
90 { return vpiConstant; }
91
vpi_get(int code)92 int __vpiStringConst::vpi_get(int code)
93 {
94 switch (code) {
95 case vpiSize:
96 return strlen(value_)*8;
97
98 case vpiSigned:
99 return 0;
100
101 case vpiConstType:
102 return vpiStringConst;
103
104 case vpiAutomatic:
105 return 0;
106
107 #if defined(CHECK_WITH_VALGRIND) || defined(BR916_STOPGAP_FIX)
108 case _vpiFromThr:
109 return _vpiNoThr;
110 #endif
111
112 default:
113 fprintf(stderr, "vvp error: get %d not supported "
114 "by vpiStringConst\n", code);
115 assert(0);
116 return 0;
117 }
118 }
119
vpi_get_value(p_vpi_value vp)120 void __vpiStringConst::vpi_get_value(p_vpi_value vp)
121 {
122 unsigned uint_value;
123 p_vpi_vecval vecp;
124 unsigned size = strlen(value_);
125 char*rbuf = 0;
126 char*cp;
127
128 switch (vp->format) {
129 case vpiObjTypeVal:
130 /* String parameters by default have vpiStringVal values. */
131 vp->format = vpiStringVal;
132 // fallthrough
133 case vpiStringVal:
134 rbuf = (char *) need_result_buf(size + 1, RBUF_VAL);
135 strcpy(rbuf, value_);
136 vp->value.str = rbuf;
137 break;
138
139 case vpiDecStrVal:
140 if (size > 4){
141 // We only support standard integers. Ignore other bytes...
142 size = 4;
143 fprintf(stderr, "Warning (vpi_const.cc): %%d on constant strings only looks "
144 "at first 4 bytes!\n");
145 }
146 rbuf = (char *) need_result_buf(size + 1, RBUF_VAL);
147 uint_value = 0;
148 for(unsigned i=0; i<size; i += 1){
149 uint_value <<=8;
150 uint_value += (unsigned char)(value_[i]);
151 }
152 sprintf(rbuf, "%u", uint_value);
153 vp->value.str = rbuf;
154 break;
155
156 case vpiBinStrVal:
157 rbuf = (char *) need_result_buf(8 * size + 1, RBUF_VAL);
158 cp = rbuf;
159 for(unsigned i=0; i<size; i += 1){
160 for(int bit=7; bit>=0; bit -= 1){
161 *cp++ = "01"[ (value_[i]>>bit)&1 ];
162 }
163 }
164 *cp = 0;
165 vp->value.str = rbuf;
166 break;
167
168 case vpiHexStrVal:
169 rbuf = (char *) need_result_buf(2 * size + 1, RBUF_VAL);
170 cp = rbuf;
171 for(unsigned i=0; i<size; i += 1){
172 for(int nibble=1; nibble>=0; nibble -= 1){
173 *cp++ = "0123456789abcdef"[ (value_[i]>>(nibble*4))&15 ];
174 }
175 }
176 *cp = 0;
177 vp->value.str = rbuf;
178 break;
179
180 case vpiOctStrVal:
181 fprintf(stderr, "ERROR (vpi_const.cc): %%o display of constant strings not yet implemented\n");
182 assert(0);
183 break;
184
185 case vpiIntVal:
186 vp->value.integer = 0;
187 for(unsigned i=0; i<size; i += 1){
188 for(int bit=7; bit>=0; bit -= 1){
189 vp->value.integer <<= 1;
190 vp->value.integer += (value_[i]>>bit)&1;
191 }
192 }
193 break;
194
195 case vpiVectorVal:
196 vp->value.vector = (p_vpi_vecval)
197 need_result_buf((size+3)/4*
198 sizeof(s_vpi_vecval),
199 RBUF_VAL);
200 uint_value = 0;
201 vecp = vp->value.vector;
202 vecp->aval = vecp->bval = 0;
203 for(unsigned i=0; i<size; i += 1){
204 vecp->aval |= value_[i] << uint_value*8;
205 uint_value += 1;
206 if (uint_value > 3) {
207 uint_value = 0;
208 vecp += 1;
209 vecp->aval = vecp->bval = 0;
210 }
211 }
212 break;
213
214
215 default:
216 fprintf(stderr, "ERROR (vpi_const.cc): vp->format: %d\n",
217 (int)vp->format);
218 assert(0);
219
220 vp->format = vpiSuppressVal;
221 break;
222 }
223 }
224
225
226 struct __vpiStringConstTEMP : public __vpiStringConst {
__vpiStringConstTEMP__vpiStringConstTEMP227 explicit inline __vpiStringConstTEMP(char*v) : __vpiStringConst(v) { }
228 free_object_fun_t free_object_fun(void);
229 };
230
free_temp_string(vpiHandle obj)231 static int free_temp_string(vpiHandle obj)
232 {
233 struct __vpiStringConstTEMP*rfp = dynamic_cast<__vpiStringConstTEMP*>(obj);
234 delete rfp;
235 return 1;
236 }
237
free_object_fun(void)238 __vpiHandle::free_object_fun_t __vpiStringConstTEMP::free_object_fun(void)
239 { return &free_temp_string; }
240
vpip_make_string_const(char * text,bool persistent_flag)241 vpiHandle vpip_make_string_const(char*text, bool persistent_flag)
242 {
243 __vpiStringConst*obj;
244
245 obj = persistent_flag? new __vpiStringConst(text) : new __vpiStringConstTEMP(text);
246
247 return obj;
248 }
249
250
251 class __vpiStringParam : public __vpiStringConst {
252 public:
253 __vpiStringParam(char*txt, char*name);
254 ~__vpiStringParam();
255 int get_type_code(void) const;
256 int vpi_get(int code);
257 char*vpi_get_str(int code);
258 vpiHandle vpi_handle(int code);
259
260 __vpiScope* scope;
261 bool local_flag;
262 unsigned file_idx;
263 unsigned lineno;
264 private:
265 const char*basename_;
266 };
267
__vpiStringParam(char * txt,char * nam)268 inline __vpiStringParam::__vpiStringParam(char*txt, char*nam)
269 : __vpiStringConst(txt)
270 {
271 basename_ = nam;
272 }
273
~__vpiStringParam()274 __vpiStringParam::~__vpiStringParam()
275 {
276 delete[]basename_;
277 }
278
get_type_code(void) const279 int __vpiStringParam::get_type_code(void) const
280 { return vpiParameter; }
281
vpi_get(int code)282 int __vpiStringParam::vpi_get(int code)
283 {
284 switch (code) {
285 case vpiLineNo :
286 return lineno;
287
288 case vpiLocalParam :
289 return local_flag;
290
291 default :
292 return __vpiStringConst::vpi_get(code);
293 }
294 }
295
296
vpi_get_str(int code)297 char*__vpiStringParam::vpi_get_str(int code)
298 {
299 if (code == vpiFile) {
300 return simple_set_rbuf_str(file_names[file_idx]);
301 }
302
303 return generic_get_str(code, scope, basename_, NULL);
304 }
305
306
vpi_handle(int code)307 vpiHandle __vpiStringParam::vpi_handle(int code)
308 {
309 switch (code) {
310 case vpiScope:
311 return scope;
312
313 case vpiModule:
314 return vpip_module(scope);
315
316 default:
317 return 0;
318 }
319 }
320
vpip_make_string_param(char * name,char * text,bool local_flag,long file_idx,long lineno)321 vpiHandle vpip_make_string_param(char*name, char*text,
322 bool local_flag, long file_idx, long lineno)
323 {
324 __vpiStringParam*obj = new __vpiStringParam(text, name);
325 obj->scope = vpip_peek_current_scope();
326 obj->local_flag = local_flag;
327 obj->file_idx = (unsigned) file_idx;
328 obj->lineno = (unsigned) lineno;
329
330 return obj;
331 }
332
333
334
__vpiBinaryConst()335 inline __vpiBinaryConst::__vpiBinaryConst()
336 { }
337
get_type_code(void) const338 int __vpiBinaryConst::get_type_code(void) const
339 { return vpiConstant; }
340
vpi_get(int code)341 int __vpiBinaryConst::vpi_get(int code)
342 {
343 switch (code) {
344 case vpiConstType:
345 return vpiBinaryConst;
346
347 case vpiLineNo:
348 return 0; // Not implemented for now!
349
350 case vpiSigned:
351 return signed_flag? 1 : 0;
352
353 case vpiSize:
354 return bits.size();
355
356 case vpiAutomatic:
357 return 0;
358
359 #if defined(CHECK_WITH_VALGRIND) || defined(BR916_STOPGAP_FIX)
360 case _vpiFromThr:
361 return _vpiNoThr;
362 #endif
363
364 default:
365 fprintf(stderr, "vvp error: get %d not supported "
366 "by vpiBinaryConst\n", code);
367 assert(0);
368 return 0;
369 }
370 }
371
372
vpi_get_value(p_vpi_value val)373 void __vpiBinaryConst::vpi_get_value(p_vpi_value val)
374 {
375 switch (val->format) {
376
377 case vpiObjTypeVal:
378 case vpiBinStrVal:
379 case vpiDecStrVal:
380 case vpiOctStrVal:
381 case vpiHexStrVal:
382 case vpiScalarVal:
383 case vpiIntVal:
384 case vpiVectorVal:
385 case vpiStringVal:
386 case vpiRealVal:
387 vpip_vec4_get_value(bits, bits.size(), signed_flag, val);
388 break;
389
390 default:
391 fprintf(stderr, "vvp error: format %d not supported "
392 "by vpiBinaryConst\n", (int)val->format);
393 val->format = vpiSuppressVal;
394 break;
395 }
396 }
397
398
399 /*
400 * Make a VPI constant from a vector string. The string is normally a
401 * ASCII string, with each letter a 4-value bit. The first character
402 * may be an 's' if the vector is signed.
403 */
vpip_make_binary_const(unsigned wid,const char * bits)404 vpiHandle vpip_make_binary_const(unsigned wid, const char*bits)
405 {
406 struct __vpiBinaryConst*obj = new __vpiBinaryConst;
407
408 obj->signed_flag = 0;
409 obj->sized_flag = 0;
410
411 const char*bp = bits;
412 if (*bp == 's') {
413 bp += 1;
414 obj->signed_flag = 1;
415 }
416
417 obj->bits = vector4_from_text(bp, wid);
418
419 return obj;
420 }
421
vector4_from_text(const char * bits,unsigned wid)422 vvp_vector4_t vector4_from_text(const char*bits, unsigned wid)
423 {
424 vvp_vector4_t res (wid);
425
426 for (unsigned idx = 0 ; idx < wid ; idx += 1) {
427 vvp_bit4_t val = BIT4_0;
428 switch (bits[wid-idx-1]) {
429 case '0':
430 val = BIT4_0;
431 break;
432 case '1':
433 val = BIT4_1;
434 break;
435 case 'x':
436 val = BIT4_X;
437 break;
438 case 'z':
439 val = BIT4_Z;
440 break;
441 }
442
443 res.set_bit(idx, val);
444 }
445
446 return res;
447 }
448
449 struct __vpiBinaryParam : public __vpiBinaryConst {
450 __vpiBinaryParam(const vvp_vector4_t&b, char*name);
451 ~__vpiBinaryParam();
452 int get_type_code(void) const;
453 int vpi_get(int code);
454 char*vpi_get_str(int code);
455 vpiHandle vpi_handle(int code);
456
457 __vpiScope*scope;
458 unsigned file_idx;
459 unsigned lineno;
460 bool local_flag;
461 private:
462 char*basename_;
463 };
464
__vpiBinaryParam(const vvp_vector4_t & b,char * nam)465 inline __vpiBinaryParam::__vpiBinaryParam(const vvp_vector4_t&b, char*nam)
466 {
467 bits = b;
468 basename_ = nam;
469 }
470
~__vpiBinaryParam()471 __vpiBinaryParam::~__vpiBinaryParam()
472 {
473 delete[]basename_;
474 }
475
get_type_code(void) const476 int __vpiBinaryParam::get_type_code(void) const
477 { return vpiParameter; }
478
vpi_get(int code)479 int __vpiBinaryParam::vpi_get(int code)
480 {
481 switch (code) {
482 case vpiLineNo :
483 return lineno;
484
485 case vpiLocalParam :
486 return local_flag;
487
488 default :
489 return __vpiBinaryConst::vpi_get(code);
490 }
491 }
492
vpi_get_str(int code)493 char*__vpiBinaryParam::vpi_get_str(int code)
494 {
495 if (code == vpiFile)
496 return simple_set_rbuf_str(file_names[file_idx]);
497
498 return generic_get_str(code, scope, basename_, NULL);
499 }
500
501
vpi_handle(int code)502 vpiHandle __vpiBinaryParam::vpi_handle(int code)
503 {
504 switch (code) {
505 case vpiScope:
506 return scope;
507
508 case vpiModule:
509 return vpip_module(scope);
510
511 default:
512 return 0;
513 }
514 }
515
516
vpip_make_binary_param(char * name,const vvp_vector4_t & bits,bool signed_flag,bool local_flag,long file_idx,long lineno)517 vpiHandle vpip_make_binary_param(char*name, const vvp_vector4_t&bits,
518 bool signed_flag, bool local_flag,
519 long file_idx, long lineno)
520 {
521 struct __vpiBinaryParam*obj = new __vpiBinaryParam(bits, name);
522
523 obj->signed_flag = signed_flag? 1 : 0;
524 obj->sized_flag = 0;
525 obj->local_flag = local_flag;
526 obj->scope = vpip_peek_current_scope();
527 obj->file_idx = (unsigned) file_idx;
528 obj->lineno = (unsigned) lineno;
529
530 return obj;
531 }
532
533
534
__vpiDecConst(int val)535 __vpiDecConst::__vpiDecConst(int val)
536 {
537 value = val;
538 }
539
__vpiDecConst(const __vpiDecConst & that)540 __vpiDecConst::__vpiDecConst(const __vpiDecConst&that)
541 : __vpiHandle(), value(that.value)
542 {
543 }
544
545
get_type_code(void) const546 int __vpiDecConst::get_type_code(void) const
547 { return vpiConstant; }
548
vpi_get(int code)549 int __vpiDecConst::vpi_get(int code)
550 {
551 switch (code) {
552 case vpiConstType:
553 return vpiDecConst;
554
555 case vpiSigned:
556 return 1;
557
558 case vpiSize:
559 return 32;
560
561 case vpiAutomatic:
562 return 0;
563
564 #if defined(CHECK_WITH_VALGRIND) || defined(BR916_STOPGAP_FIX)
565 case _vpiFromThr:
566 return _vpiNoThr;
567 #endif
568
569 default:
570 fprintf(stderr, "vvp error: get %d not supported "
571 "by vpiDecConst\n", code);
572 assert(0);
573 return 0;
574 }
575 }
576
577
vpi_get_value(p_vpi_value vp)578 void __vpiDecConst::vpi_get_value(p_vpi_value vp)
579 {
580 char*rbuf = (char *) need_result_buf(64 + 1, RBUF_VAL);
581 char*cp = rbuf;
582
583 switch (vp->format) {
584
585 case vpiObjTypeVal:
586 case vpiIntVal: {
587 vp->value.integer = value;
588 break;
589 }
590
591 case vpiDecStrVal:
592 sprintf(rbuf, "%d", value);
593
594 vp->value.str = rbuf;
595 break;
596
597 case vpiBinStrVal:
598 for(int bit=31; bit>=0;bit--){
599 *cp++ = "01"[ (value>>bit)&1 ];
600 }
601 *cp = 0;
602
603 vp->value.str = rbuf;
604 break;
605
606 case vpiHexStrVal:
607 sprintf(rbuf, "%08x", value);
608
609 vp->value.str = rbuf;
610 break;
611
612 case vpiOctStrVal:
613 sprintf(rbuf, "%011x", value);
614
615 vp->value.str = rbuf;
616 break;
617
618 default:
619 fprintf(stderr, "vvp error (vpi_const.cc): format %d not supported "
620 "by vpiDecConst\n", (int)vp->format);
621 vp->format = vpiSuppressVal;
622 break;
623 }
624 }
625
626
__vpiRealConst(double val)627 inline __vpiRealConst::__vpiRealConst(double val)
628 : value(val)
629 { }
630
get_type_code(void) const631 int __vpiRealConst::get_type_code(void) const
632 { return vpiConstant; }
633
vpi_get(int code)634 int __vpiRealConst::vpi_get(int code)
635 {
636 switch (code) {
637 case vpiLineNo:
638 return 0; // Not implemented for now!
639
640 case vpiSize:
641 return 1;
642
643 case vpiConstType:
644 return vpiRealConst;
645
646 case vpiSigned:
647 return 1;
648
649 case vpiAutomatic:
650 return 0;
651
652 #if defined(CHECK_WITH_VALGRIND) || defined(BR916_STOPGAP_FIX)
653 case _vpiFromThr:
654 return _vpiNoThr;
655 #endif
656
657 default:
658 fprintf(stderr, "vvp error: get %d not supported "
659 "by vpiRealConst\n", code);
660 assert(0);
661 return 0;
662 }
663 }
664
665
vpi_get_value(p_vpi_value val)666 void __vpiRealConst::vpi_get_value(p_vpi_value val)
667 {
668 vpip_real_get_value(value, val);
669 }
670
671
vpip_make_real_const(double value)672 vpiHandle vpip_make_real_const(double value)
673 {
674 __vpiRealConst*obj = new __vpiRealConst(value);
675 return obj;
676 }
677
678 struct __vpiRealParam : public __vpiRealConst {
679 __vpiRealParam(double val, char*name);
680 ~__vpiRealParam();
681 int get_type_code(void) const;
682 int vpi_get(int code);
683 char*vpi_get_str(int code);
684 vpiHandle vpi_handle(int code);
685
686 __vpiScope* scope;
687 bool local_flag;
688 unsigned file_idx;
689 unsigned lineno;
690 private:
691 const char*basename_;
692 };
693
694
__vpiRealParam(double val,char * name)695 inline __vpiRealParam::__vpiRealParam(double val, char*name)
696 : __vpiRealConst(val)
697 {
698 basename_ = name;
699 }
700
~__vpiRealParam()701 __vpiRealParam::~__vpiRealParam()
702 {
703 delete[]basename_;
704 }
705
706
get_type_code(void) const707 int __vpiRealParam::get_type_code(void) const
708 { return vpiParameter; }
709
vpi_get(int code)710 int __vpiRealParam::vpi_get(int code)
711 {
712 switch (code) {
713 case vpiLineNo :
714 return lineno;
715
716 case vpiLocalParam :
717 return local_flag;
718
719 default :
720 return __vpiRealConst::vpi_get(code);
721 }
722 }
723
vpi_get_str(int code)724 char* __vpiRealParam::vpi_get_str(int code)
725 {
726 if (code == vpiFile)
727 return simple_set_rbuf_str(file_names[file_idx]);
728
729 return generic_get_str(code, scope, basename_, NULL);
730 }
731
vpi_handle(int code)732 vpiHandle __vpiRealParam::vpi_handle(int code)
733 {
734 switch (code) {
735 case vpiScope:
736 return scope;
737
738 case vpiModule:
739 return vpip_module(scope);
740
741 default:
742 return 0;
743 }
744 }
745
746
vpip_make_real_param(char * name,double value,bool local_flag,long file_idx,long lineno)747 vpiHandle vpip_make_real_param(char*name, double value,
748 bool local_flag, long file_idx, long lineno)
749 {
750 struct __vpiRealParam*obj = new __vpiRealParam(value, name);
751
752 obj->scope = vpip_peek_current_scope();
753 obj->local_flag = local_flag;
754 obj->file_idx = (unsigned) file_idx;
755 obj->lineno = (unsigned) lineno;
756
757 return obj;
758 }
759
760 #ifdef CHECK_WITH_VALGRIND
constant_delete(vpiHandle item)761 void constant_delete(vpiHandle item)
762 {
763 assert(item->get_type_code() == vpiConstant);
764 switch(vpi_get(vpiConstType, item)) {
765 case vpiStringConst:
766 delete dynamic_cast<__vpiStringConst*>(item);
767 break;
768 case vpiDecConst:
769 delete dynamic_cast<__vpiDecConst*>(item);
770 break;
771 case vpiBinaryConst:
772 delete dynamic_cast<__vpiBinaryConst*>(item);
773 break;
774 case vpiRealConst:
775 delete dynamic_cast<__vpiRealConst*>(item);
776 break;
777 default:
778 assert(0);
779 }
780 }
781
parameter_delete(vpiHandle item)782 void parameter_delete(vpiHandle item)
783 {
784 switch(vpi_get(vpiConstType, item)) {
785 case vpiStringConst: {
786 struct __vpiStringParam*rfp = dynamic_cast<__vpiStringParam*>(item);
787 delete rfp;
788 break; }
789 case vpiBinaryConst: {
790 struct __vpiBinaryParam*rfp = dynamic_cast<__vpiBinaryParam*>(item);
791 delete rfp;
792 break; }
793 case vpiRealConst: {
794 struct __vpiRealParam*rfp = dynamic_cast<__vpiRealParam*>(item);
795 delete rfp;
796 break; }
797 default:
798 assert(0);
799 }
800 }
801 #endif
802