1 /*
2  * Copyright (c) 2008-2020 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  "version_base.h"
21 # include  "vpi_priv.h"
22 # include  "schedule.h"
23 #ifdef CHECK_WITH_VALGRIND
24 # include  "vvp_cleanup.h"
25 #endif
26 # include  <vector>
27 # include  <cstdio>
28 # include  <cstdarg>
29 # include  <cstring>
30 # include  <cassert>
31 # include  <cstdlib>
32 # include  <cmath>
33 # include  <iostream>
34 
35 using namespace std;
36 vpi_mode_t vpi_mode_flag = VPI_MODE_NONE;
37 FILE*vpi_trace = 0;
38 
39 static s_vpi_vlog_info  vpi_vlog_info;
40 static s_vpi_error_info vpip_last_error = { 0, 0, 0, 0, 0, 0, 0 };
41 
~__vpiHandle()42 __vpiHandle::~__vpiHandle()
43 { }
44 
vpi_get(int)45 int __vpiHandle::vpi_get(int)
46 { return vpiUndefined; }
47 
vpi_get_str(int)48 char* __vpiHandle::vpi_get_str(int)
49 { return 0; }
50 
vpi_get_value(p_vpi_value)51 void __vpiHandle::vpi_get_value(p_vpi_value)
52 { }
53 
vpi_put_value(p_vpi_value,int)54 vpiHandle __vpiHandle::vpi_put_value(p_vpi_value, int)
55 { return 0; }
56 
vpi_handle(int)57 vpiHandle __vpiHandle::vpi_handle(int)
58 { return 0; }
59 
vpi_iterate(int)60 vpiHandle __vpiHandle::vpi_iterate(int)
61 { return 0; }
62 
vpi_index(int)63 vpiHandle __vpiHandle::vpi_index(int)
64 { return 0; }
65 
vpi_get_delays(p_vpi_delay)66 void __vpiHandle::vpi_get_delays(p_vpi_delay)
67 { }
68 
vpi_put_delays(p_vpi_delay)69 void __vpiHandle::vpi_put_delays(p_vpi_delay)
70 { }
71 
__vpiBaseVar(__vpiScope * scope,const char * name,vvp_net_t * net)72 __vpiBaseVar::__vpiBaseVar(__vpiScope*scope, const char*name, vvp_net_t*net)
73 : scope_(scope), name_(name), net_(net)
74 {
75 }
76 
77 #ifdef CHECK_WITH_VALGRIND
~__vpiBaseVar()78 __vpiBaseVar::~__vpiBaseVar()
79 {
80       vvp_net_delete(net_);
81 }
82 #endif
83 
84 /*
85  * The default behavior for the vpi_free_object to an object is to
86  * suppress the actual operation. This is because handles are
87  * generally allocated semi-permanently within vvp context. Dynamic
88  * objects will override the free_object_fun method to return an
89  * appropriately effective function.
90  */
suppress_free(vpiHandle)91 static int suppress_free(vpiHandle)
92 { return 1; }
free_object_fun(void)93 __vpiHandle::free_object_fun_t __vpiHandle::free_object_fun(void)
94 { return &suppress_free; }
95 
96 /*
97  * The vpip_string function creates a constant string from the pass
98  * input. This constant string is permanently allocated from an
99  * efficient string buffer store.
100  */
101 struct vpip_string_chunk {
102       struct vpip_string_chunk*next;
103       char data[64*1024 - sizeof (struct vpip_string_chunk*)];
104 };
105 
vpip_size(__vpiSignal * sig)106 unsigned vpip_size(__vpiSignal *sig)
107 {
108       return abs(sig->msb.get_value() - sig->lsb.get_value()) + 1;
109 }
110 
vpip_scope(__vpiSignal * sig)111 __vpiScope* vpip_scope(__vpiSignal*sig)
112 {
113       if (sig->is_netarray)
114 	    return  (__vpiScope*) vpi_handle(vpiScope, sig->within.parent);
115       else
116 	    return sig->within.scope;
117 }
118 
vpip_scope(__vpiRealVar * sig)119 __vpiScope* vpip_scope(__vpiRealVar*sig)
120 {
121       if (sig->is_netarray)
122 	    return  (__vpiScope*) vpi_handle(vpiScope, sig->within.parent);
123       else
124 	    return sig->within.scope;
125 }
126 
vpip_module(__vpiScope * scope)127 vpiHandle vpip_module(__vpiScope*scope)
128 {
129       while(scope && scope->get_type_code() != vpiModule) {
130 	    scope = scope->scope;
131       }
132       assert(scope);
133       return scope;
134 }
135 
vpip_string(const char * str)136 const char *vpip_string(const char*str)
137 {
138       static vpip_string_chunk first_chunk = {0, {0}};
139       static vpip_string_chunk*chunk_list = &first_chunk;
140       static unsigned chunk_fill = 0;
141 
142       unsigned len = strlen(str);
143       assert( (len+1) <= sizeof chunk_list->data );
144 
145       if ( (len+1) > (sizeof chunk_list->data - chunk_fill) ) {
146 	    vpip_string_chunk*tmp = new vpip_string_chunk;
147 	    tmp->next = chunk_list;
148 	    chunk_list = tmp;
149 	    chunk_fill = 0;
150       }
151 
152       char*res = chunk_list->data + chunk_fill;
153       chunk_fill += len + 1;
154 
155       strcpy(res, str);
156       return res;
157 }
158 
hash_string(const char * text)159 static unsigned hash_string(const char*text)
160 {
161       unsigned h = 0;
162 
163       while (*text) {
164 	    h = (h << 4) ^ (h >> 28) ^ (unsigned)*text;
165 	    text += 1;
166       }
167       return h;
168 }
169 
vpip_name_string(const char * text)170 const char* vpip_name_string(const char*text)
171 {
172       const unsigned HASH_SIZE = 4096;
173       static const char*hash_table[HASH_SIZE] = {0};
174 
175       unsigned hash_value = hash_string(text) % HASH_SIZE;
176 
177 	/* If we easily find the string in the hash table, then return
178 	   that and be done. */
179       if (hash_table[hash_value]
180 	  && (strcmp(hash_table[hash_value], text) == 0)) {
181 	    return hash_table[hash_value];
182       }
183 
184 	/* The existing hash entry is not a match. Replace it with the
185 	   newly allocated value, and return the new pointer as the
186 	   result to the add. */
187       const char*res = vpip_string(text);
188       hash_table[hash_value] = res;
189 
190       return res;
191 }
192 
vpi_chk_error(p_vpi_error_info info)193 PLI_INT32 vpi_chk_error(p_vpi_error_info info)
194 {
195       if (vpip_last_error.state == 0)
196 	    return 0;
197 
198       info->state = vpip_last_error.state;
199       info->level = vpip_last_error.level;
200       info->message = vpip_last_error.message;
201       info->product = vpi_vlog_info.product;
202       info->code = (char *) "";
203       info->file = 0;
204       info->line = 0;
205 
206       return info->level;
207 }
208 
vpi_compare_objects(vpiHandle obj1,vpiHandle obj2)209 PLI_INT32 vpi_compare_objects(vpiHandle obj1, vpiHandle obj2)
210 {
211       assert(obj1);
212       assert(obj2);
213 
214 	// Does this actually work for all cases?
215       if (obj1 != obj2) return 0;
216       else return 1;
217 }
218 
219 /*
220  * Copy the internal information to the data structure. Do not free or
221  * change the tfname/user_data since they are a pointer to the real
222  * string/data values. We also support passing a task or function handle
223  * instead of just a handle to a vpiUserSystf.
224  */
vpi_get_systf_info(vpiHandle ref,p_vpi_systf_data data)225 void vpi_get_systf_info(vpiHandle ref, p_vpi_systf_data data)
226 {
227       struct __vpiUserSystf* rfp = dynamic_cast<__vpiUserSystf*>(ref);
228       if (rfp == 0) {
229 	    struct __vpiSysTaskCall*call = dynamic_cast<__vpiSysTaskCall*>(ref);
230 	    assert(call);
231 	    rfp = call->defn;
232       }
233 
234 	/* Assert that vpiUserDefn is true! */
235       assert(rfp->is_user_defn);
236 
237       data->type = rfp->info.type;
238       data->sysfunctype = rfp->info.sysfunctype;
239       data->tfname = rfp->info.tfname;
240       data->calltf = rfp->info.calltf;
241       data->compiletf = rfp->info.compiletf;
242       data->sizetf = rfp->info.sizetf;
243       data->user_data = rfp->info.user_data;
244 }
245 
246 /*
247  * When a task is called, this value is set so that vpi_handle can
248  * fathom the vpi_handle(vpiSysTfCall,0) function.
249  */
250 struct __vpiSysTaskCall*vpip_cur_task = 0;
251 
vpi_free_object(vpiHandle ref)252 PLI_INT32 vpi_free_object(vpiHandle ref)
253 {
254       int rtn;
255 
256       if (vpi_trace) {
257 	    fprintf(vpi_trace, "vpi_free_object(%p)", ref);
258 	    fflush(vpi_trace);
259       }
260 
261       assert(ref);
262       __vpiHandle::free_object_fun_t fun = ref->free_object_fun();
263       rtn = fun (ref);
264 
265       if (vpi_trace)
266 	    fprintf(vpi_trace, " --> %d\n", rtn);
267 
268       return rtn;
269 }
270 
vpip_get_global(int property)271 static int vpip_get_global(int property)
272 {
273       switch (property) {
274 
275 	  case vpiTimeUnit:
276 	  case vpiTimePrecision:
277 	    return vpip_get_time_precision();
278 
279 	  default:
280 	    fprintf(stderr, "vpi error: bad global property: %d\n", property);
281 	    assert(0);
282 	    return vpiUndefined;
283       }
284 }
285 
vpi_property_str(PLI_INT32 code)286 static const char* vpi_property_str(PLI_INT32 code)
287 {
288       static char buf[32];
289       switch (code) {
290 	  case vpiConstType:
291 	    return "vpiConstType";
292 	  case vpiName:
293 	    return "vpiName";
294 	  case vpiFullName:
295 	    return "vpiFullName";
296 	  case vpiTimeUnit:
297 	    return "vpiTimeUnit";
298 	  case vpiTimePrecision:
299 	    return "vpiTimePrecision";
300           case vpiSize:
301 	    return "vpiSize";
302 	  default:
303 	    sprintf(buf, "%d", (int)code);
304       }
305       return buf;
306 }
307 
vpi_type_values(PLI_INT32 code)308 static const char* vpi_type_values(PLI_INT32 code)
309 {
310       static char buf[32];
311       switch (code) {
312 	  case vpiArrayType:
313 	    return "vpiArrayType";
314 	  case vpiBitVar:
315 	    return "vpiBitVar";
316 	  case vpiByteVar:
317 	    return "vpiByteVar";
318 	  case vpiClassVar:
319 	    return "vpiClassVar";
320 	  case vpiConstant:
321 	    return "vpiConstant";
322 	  case vpiEnumTypespec:
323 	    return "vpiEnumTypespec";
324 	  case vpiFunction:
325 	    return "vpiFunction";
326 	  case vpiGenScope:
327 	    return "vpiGenScope";
328 	  case vpiIntVar:
329 	    return "vpiIntVar";
330 	  case vpiIntegerVar:
331 	    return "vpiIntegerVar";
332 	  case vpiIterator:
333 	    return "vpiIterator";
334 	  case vpiLongIntVar:
335 	    return "vpiLongIntVar";
336 	  case vpiMemory:
337 	    return "vpiMemory";
338 	  case vpiMemoryWord:
339 	    return "vpiMemoryWord";
340 	  case vpiModule:
341 	    return "vpiModule";
342 	  case vpiNamedBegin:
343 	    return "vpiNamedBegin";
344 	  case vpiNamedEvent:
345 	    return "vpiNamedEvent";
346 	  case vpiNamedFork:
347 	    return "vpiNamedFork";
348 	  case vpiPackage:
349 	    return "vpiPackage";
350 	  case vpiPathTerm:
351 	    return "vpiPathTerm";
352 	  case vpiPort:
353 	    return "vpiPort";
354 	  case vpiNet:
355 	    return "vpiNet";
356 	  case vpiNetArray:
357 	    return "vpiNetArray";
358 	  case vpiNetBit:
359 	    return "vpiNetBit";
360 	  case vpiParameter:
361 	    return "vpiParameter";
362 	  case vpiPartSelect:
363 	    return "vpiPartSelect";
364 	  case vpiRealVar:
365 	    return "vpiRealVar";
366 	  case vpiReg:
367 	    return "vpiReg";
368 	  case vpiRegBit:
369 	    return "vpiRegBit";
370 	  case vpiShortIntVar:
371 	    return "vpiShortIntVar";
372 	  case vpiStringVar:
373 	    return "vpiStringVar";
374 	  case vpiSysFuncCall:
375 	    return "vpiSysFuncCall";
376 	  case vpiSysTaskCall:
377 	    return "vpiSysTaskCall";
378 	  case vpiTask:
379 	    return "vpiTask";
380 	  case vpiTimeVar:
381 	    return "vpiTimeVar";
382 	  case vpiUserSystf:
383 	    return "vpiUserSystf";
384 	  default:
385 	    sprintf(buf, "%d", (int)code);
386       }
387       return buf;
388 }
389 
vpi_get(int property,vpiHandle ref)390 PLI_INT32 vpi_get(int property, vpiHandle ref)
391 {
392 	/* We don't care what the ref is there is only one delay selection. */
393       if (property == _vpiDelaySelection) return vpip_delay_selection;
394 
395       if (ref == 0)
396 	    return vpip_get_global(property);
397 
398       if (property == vpiType) {
399 	    if (vpi_trace) {
400 		  fprintf(vpi_trace, "vpi_get(vpiType, %p) --> %s\n",
401 			  ref, vpi_type_values(ref->get_type_code()));
402 	    }
403 
404 	    if (ref->get_type_code() == vpiMemory && is_net_array(ref))
405 		  return vpiNetArray;
406 	    else
407 		  return ref->get_type_code();
408       }
409 
410       int res = ref->vpi_get(property);
411 
412       if (vpi_trace) {
413 	    fprintf(vpi_trace, "vpi_get(%s, %p) --> %d\n",
414 		    vpi_property_str(property), ref, res);
415       }
416 
417       return res;
418 }
419 
vpi_get_str(PLI_INT32 property,vpiHandle ref)420 char* vpi_get_str(PLI_INT32 property, vpiHandle ref)
421 {
422 	/* We don't care what the ref is there is only one delay selection. */
423       if (property == _vpiDelaySelection) {
424 	    switch (vpip_delay_selection) {
425 		case _vpiDelaySelMinimum:
426 		  return simple_set_rbuf_str("MINIMUM");
427 		case _vpiDelaySelTypical:
428 		  return simple_set_rbuf_str("TYPICAL");
429 		case _vpiDelaySelMaximum:
430 		  return simple_set_rbuf_str("MAXIMUM");
431 		default:
432 		  assert(0);
433 	    }
434       }
435 
436       if (ref == 0) {
437 	    fprintf(stderr, "vpi error: vpi_get_str(%s, 0) called "
438 		    "with null vpiHandle.\n", vpi_property_str(property));
439 	    return 0;
440       }
441 
442       if (property == vpiType) {
443 	    if (vpi_trace) {
444 		  fprintf(vpi_trace, "vpi_get(vpiType, %p) --> %s\n",
445 			  ref, vpi_type_values(ref->get_type_code()));
446 	    }
447 
448             PLI_INT32 type;
449 	    if (ref->get_type_code() == vpiMemory && is_net_array(ref))
450 		  type = vpiNetArray;
451 	    else
452 		  type = ref->get_type_code();
453 	    return (char *)vpi_type_values(type);
454       }
455 
456       char*res = ref->vpi_get_str(property);
457 
458       if (vpi_trace) {
459 	    fprintf(vpi_trace, "vpi_get_str(%s, %p) --> %s\n",
460 		    vpi_property_str(property), ref, res? res : "<NULL>");
461       }
462 
463       return res;
464 }
465 
vpip_time_units_from_handle(vpiHandle obj)466 int vpip_time_units_from_handle(vpiHandle obj)
467 {
468       struct __vpiSysTaskCall*task;
469       __vpiScope*scope;
470       struct __vpiSignal*signal;
471       __vpiNamedEvent*event;
472 
473       if (obj == 0)
474 	    return vpip_get_time_precision();
475 
476       switch (obj->get_type_code()) {
477 	  case vpiSysTaskCall:
478 	    task = dynamic_cast<__vpiSysTaskCall*>(obj);
479 	    return task->scope->time_units;
480 
481 	  case vpiModule:
482 	    scope = dynamic_cast<__vpiScope*>(obj);
483 	    return scope->time_units;
484 
485 	  case vpiNet:
486 	  case vpiReg:
487 	    signal = dynamic_cast<__vpiSignal*>(obj);
488 	    scope = vpip_scope(signal);
489 	    return scope->time_units;
490 
491 	  case vpiNamedEvent:
492 	    event = dynamic_cast<__vpiNamedEvent*>(obj);
493 	    scope = event->get_scope();
494 	    return scope->time_units;
495 
496 	  default:
497 	    fprintf(stderr, "ERROR: vpip_time_units_from_handle called with "
498 		    "object handle type=%u\n", obj->get_type_code());
499 	    assert(0);
500 	    return 0;
501       }
502 }
503 
vpip_time_precision_from_handle(vpiHandle obj)504 int vpip_time_precision_from_handle(vpiHandle obj)
505 {
506       struct __vpiSysTaskCall*task;
507       __vpiScope*scope;
508       struct __vpiSignal*signal;
509 
510       if (obj == 0)
511 	    return vpip_get_time_precision();
512 
513       switch (obj->get_type_code()) {
514 	  case vpiSysTaskCall:
515 	    task = dynamic_cast<__vpiSysTaskCall*>(obj);
516 	    return task->scope->time_precision;
517 
518 	  case vpiModule:
519 	    scope = dynamic_cast<__vpiScope*>(obj);
520 	    return scope->time_precision;
521 
522 	  case vpiNet:
523 	  case vpiReg:
524 	    signal = dynamic_cast<__vpiSignal*>(obj);
525 	    scope = vpip_scope(signal);
526 	    return scope->time_precision;
527 
528 	  default:
529 	    fprintf(stderr, "ERROR: vpip_time_precision_from_handle called "
530 		    "with object handle type=%u\n", obj->get_type_code());
531 	    assert(0);
532 	    return 0;
533       }
534 }
535 
vpi_get_time(vpiHandle obj,s_vpi_time * vp)536 void vpi_get_time(vpiHandle obj, s_vpi_time*vp)
537 {
538       int scale;
539       vvp_time64_t time;
540 
541       assert(vp);
542 
543       time = schedule_simtime();
544 
545       switch (vp->type) {
546           case vpiSimTime:
547 	    vp->high = (time >> 32) & 0xffffffff;
548 	    vp->low = time & 0xffffffff;
549 	    break;
550 
551           case vpiScaledRealTime:
552 	    scale = vpip_get_time_precision() -
553 	            vpip_time_units_from_handle(obj);
554 	    if (scale >= 0) vp->real = (double)time * pow(10.0, scale);
555 	    else vp->real = (double)time / pow(10.0, -scale);
556 	    break;
557 
558           default:
559             fprintf(stderr, "vpi_get_time: unknown type: %d\n", (int)vp->type);
560             assert(0);
561 	    break;
562       }
563 }
564 
vpi_get_vlog_info(p_vpi_vlog_info vlog_info_p)565 PLI_INT32 vpi_get_vlog_info(p_vpi_vlog_info vlog_info_p)
566 {
567     if (vlog_info_p != 0) {
568 	  *vlog_info_p = vpi_vlog_info;
569 	  return 1;
570     } else {
571 	  return 0;
572     }
573 }
574 
vpi_set_vlog_info(int argc,char ** argv)575 void vpi_set_vlog_info(int argc, char** argv)
576 {
577     static char icarus_product[] = "Icarus Verilog";
578     static char icarus_version[] = VERSION;
579     vpi_vlog_info.product = icarus_product;
580     vpi_vlog_info.version = icarus_version;
581     vpi_vlog_info.argc    = argc;
582     vpi_vlog_info.argv    = argv;
583 
584     static char trace_buf[1024];
585     if (const char*path = getenv("VPI_TRACE"))  {
586 	  if (!strcmp(path,"-"))
587 		vpi_trace = stdout;
588 	  else {
589 		vpi_trace = fopen(path, "w");
590 		if (!vpi_trace) {
591 		      perror(path);
592 		      exit(1);
593 		}
594 		setvbuf(vpi_trace, trace_buf, _IOLBF, sizeof(trace_buf));
595 	  }
596     }
597 }
598 
vec4_get_value_string(const vvp_vector4_t & word_val,unsigned width,s_vpi_value * vp)599 static void vec4_get_value_string(const vvp_vector4_t&word_val, unsigned width,
600 				  s_vpi_value*vp)
601 {
602       unsigned nchar = width / 8;
603       unsigned tail = width % 8;
604 
605       char*rbuf = (char *) need_result_buf(nchar + 1, RBUF_VAL);
606       char*cp = rbuf;
607 
608       if (tail > 0) {
609 	    char char_val = 0;
610 	    for (unsigned idx = width-tail; idx < width ;  idx += 1) {
611 		  vvp_bit4_t val = word_val.value(idx);
612 		  if (val == BIT4_1)
613 			char_val |= 1 << idx;
614 	    }
615 
616 	    if (char_val != 0)
617 		  *cp++ = char_val;
618       }
619 
620       for (unsigned idx = 0 ;  idx < nchar ;  idx += 1) {
621 	    unsigned bit = (nchar - idx - 1) * 8;
622 	    char char_val = 0;
623 	    for (unsigned bdx = 0 ;  bdx < 8 ;  bdx += 1) {
624 		  vvp_bit4_t val = word_val.value(bit+bdx);
625 		  if (val == BIT4_1)
626 			char_val |= 1 << bdx;
627 	    }
628 	    if (char_val != 0)
629 		  *cp++ = char_val;
630       }
631 
632       *cp = 0;
633       vp->value.str = rbuf;
634 }
635 
636 /*
637  * This is a generic function to convert a vvp_vector4_t value into a
638  * vpi_value structure. The format is selected by the format of the
639  * value pointer. The width is the real width of the word, in case the
640  * word_val width is not accurate.
641  */
vpip_vec4_get_value(const vvp_vector4_t & word_val,unsigned width,bool signed_flag,s_vpi_value * vp)642 void vpip_vec4_get_value(const vvp_vector4_t&word_val, unsigned width,
643 			 bool signed_flag, s_vpi_value*vp)
644 {
645       char *rbuf = 0;
646 
647       switch (vp->format) {
648 	  default:
649 	    fprintf(stderr, "sorry: Format %d not implemented for "
650 	                    "getting vector values.\n", (int)vp->format);
651 	    assert(0);
652 
653 	  case vpiSuppressVal:
654 	    break;
655 
656 	  case vpiBinStrVal:
657 	    rbuf = (char *) need_result_buf(width+1, RBUF_VAL);
658 	    for (unsigned idx = 0 ;  idx < width ;  idx += 1) {
659 		  vvp_bit4_t bit = word_val.value(idx);
660 		  rbuf[width-idx-1] = vvp_bit4_to_ascii(bit);
661 	    }
662 	    rbuf[width] = 0;
663 	    vp->value.str = rbuf;
664 	    break;
665 
666 	  case vpiOctStrVal: {
667 		unsigned hwid = ((width+2) / 3) + 1;
668 		rbuf = (char *) need_result_buf(hwid, RBUF_VAL);
669 		vpip_vec4_to_oct_str(word_val, rbuf, hwid);
670 		vp->value.str = rbuf;
671 		break;
672 	  }
673 
674 	  case vpiDecStrVal: {
675 // HERE need a better estimate.
676 		rbuf = (char *) need_result_buf(width+1, RBUF_VAL);
677 		vpip_vec4_to_dec_str(word_val, rbuf, width+1, signed_flag);
678 		vp->value.str = rbuf;
679 		break;
680 	  }
681 
682 	  case vpiHexStrVal: {
683 		unsigned  hwid = ((width + 3) / 4) + 1;
684 		rbuf = (char *) need_result_buf(hwid, RBUF_VAL);
685 		vpip_vec4_to_hex_str(word_val, rbuf, hwid);
686 		vp->value.str = rbuf;
687 		break;
688 	  }
689 
690           case vpiScalarVal: {
691 	        // scalars should be of size 1
692 	        assert(width == 1);
693 	        switch(word_val.value(0)) {
694 		    case BIT4_0:
695 		      vp->value.scalar = vpi0;
696 		      break;
697 	            case BIT4_1:
698                       vp->value.scalar = vpi1;
699                       break;
700 	            case BIT4_X:
701                       vp->value.scalar = vpiX;
702                       break;
703 	            case BIT4_Z:
704                       vp->value.scalar = vpiZ;
705                       break;
706 		}
707                 break;
708           }
709 
710 	  case vpiIntVal: {
711 		long val = 0;
712 		vvp_bit4_t pad = BIT4_0;
713 		if (signed_flag && word_val.size() > 0)
714 		      pad = word_val.value(word_val.size()-1);
715 
716 		for (unsigned idx = 0 ; idx < 8*sizeof(val) ;  idx += 1) {
717 		      vvp_bit4_t val4 = pad;
718 		      if (idx < word_val.size())
719 			    val4 = word_val.value(idx);
720 		      if (val4 == BIT4_1)
721 			    val |= 1L << idx;
722 		}
723 
724 		vp->value.integer = val;
725 		break;
726 	  }
727 
728 	  case vpiObjTypeVal:
729 	    // Use the following case to actually set the value!
730 	    vp->format = vpiVectorVal;
731 	    // fallthrough
732 	  case vpiVectorVal: {
733 		unsigned hwid = (width + 31)/32;
734 
735 		s_vpi_vecval *op = (p_vpi_vecval)
736 			need_result_buf(hwid * sizeof(s_vpi_vecval), RBUF_VAL);
737 		vp->value.vector = op;
738 
739 		op->aval = op->bval = 0;
740 		for (unsigned idx = 0 ;  idx < width ;  idx += 1) {
741 		      switch (word_val.value(idx)) {
742 			  case BIT4_0:
743 			    op->aval &= ~(1 << idx % 32);
744 			    op->bval &= ~(1 << idx % 32);
745 			    break;
746 			  case BIT4_1:
747 			    op->aval |=  (1 << idx % 32);
748 			    op->bval &= ~(1 << idx % 32);
749 			    break;
750 			  case BIT4_X:
751 			    op->aval |= (1 << idx % 32);
752 			    op->bval |= (1 << idx % 32);
753 			    break;
754 			  case BIT4_Z:
755 			    op->aval &= ~(1 << idx % 32);
756 			    op->bval |=  (1 << idx % 32);
757 			    break;
758 		      }
759 		      if (!((idx+1) % 32) && (idx+1 < width)) {
760 			    op++;
761 			    op->aval = op->bval = 0;
762 		      }
763 		}
764 		break;
765 	  }
766 
767 	  case vpiStringVal:
768 		vec4_get_value_string(word_val, width, vp);
769 		break;
770 
771 	  case vpiRealVal:
772 		vector4_to_value(word_val, vp->value.real, signed_flag);
773 		break;
774       }
775 }
776 
vpip_vec2_get_value(const vvp_vector2_t & word_val,unsigned width,bool signed_flag,s_vpi_value * vp)777 void vpip_vec2_get_value(const vvp_vector2_t&word_val, unsigned width,
778 			 bool signed_flag, s_vpi_value*vp)
779 {
780       switch (vp->format) {
781 	  default:
782 	    fprintf(stderr, "sorry: Format %d not implemented for "
783 	                    "getting vector2 values.\n", (int)vp->format);
784 	    assert(0);
785 
786 	  case vpiSuppressVal:
787 	    break;
788 
789 	  case vpiObjTypeVal:
790 	    vp->format = vpiIntVal;
791 	    // fallthrough
792 	  case vpiIntVal:
793 	    vector2_to_value(word_val, vp->value.integer, signed_flag);
794 	    break;
795 
796 	  case vpiVectorVal: {
797 		unsigned hwid = (width + 31)/32;
798 
799 		s_vpi_vecval *op = (p_vpi_vecval)
800 			need_result_buf(hwid * sizeof(s_vpi_vecval), RBUF_VAL);
801 		vp->value.vector = op;
802 
803 		op->aval = op->bval = 0;
804 		for (unsigned idx = 0 ;  idx < width ;  idx += 1) {
805 		      if (word_val.value(idx)) {
806 			    op->aval |=  (1 << idx % 32);
807 			    op->bval &= ~(1 << idx % 32);
808 		      } else {
809 			    op->aval &= ~(1 << idx % 32);
810 			    op->bval &= ~(1 << idx % 32);
811 		      }
812 		      if (!((idx+1) % 32) && (idx+1 < width)) {
813 			    op++;
814 			    op->aval = op->bval = 0;
815 		      }
816 		}
817 		break;
818 	  }
819       }
820 
821 }
822 
823 /*
824  * Convert a real value to the appropriate integer.
825  */
get_real_as_int(double real)826 static PLI_INT32 get_real_as_int(double real)
827 {
828       double rtn;
829 
830 	/* We would normally want to return 'bx for a NaN or
831 	 * +/- infinity, but for an integer the standard says
832 	 * to convert 'bx to 0, so we just return 0. */
833       if (real != real || (real && (real == 0.5*real))) {
834 	    return 0;
835       }
836 
837 	/* Round away from zero. */
838       if (real >= 0.0) {
839 	    rtn = floor(real);
840 	    if (real >= (rtn + 0.5)) rtn += 1.0;
841       } else {
842 	    rtn = ceil(real);
843 	    if (real <= (rtn - 0.5)) rtn -= 1.0;
844       }
845 
846       return (PLI_INT32) rtn;
847 }
848 
849 /*
850  * This is a generic function to convert a double value into a
851  * vpi_value structure. The format is selected by the format of the
852  * value pointer.
853  */
vpip_real_get_value(double real,s_vpi_value * vp)854 void vpip_real_get_value(double real, s_vpi_value*vp)
855 {
856       char *rbuf = 0;
857 
858       switch (vp->format) {
859 	  default:
860 	    fprintf(stderr, "sorry: Format %d not implemented for "
861 	                    "getting real values.\n", (int)vp->format);
862 	    assert(0);
863 
864 	  case vpiSuppressVal:
865 	    break;
866 
867 	  case vpiObjTypeVal:
868 	    // Use the following case to actually set the value!
869 	    vp->format = vpiRealVal;
870 	    // fallthrough
871 	  case vpiRealVal:
872 	    vp->value.real = real;
873 	    break;
874 
875 	  case vpiIntVal:
876 	    vp->value.integer = get_real_as_int(real);
877 	    break;
878 
879 	  case vpiDecStrVal:
880 	    rbuf = (char *) need_result_buf(1025, RBUF_VAL);
881 	    vpip_vec4_to_dec_str(vvp_vector4_t(1024, real), rbuf, 1025, true);
882 	    vp->value.str = rbuf;
883 	    break;
884       }
885 }
886 
real_from_vpi_value(s_vpi_value * vp)887 double real_from_vpi_value(s_vpi_value*vp)
888 {
889       vvp_vector4_t vec4(1024);
890       double result;
891       bool is_signed = false;
892 
893       switch (vp->format) {
894 	  default:
895 	    fprintf(stderr, "sorry: Format %d not implemented for "
896 	                    "putting real values.\n", (int)vp->format);
897 	    assert(0);
898 
899 	  case vpiRealVal:
900 	    result = vp->value.real;
901 	    break;
902 
903 	  case vpiIntVal:
904 	    result = (double) vp->value.integer;
905 	    break;
906 
907 	  case vpiBinStrVal:
908 	    vpip_bin_str_to_vec4(vec4, vp->value.str);
909 	    if (vp->value.str[0] == '-') is_signed = true;
910 	    vector4_to_value(vec4, result, is_signed);
911 	    break;
912 
913 	  case vpiOctStrVal:
914 	    vpip_oct_str_to_vec4(vec4, vp->value.str);
915 	    if (vp->value.str[0] == '-') is_signed = true;
916 	    vector4_to_value(vec4, result, is_signed);
917 	    break;
918 
919 	  case vpiDecStrVal:
920 	    vpip_dec_str_to_vec4(vec4, vp->value.str);
921 	    if (vp->value.str[0] == '-') is_signed = true;
922 	    vector4_to_value(vec4, result, is_signed);
923 	    break;
924 
925 	  case vpiHexStrVal:
926 	    vpip_hex_str_to_vec4(vec4, vp->value.str);
927 	    if (vp->value.str[0] == '-') is_signed = true;
928 	    vector4_to_value(vec4, result, is_signed);
929 	    break;
930 
931       }
932 
933       return result;
934 }
935 
vpip_string_get_value(const string & val,s_vpi_value * vp)936 void vpip_string_get_value(const string&val, s_vpi_value*vp)
937 {
938       char *rbuf = 0;
939 
940       switch (vp->format) {
941 	  default:
942 	    fprintf(stderr, "sorry: Format %d not implemented for "
943 	                    "getting string values.\n", (int)vp->format);
944 	    assert(0);
945 
946 	  case vpiSuppressVal:
947 	    break;
948 
949 	  case vpiObjTypeVal:
950 	    // Use the following case to actually set the value!
951 	    vp->format = vpiStringVal;
952 	    // fallthrough
953 	  case vpiStringVal:
954 	    rbuf = (char *) need_result_buf(val.size() + 1, RBUF_VAL);
955 	    strcpy(rbuf, val.c_str());
956 	    vp->value.str = rbuf;
957 	    break;
958       }
959 }
960 
961 
vpi_get_value(vpiHandle expr,s_vpi_value * vp)962 void vpi_get_value(vpiHandle expr, s_vpi_value*vp)
963 {
964       assert(expr);
965       assert(vp);
966 
967 	// Never bother with suppressed values. All the derived
968 	// classes can ignore this type.
969       if (vp->format == vpiSuppressVal)
970 	    return;
971 
972       expr->vpi_get_value(vp);
973 
974       if (vpi_trace) switch (vp->format) {
975 		case vpiStringVal:
976 		  fprintf(vpi_trace,"vpi_get_value(%p=<%d>) -> string=\"%s\"\n",
977 			  expr, expr->get_type_code(), vp->value.str);
978 		  break;
979 
980 		case vpiBinStrVal:
981 		  fprintf(vpi_trace, "vpi_get_value(<%d>...) -> binstr=%s\n",
982 			  expr->get_type_code(), vp->value.str);
983 		  break;
984 
985 		case vpiIntVal:
986 		  fprintf(vpi_trace, "vpi_get_value(<%d>...) -> int=%d\n",
987 			  expr->get_type_code(), (int)vp->value.integer);
988 		  break;
989 
990 		case vpiSuppressVal:
991 		  fprintf(vpi_trace, "vpi_get_value(<%d>...) -> <suppress>\n",
992 			  expr->get_type_code());
993 		  break;
994 
995 		default:
996 		  fprintf(vpi_trace, "vpi_get_value(<%d>...) -> <%d>=?\n",
997 			  expr->get_type_code(), (int)vp->format);
998 	    }
999 }
1000 
1001 struct vpip_put_value_event : vvp_gen_event_s {
1002       vpiHandle handle;
1003       s_vpi_value value;
1004       int flags;
1005       virtual void run_run();
~vpip_put_value_eventvpip_put_value_event1006       ~vpip_put_value_event() { }
1007 };
1008 
run_run()1009 void vpip_put_value_event::run_run()
1010 {
1011       handle->vpi_put_value(&value, flags);
1012       switch (value.format) {
1013 	    /* Free the copied string. */
1014 	  case vpiBinStrVal:
1015 	  case vpiOctStrVal:
1016 	  case vpiDecStrVal:
1017 	  case vpiHexStrVal:
1018 	  case vpiStringVal:
1019 	    free(value.value.str);
1020 	    break;
1021 	    /* Free the copied time structure. */
1022 	  case vpiTimeVal:
1023 	    free(value.value.time);
1024 	    break;
1025 	    /* Free the copied vector structure. */
1026 	  case vpiVectorVal:
1027 	    free(value.value.vector);
1028 	    break;
1029 	    /* Free the copied strength structure. */
1030 	  case vpiStrengthVal:
1031 	    free(value.value.strength);
1032 	    break;
1033 	    /* Everything else is static in the structure. */
1034 	  default:
1035 	    break;
1036       }
1037 }
1038 
1039 /* Make a copy of a pointer to a time structure. */
timedup(t_vpi_time * val)1040 static t_vpi_time *timedup(t_vpi_time *val)
1041 {
1042       t_vpi_time *rtn;
1043       rtn = static_cast<t_vpi_time *> (malloc(sizeof(t_vpi_time)));
1044       *rtn = *val;
1045       return rtn;
1046 }
1047 
1048 /* Make a copy of a pointer to a vector value structure. */
vectordup(t_vpi_vecval * val,PLI_INT32 size)1049 static t_vpi_vecval *vectordup(t_vpi_vecval *val, PLI_INT32 size)
1050 {
1051       unsigned num_bytes;
1052       t_vpi_vecval *rtn;
1053       assert(size > 0);
1054       num_bytes = ((size + 31)/32)*sizeof(t_vpi_vecval);
1055       rtn = static_cast<t_vpi_vecval *> (malloc(num_bytes));
1056       memcpy(rtn, val, num_bytes);
1057       return rtn;
1058 }
1059 
1060 /* Make a copy of a pointer to a strength structure. */
strengthdup(t_vpi_strengthval * val)1061 static t_vpi_strengthval *strengthdup(t_vpi_strengthval *val)
1062 {
1063       t_vpi_strengthval *rtn;
1064       rtn = static_cast<t_vpi_strengthval *>
1065             (malloc(sizeof(t_vpi_strengthval)));
1066       *rtn = *val;
1067       return rtn;
1068 }
1069 
vpi_put_value(vpiHandle obj,s_vpi_value * vp,s_vpi_time * when,PLI_INT32 flags)1070 vpiHandle vpi_put_value(vpiHandle obj, s_vpi_value*vp,
1071 			s_vpi_time*when, PLI_INT32 flags)
1072 {
1073       assert(obj);
1074 
1075       flags &= ~vpiReturnEvent;
1076 
1077       if (flags!=vpiNoDelay && flags!=vpiForceFlag && flags!=vpiReleaseFlag) {
1078 	    vvp_time64_t dly;
1079 	    int scale;
1080 
1081 	    if (vpi_get(vpiAutomatic, obj)) {
1082 		  fprintf(stderr, "VPI error: cannot put a value with "
1083 				  "a delay on automatically allocated "
1084 				  "variable '%s'.\n",
1085 				  vpi_get_str(vpiName, obj));
1086 		  return 0;
1087 	    }
1088 
1089 	    assert(when != 0);
1090 
1091 	    switch (when->type) {
1092 		case vpiScaledRealTime:
1093 		  scale = vpip_time_units_from_handle(obj) -
1094 		          vpip_get_time_precision();
1095 		  if (scale >= 0) {
1096 			dly = (vvp_time64_t)(when->real * pow(10.0, scale));
1097 		  } else {
1098 			dly = (vvp_time64_t)(when->real / pow(10.0, -scale));
1099 		  }
1100 		  break;
1101 		case vpiSimTime:
1102 		  dly = vpip_timestruct_to_time(when);
1103 		  break;
1104 		default:
1105 		  dly = 0;
1106 		  break;
1107 	    }
1108 
1109 	    if ((dly == 0) && schedule_at_rosync()) {
1110 		  fprintf(stderr, "VPI error: attempted to put a value to "
1111 				  "variable '%s' during a read-only synch "
1112 				  "callback.\n", vpi_get_str(vpiName, obj));
1113 		  return 0;
1114 	    }
1115 
1116 	    vpip_put_value_event*put = new vpip_put_value_event;
1117 	    put->handle = obj;
1118 	    if (dynamic_cast<__vpiNamedEvent*>(obj)) {
1119 		  put->value.format = vpiIntVal;
1120 		  put->value.value.integer = 0;
1121 	    } else {
1122 		  assert(vp);
1123 		  put->value = *vp;
1124 	    }
1125 	      /* Since this is a scheduled put event we must copy any pointer
1126 	       * data to keep it available until the event is actually run. */
1127 	    switch (put->value.format) {
1128 		  /* Copy the string items. */
1129 		case vpiBinStrVal:
1130 		case vpiOctStrVal:
1131 		case vpiDecStrVal:
1132 		case vpiHexStrVal:
1133 		case vpiStringVal:
1134 		  put->value.value.str = strdup(put->value.value.str);
1135 		  break;
1136 		  /* Copy a time pointer item. */
1137 		case vpiTimeVal:
1138 		  put->value.value.time = timedup(put->value.value.time);
1139 		  break;
1140 		  /* Copy a vector pointer item. */
1141 		case vpiVectorVal:
1142 		  put->value.value.vector = vectordup(put->value.value.vector,
1143 		                                      vpi_get(vpiSize, obj));
1144 		  break;
1145 		  /* Copy a strength pointer item. */
1146 		case vpiStrengthVal:
1147 		  put->value.value.strength =
1148 		      strengthdup(put->value.value.strength);
1149 		  break;
1150 		  /* Everything thing else is already in the structure. */
1151 		default:
1152 		  break;
1153 	    }
1154 	    put->flags = flags;
1155 	    schedule_generic(put, dly, false, true, true);
1156 	    return 0;
1157       }
1158 
1159       if (schedule_at_rosync()) {
1160             fprintf(stderr, "VPI error: attempted to put a value to "
1161 			    "variable '%s' during a read-only synch "
1162 			    "callback.\n", vpi_get_str(vpiName, obj));
1163             return 0;
1164       }
1165 
1166       obj->vpi_put_value(vp, flags);
1167 
1168       return 0;
1169 }
1170 
vpi_handle(PLI_INT32 type,vpiHandle ref)1171 vpiHandle vpi_handle(PLI_INT32 type, vpiHandle ref)
1172 {
1173       vpiHandle res = 0;
1174 
1175       if (ref == 0) {
1176 	      // A few types can apply to a nil handle. These are ways
1177 	      // that the current function can get started finding things.
1178 	    switch (type) {
1179 
1180 		case vpiScope:
1181 		    // The IEEE1364-2005 doesn't seem to allow this,
1182 		    // but some users seem to think it's handy, so
1183 		    // return the scope that contains this SysTfCall.
1184 		  assert(vpip_cur_task);
1185 		  res = vpip_cur_task->vpi_handle(vpiScope);
1186 		  break;
1187 
1188 		case vpiSysTfCall:
1189 		    // This is how VPI users get a first handle into
1190 		    // the system. This is the handle of the system
1191 		    // task/function call currently being executed.
1192 		  if (vpi_trace) {
1193 			fprintf(vpi_trace, "vpi_handle(vpiSysTfCall, 0) "
1194 				"-> %p (%s)\n", vpip_cur_task,
1195 				vpip_cur_task->defn->info.tfname);
1196 		  }
1197 		  return vpip_cur_task;
1198 
1199 		default:
1200 		  fprintf(stderr, "VPI error: vpi_handle(type=%d, ref=0).\n",
1201 			  (int)type);
1202 		  res = 0;
1203 		  break;
1204 	    }
1205 
1206       } else {
1207 
1208 	    if (type == vpiSysTfCall) {
1209 		  fprintf(stderr, "VPI error: vpi_handle(vpiSysTfCall, "
1210 			  "ref!=0).\n");
1211 		  return 0;
1212 	    }
1213 
1214 	    res = ref->vpi_handle(type);
1215       }
1216 
1217 
1218       if (vpi_trace) {
1219 	    fprintf(vpi_trace, "vpi_handle(vpiScope, ref=%p) "
1220 		    "-> %p\n", vpip_cur_task, ref);
1221       }
1222 
1223       return res;
1224 }
1225 
vpip_make_udp_iterator()1226 static vpiHandle vpip_make_udp_iterator()
1227 {
1228 // HERE: Add support for iterating over UDP definitions.
1229 //       See 26.6.16 (page 400 in 1364-2005).
1230       return 0;
1231 }
1232 
1233 /*
1234  * This function asks the object to return an iterator for
1235  * the specified reference. It is up to the iterate_ method to
1236  * allocate a properly formed iterator.
1237  */
vpi_iterate_global(int type)1238 static vpiHandle vpi_iterate_global(int type)
1239 {
1240       switch (type) {
1241 	  case vpiModule:
1242 	    return vpip_make_root_iterator();
1243 
1244 	  case vpiUdpDefn:
1245 	    return vpip_make_udp_iterator();
1246 
1247 	  case vpiUserSystf:
1248 	    return vpip_make_systf_iterator();
1249       }
1250 
1251       return 0;
1252 }
1253 
vpi_iterate(PLI_INT32 type,vpiHandle ref)1254 vpiHandle vpi_iterate(PLI_INT32 type, vpiHandle ref)
1255 {
1256       vpiHandle rtn = 0;
1257 
1258       assert(vpi_mode_flag != VPI_MODE_NONE);
1259       if (vpi_mode_flag == VPI_MODE_REGISTER) {
1260 	    fprintf(stderr, "vpi error: vpi_iterate called during "
1261 		    "vpi_register_systf. You can't do that!\n");
1262 	    return 0;
1263       }
1264 
1265       if (ref == 0)
1266 	    rtn = vpi_iterate_global(type);
1267       else
1268 	    rtn = ref->vpi_iterate(type);
1269 
1270       if (vpi_trace) {
1271 	    fprintf(vpi_trace, "vpi_iterate(%d, %p) ->%s\n",
1272 	    (int)type, ref, rtn ? "" : " (null)");
1273       }
1274 
1275       return rtn;
1276 }
1277 
vpi_handle_by_index(vpiHandle ref,PLI_INT32 idx)1278 vpiHandle vpi_handle_by_index(vpiHandle ref, PLI_INT32 idx)
1279 {
1280       assert(ref);
1281       return ref->vpi_index(idx);
1282 }
1283 
find_name(const char * name,vpiHandle handle)1284 static vpiHandle find_name(const char *name, vpiHandle handle)
1285 {
1286       vpiHandle rtn = 0;
1287       __vpiScope*ref = dynamic_cast<__vpiScope*>(handle);
1288 
1289       /* check module names */
1290       if (!strcmp(name, vpi_get_str(vpiName, handle)))
1291 	    rtn = handle;
1292 
1293       /* brute force search for the name in all objects in this scope */
1294       for (unsigned i = 0 ;  i < ref->intern.size() ;  i += 1) {
1295 	      /* The standard says that since a port does not have a full
1296 	       * name it cannot be found by name. Because of this we need
1297 	       * to skip ports here so the correct handle can be located. */
1298 	    if (vpi_get(vpiType, ref->intern[i]) == vpiPort) continue;
1299 	    char *nm = vpi_get_str(vpiName, ref->intern[i]);
1300 	    if (nm && !strcmp(name, nm)) {
1301 		  rtn = ref->intern[i];
1302 		  break;
1303 	    } else if (vpi_get(vpiType, ref->intern[i]) == vpiMemory ||
1304 	               vpi_get(vpiType, ref->intern[i]) == vpiNetArray) {
1305 		  /* We need to iterate on the words */
1306 		  vpiHandle word_i, word_h;
1307 		  word_i = vpi_iterate(vpiMemoryWord, ref->intern[i]);
1308 		  while (word_i && (word_h = vpi_scan(word_i))) {
1309 			nm = vpi_get_str(vpiName, word_h);
1310 			if (nm && !strcmp(name, nm)) {
1311 			      rtn = word_h;
1312 			      vpi_free_object(word_i);
1313 			      break;
1314 			}
1315 		  }
1316 	    }
1317 	    /* found it yet? */
1318 	    if (rtn) break;
1319       }
1320 
1321       return rtn;
1322 }
1323 
1324 // Find the end of the escaped identifier or simple identifier
find_rest(char * name)1325 static char * find_rest(char *name)
1326 {
1327       char *rest;
1328       if (*name == '\\') {
1329 	    rest = strchr(name, ' ');
1330 	    if (rest) {
1331 		  *rest++ = 0; // The space is not part of the string
1332 		    // There should be a '.' after the escaped ID if there is
1333 		    // anything more. If it is missing add it to avoid a crash
1334 		  if ((*rest != '.') && (*rest != 0)) {
1335 			*--rest = '.';
1336 			fprintf(stderr, "ERROR: Malformed scope string: \"%s\"", name);
1337 		  }
1338 		  if (*rest == 0) {
1339 			rest = 0;
1340 		  }
1341 	    }
1342       } else {
1343 	    rest = strchr(name, '.');
1344       }
1345       return rest;
1346 }
1347 
find_scope(const char * name,vpiHandle handle,int depth)1348 static vpiHandle find_scope(const char *name, vpiHandle handle, int depth)
1349 {
1350 
1351       vpiHandle iter = handle==0
1352 	    ? vpi_iterate(vpiModule, NULL)
1353 	    : vpi_iterate(vpiInternalScope, handle);
1354 
1355       vector<char> name_buf (strlen(name)+1);
1356       strcpy(&name_buf[0], name);
1357       char*nm_first = &name_buf[0];
1358       char*nm_rest = find_rest(nm_first);
1359       if (*nm_first == '\\') ++nm_first;
1360       if (nm_rest) {
1361 	    *nm_rest++ = 0;
1362       }
1363 
1364       vpiHandle rtn = 0;
1365       vpiHandle hand;
1366       while (iter && (hand = vpi_scan(iter))) {
1367 	    char *nm = vpi_get_str(vpiName, hand);
1368 
1369 	    if (strcmp(nm_first,nm)==0) {
1370 		  if (nm_rest)
1371 			rtn=find_scope(nm_rest, hand, depth+1);
1372 		  else
1373 			rtn = hand;
1374 	    }
1375 
1376 	    /* found it yet ? */
1377 	    if (rtn) {
1378 		  vpi_free_object(iter);
1379 		  break;
1380 	    }
1381       }
1382 
1383       return rtn;
1384 }
1385 
1386 // Find the end of the first escaped identifier or simple identifier
find_next(char * name)1387 static char * find_next(char *name)
1388 {
1389       char *next;
1390       if (*name == '\\') {
1391 	    next = strchr(name, ' ');
1392 	    if (next && *++next == 0) next = 0;
1393       } else {
1394 	    next = strchr(name, '.');
1395       }
1396       return next;
1397 }
1398 
vpi_handle_by_name(const char * name,vpiHandle scope)1399 vpiHandle vpi_handle_by_name(const char *name, vpiHandle scope)
1400 {
1401       vpiHandle hand;
1402 
1403       if (vpi_trace) {
1404 	    fprintf(vpi_trace, "vpi_handle_by_name(%s, %p) -->\n",
1405 		    name, scope);
1406       }
1407 
1408 	// Chop the name into path and base. For example, if the name
1409 	// is "a.b.c", then nm_path becomes "a.b" and nm_base becomes
1410 	// "c". If the name is "c" then nm_path is nil and nm_base is "c".
1411       vector<char> name_buf (strlen(name)+1);
1412       strcpy(&name_buf[0], name);
1413       char*nm_path = &name_buf[0];
1414       char*nm_base;
1415 
1416 	// Check to see if we have an escaped identifier and if so search
1417 	// the long way because a '.' could be in the escaped name.
1418       if (strchr(nm_path, '\\')) {
1419 	    char *next;
1420 	    nm_base = nm_path;
1421 	    while ((next = find_next(nm_base))) {
1422 		  nm_base = ++next;
1423 	    }
1424 	    if (nm_path == nm_base) {
1425 		  nm_path = 0;
1426 	    } else {
1427 		  *(nm_base-1) = 0;
1428 	    }
1429 
1430 	    if (*nm_base == '\\') {
1431 		    // Skip the \ at the beginning
1432 		  ++nm_base;
1433 
1434 		    // Drop the space at the end if it exists
1435 		  if ((next = strchr(nm_base, ' '))) {
1436 			*next = 0;
1437 		  }
1438 	    }
1439 
1440 	// If there is no escaped identifier then just look for the last '.'
1441       } else {
1442 	    nm_base = strrchr(nm_path, '.');
1443 	    if (nm_base) {
1444 		  *nm_base++ = 0;
1445 	    } else {
1446 		  nm_base = nm_path;
1447 		  nm_path = 0;
1448 	    }
1449       }
1450 
1451       /* If scope provided, look in corresponding module; otherwise
1452        * traverse the hierarchy specified in name to find the leaf module
1453        * and try finding it there.
1454        */
1455       if (scope) {
1456 	    /* Some implementations support either a module or a scope. */
1457 	    switch (vpi_get(vpiType, scope)) {
1458 		case vpiScope:
1459 	          hand = vpi_handle(vpiModule, scope);
1460 	          break;
1461 		case vpiModule:
1462 	          hand = scope;
1463 	          break;
1464 		default:
1465 		  if (vpi_trace) {
1466 			fprintf(vpi_trace, "vpi_handle_by_name: "
1467 				"Scope is not a vpiScope or vpiModule\n");
1468 		  }
1469 	          // Use vpi_chk_error() here when it is implemented.
1470 	          return 0;
1471 	    }
1472 
1473       } else if (nm_path) {
1474 	      // The name has a path, and no other scope handle was
1475 	      // passed in. That suggests we are looking for "a.b.c"
1476 	      // in the root scope. So convert "a.b" to a scope and
1477 	      // start there to look for "c".
1478 	    hand = find_scope(nm_path, NULL, 0);
1479 	    nm_path = 0;
1480 
1481       } else {
1482 	      // Special case: scope==<nil>, meaning we are looking in
1483 	      // the root, and there is no path to the name, i.e. the
1484 	      // string is "c" instead of "top.c". Try to find "c" as
1485 	      // a scope and return that.
1486 	    hand = find_scope(nm_base, NULL, 0);
1487       }
1488 
1489       if (hand == 0) {
1490 	    if (vpi_trace) {
1491 		  fprintf(vpi_trace, "vpi_handle_by_name: "
1492 			  "Scope does not exist. Giving up.\n");
1493 	    }
1494 
1495 	    return 0;
1496       }
1497 
1498 	// If there is a path part, then use it to find the
1499 	// scope. For example, if the full name is a.b.c, then
1500 	// the nm_path string is a.b and we search for that
1501 	// scope. If we find it, then set hand to that scope.
1502       if (nm_path) {
1503 	    vpiHandle tmp = find_scope(nm_path, hand, 0);
1504 	    while (tmp == 0 && hand != 0) {
1505 		  hand = vpi_handle(vpiScope, hand);
1506 		  tmp = find_scope(nm_path, hand, 0);
1507 	    }
1508 	    hand = tmp;
1509       }
1510 
1511 	// Now we have the correct scope, look for the item.
1512       vpiHandle out = find_name(nm_base, hand);
1513 
1514       if (vpi_trace) {
1515 	    fprintf(vpi_trace, "vpi_handle_by_name: DONE\n");
1516       }
1517 
1518       return out;
1519 }
1520 
1521 
1522 /*
1523   We increment the two vpi methods to enable the
1524   read/write of SDF delay values from/into
1525   the modpath vpiHandle
1526 
1527 
1528   basically, they will redirect the generic vpi_interface
1529 
1530   vpi_get_delay ( .. )
1531   vpi_put_delay ( .. )
1532 
1533 
1534   to the
1535 
1536   modpath_get_delay ( .. ) ;
1537   modpath_put_delay ( .. ) ;
1538 
1539 */
1540 
1541 
1542 
vpi_get_delays(vpiHandle expr,p_vpi_delay delays)1543 void vpi_get_delays(vpiHandle expr, p_vpi_delay delays)
1544 {
1545       assert(expr);
1546       assert(delays);
1547 
1548       expr->vpi_get_delays(delays);
1549 
1550       if (vpi_trace) {
1551 	    fprintf(vpi_trace,
1552 		    "vpi_get_delays(%p, %p) -->\n", expr, delays);
1553       }
1554 }
1555 
1556 
vpi_put_delays(vpiHandle expr,p_vpi_delay delays)1557 void vpi_put_delays(vpiHandle expr, p_vpi_delay delays)
1558 {
1559       assert(expr  );
1560       assert(delays );
1561 
1562       expr->vpi_put_delays(delays);
1563 
1564       if (vpi_trace) {
1565 	    fprintf(vpi_trace,
1566 		    "vpi_put_delays(%p, %p) -->\n", expr, delays);
1567       }
1568 }
1569 
1570 
1571 
1572 
1573 
1574 
1575 
1576 
vpi_vprintf(const char * fmt,va_list ap)1577 extern "C" PLI_INT32 vpi_vprintf(const char*fmt, va_list ap)
1578 {
1579       return vpi_mcd_vprintf(1, fmt, ap);
1580 }
1581 
vpi_printf(const char * fmt,...)1582 extern "C" PLI_INT32 vpi_printf(const char *fmt, ...)
1583 {
1584       va_list ap;
1585       va_start(ap, fmt);
1586       int r = vpi_mcd_vprintf(1, fmt, ap);
1587       va_end(ap);
1588       return r;
1589 }
1590 
vpi_flush(void)1591 extern "C" PLI_INT32 vpi_flush(void)
1592 {
1593       return vpi_mcd_flush(1);
1594 }
1595 
1596 
vpi_sim_vcontrol(int operation,va_list ap)1597 extern "C" void vpi_sim_vcontrol(int operation, va_list ap)
1598 {
1599       long diag_msg;
1600 
1601       switch (operation) {
1602 	  case vpiFinish:
1603 	  case __ivl_legacy_vpiFinish:
1604             diag_msg = va_arg(ap, long);
1605 	    schedule_finish(diag_msg);
1606 	    break;
1607 
1608 	  case vpiStop:
1609 	  case __ivl_legacy_vpiStop:
1610             diag_msg = va_arg(ap, long);
1611 	    schedule_stop(diag_msg);
1612 	    break;
1613 
1614 	  default:
1615 	    fprintf(stderr, "Unsupported operation %d.\n", operation);
1616 	    assert(0);
1617       }
1618 }
1619 
vpi_sim_control(PLI_INT32 operation,...)1620 extern "C" void vpi_sim_control(PLI_INT32 operation, ...)
1621 {
1622       va_list ap;
1623       va_start(ap, operation);
1624       vpi_sim_vcontrol(operation, ap);
1625       va_end(ap);
1626 }
1627 
vpi_control(PLI_INT32 operation,...)1628 extern "C" void vpi_control(PLI_INT32 operation, ...)
1629 {
1630       va_list ap;
1631       va_start(ap, operation);
1632       vpi_sim_vcontrol(operation, ap);
1633       va_end(ap);
1634 }
1635 
1636 /*
1637  * This routine calculated the return value for $clog2.
1638  * It is easier to do it here vs trying to to use the VPI interface.
1639  */
vpip_calc_clog2(vpiHandle arg)1640 extern "C" s_vpi_vecval vpip_calc_clog2(vpiHandle arg)
1641 {
1642       s_vpi_vecval rtn;
1643       s_vpi_value val;
1644       vvp_vector4_t vec4;
1645       bool is_neg = false;  // At this point only a real can be negative.
1646 
1647 	/* Get the value as a vvp_vector4_t. */
1648       val.format = vpiObjTypeVal;
1649       vpi_get_value(arg, &val);
1650       if (val.format == vpiRealVal) {
1651 	    vpi_get_value(arg, &val);
1652 	      /* All double values can be represented in 1024 bits. */
1653 	    vec4 = vvp_vector4_t(1024, val.value.real);
1654 	    if (val.value.real < 0) is_neg = true;
1655       } else {
1656 	    val.format = vpiVectorVal;
1657 	    vpi_get_value(arg, &val);
1658 	    unsigned wid = vpi_get(vpiSize, arg);
1659 	    vec4 = vvp_vector4_t(wid, BIT4_0);
1660 	    for (unsigned idx=0; idx < wid; idx += 1) {
1661 		PLI_INT32 aval = val.value.vector[idx/32].aval;
1662 		PLI_INT32 bval = val.value.vector[idx/32].bval;
1663 		aval >>= idx % 32;
1664 		bval >>= idx % 32;
1665 		int bitmask = (aval&1) | ((bval<<1)&2);
1666 		vvp_bit4_t bit = scalar_to_bit4(bitmask);
1667 		vec4.set_bit(idx, bit);
1668 	    }
1669       }
1670 
1671       if (vec4.has_xz()) {
1672 	    rtn.aval = rtn.bval = 0xFFFFFFFFU;  /* Set to 'bx. */
1673 	    return rtn;
1674       }
1675 
1676       vvp_vector2_t vec2(vec4);
1677 
1678       if (is_neg) vec2.trim_neg(); /* This is a special trim! */
1679       else vec2.trim(); /* This makes less work shifting. */
1680 
1681 	/* Calculate the clog2 result. */
1682       PLI_INT32 res = 0;
1683       if (!vec2.is_zero()) {
1684 	    vec2 -= vvp_vector2_t(1, vec2.size());
1685 	    while(!vec2.is_zero()) {
1686 		  res += 1;
1687 		  vec2 >>= 1;
1688 	    }
1689       }
1690 
1691       rtn.aval = res;
1692       rtn.bval = 0;
1693       return rtn;
1694 }
1695 
1696 /*
1697  * This routine provides the information needed to implement $countdrivers.
1698  * It is done here for performance reasons - interrogating the drivers
1699  * individually via the VPI interface would be much slower.
1700  */
vpip_count_drivers(vpiHandle ref,unsigned idx,unsigned counts[4])1701 extern "C" void vpip_count_drivers(vpiHandle ref, unsigned idx,
1702                                    unsigned counts[4])
1703 {
1704       struct __vpiSignal*rfp = dynamic_cast<__vpiSignal*>(ref);
1705       assert(rfp);
1706       rfp->node->count_drivers(idx, counts);
1707 }
1708 
1709 #if defined(__MINGW32__) || defined (__CYGWIN__)
1710 vpip_routines_s vpi_routines = {
1711     .register_cb                = vpi_register_cb,
1712     .remove_cb                  = vpi_remove_cb,
1713     .register_systf             = vpi_register_systf,
1714     .get_systf_info             = vpi_get_systf_info,
1715     .handle_by_name             = vpi_handle_by_name,
1716     .handle_by_index            = vpi_handle_by_index,
1717     .handle                     = vpi_handle,
1718     .iterate                    = vpi_iterate,
1719     .scan                       = vpi_scan,
1720     .get                        = vpi_get,
1721     .get_str                    = vpi_get_str,
1722     .get_delays                 = vpi_get_delays,
1723     .put_delays                 = vpi_put_delays,
1724     .get_value                  = vpi_get_value,
1725     .put_value                  = vpi_put_value,
1726     .get_time                   = vpi_get_time,
1727     .get_userdata               = vpi_get_userdata,
1728     .put_userdata               = vpi_put_userdata,
1729     .mcd_open                   = vpi_mcd_open,
1730     .mcd_close                  = vpi_mcd_close,
1731     .mcd_flush                  = vpi_mcd_flush,
1732     .mcd_name                   = vpi_mcd_name,
1733     .mcd_vprintf                = vpi_mcd_vprintf,
1734     .flush                      = vpi_flush,
1735     .vprintf                    = vpi_vprintf,
1736     .chk_error                  = vpi_chk_error,
1737     .compare_objects            = vpi_compare_objects,
1738     .free_object                = vpi_free_object,
1739     .get_vlog_info              = vpi_get_vlog_info,
1740     .vcontrol                   = vpi_sim_vcontrol,
1741     .fopen                      = vpi_fopen,
1742     .get_file                   = vpi_get_file,
1743     .calc_clog2                 = vpip_calc_clog2,
1744     .count_drivers              = vpip_count_drivers,
1745     .format_strength            = vpip_format_strength,
1746     .make_systf_system_defined  = vpip_make_systf_system_defined,
1747     .mcd_rawwrite               = vpip_mcd_rawwrite,
1748     .set_return_value           = vpip_set_return_value,
1749 };
1750 #endif
1751