1 /*
2  * Copyright (c) 2001-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 /*
21  * vpiReg handles are handled here. These objects represent vectors of
22  * .var objects that can be manipulated by the VPI module.
23  */
24 
25 # include  "compile.h"
26 # include  "vpi_priv.h"
27 # include  "vvp_net_sig.h"
28 # include  "vvp_island.h"
29 # include  "schedule.h"
30 # include  "statistics.h"
31 # include  "config.h"
32 #ifdef CHECK_WITH_VALGRIND
33 # include  "vvp_cleanup.h"
34 #endif
35 # include  <cmath>
36 # include  <iostream>
37 # include  <cstdio>
38 # include  <cstdlib>
39 # include  <climits>
40 # include  <cstring>
41 # include  <cassert>
42 #ifdef CHECK_WITH_VALGRIND
43 # include  <valgrind/memcheck.h>
44 #endif
45 # include  "ivl_alloc.h"
46 
47 /*
48  * Hex digits that represent 4-value bits of Verilog are not as
49  * trivially obvious to display as if the bits were the usual 2-value
50  * bits. So, although it is possible to write a function that
51  * generates a correct character for 4*4-value bits, it is easier to
52  * just perform the lookup in a table. This only takes 256 bytes,
53  * which is not many executable instructions:-)
54  *
55  * The table is calculated at compile time, therefore, by the
56  * draw_tt.c program.
57  */
58 extern const char hex_digits[256];
59 extern const char oct_digits[64];
60 
61 /*
62  * The string values need a result buf to hold the results. This
63  * buffer can be reused for that purpose. Whenever I have a need, the
64  * need_result_buf function makes sure that need can be met.
65  */
need_result_buf(unsigned cnt,vpi_rbuf_t type)66 void *need_result_buf(unsigned cnt, vpi_rbuf_t type)
67 {
68       static void*result_buf[2] = {0, 0};
69       static size_t result_buf_size[2] = {0, 0};
70 
71       if (type == RBUF_DEL) {
72 	    free(result_buf[RBUF_VAL]);
73 	    result_buf[RBUF_VAL] = 0;
74 	    result_buf_size[RBUF_VAL] = 0;
75 
76 	    free(result_buf[RBUF_STR]);
77 	    result_buf[RBUF_STR] = 0;
78 	    result_buf_size[RBUF_STR] = 0;
79 
80 	    return 0;
81       }
82 
83       cnt = (cnt + 0x0fff) & ~0x0fff;
84 
85       if (result_buf_size[type] == 0) {
86 	    result_buf[type] = malloc(cnt);
87 	    result_buf_size[type] = cnt;
88       } else if (result_buf_size[type] < cnt) {
89 	    result_buf[type] = realloc(result_buf[type], cnt);
90 	    result_buf_size[type] = cnt;
91       }
92 
93       return result_buf[type];
94 }
95 
simple_set_rbuf_str(const char * s1)96 char *simple_set_rbuf_str(const char *s1)
97 {
98       char *res = (char *) need_result_buf(strlen(s1)+1, RBUF_STR);
99       if (res) strcpy(res,s1);
100       return res;
101 }
102 
generic_get_str(int code,vpiHandle ref,const char * name,const char * index)103 char *generic_get_str(int code, vpiHandle ref, const char *name, const char *index)
104 {
105       size_t len = strlen(name) + 1;  /* include space for null termination */
106       char *bn = NULL;
107       if (code == vpiFullName) {
108 	    bn = strdup(vpi_get_str(code,ref));
109 	    len += strlen(bn) + 1;  /* include space for "." separator */
110       }
111       if (index != NULL) len += strlen(index) + 2;  /* include space for brackets */
112 
113       char *res = (char *) need_result_buf(len, RBUF_STR);
114       if (!res) {
115 	    free(bn);
116 	    return NULL;
117       }
118       *res=0;  /* start with nothing */
119 
120 	/* if this works, I can make it more efficient later */
121       if (bn != NULL) {
122 	    strcat(res, bn);
123 	    strcat(res, ".");
124 	    free(bn);
125       }
126       strcat(res, name);
127       if (index != NULL) {
128 	    strcat(res, "[");
129 	    strcat(res, index);
130 	    strcat(res, "]");
131       }
132       return res;
133 }
134 
135 static vpiHandle fill_in_net4(struct __vpiSignal*obj, __vpiScope*scope,
136                               const char*name, int msb, int lsb,
137                               bool signed_flag, vvp_net_t*node);
138 
fill_in_var4(struct __vpiSignal * obj,const char * name,int msb,int lsb,bool signed_flag,vvp_net_t * node)139 static vpiHandle fill_in_var4(struct __vpiSignal*obj,
140                               const char*name, int msb, int lsb,
141                               bool signed_flag, vvp_net_t*node)
142 {
143 	// Variable declarations are always resolved immediately,
144 	// so we can assume they belong in the current scope.
145       return fill_in_net4(obj, vpip_peek_current_scope(),
146 			  name, msb, lsb, signed_flag, node);
147 }
148 
149 /*
150  * The standard formatting/conversion routines.
151  * They work with full or partial signals.
152  */
153 
format_vpiBinStrVal(vvp_signal_value * sig,int base,unsigned wid,s_vpi_value * vp)154 static void format_vpiBinStrVal(vvp_signal_value*sig, int base, unsigned wid,
155                                 s_vpi_value*vp)
156 {
157       char *rbuf = (char *) need_result_buf(wid+1, RBUF_VAL);
158       long end = base + (signed)wid;
159       long offset = end - 1;
160       long ssize = (signed)sig->value_size();
161 
162       for (long idx = base ;  idx < end ;  idx += 1) {
163 	    if (idx < 0 || idx >= ssize) {
164                   rbuf[offset-idx] = 'x';
165 	    } else {
166                   rbuf[offset-idx] = vvp_bit4_to_ascii(sig->value(idx));
167 	    }
168       }
169       rbuf[wid] = 0;
170 
171       vp->value.str = rbuf;
172 }
173 
format_vpiOctStrVal(vvp_signal_value * sig,int base,unsigned wid,s_vpi_value * vp)174 static void format_vpiOctStrVal(vvp_signal_value*sig, int base, unsigned wid,
175                                 s_vpi_value*vp)
176 {
177       unsigned dwid = (wid + 2) / 3;
178       char *rbuf = (char *) need_result_buf(dwid+1, RBUF_VAL);
179       long end = base + (signed)wid;
180       long ssize = (signed)sig->value_size();
181       unsigned val = 0;
182 
183       rbuf[dwid] = 0;
184       for (long idx = base ;  idx < end ;  idx += 1) {
185 	    unsigned bit = 0;
186 	    if (idx < 0 || idx >= ssize) {
187                   bit = 2; // BIT4_X
188 	    } else {
189                   switch (sig->value(idx)) {
190 		      case BIT4_0:
191 			bit = 0;
192 			break;
193 		      case BIT4_1:
194 			bit = 1;
195 			break;
196 		      case BIT4_X:
197 			bit = 2;
198 			break;
199 		      case BIT4_Z:
200 			bit = 3;
201 			break;
202                   }
203 	    }
204 	    val |= bit << 2*((idx-base) % 3);
205 
206 	    if ((idx-base) % 3 == 2) {
207 		dwid -= 1;
208 		rbuf[dwid] = oct_digits[val];
209 		val = 0;
210 	    }
211       }
212 
213 	/* Fill in X or Z if they are the only thing in the value. */
214       switch (wid % 3) {
215 	  case 1:
216 	    if (val == 2) val = 42;
217 	    else if (val == 3) val = 63;
218 	    break;
219 	  case 2:
220 	    if (val == 10) val = 42;
221 	    else if (val == 15) val = 63;
222 	    break;
223       }
224 
225       if (dwid > 0) rbuf[0] = oct_digits[val];
226 
227       vp->value.str = rbuf;
228 }
229 
format_vpiHexStrVal(vvp_signal_value * sig,int base,unsigned wid,s_vpi_value * vp)230 static void format_vpiHexStrVal(vvp_signal_value*sig, int base, unsigned wid,
231                                 s_vpi_value*vp)
232 {
233       unsigned dwid = (wid + 3) / 4;
234       char *rbuf = (char *) need_result_buf(dwid+1, RBUF_VAL);
235       long end = base + (signed)wid;
236       long ssize = (signed)sig->value_size();
237       unsigned val = 0;
238 
239       rbuf[dwid] = 0;
240       for (long idx = base ;  idx < end ;  idx += 1) {
241 	    unsigned bit = 0;
242 	    if (idx < 0 || idx >= ssize) {
243                   bit = 2; // BIT4_X
244 	    } else {
245                   switch (sig->value(idx)) {
246 		      case BIT4_0:
247 			bit = 0;
248 			break;
249 		      case BIT4_1:
250 			bit = 1;
251 			break;
252 		      case BIT4_X:
253 			bit = 2;
254 			break;
255 		      case BIT4_Z:
256 			bit = 3;
257 			break;
258                   }
259 	    }
260 	    val |= bit << 2*((idx-base) % 4);
261 
262 	    if ((idx-base) % 4 == 3) {
263 		dwid -= 1;
264 		rbuf[dwid] = hex_digits[val];
265 		val = 0;
266 	    }
267       }
268 
269 	/* Fill in X or Z if they are the only thing in the value. */
270       switch (wid % 4) {
271 	  case 1:
272 	    if (val == 2) val = 170;
273 	    else if (val == 3) val = 255;
274 	    break;
275 	  case 2:
276 	    if (val == 10) val = 170;
277 	    else if (val == 15) val = 255;
278 	    break;
279 	  case 3:
280 	    if (val == 42) val = 170;
281 	    else if (val == 63) val = 255;
282 	    break;
283       }
284 
285       if (dwid > 0) rbuf[0] = hex_digits[val];
286 
287       vp->value.str = rbuf;
288 }
289 
format_vpiDecStrVal(vvp_signal_value * sig,int base,unsigned wid,int signed_flag,s_vpi_value * vp)290 static void format_vpiDecStrVal(vvp_signal_value*sig, int base, unsigned wid,
291                                 int signed_flag, s_vpi_value*vp)
292 {
293       unsigned hwid = (sig->value_size()+2) / 3 + 1;
294       char *rbuf = (char *) need_result_buf(hwid, RBUF_VAL);
295       long ssize = (signed)sig->value_size();
296       long end = base + (signed)wid;
297 
298 	/* Do we have an end outside of the real signal vector. */
299       if (base < 0 || end > ssize) {
300 	    bool all_x = true;
301 	    if (end > ssize) end = ssize;
302 	    if (base < 0) base = 0;
303 	    for (long idx = base ;  idx < end ;  idx += 1) {
304 		  if (sig->value(idx) != BIT4_X) {
305 			all_x = false;
306 			break;
307 		  }
308 	    }
309 
310 	    if (all_x) {
311 		  rbuf[0] = 'x';
312 	    } else {
313 		  rbuf[0] = 'X';
314 	    }
315 	    rbuf[1] = 0;
316 
317 	    vp->value.str = rbuf;
318 	    return;
319       }
320 
321       vvp_vector4_t vec4;
322       if (base == 0 && end == ssize) {
323 	    sig->vec4_value(vec4);
324       } else {
325 	    vvp_vector4_t tmp;
326 	    sig->vec4_value(tmp);
327 	    vec4 = tmp.subvalue(base, wid);
328       }
329 
330       vpip_vec4_to_dec_str(vec4, rbuf, hwid, signed_flag);
331 
332       vp->value.str = rbuf;
333 }
334 
format_vpiIntVal(vvp_signal_value * sig,int base,unsigned wid,int signed_flag,s_vpi_value * vp)335 static void format_vpiIntVal(vvp_signal_value*sig, int base, unsigned wid,
336                              int signed_flag, s_vpi_value*vp)
337 {
338       vvp_vector4_t tmp;
339       sig->vec4_value(tmp);
340       vvp_vector4_t sub = tmp.subvalue(base, wid);
341 
342 	// Normally, we'd be OK with just using long in the call to
343 	// vector4_to_value, but some compilers seem to take long as
344 	// distinct from int32_t AND int64_t. Since the condition is
345 	// constant, the compiler should eliminate the dead code.
346       if (sizeof(vp->value.integer) == sizeof(int32_t)) {
347 	    int32_t val = 0;
348 	    vector4_to_value(sub, val, signed_flag, false);
349 	    vp->value.integer = val;
350       } else {
351 	    assert(sizeof(vp->value.integer) == sizeof(int64_t));
352 	    int64_t val = 0;
353 	    vector4_to_value(sub, val, signed_flag, false);
354 	    vp->value.integer = val;
355       }
356 }
357 
format_vpiRealVal(vvp_signal_value * sig,int base,unsigned wid,int signed_flag,s_vpi_value * vp)358 static void format_vpiRealVal(vvp_signal_value*sig, int base, unsigned wid,
359                               int signed_flag, s_vpi_value*vp)
360 {
361       vvp_vector4_t vec4(wid);
362       long ssize = (signed)sig->value_size();
363       long end = base + (signed)wid;
364       if (end > ssize) end = ssize;
365 
366       for (long idx = (base < 0) ? 0 : base ;  idx < end ;  idx += 1) {
367 	    vec4.set_bit(idx-base, sig->value(idx));
368       }
369 
370       vp->value.real = 0.0;
371       vector4_to_value(vec4, vp->value.real, signed_flag);
372 }
373 
format_vpiStringVal(vvp_signal_value * sig,int base,unsigned wid,s_vpi_value * vp)374 static void format_vpiStringVal(vvp_signal_value*sig, int base, unsigned wid,
375                                 s_vpi_value*vp)
376 {
377       /* The result will use a character for each 8 bits of the
378 	 vector. Add one extra character for the highest bits that
379 	 don't form an 8 bit group. */
380       char *rbuf = (char *) need_result_buf(wid/8 + ((wid&7)!=0) + 1, RBUF_VAL);
381       char *cp = rbuf;
382 
383       char tmp = 0;
384       for (long idx = base+(signed)wid-1; idx >= base; idx -= 1) {
385 	    tmp <<= 1;
386 
387 	    if (idx >=0 && idx < (signed)sig->value_size() &&
388 	        sig->value(idx) == BIT4_1) {
389 		   tmp |= 1;
390 	    }
391 
392 	    if (((idx-base)&7)==0){
393 		  /* Skip leading nulls. */
394 		  if (tmp == 0 && cp == rbuf)
395 			continue;
396 
397 		  /* Nulls in the middle get turned into spaces. */
398 		  *cp++ = tmp ? tmp : ' ';
399 		  tmp = 0;
400 	    }
401       }
402       *cp++ = 0;
403 
404       vp->value.str = rbuf;
405 }
406 
format_vpiScalarVal(vvp_signal_value * sig,int base,s_vpi_value * vp)407 static void format_vpiScalarVal(vvp_signal_value*sig, int base,
408                                 s_vpi_value*vp)
409 {
410       if (base >= 0 && base < (signed)sig->value_size()) {
411 	    switch (sig->value(base)) {
412 		case BIT4_0:
413 		  vp->value.scalar = vpi0;
414 		  break;
415 		case BIT4_1:
416 		  vp->value.scalar = vpi1;
417 		  break;
418 		case BIT4_X: {
419 		  vvp_scalar_t strn = sig->scalar_value(base);
420 		  if (strn.strength0() == 1) vp->value.scalar = vpiH;
421 		  else if (strn.strength1() == 1) vp->value.scalar = vpiL;
422 		  else vp->value.scalar = vpiX;
423 		  break;
424 		}
425 		case BIT4_Z:
426 		  vp->value.scalar = vpiZ;
427 		  break;
428 	    }
429       } else {
430 	    vp->value.scalar = vpiX;
431       }
432 }
433 
format_vpiStrengthVal(vvp_signal_value * sig,int base,unsigned wid,s_vpi_value * vp)434 static void format_vpiStrengthVal(vvp_signal_value*sig, int base,
435                                   unsigned wid, s_vpi_value*vp)
436 {
437       long end = base + (signed)wid;
438       s_vpi_strengthval*op;
439 
440       op = (s_vpi_strengthval*)
441 	    need_result_buf(wid * sizeof(s_vpi_strengthval), RBUF_VAL);
442 
443       for (long idx = base ;  idx < end ;  idx += 1) {
444 	    if (idx >=0 && idx < (signed)sig->value_size()) {
445 		  vvp_scalar_t val = sig->scalar_value(idx);
446 
447 		  /* vvp_scalar_t strengths are 0-7, but the vpi strength
448 		     is bit0-bit7. This gets the vpi form of the strengths
449 		     from the vvp_scalar_t strengths. */
450 		  unsigned s0 = 1 << val.strength0();
451 		  unsigned s1 = 1 << val.strength1();
452 
453 		  switch (val.value()) {
454 		      case BIT4_0:
455 			op[idx-base].logic = vpi0;
456 			op[idx-base].s0 = s0|s1;
457 			op[idx-base].s1 = 0;
458 			break;
459 
460 		      case BIT4_1:
461 			op[idx-base].logic = vpi1;
462 			op[idx-base].s0 = 0;
463 			op[idx-base].s1 = s0|s1;
464 			break;
465 
466 		      case BIT4_X:
467 			op[idx-base].logic = vpiX;
468 			op[idx-base].s0 = s0;
469 			op[idx-base].s1 = s1;
470 			break;
471 
472 		      case BIT4_Z:
473 			op[idx-base].logic = vpiZ;
474 			op[idx-base].s0 = vpiHiZ;
475 			op[idx-base].s1 = vpiHiZ;
476 			break;
477 		  }
478 	    } else {
479 		  op[idx-base].logic = vpiX;
480 		  op[idx-base].s0 = vpiStrongDrive;
481 		  op[idx-base].s1 = vpiStrongDrive;
482 	    }
483       }
484 
485       vp->value.strength = op;
486 }
487 
format_vpiVectorVal(vvp_signal_value * sig,int base,unsigned wid,s_vpi_value * vp)488 static void format_vpiVectorVal(vvp_signal_value*sig, int base, unsigned wid,
489                                 s_vpi_value*vp)
490 {
491       long end = base + (signed)wid;
492       unsigned int obit = 0;
493       unsigned hwid = (wid + 31)/32;
494 
495       s_vpi_vecval *op = (p_vpi_vecval)
496                          need_result_buf(hwid * sizeof(s_vpi_vecval), RBUF_VAL);
497       vp->value.vector = op;
498 
499       op->aval = op->bval = 0;
500       for (long idx = base ;  idx < end ;  idx += 1) {
501 	    if (base >= 0 && base < (signed)sig->value_size()) {
502 		switch (sig->value(idx)) {
503 		case BIT4_0:
504 		  op->aval &= ~(1 << obit);
505 		  op->bval &= ~(1 << obit);
506 		  break;
507 		case BIT4_1:
508 		  op->aval |= (1 << obit);
509 		  op->bval &= ~(1 << obit);
510 		  break;
511 		case BIT4_X:
512 		  op->aval |= (1 << obit);
513 		  op->bval |= (1 << obit);
514 		  break;
515 		case BIT4_Z:
516 		  op->aval &= ~(1 << obit);
517 		  op->bval |= (1 << obit);
518 		  break;
519 		}
520 	    } else {  /* BIT4_X */
521 		  op->aval |= (1 << obit);
522 		  op->bval |= (1 << obit);
523 	    }
524 
525 	    obit++;
526 	    if (!(obit % 32)) {
527 		  op += 1;
528 		  if ((op - vp->value.vector) < (ptrdiff_t)hwid)
529 			op->aval = op->bval = 0;
530 		  obit = 0;
531 	    }
532       }
533 }
534 
535 /*
536  * implement vpi_get for vpiReg objects.
537  */
signal_get(int code,vpiHandle ref)538 static int signal_get(int code, vpiHandle ref)
539 {
540       struct __vpiSignal*rfp = dynamic_cast<__vpiSignal*>(ref);
541       assert(rfp);
542 
543       switch (code) {
544 	  case vpiLineNo:
545 	    return 0;  // Not implemented for now!
546 
547 	  case vpiSigned:
548 	    return rfp->signed_flag != 0;
549 
550 	  case vpiArray:
551 	    return rfp->is_netarray != 0;
552 
553 	  case vpiIndex: // This only works while we have a single index.
554 	    if (rfp->is_netarray) {
555 		  s_vpi_value vp;
556 		  vp.format = vpiIntVal;
557 		  vpi_get_value(rfp->id.index, &vp);
558 		  return vp.value.integer;
559 	    } else {
560 		  return vpiUndefined;
561 	    }
562 
563 	  case vpiSize:
564 	    return rfp->width();
565 
566 	  case vpiNetType:
567 	    if (ref->get_type_code()==vpiNet)
568 		  return vpiWire;
569 	    else
570 		  return vpiUndefined;
571 
572 	  case vpiLeftRange:
573             return rfp->msb.get_value();
574 
575 	  case vpiRightRange:
576             return rfp->lsb.get_value();
577 
578 	  case vpiScalar:
579 	    return (rfp->msb.get_value() == 0 && rfp->lsb.get_value() == 0);
580 	  case vpiVector:
581 	    return (rfp->msb.get_value() != rfp->lsb.get_value());
582 
583           case vpiAutomatic:
584             return vpip_scope(rfp)->is_automatic() ? 1  : 0;
585 
586 #ifdef BR916_STOPGAP_FIX
587           case _vpiFromThr:
588             return _vpiNoThr;
589 #endif
590 
591 	    // This private property must return zero when undefined.
592 	  case _vpiNexusId:
593 	    if (rfp->msb.get_value() == rfp->lsb.get_value())
594 		  return (int) (uintptr_t) rfp->node;
595 	    else
596 		  return 0;
597 
598 	  default:
599 	    fprintf(stderr, "VPI error: unknown signal_get property %d.\n",
600 	            code);
601 	    return vpiUndefined;
602       }
603 }
604 
signal_get_str(int code,vpiHandle ref)605 static char* signal_get_str(int code, vpiHandle ref)
606 {
607       struct __vpiSignal*rfp = dynamic_cast<__vpiSignal*>(ref);
608       assert(rfp);
609 
610       if (code == vpiFile) {  // Not implemented for now!
611 	    return simple_set_rbuf_str(file_names[0]);
612       }
613 
614       if ((code != vpiName) && (code != vpiFullName)) return NULL;
615 
616       char *nm, *ixs;
617       if (rfp->is_netarray) {
618 	    nm = strdup(vpi_get_str(vpiName, rfp->within.parent));
619 	    s_vpi_value vp;
620 	    vp.format = vpiDecStrVal;
621 	    vpi_get_value(rfp->id.index, &vp);
622 	    ixs = vp.value.str;  /* do I need to strdup() this? */
623       } else {
624 	    nm = strdup(rfp->id.name);
625 	    ixs = NULL;
626       }
627 
628 	/* The scope information is added here for vpiFullName. */
629       char *rbuf = generic_get_str(code, vpip_scope(rfp), nm, ixs);
630       free(nm);
631       return rbuf;
632 }
633 
signal_get_handle(int code,vpiHandle ref)634 static vpiHandle signal_get_handle(int code, vpiHandle ref)
635 {
636       struct __vpiSignal*rfp = dynamic_cast<__vpiSignal*>(ref);
637       assert(rfp);
638 
639       switch (code) {
640 
641 	  case vpiParent:
642 	    return rfp->is_netarray? rfp->within.parent : 0;
643 
644 	  case vpiIndex:
645 	    return rfp->is_netarray? rfp->id.index : 0;
646 
647 	  case vpiLeftRange:
648 	    return &rfp->msb;
649 	  case vpiRightRange:
650 	    return &rfp->lsb;
651 
652 	  case vpiScope:
653 	    return vpip_scope(rfp);
654 
655 	  case vpiModule:
656 	    return vpip_module(vpip_scope(rfp));
657       }
658 
659       return 0;
660 }
661 
signal_iterate(int code,vpiHandle ref)662 static vpiHandle signal_iterate(int code, vpiHandle ref)
663 {
664       struct __vpiSignal*rfp = dynamic_cast<__vpiSignal*>(ref);
665       assert(rfp);
666 
667       if (code == vpiIndex) {
668 	    return rfp->is_netarray ? rfp->id.index->vpi_iterate(code) : 0;
669       }
670 
671       return 0;
672 }
673 
make_bits()674 void __vpiSignal::make_bits()
675 {
676       assert(bits == NULL);
677       bits = new struct __vpiBit[width() + 1];
678 
679 	// Make word[-1] point to the parent.
680       bits->parent = this;
681 	// Now point to word[0].
682       bits += 1;
683 
684 	// Update each bit to point to the base
685       struct __vpiBit*base = bits;
686       for (unsigned idx = 0; idx < width(); idx += 1) {
687 	    base[idx].bit0 = base;
688 	    int real_idx;
689 	    if (msb.get_value() >= lsb.get_value()) {
690 		  real_idx = idx + lsb.get_value();
691 	    } else {
692 		  real_idx = lsb.get_value() - idx;
693 	    }
694 	    base[idx].index = new __vpiDecConst(real_idx);
695       }
696 }
697 
get_index(int idx)698 vpiHandle __vpiSignal::get_index(int idx)
699 {
700 	/* Check to see if the index is in range. */
701       if (msb.get_value() >= lsb.get_value()) {
702 	    if ((idx > msb.get_value()) || (idx < lsb.get_value())) return 0;
703       } else {
704 	    if ((idx < msb.get_value()) || (idx > lsb.get_value())) return 0;
705       }
706 
707 	/* Normalize the index */
708       unsigned norm_idx;
709       if (msb.get_value() >= lsb.get_value()) {
710 	    norm_idx = idx - lsb.get_value();
711       } else {
712 	    norm_idx = lsb.get_value() - idx;
713       }
714 
715       if (bits == NULL) make_bits();
716 
717       return &(bits[norm_idx].as_bit);
718 }
719 
get_bit_value(struct __vpiBit * bit,p_vpi_value vp)720 void __vpiSignal::get_bit_value(struct __vpiBit*bit, p_vpi_value vp)
721 {
722       unsigned index = bit->get_norm_index();
723 
724       vvp_signal_value*vsig = dynamic_cast<vvp_signal_value*>(node->fil);
725       assert(vsig);
726 
727       if (vp->format == vpiObjTypeVal) {
728 	    vp->format = vpiIntVal;
729       }
730 
731       switch (vp->format) {
732 	case vpiBinStrVal:
733             format_vpiBinStrVal(vsig, index, 1, vp);
734 	    break;
735 
736 	case vpiOctStrVal:
737             format_vpiOctStrVal(vsig, index, 1, vp);
738 	    break;
739 
740 	case vpiDecStrVal:
741             format_vpiDecStrVal(vsig, index, 1, false, vp);
742 	    break;
743 
744 	case vpiHexStrVal:
745             format_vpiHexStrVal(vsig, index, 1, vp);
746 	    break;
747 
748 	case vpiStringVal:
749             format_vpiStringVal(vsig, index, 1, vp);
750 	    break;
751 
752 	case vpiIntVal:
753             format_vpiIntVal(vsig, index, 1, false, vp);
754 	    break;
755 
756 	case vpiRealVal:
757             format_vpiRealVal(vsig, index, 1, false, vp);
758 	    break;
759 
760 	case vpiScalarVal:
761             format_vpiScalarVal(vsig, index, vp);
762 	    break;
763 
764         case vpiStrengthVal:
765             format_vpiStrengthVal(vsig, index, 1, vp);
766             break;
767 
768 	case vpiVectorVal:
769             format_vpiVectorVal(vsig, index, 1, vp);
770 	    break;
771 
772 	default:
773 	    fprintf(stderr, "internal error: get_value() "
774 		    "type %d is not implemented for bit "
775 		    "select %s[%d] in scope %s.\n",
776 		    (int)vp->format, vpi_get_str(vpiName),
777 		    bit->get_index(),
778 	            vpip_scope(this)->scope_name());
779 	    assert(0);
780       };
781 }
782 
put_bit_value(struct __vpiBit * bit,p_vpi_value vp,int flags)783 vpiHandle __vpiSignal::put_bit_value(struct __vpiBit*bit, p_vpi_value vp, int flags)
784 {
785       unsigned index = bit->get_norm_index();
786       vvp_net_ptr_t dest(node, 0);
787       vvp_vector4_t val = vec4_from_vpi_value(vp, 1);
788 
789       if ((flags == vpiForceFlag) || (flags == vpiReleaseFlag)) {
790 	    fprintf(stderr, "Sorry: vpi_put_value() for %s does not "
791 	                    "currently support force/release.\n",
792 	                    bit->as_bit.vpi_get_str(vpiFullName));
793 	    return NULL;
794       }
795 
796       if ((get_type_code() == vpiNet) &&
797           !dynamic_cast<vvp_island_port*>(node->fun)) {
798 	    node->send_vec4_pv(val, index, 1, width(),
799 	                            vthread_get_wt_context());
800       } else {
801 	    vvp_send_vec4_pv(dest, val, index, 1, width(),
802 	                     vthread_get_wt_context());
803       }
804 
805 	// This is not a scheduled event so there is no event to return
806       return NULL;
807 }
808 
signal_index(int idx,vpiHandle ref)809 static vpiHandle signal_index(int idx, vpiHandle ref)
810 {
811       struct __vpiSignal*rfp = dynamic_cast<__vpiSignal*>(ref);
812       assert(rfp);
813 
814 	/* We can only get the bit for a net or reg. */
815       PLI_INT32 type = vpi_get(vpiType, ref);
816       if ((type != vpiNet) && (type != vpiReg)) return 0;
817 
818       return rfp->get_index(idx);
819 }
820 
width(void) const821 unsigned __vpiSignal::width(void) const
822 {
823       unsigned wid = (msb.get_value() >= lsb.get_value())
824 	    ? (msb.get_value() - lsb.get_value() + 1)
825 	    : (lsb.get_value() - msb.get_value() + 1);
826 
827       return wid;
828 }
829 
830 /*
831  * The get_value method reads the values of the functors and returns
832  * the vector to the caller. This causes no side-effect, and reads the
833  * variables like a %load would.
834  */
signal_get_value(vpiHandle ref,s_vpi_value * vp)835 static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
836 {
837       struct __vpiSignal*rfp = dynamic_cast<__vpiSignal*>(ref);
838       assert(rfp);
839 
840       unsigned wid = rfp->width();
841 
842       vvp_signal_value*vsig = dynamic_cast<vvp_signal_value*>(rfp->node->fil);
843       assert(vsig);
844 
845       switch (vp->format) {
846 
847 	  case vpiIntVal:
848 	    format_vpiIntVal(vsig, 0, wid, rfp->signed_flag, vp);
849 	    break;
850 
851 	  case vpiScalarVal:
852 	    format_vpiScalarVal(vsig, 0, vp);
853 	    break;
854 
855 	  case vpiStrengthVal:
856 	    format_vpiStrengthVal(vsig, 0, wid, vp);
857 	    break;
858 
859 	  case vpiBinStrVal:
860 	    format_vpiBinStrVal(vsig, 0, wid, vp);
861 	    break;
862 
863 	  case vpiHexStrVal:
864 	    format_vpiHexStrVal(vsig, 0, wid, vp);
865 	    break;
866 
867 	  case vpiOctStrVal:
868 	    format_vpiOctStrVal(vsig, 0, wid, vp);
869 	    break;
870 
871 	  case vpiDecStrVal:
872 	    format_vpiDecStrVal(vsig, 0, wid, rfp->signed_flag, vp);
873 	    break;
874 
875 	  case vpiStringVal:
876 	    format_vpiStringVal(vsig, 0, wid, vp);
877 	    break;
878 
879 	  case vpiVectorVal:
880 	    format_vpiVectorVal(vsig, 0, wid, vp);
881 	    break;
882 
883 	  case vpiRealVal:
884 	    format_vpiRealVal(vsig, 0, wid, rfp->signed_flag, vp);
885 	    break;
886 
887 	  case vpiObjTypeVal:
888 	    if (wid == 1) {
889 		  vp->format = vpiScalarVal;
890 		  format_vpiScalarVal(vsig, 0, vp);
891 	    } else {
892 		  vp->format = vpiVectorVal;
893 		  format_vpiVectorVal(vsig, 0, wid, vp);
894 	    }
895 	    break;
896 
897 	  default:
898 	    fprintf(stderr, "vvp internal error: get_value: "
899 		    "value type %d not implemented."
900 		    " Signal is %s in scope %s\n",
901 		    (int)vp->format, vpi_get_str(vpiName, ref),
902 		    vpip_scope(rfp)->scope_name());
903 	    assert(0);
904       }
905 }
906 
907 /*
908  * The put_value method writes the value into the vector, and returns
909  * the affected ref. This operation works much like the %set or
910  * %assign instructions and causes all the side-effects that the
911  * equivalent instruction would cause.
912  */
913 
from_stringval(const char * str,unsigned wid)914 static vvp_vector4_t from_stringval(const char*str, unsigned wid)
915 {
916       unsigned idx;
917       const char*cp;
918 
919       cp = str + strlen(str);
920       idx = 0;
921 
922       vvp_vector4_t val(wid, BIT4_0);
923 
924       while ((idx < wid) && (cp > str)) {
925 	    unsigned byte = *--cp;
926 	    int bit;
927 
928 	    for (bit = 0 ;  (bit < 8) && (idx < wid) ;  bit += 1) {
929 		  if (byte & 1)
930 			val.set_bit(idx, BIT4_1);
931 
932 		  byte >>= 1;
933 		  idx += 1;
934 	    }
935       }
936 
937       return val;
938 }
939 
signal_put_value(vpiHandle ref,s_vpi_value * vp,int flags)940 static vpiHandle signal_put_value(vpiHandle ref, s_vpi_value*vp, int flags)
941 {
942       unsigned wid;
943       struct __vpiSignal*rfp = dynamic_cast<__vpiSignal*>(ref);
944       assert(rfp);
945       vvp_net_ptr_t dest(rfp->node, 0);
946 
947       bool net_flag = ref->get_type_code()==vpiNet;
948 
949 	/* If this is a release, then we are not really putting a
950 	   value. Instead, issue a release "command" to the signal
951 	   node to cause it to release a forced value. Note that
952 	   if this net is attached to an island, we need to rerun
953 	   the calculations immediately so we can return the
954 	   released value. */
955       if (flags == vpiReleaseFlag) {
956 	    assert(rfp->node->fil);
957 	    rfp->node->fil->force_unlink();
958 	    rfp->node->fil->release(dest, net_flag);
959 	    rfp->node->fun->force_flag(true);
960 	    signal_get_value(ref, vp);
961 	    return ref;
962       }
963 
964 	/* Make a vvp_vector4_t vector to receive the translated value
965 	   that we are going to poke. This will get populated
966 	   differently depending on the format. */
967       wid = (rfp->msb.get_value() >= rfp->lsb.get_value())
968 	    ? (rfp->msb.get_value() - rfp->lsb.get_value() + 1)
969 	    : (rfp->lsb.get_value() - rfp->msb.get_value() + 1);
970 
971       vvp_vector4_t val = vec4_from_vpi_value(vp, wid);
972 
973       if (flags == vpiForceFlag) {
974 	    vvp_vector2_t mask (vvp_vector2_t::FILL1, wid);
975 	    rfp->node->force_vec4(val, mask);
976       } else if (net_flag && !dynamic_cast<vvp_island_port*>(rfp->node->fun)) {
977 	    rfp->node->send_vec4(val, vthread_get_wt_context());
978       } else {
979 	    vvp_send_vec4(dest, val, vthread_get_wt_context());
980       }
981       return ref;
982 }
983 
vec4_from_vpi_value(s_vpi_value * vp,unsigned wid)984 vvp_vector4_t vec4_from_vpi_value(s_vpi_value*vp, unsigned wid)
985 {
986       vvp_vector4_t val (wid, BIT4_0);
987 
988       switch (vp->format) {
989 
990 	  case vpiIntVal: {
991 		long vpi_val = vp->value.integer;
992 		for (unsigned idx = 0 ;  idx < wid ;  idx += 1) {
993 		      vvp_bit4_t bit = (vpi_val & 1) ? BIT4_1 : BIT4_0;
994 		      val.set_bit(idx, bit);
995 		      vpi_val >>= 1;
996 		}
997 		break;
998 	  }
999 
1000 	  case vpiVectorVal:
1001 	    for (unsigned idx = 0 ;  idx < wid ;  idx += 1) {
1002 		  unsigned long aval = vp->value.vector[idx/32].aval;
1003 		  unsigned long bval = vp->value.vector[idx/32].bval;
1004 		  aval >>= idx%32;
1005 		  bval >>= idx%32;
1006 		  int bitmask = (aval&1) | ((bval<<1)&2);
1007 		  vvp_bit4_t bit = scalar_to_bit4(bitmask);
1008 		  val.set_bit(idx, bit);
1009 	    }
1010 	    break;
1011 	  case vpiBinStrVal:
1012 	    vpip_bin_str_to_vec4(val, vp->value.str);
1013 	    break;
1014 	  case vpiOctStrVal:
1015 	    vpip_oct_str_to_vec4(val, vp->value.str);
1016 	    break;
1017 	  case vpiDecStrVal:
1018 	    vpip_dec_str_to_vec4(val, vp->value.str);
1019 	    break;
1020 	  case vpiHexStrVal:
1021 	    vpip_hex_str_to_vec4(val, vp->value.str);
1022 	    break;
1023 	  case vpiScalarVal:
1024 	    val.set_bit(0, scalar_to_bit4(vp->value.scalar));
1025 	    break;
1026 	  case vpiStringVal:
1027 	    val = from_stringval(vp->value.str, wid);
1028 	    break;
1029 	  case vpiRealVal:
1030 	    val = vvp_vector4_t(wid, vp->value.real);
1031 	    break;
1032 
1033 	  default:
1034 	    fprintf(stderr, "vvp internal error: put_value: "
1035 		    "value type %d not implemented here.\n",
1036 		    (int)vp->format);
1037 	    assert(0);
1038 
1039       }
1040 
1041       return val;
1042 }
1043 
vpi_get(int code)1044 int __vpiSignal::vpi_get(int code)
1045 { return signal_get(code, this); }
1046 
vpi_get_str(int code)1047 char* __vpiSignal::vpi_get_str(int code)
1048 { return signal_get_str(code, this); }
1049 
vpi_get_value(p_vpi_value val)1050 void __vpiSignal::vpi_get_value(p_vpi_value val)
1051 { signal_get_value(this, val); }
1052 
vpi_put_value(p_vpi_value val,int flags)1053 vpiHandle __vpiSignal::vpi_put_value(p_vpi_value val, int flags)
1054 { return signal_put_value(this, val, flags); }
1055 
vpi_handle(int code)1056 vpiHandle __vpiSignal::vpi_handle(int code)
1057 { return signal_get_handle(code, this); }
1058 
vpi_iterate(int code)1059 vpiHandle __vpiSignal::vpi_iterate(int code)
1060 { return signal_iterate(code, this); }
1061 
vpi_index(int idx)1062 vpiHandle __vpiSignal::vpi_index(int idx)
1063 { return signal_index(idx, this); }
1064 
1065 struct signal_reg : public __vpiSignal {
signal_regsignal_reg1066       inline signal_reg() { }
get_type_codesignal_reg1067       int get_type_code(void) const { return vpiReg; }
1068 };
1069 
1070 struct signal_integer : public __vpiSignal {
signal_integersignal_integer1071       inline signal_integer() { }
get_type_codesignal_integer1072       int get_type_code(void) const { return vpiIntegerVar; }
1073 };
1074 
1075 struct signal_net : public __vpiSignal {
signal_netsignal_net1076       inline signal_net() { }
get_type_codesignal_net1077       int get_type_code(void) const { return vpiNet; }
1078 };
1079 
1080 struct signal_byte : public __vpiSignal {
signal_bytesignal_byte1081       inline signal_byte() { }
get_type_codesignal_byte1082       int get_type_code(void) const { return vpiByteVar; }
1083 };
1084 
1085 struct signal_bitvar : public __vpiSignal {
signal_bitvarsignal_bitvar1086       inline signal_bitvar() { }
get_type_codesignal_bitvar1087       int get_type_code(void) const { return vpiBitVar; }
1088 };
1089 
1090 struct signal_shortint : public __vpiSignal {
signal_shortintsignal_shortint1091       inline signal_shortint() { }
get_type_codesignal_shortint1092       int get_type_code(void) const { return vpiShortIntVar; }
1093 };
1094 
1095 struct signal_int : public __vpiSignal {
signal_intsignal_int1096       inline signal_int() { }
get_type_codesignal_int1097       int get_type_code(void) const { return vpiIntVar; }
1098 };
1099 
1100 struct signal_longint : public __vpiSignal {
signal_longintsignal_longint1101       inline signal_longint() { }
get_type_codesignal_longint1102       int get_type_code(void) const { return vpiLongIntVar; }
1103 };
1104 
1105 
1106 /*
1107  * Construct a vpiIntegerVar object. Indicate the type using a flag
1108  * to minimize the code modifications. Icarus implements integers
1109  * as 'reg signed [31:0]'.
1110  */
vpip_make_int4(const char * name,int msb,int lsb,vvp_net_t * vec)1111 vpiHandle vpip_make_int4(const char*name, int msb, int lsb, vvp_net_t*vec)
1112 {
1113       __vpiSignal*obj = new signal_integer;
1114       return fill_in_var4(obj, name, msb, lsb, true, vec);
1115 }
1116 
1117 /*
1118  * Construct the two-state SystemVerilog variables.
1119  */
vpip_make_int2(const char * name,int msb,int lsb,bool signed_flag,vvp_net_t * vec)1120 vpiHandle vpip_make_int2(const char*name, int msb, int lsb, bool signed_flag,
1121                          vvp_net_t*vec)
1122 {
1123       __vpiSignal*obj;
1124 
1125 	// All unsigned 2-state variables are a vpiBitVar. All 2-state
1126 	// variables with a non-zero lsb are also a vpiBitVar.
1127       if ((! signed_flag) || (lsb != 0) ) {
1128 	    obj = new signal_bitvar;
1129       } else {
1130 	      // These could also be bit declarations with matching
1131 	      // information, but for now they get the apparent type.
1132 	    switch (msb) {
1133 		case 7:
1134 		  obj = new signal_byte;
1135 		  break;
1136 		case 15:
1137 		  obj = new signal_shortint;
1138 		  break;
1139 		case 31:
1140 		  obj = new signal_int;
1141 		  break;
1142 		case 63:
1143 		  obj = new signal_longint;
1144 		  break;
1145 		default:
1146 		    // Every other type of bit vector is a vpiBitVar with
1147 		    // array dimensions.
1148 		  obj = new signal_bitvar;
1149 		  break;
1150 	    }
1151       }
1152 
1153       return fill_in_var4(obj, name, msb, lsb, signed_flag, vec);
1154 }
1155 
1156 /*
1157  * Construct a vpiReg/vpiLogicVar object. It's like a net, except for the type.
1158  */
vpip_make_var4(const char * name,int msb,int lsb,bool signed_flag,vvp_net_t * vec)1159 vpiHandle vpip_make_var4(const char*name, int msb, int lsb,
1160 			bool signed_flag, vvp_net_t*vec)
1161 {
1162       __vpiSignal*obj = new signal_reg;
1163       return fill_in_var4(obj, name, msb, lsb, signed_flag, vec);
1164 }
1165 
1166 #ifdef CHECK_WITH_VALGRIND
1167 static struct vpiSignal_plug **signal_pool = 0;
1168 static unsigned signal_pool_count = 0;
1169 static unsigned long signal_count = 0;
1170 static unsigned long signal_dels = 0;
1171 #endif
1172 
1173 struct vpiSignal_plug {
1174       unsigned char space[sizeof (struct __vpiSignal)];
1175 #ifdef CHECK_WITH_VALGRIND
1176       struct vpiSignal_plug *pool;
1177 #endif
1178 };
1179 
operator new(size_t siz)1180 void* __vpiSignal::operator new(size_t siz)
1181 {
1182 #ifdef CHECK_WITH_VALGRIND
1183       assert(siz == sizeof(struct vpiSignal_plug) - sizeof(struct vpiSignal_plug *));
1184 #else
1185       assert(siz == sizeof(struct vpiSignal_plug));
1186 #endif
1187       static struct vpiSignal_plug*alloc_array = 0;
1188       static unsigned alloc_index = 0;
1189       const unsigned alloc_count = 512;
1190 
1191       if ((alloc_array == 0) || (alloc_index == alloc_count)) {
1192 	    alloc_array = (struct vpiSignal_plug*)
1193 		  calloc(alloc_count, sizeof(struct vpiSignal_plug));
1194 	    alloc_index = 0;
1195 #ifdef CHECK_WITH_VALGRIND
1196 	    VALGRIND_MAKE_MEM_NOACCESS(alloc_array, alloc_count *
1197 	                                            sizeof(struct vpiSignal_plug));
1198 	    VALGRIND_CREATE_MEMPOOL(alloc_array, 0, 1);
1199 	    signal_pool_count += 1;
1200 	    signal_pool = (vpiSignal_plug **) realloc(signal_pool,
1201 	                  signal_pool_count*sizeof(vpiSignal_plug **));
1202 	    signal_pool[signal_pool_count-1] = alloc_array;
1203 #endif
1204       }
1205 
1206       struct vpiSignal_plug*cur = alloc_array + alloc_index;
1207 #ifdef CHECK_WITH_VALGRIND
1208       VALGRIND_MEMPOOL_ALLOC(alloc_array, cur, sizeof(struct vpiSignal_plug));
1209       cur->pool = alloc_array;
1210       signal_count += 1;
1211 #endif
1212       alloc_index += 1;
1213       return cur;
1214 }
1215 
operator delete(void *)1216 void __vpiSignal::operator delete(void*)
1217 {
1218       assert(0);
1219 }
1220 
1221 #ifdef CHECK_WITH_VALGRIND
signal_delete(vpiHandle item)1222 void signal_delete(vpiHandle item)
1223 {
1224       struct __vpiSignal *obj = static_cast<__vpiSignal *> (item);
1225       assert(obj->node->fil);
1226       obj->node->fil->clear_all_callbacks();
1227       vvp_net_delete(obj->node);
1228       if (obj->bits) {
1229 	    for (unsigned idx=0; idx<obj->width(); idx+=1) {
1230 		  delete obj->bits[idx].index;
1231 	    }
1232 	    obj->bits -= 1;
1233 	    delete [] obj->bits;
1234       }
1235       signal_dels += 1;
1236       VALGRIND_MEMPOOL_FREE(reinterpret_cast<vpiSignal_plug *>(obj)->pool, obj);
1237 }
1238 
signal_pool_delete()1239 void signal_pool_delete()
1240 {
1241       if (RUNNING_ON_VALGRIND && (signal_count != signal_dels)) {
1242 	    fflush(NULL);
1243 	    VALGRIND_PRINTF("Error: vvp missed deleting %ld of %lu signal(s).",
1244 	                    (long) signal_count - signal_dels, signal_count);
1245       }
1246 
1247       for (unsigned idx = 0; idx < signal_pool_count; idx += 1) {
1248 	    VALGRIND_DESTROY_MEMPOOL(signal_pool[idx]);
1249 	    free(signal_pool[idx]);
1250       }
1251 
1252       free(signal_pool);
1253       signal_pool = 0;
1254       signal_pool_count = 0;
1255 }
1256 #endif
1257 
1258 /*
1259  * Construct a vpiNet object. Give the object specified dimensions,
1260  * and point to the specified functor for the lsb.
1261  *
1262  * The name is the PLI name for the object. If it is an array it is
1263  * <name>[<index>].
1264  */
fill_in_net4(struct __vpiSignal * obj,__vpiScope * scope,const char * name,int msb,int lsb,bool signed_flag,vvp_net_t * node)1265 static vpiHandle fill_in_net4(struct __vpiSignal*obj, __vpiScope*scope,
1266 			      const char*name, int msb, int lsb,
1267 			      bool signed_flag, vvp_net_t*node)
1268 {
1269       obj->id.name = name? vpip_name_string(name) : 0;
1270       obj->msb = __vpiDecConst(msb);
1271       obj->lsb = __vpiDecConst(lsb);
1272       obj->signed_flag = signed_flag? 1 : 0;
1273       obj->is_netarray = 0;
1274       obj->node = node;
1275 
1276 	// Place this object within a scope. If this object is
1277 	// attached to an array, then this value will be replaced with
1278 	// the handle to the parent.
1279       obj->within.scope = scope;
1280 
1281       count_vpi_nets += 1;
1282 
1283       return obj;
1284 }
1285 
vpip_make_net4(__vpiScope * scope,const char * name,int msb,int lsb,bool signed_flag,vvp_net_t * node)1286 vpiHandle vpip_make_net4(__vpiScope*scope,
1287 			 const char*name, int msb, int lsb,
1288 			 bool signed_flag, vvp_net_t*node)
1289 {
1290       struct __vpiSignal*obj = new signal_net;
1291       return fill_in_net4(obj, scope, name, msb, lsb, signed_flag, node);
1292 }
1293 
PV_get_base(struct __vpiPV * rfp)1294 static int PV_get_base(struct __vpiPV*rfp)
1295 {
1296 	/* We return from the symbol base if it is defined. */
1297       if (rfp->sbase != 0) {
1298 	    s_vpi_value val;
1299 	      /* Check to see if the value is defined. */
1300 	    val.format = vpiVectorVal;
1301 	    vpi_get_value(rfp->sbase, &val);
1302 	    int words = (vpi_get(vpiSize, rfp->sbase)-1)/32 + 1;
1303 	    for(int idx = 0; idx < words; idx += 1) {
1304 		    /* Return INT_MIN to indicate an X base. */
1305 		  if (val.value.vector[idx].bval != 0) return INT_MIN;
1306 	    }
1307 	      /* The value is defined so get and return it. */
1308 	    val.format = vpiIntVal;
1309 	    vpi_get_value(rfp->sbase, &val);
1310 	    return val.value.integer;
1311       }
1312 
1313 	/* If the width is zero then tbase is the constant. */
1314       return rfp->tbase;
1315 }
1316 
PV_get(int code,vpiHandle ref)1317 static int PV_get(int code, vpiHandle ref)
1318 {
1319       struct __vpiPV*rfp = dynamic_cast<__vpiPV*>(ref);
1320       assert(rfp);
1321 
1322       int rval = 0;
1323       switch (code) {
1324 	case vpiLineNo:
1325 	    return 0;  // Not implemented for now!
1326 
1327 	case vpiSigned:
1328 	    return 0;  // A part/bit select is always unsigned!
1329 
1330 	case vpiSize:
1331 	    return rfp->width;
1332 
1333 	  /* This is like the &A<> in array.cc. */
1334 	case vpiConstantSelect:
1335 	    return rfp->sbase == 0;
1336 
1337 	case vpiLeftRange:
1338             rval += rfp->width - 1;
1339 	    // fallthrough
1340 	case vpiRightRange:
1341 	    rval += vpi_get(vpiRightRange, rfp->parent) + PV_get_base(rfp);
1342 	    return rval;
1343 
1344         case vpiAutomatic:
1345             return vpi_get(vpiAutomatic, rfp->parent);
1346 
1347 #if defined(CHECK_WITH_VALGRIND) || defined(BR916_STOPGAP_FIX)
1348         case _vpiFromThr:
1349             return _vpi_at_PV;
1350 #endif
1351 
1352 	default:
1353 	    fprintf(stderr, "PV_get: property %d is unknown\n", code);
1354       }
1355 
1356       return 0;
1357 }
1358 
PV_get_str(int code,vpiHandle ref)1359 static char* PV_get_str(int code, vpiHandle ref)
1360 {
1361       struct __vpiPV*rfp = dynamic_cast<__vpiPV*>(ref);
1362       assert(rfp);
1363 
1364       switch (code) {
1365 	case vpiFile:  // Not implemented for now!
1366 	    return simple_set_rbuf_str(file_names[0]);
1367 
1368 	case vpiName:
1369 	case vpiFullName: {
1370 	    const char*nm = vpi_get_str(code, rfp->parent);
1371 	    size_t len = 256+strlen(nm);
1372 	    char *full = (char *) malloc(len);
1373 	    snprintf(full, len, "%s[%d:%d]", nm,
1374 	                                     (int)vpi_get(vpiLeftRange, ref),
1375 	                                     (int)vpi_get(vpiRightRange, ref));
1376 	    full[len-1] = 0;
1377 	    char *res = simple_set_rbuf_str(full);
1378 	    free(full);
1379 	    return res;
1380 	}
1381 
1382 	default:
1383 	    fprintf(stderr, "PV_get_str: property %d is unknown.\n", code);
1384       }
1385 
1386       return 0;
1387 }
1388 
PV_get_value(vpiHandle ref,p_vpi_value vp)1389 static void PV_get_value(vpiHandle ref, p_vpi_value vp)
1390 {
1391       struct __vpiPV*rfp = dynamic_cast<__vpiPV*>(ref);
1392       assert(rfp);
1393 
1394       vvp_signal_value*sig = dynamic_cast<vvp_signal_value*>(rfp->net->fil);
1395       assert(sig);
1396 
1397       switch (vp->format) {
1398 
1399 	  case vpiIntVal:
1400 	    format_vpiIntVal(sig, PV_get_base(rfp), rfp->width, 0, vp);
1401 	    break;
1402 
1403 	  case vpiBinStrVal:
1404 	    format_vpiBinStrVal(sig, PV_get_base(rfp), rfp->width, vp);
1405 	    break;
1406 
1407 	  case vpiOctStrVal:
1408 	    format_vpiOctStrVal(sig, PV_get_base(rfp), rfp->width, vp);
1409 	    break;
1410 
1411 	  case vpiHexStrVal:
1412 	    format_vpiHexStrVal(sig, PV_get_base(rfp), rfp->width, vp);
1413 	    break;
1414 
1415 	  case vpiDecStrVal:
1416 	    format_vpiDecStrVal(sig, PV_get_base(rfp), rfp->width, 0, vp);
1417 	    break;
1418 
1419 	  case vpiStringVal:
1420 	    format_vpiStringVal(sig, PV_get_base(rfp), rfp->width, vp);
1421 	    break;
1422 
1423 	  case vpiScalarVal:
1424 	    format_vpiScalarVal(sig, PV_get_base(rfp), vp);
1425 	    break;
1426 
1427 	  case vpiStrengthVal:
1428 	    format_vpiStrengthVal(sig, PV_get_base(rfp), rfp->width, vp);
1429 	    break;
1430 
1431 	  case vpiVectorVal:
1432 	    format_vpiVectorVal(sig, PV_get_base(rfp), rfp->width, vp);
1433 	    break;
1434 
1435 	  case vpiRealVal:
1436 	    format_vpiRealVal(sig, PV_get_base(rfp), rfp->width, 0, vp);
1437 	    break;
1438 
1439 	  default:
1440 	    fprintf(stderr, "vvp internal error: PV_get_value: "
1441 		    "value type %d not implemented. Signal is %s.\n",
1442 		    (int)vp->format, vpi_get_str(vpiFullName, rfp->parent));
1443 	    assert(0);
1444       }
1445 }
1446 
PV_put_value(vpiHandle ref,p_vpi_value vp,int flags)1447 static vpiHandle PV_put_value(vpiHandle ref, p_vpi_value vp, int flags)
1448 {
1449       struct __vpiPV*rfp = dynamic_cast<__vpiPV*>(ref);
1450       assert(rfp);
1451       vvp_signal_value*sig = dynamic_cast<vvp_signal_value*>(rfp->net->fil);
1452       assert(sig);
1453 
1454       unsigned sig_size = sig->value_size();
1455       unsigned width = rfp->width;
1456       int base = PV_get_base(rfp);
1457       if (base >= (signed) sig_size) return 0;
1458       if (base + (signed) width < 0) return 0;
1459 
1460       vvp_vector4_t val;
1461       if (flags != vpiReleaseFlag) {
1462 	    val = vec4_from_vpi_value(vp, width);
1463       }
1464 
1465 	/*
1466 	 * If the base is less than zero then trim off any unneeded
1467 	 * lower bits.
1468 	 */
1469       if (base < 0) {
1470 	    width += base;
1471 	    if (flags != vpiReleaseFlag) {
1472 		  val = val.subvalue(-base, width);
1473 	    }
1474 	    base = 0;
1475       }
1476 
1477 	/*
1478 	 * If the value is wider than the signal then trim off any
1479 	 * unneeded upper bits.
1480 	 */
1481       if (base+width > sig_size) {
1482 	    width = sig_size - base;
1483 	    if (flags != vpiReleaseFlag) {
1484 		  val = val.subvalue(0, width);
1485 	    }
1486       }
1487 
1488       assert(rfp->parent);
1489       bool net_flag = rfp->parent->get_type_code()==vpiNet;
1490       bool full_sig = base == 0 && width == sig_size;
1491 
1492       vvp_net_ptr_t dest(rfp->net, 0);
1493 
1494 	/* If this is a release, then we are not really putting a
1495 	   value. Instead, issue a release "command" to the signal
1496 	   node to cause it to release a forced value.  Note that
1497 	   if this net is attached to an island, we need to rerun
1498 	   the calculations immediately so we can return the
1499 	   released value.*/
1500       if (flags == vpiReleaseFlag) {
1501 	    assert(rfp->net->fil);
1502 	      // XXXX Can't really do this if this is a partial release?
1503 	    rfp->net->fil->force_unlink();
1504 	    if (full_sig) {
1505 		  rfp->net->fil->release(dest, net_flag);
1506 	    } else {
1507 		  rfp->net->fil->release_pv(dest, base, width, net_flag);
1508 	    }
1509 	    rfp->net->fun->force_flag(true);
1510 	    PV_get_value(ref, vp);
1511 	    return ref;
1512       }
1513 
1514       if (flags == vpiForceFlag) {
1515 	    if (full_sig) {
1516 		  vvp_vector2_t mask (vvp_vector2_t::FILL1, sig_size);
1517 		  rfp->net->force_vec4(val, mask);
1518 	    } else {
1519 		  vvp_vector2_t mask (vvp_vector2_t::FILL0, sig_size);
1520 		  for (unsigned idx = 0 ; idx < width ; idx += 1)
1521 		        mask.set_bit(base+idx, 1);
1522 
1523 		  vvp_vector4_t tmp (sig_size, BIT4_Z);
1524 
1525 		    // vvp_net_t::force_vec4 propagates all the bits of the
1526 		    // forced vector value, regardless of the mask. This
1527 		    // ensures the unforced bits retain their current value.
1528 		  sig->vec4_value(tmp);
1529 
1530 		  tmp.set_vec(base, val);
1531 		  rfp->net->force_vec4(tmp, mask);
1532 	    }
1533       } else if (net_flag && !dynamic_cast<vvp_island_port*>(rfp->net->fun)) {
1534 	    if (full_sig) {
1535 		  rfp->net->send_vec4(val, vthread_get_wt_context());
1536 	    } else {
1537 		  rfp->net->send_vec4_pv(val, base, width, sig_size,
1538 		                         vthread_get_wt_context());
1539 	    }
1540       } else {
1541 	    if (full_sig) {
1542 		  vvp_send_vec4(dest, val, vthread_get_wt_context());
1543 	    } else {
1544 		  vvp_send_vec4_pv(dest, val, base, width, sig_size,
1545 	                           vthread_get_wt_context());
1546 	    }
1547       }
1548       return 0;
1549 }
1550 
PV_get_handle(int code,vpiHandle ref)1551 static vpiHandle PV_get_handle(int code, vpiHandle ref)
1552 {
1553       struct __vpiPV*rfp = dynamic_cast<__vpiPV*>(ref);
1554       assert(rfp);
1555 
1556       switch (code) {
1557 	  case vpiParent:
1558 	    return rfp->parent;
1559 
1560 	  case vpiScope:
1561 	    return vpi_handle(vpiScope, rfp->parent);
1562 
1563 	  case vpiModule:
1564 	    return vpi_handle(vpiModule, rfp->parent);
1565       }
1566 
1567       return 0;
1568 }
1569 
__vpiPV()1570 inline __vpiPV::__vpiPV()
1571 { }
1572 
get_type_code(void) const1573 int __vpiPV::get_type_code(void) const
1574 { return vpiPartSelect; }
1575 
vpi_get(int code)1576 int __vpiPV::vpi_get(int code)
1577 { return PV_get(code, this); }
1578 
vpi_get_str(int code)1579 char* __vpiPV::vpi_get_str(int code)
1580 { return PV_get_str(code, this); }
1581 
vpi_get_value(p_vpi_value val)1582 void __vpiPV::vpi_get_value(p_vpi_value val)
1583 { PV_get_value(this, val); }
1584 
vpi_put_value(p_vpi_value val,int flags)1585 vpiHandle __vpiPV::vpi_put_value(p_vpi_value val, int flags)
1586 { return PV_put_value(this, val, flags); }
1587 
vpi_handle(int code)1588 vpiHandle __vpiPV::vpi_handle(int code)
1589 { return PV_get_handle(code, this); }
1590 
vpip_make_PV(char * var,int base,int width)1591 vpiHandle vpip_make_PV(char*var, int base, int width)
1592 {
1593       struct __vpiPV*obj = new __vpiPV;
1594       compile_vpi_lookup(&obj->parent, strdup(var));
1595       obj->sbase = 0;
1596       obj->tbase = base;
1597       obj->width = (unsigned) width;
1598       obj->net = 0;
1599       functor_ref_lookup(&obj->net, var);
1600 
1601       return obj;
1602 }
1603 
vpip_make_PV(char * var,char * symbol,int width)1604 vpiHandle vpip_make_PV(char*var, char*symbol, int width)
1605 {
1606       struct __vpiPV*obj = new __vpiPV;
1607       compile_vpi_lookup(&obj->parent, strdup(var));
1608       compile_vpi_lookup(&obj->sbase, symbol);
1609       obj->tbase = 0;
1610       obj->width = (unsigned) width;
1611       obj->net = 0;
1612       functor_ref_lookup(&obj->net, var);
1613 
1614       return obj;
1615 }
1616 
vpip_make_PV(char * var,vpiHandle handle,int width)1617 vpiHandle vpip_make_PV(char*var, vpiHandle handle, int width)
1618 {
1619       struct __vpiPV*obj = new __vpiPV;
1620       compile_vpi_lookup(&obj->parent, strdup(var));
1621       obj->sbase = handle;
1622       obj->tbase = 0;
1623       obj->width = (unsigned) width;
1624       obj->net = 0;
1625       functor_ref_lookup(&obj->net, var);
1626 
1627       return obj;
1628 }
1629 
1630 #ifdef CHECK_WITH_VALGRIND
PV_delete(vpiHandle item)1631 void PV_delete(vpiHandle item)
1632 {
1633       struct __vpiPV *obj = dynamic_cast<__vpiPV*>(item);
1634       if (obj->sbase) {
1635 	    switch (obj->sbase->get_type_code()) {
1636 		case vpiMemoryWord:
1637 		  if (vpi_get(_vpiFromThr, obj->sbase) == _vpi_at_A) {
1638 			A_delete(obj->sbase);
1639 		  }
1640 		  break;
1641 		case vpiPartSelect:
1642 		  assert(vpi_get(_vpiFromThr, obj->sbase) == _vpi_at_PV);
1643 		  PV_delete(obj->sbase);
1644 		  break;
1645 	    }
1646       }
1647       assert(obj->net->fil);
1648       obj->net->fil->clear_all_callbacks();
1649       delete obj;
1650 }
1651 #endif
1652