1 /*
2 * Copyright (c) 2007-2013 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 "array_common.h"
21 # include "array.h"
22 # include "symbols.h"
23 # include "schedule.h"
24 # include "vpi_priv.h"
25 # include "vvp_net_sig.h"
26 # include "vvp_darray.h"
27 # include "config.h"
28 #ifdef CHECK_WITH_VALGRIND
29 #include "vvp_cleanup.h"
30 #endif
31 # include <cstdlib>
32 # include <cstring>
33 # include <climits>
34 # include <iostream>
35 # include "compile.h"
36 # include <cassert>
37 # include "ivl_alloc.h"
38
39 unsigned long count_net_arrays = 0;
40 unsigned long count_net_array_words = 0;
41 unsigned long count_var_arrays = 0;
42 unsigned long count_var_array_words = 0;
43 unsigned long count_real_arrays = 0;
44 unsigned long count_real_array_words = 0;
45
46 static symbol_map_s<struct __vpiArray>* array_table =0;
47
48 class vvp_fun_arrayport;
49 static void array_attach_port(vvp_array_t, vvp_fun_arrayport*);
50
array_find(const char * label)51 vvp_array_t array_find(const char*label)
52 {
53 if (array_table == 0)
54 return 0;
55
56 vvp_array_t v = array_table->sym_get_value(label);
57 return v;
58 }
59
60 struct __vpiArrayVthrA : public __vpiHandle {
get_type_code__vpiArrayVthrA61 int get_type_code(void) const { return vpiMemoryWord; }
62 int vpi_get(int code);
63 char* vpi_get_str(int code);
64 void vpi_get_value(p_vpi_value val);
65 vpiHandle vpi_put_value(p_vpi_value val, int flags);
66 vpiHandle vpi_handle(int code);
67
68 struct __vpiArray*array;
69 // If this is set, then use it to get the index value.
70 vpiHandle address_handle;
71 // If wid==0, then address is the address into the array.
72 unsigned address;
73
get_address__vpiArrayVthrA74 unsigned get_address() const
75 {
76 if (address_handle) {
77 s_vpi_value vp;
78 /* Check to see if the value is defined. */
79 vp.format = vpiVectorVal;
80 address_handle->vpi_get_value(&vp);
81 int words = (address_handle->vpi_get(vpiSize)-1)/32 + 1;
82 for(int idx = 0; idx < words; idx += 1) {
83 /* Return UINT_MAX to indicate an X base. */
84 if (vp.value.vector[idx].bval != 0) return UINT_MAX;
85 }
86 /* The value is defined so get and return it. */
87 vp.format = vpiIntVal;
88 address_handle->vpi_get_value(&vp);
89 return vp.value.integer;
90 }
91
92 return address;
93 }
94 };
95
96
97 struct __vpiArrayVthrAPV : public __vpiHandle {
get_type_code__vpiArrayVthrAPV98 int get_type_code(void) const { return vpiPartSelect; }
99 int vpi_get(int code);
100 char* vpi_get_str(int code);
101 void vpi_get_value(p_vpi_value val);
102 vpiHandle vpi_handle(int code);
103
104 struct __vpiArray*array;
105 unsigned word_sel;
106 unsigned part_bit;
107 unsigned part_wid;
108 };
109
is_net_array(vpiHandle obj)110 bool is_net_array(vpiHandle obj)
111 {
112 struct __vpiArray*rfp = dynamic_cast<__vpiArray*> (obj);
113 assert(rfp);
114
115 if (rfp->nets != 0) return true;
116 return false;
117 }
118
119 // This function return true if the underlying array words are real.
vpi_array_is_real(const vvp_array_t arr)120 static bool vpi_array_is_real(const vvp_array_t arr)
121 {
122 // Check to see if this is a variable/register array.
123 if (arr->vals4 != 0) // A bit based variable/register array.
124 return false;
125
126 if (dynamic_cast<vvp_darray_real*> (arr->vals))
127 return true;
128
129 if (arr->vals != 0)
130 return false;
131
132 // This must be a net array so look at element 0 to find the type.
133 assert(arr->nets != 0);
134 assert(arr->get_size() > 0);
135 struct __vpiRealVar*rsig = dynamic_cast<__vpiRealVar*>(arr->nets[0]);
136 if (rsig) {
137 return true;
138 }
139
140 return false;
141 }
142
vpi_array_is_string(const vvp_array_t arr)143 static bool vpi_array_is_string(const vvp_array_t arr)
144 {
145 // Check to see if this is a variable/register array.
146 if (arr->vals4 != 0) // A bit based variable/register array.
147 return false;
148
149 if (dynamic_cast<vvp_darray_string*> (arr->vals))
150 return true;
151
152 return false;
153 }
154
get_word_size() const155 int __vpiArray::get_word_size() const
156 {
157 unsigned width;
158
159 assert(get_size() > 0);
160 /* For a net array we need to get the width from the first element. */
161 if (nets) {
162 assert(vals4 == 0 && vals == 0);
163 struct __vpiSignal*vsig = dynamic_cast<__vpiSignal*>(nets[0]);
164 assert(vsig);
165 width = vpip_size(vsig);
166 /* For a variable array we can get the width from vals_width. */
167 } else {
168 assert(vals4 || vals);
169 width = vals_width;
170 }
171
172 return width;
173 }
174
get_word_str(struct __vpiArrayWord * word,int code)175 char*__vpiArray::get_word_str(struct __vpiArrayWord*word, int code)
176 {
177 unsigned index = word->get_index();
178
179 if (code == vpiFile) { // Not implemented for now!
180 return simple_set_rbuf_str(file_names[0]);
181 }
182
183 char sidx [64];
184 snprintf(sidx, 63, "%d", (int)index + first_addr.get_value());
185 return generic_get_str(code, get_scope(), name, sidx);
186 }
187
get_word_value(struct __vpiArrayWord * word,p_vpi_value vp)188 void __vpiArray::get_word_value(struct __vpiArrayWord*word, p_vpi_value vp)
189 {
190 unsigned index = word->get_index();
191
192 // Determine the appropriate format (The Verilog PLI Handbook 5.2.10)
193 if(vp->format == vpiObjTypeVal) {
194 if(vpi_array_is_real(this))
195 vp->format = vpiRealVal;
196 else if(vpi_array_is_string(this))
197 vp->format = vpiStringVal;
198 else
199 vp->format = vpiIntVal;
200 }
201
202 if(vals4) {
203 vpip_vec4_get_value(vals4->get_word(index),
204 vals4->width(), signed_flag, vp);
205 } else if(vals) {
206 switch(vp->format) {
207 case vpiBinStrVal:
208 case vpiOctStrVal:
209 case vpiDecStrVal:
210 case vpiHexStrVal:
211 case vpiScalarVal:
212 case vpiIntVal:
213 {
214 vvp_vector4_t v;
215 vals->get_word(index, v);
216 vpip_vec4_get_value(v, vals_width, signed_flag, vp);
217 }
218 break;
219
220 case vpiVectorVal:
221 {
222 vvp_vector4_t v;
223 vals->get_word(index, v);
224 vpip_vec2_get_value(v, vals_width, signed_flag, vp);
225 }
226 break;
227
228 case vpiRealVal:
229 {
230 double d;
231 vals->get_word(index, d);
232 vpip_real_get_value(d, vp);
233 }
234 break;
235
236 case vpiStringVal:
237 {
238 string s;
239 vals->get_word(index, s);
240 vpip_string_get_value(s, vp);
241 }
242 break;
243
244 default:
245 fprintf(stderr, "vpi sorry: format is not implemented\n");
246 assert(false);
247 }
248 }
249 }
250
put_word_value(struct __vpiArrayWord * word,p_vpi_value vp,int)251 void __vpiArray::put_word_value(struct __vpiArrayWord*word, p_vpi_value vp, int)
252 {
253 unsigned index = word->get_index();
254 vvp_vector4_t val = vec4_from_vpi_value(vp, vals_width);
255 set_word(index, 0, val);
256 }
257
get_iter_index(struct __vpiArrayIterator *,int idx)258 vpiHandle __vpiArray::get_iter_index(struct __vpiArrayIterator*, int idx)
259 {
260 if (nets) return nets[idx];
261
262 assert(vals4 || vals);
263
264 if (vals_words == 0) make_vals_words();
265
266 return &(vals_words[idx].as_word);
267 }
268
vpi_get(int code)269 int __vpiArray::vpi_get(int code)
270 {
271 switch (code) {
272 case vpiLineNo:
273 return 0; // Not implemented for now!
274
275 case vpiSize:
276 return get_size();
277
278 case vpiAutomatic:
279 return scope->is_automatic()? 1 : 0;
280
281 default:
282 return 0;
283 }
284 }
285
vpi_get_str(int code)286 char* __vpiArray::vpi_get_str(int code)
287 {
288 if (code == vpiFile) { // Not implemented for now!
289 return simple_set_rbuf_str(file_names[0]);
290 }
291
292 return generic_get_str(code, scope, name, NULL);
293 }
294
vpi_handle(int code)295 vpiHandle __vpiArray::vpi_handle(int code)
296 {
297 switch (code) {
298 case vpiLeftRange:
299 if (swap_addr) return &last_addr;
300 else return &first_addr;
301
302 case vpiRightRange:
303 if (swap_addr) return &first_addr;
304 else return &last_addr;
305
306 case vpiScope:
307 return scope;
308
309 case vpiModule:
310 return vpip_module(scope);
311 }
312
313 return 0;
314 }
315
316 /*
317 * VPI code passes indices that are not yet converted to canonical
318 * form, so this index function does it here.
319 */
vpi_index(int index)320 vpiHandle __vpiArray::vpi_index(int index)
321 {
322 index -= first_addr.get_value();
323 if (index >= (long) get_size())
324 return 0;
325 if (index < 0)
326 return 0;
327
328 if (nets != 0) {
329 return nets[index];
330 }
331
332 if (vals_words == 0)
333 make_vals_words();
334
335 return &(vals_words[index].as_word);
336 }
337
vpi_get(int code)338 int __vpiArrayWord::as_word_t::vpi_get(int code)
339 {
340 struct __vpiArrayWord*obj = array_var_word_from_handle(this);
341 assert(obj);
342 struct __vpiArrayBase*parent = obj->get_parent();
343 t_vpi_value val;
344
345 switch (code) {
346 case vpiLineNo:
347 return 0; // Not implemented for now!
348
349 case vpiSize:
350 return parent->get_word_size();
351
352 case vpiLeftRange:
353 val.format = vpiIntVal;
354 parent->get_left_range()->vpi_get_value(&val);
355 assert(val.format == vpiIntVal);
356 return val.value.integer;
357
358 case vpiRightRange:
359 val.format = vpiIntVal;
360 parent->get_right_range()->vpi_get_value(&val);
361 assert(val.format == vpiIntVal);
362 return val.value.integer;
363
364 case vpiIndex:
365 {
366 int base_offset = 0;
367 struct __vpiArray*base = dynamic_cast<__vpiArray*> (parent);
368 if (base) {
369 val.format = vpiIntVal;
370 base->first_addr.vpi_get_value(&val);
371 base_offset += val.value.integer;
372 }
373 val.format = vpiIntVal;
374 obj->as_index.vpi_get_value(&val);
375 assert(val.format == vpiIntVal);
376 return val.value.integer + base_offset;
377 }
378
379 case vpiAutomatic:
380 return parent->get_scope()->is_automatic()? 1 : 0;
381
382 #if defined(CHECK_WITH_VALGRIND) || defined(BR916_STOPGAP_FIX)
383 case _vpiFromThr:
384 return _vpiNoThr;
385 #endif
386
387 default:
388 return 0;
389 }
390 }
391
392
vpi_get(int code)393 int __vpiArrayVthrA::vpi_get(int code)
394 {
395 switch (code) {
396 case vpiLineNo:
397 return 0; // Not implemented for now!
398
399 case vpiSize:
400 return array->get_word_size();
401
402 case vpiLeftRange:
403 return array->msb.get_value();
404
405 case vpiRightRange:
406 return array->lsb.get_value();
407
408 case vpiIndex:
409 return (int)get_address() + array->first_addr.get_value();
410
411 case vpiAutomatic:
412 return array->get_scope()->is_automatic() ? 1 : 0;
413
414 #if defined(CHECK_WITH_VALGRIND) || defined(BR916_STOPGAP_FIX)
415 case _vpiFromThr:
416 return _vpi_at_A;
417 #endif
418
419 // If address_handle is not zero we definitely have a
420 // variable.
421 case vpiConstantSelect:
422 return address_handle == 0;
423
424 default:
425 return 0;
426 }
427 }
428
vpi_get_str(int code)429 char* __vpiArrayVthrA::vpi_get_str(int code)
430 {
431 if (code == vpiFile) { // Not implemented for now!
432 return simple_set_rbuf_str(file_names[0]);
433 }
434
435 char sidx [64];
436 snprintf(sidx, 63, "%d", (int)get_address() + array->first_addr.get_value());
437 return generic_get_str(code, array->get_scope(), array->name, sidx);
438 }
439
vpi_get_value(p_vpi_value vp)440 void __vpiArrayVthrA::vpi_get_value(p_vpi_value vp)
441 {
442 assert(array);
443
444 unsigned index = get_address();
445 if (vpi_array_is_real(array)) {
446 double tmp = array->get_word_r(index);
447 vpip_real_get_value(tmp, vp);
448 } else if (vpi_array_is_string(array)) {
449 string tmp = array->get_word_str(index);
450 vpip_string_get_value(tmp, vp);
451 } else {
452 vvp_vector4_t tmp = array->get_word(index);
453 unsigned width = array->get_word_size();
454 vpip_vec4_get_value(tmp, width, array->signed_flag, vp);
455 }
456 }
457
vpi_put_value(p_vpi_value vp,int)458 vpiHandle __vpiArrayVthrA::vpi_put_value(p_vpi_value vp, int)
459 {
460 unsigned index = get_address();
461
462 assert(array);
463 assert(index < array->get_size());
464
465 if (vpi_array_is_real(array)) {
466 double val = real_from_vpi_value(vp);
467 array->set_word(index, val);
468 } else {
469 unsigned width = array->get_word_size();
470 vvp_vector4_t val = vec4_from_vpi_value(vp, width);
471 array->set_word(index, 0, val);
472 }
473
474 return this;
475 }
476
vpi_handle(int code)477 vpiHandle __vpiArrayVthrA::vpi_handle(int code)
478 {
479 switch (code) {
480 case vpiIndex:
481 break; // Not implemented!
482
483 case vpiLeftRange:
484 return &array->msb;
485
486 case vpiRightRange:
487 return &array->lsb;
488
489 case vpiParent:
490 case vpiArray:
491 return array;
492
493 case vpiScope:
494 return array->get_scope();
495
496 case vpiModule:
497 return vpip_module(array->get_scope());
498 }
499
500 return 0;
501 }
502
503
vpi_get(int code)504 int __vpiArrayVthrAPV::vpi_get(int code)
505 {
506 switch (code) {
507 case vpiLineNo:
508 return 0; // Not implemented for now!
509
510 case vpiSize:
511 return part_wid;
512
513 case vpiLeftRange:
514 return part_bit + part_wid - 1;
515
516 case vpiRightRange:
517 return part_bit;
518
519 case vpiAutomatic:
520 return array->get_scope()->is_automatic() ? 1 : 0;
521
522 #if defined(CHECK_WITH_VALGRIND) || defined(BR916_STOPGAP_FIX)
523 case _vpiFromThr:
524 return _vpi_at_APV;
525 #endif
526
527 case vpiConstantSelect:
528 return 1;
529
530 default:
531 return 0;
532 }
533 }
534
vpi_get_str(int code)535 char* __vpiArrayVthrAPV::vpi_get_str(int code)
536 {
537 if (code == vpiFile) { // Not implemented for now!
538 return simple_set_rbuf_str(file_names[0]);
539 }
540
541 char sidx [64];
542 snprintf(sidx, 63, "%u", word_sel + array->first_addr.get_value());
543 return generic_get_str(code, array->get_scope(), array->name, sidx);
544 }
545
vpi_get_value(p_vpi_value vp)546 void __vpiArrayVthrAPV::vpi_get_value(p_vpi_value vp)
547 {
548 assert(array);
549
550 unsigned index = word_sel;
551 if (vpi_array_is_real(array)) {
552 double tmp = array->get_word_r(index);
553 vpip_real_get_value(tmp, vp);
554 } else {
555 vvp_vector4_t tmp = array->get_word(index);
556 tmp = tmp.subvalue(part_bit, part_wid);
557 vpip_vec4_get_value(tmp, part_wid, array->signed_flag, vp);
558 }
559 }
560
vpi_handle(int code)561 vpiHandle __vpiArrayVthrAPV::vpi_handle(int code)
562 {
563 switch (code) {
564 // Not currently implemented. We would need to create a VPI
565 // object for the memory word.
566 case vpiParent:
567 return 0;
568
569 // Not part of the Verilog standard. We use this internally.
570 case vpiArray:
571 return array;
572
573 case vpiScope:
574 return array->get_scope();
575
576 case vpiModule:
577 return vpip_module(array->get_scope());
578 }
579
580 return 0;
581 }
582
set_word(unsigned address,unsigned part_off,const vvp_vector4_t & val)583 void __vpiArray::set_word(unsigned address, unsigned part_off, const vvp_vector4_t&val)
584 {
585 if (address >= get_size())
586 return;
587
588 if (vals4) {
589 assert(nets == 0);
590 if (part_off != 0 || val.size() != vals_width) {
591 vvp_vector4_t tmp = vals4->get_word(address);
592 if ((part_off + val.size()) > tmp.size()) {
593 cerr << "part_off=" << part_off
594 << " val.size()=" << val.size()
595 << " vals[address].size()=" << tmp.size()
596 << " vals_width=" << vals_width << endl;
597 assert(0);
598 }
599 tmp.set_vec(part_off, val);
600 vals4->set_word(address, tmp);
601 } else {
602 vals4->set_word(address, val);
603 }
604 word_change(address);
605 return;
606 }
607
608 if (vals) {
609 assert(nets == 0);
610 // FIXME: For now, assume no part select of word?
611 assert(part_off==0);
612 assert(val.size() == vals_width);
613 vals->set_word(address, val);
614 word_change(address);
615 return;
616 }
617
618 assert(nets != 0);
619
620 // Select the word of the array that we affect.
621 vpiHandle word = nets[address];
622 struct __vpiSignal*vsig = dynamic_cast<__vpiSignal*>(word);
623 assert(vsig);
624
625 vsig->node->send_vec4_pv(val, part_off, val.size(), vpip_size(vsig), 0);
626 word_change(address);
627 }
628
set_word(unsigned address,double val)629 void __vpiArray::set_word(unsigned address, double val)
630 {
631 assert(vals != 0);
632 assert(nets == 0);
633
634 if (address >= vals->get_size())
635 return;
636
637 vals->set_word(address, val);
638 word_change(address);
639 }
640
set_word(unsigned address,const string & val)641 void __vpiArray::set_word(unsigned address, const string&val)
642 {
643 assert(vals != 0);
644 assert(nets == 0);
645
646 if (address >= vals->get_size())
647 return;
648
649 vals->set_word(address, val);
650 word_change(address);
651 }
652
set_word(unsigned address,const vvp_object_t & val)653 void __vpiArray::set_word(unsigned address, const vvp_object_t&val)
654 {
655 assert(vals != 0);
656 assert(nets == 0);
657
658 if (address >= vals->get_size())
659 return;
660
661 vals->set_word(address, val);
662 word_change(address);
663 }
664
get_word(unsigned address)665 vvp_vector4_t __vpiArray::get_word(unsigned address)
666 {
667 if (vals4) {
668 assert(nets == 0);
669 assert(vals == 0);
670 return vals4->get_word(address);
671 }
672
673 if (vals) {
674 assert(nets == 0);
675 assert(vals4== 0);
676 if (address >= vals->get_size())
677 return vvp_vector4_t(vals_width, BIT4_X);
678
679 vvp_vector4_t val;
680 vals->get_word(address, val);
681 return val;
682 }
683
684 assert(vals4 == 0);
685 assert(vals == 0);
686 assert(nets != 0);
687
688 if (address >= get_size()) {
689 // Reading outside the array. Return X's but get the
690 // width by looking at a word that we know is present.
691 assert(get_size() > 0);
692 vpiHandle word = nets[0];
693 assert(word);
694 struct __vpiSignal*vsig = dynamic_cast<__vpiSignal*>(word);
695 assert(vsig);
696 vvp_signal_value*sig = dynamic_cast<vvp_signal_value*> (vsig->node->fil);
697 assert(sig);
698 return vvp_vector4_t(sig->value_size(), BIT4_X);
699 }
700
701 vpiHandle word = nets[address];
702 struct __vpiSignal*vsig = dynamic_cast<__vpiSignal*>(word);
703 assert(vsig);
704 vvp_signal_value*sig = dynamic_cast<vvp_signal_value*> (vsig->node->fil);
705 assert(sig);
706
707 vvp_vector4_t val;
708 sig->vec4_value(val);
709 return val;
710 }
711
get_word_r(unsigned address)712 double __vpiArray::get_word_r(unsigned address)
713 {
714 if (vals) {
715 assert(vals4 == 0);
716 assert(nets == 0);
717 // In this context, address out of bounds returns 0.0
718 // instead of an error.
719 if (address >= vals->get_size())
720 return 0.0;
721
722 double val;
723 vals->get_word(address, val);
724 return val;
725 }
726
727 assert(nets);
728 vpiHandle word = nets[address];
729 struct __vpiRealVar*vsig = dynamic_cast<__vpiRealVar*>(word);
730 assert(vsig);
731 vvp_signal_value*sig = dynamic_cast<vvp_signal_value*> (vsig->net->fil);
732 assert(sig);
733
734 double val = sig->real_value();
735 return val;
736 }
737
get_word_obj(unsigned address,vvp_object_t & val)738 void __vpiArray::get_word_obj(unsigned address, vvp_object_t&val)
739 {
740 if (vals) {
741 assert(vals4 == 0);
742 assert(nets == 0);
743 // In this context, address out of bounds returns 0.0
744 // instead of an error.
745 if (address >= vals->get_size()) {
746 val = vvp_object_t();
747 return;
748 }
749
750 vals->get_word(address, val);
751 return;
752 }
753
754 assert(nets);
755 // Arrays of string nets not implemented!
756 assert(0);
757 return;
758 }
759
get_word_str(unsigned address)760 string __vpiArray::get_word_str(unsigned address)
761 {
762 if (vals) {
763 assert(vals4 == 0);
764 assert(nets == 0);
765 // In this context, address out of bounds returns 0.0
766 // instead of an error.
767 if (address >= vals->get_size())
768 return "";
769
770 string val;
771 vals->get_word(address, val);
772 return val;
773 }
774
775 assert(nets);
776 // Arrays of string nets not implemented!
777 assert(0);
778 return "";
779 }
780
vpip_make_array(char * label,const char * name,int first_addr,int last_addr,bool signed_flag)781 vpiHandle vpip_make_array(char*label, const char*name,
782 int first_addr, int last_addr,
783 bool signed_flag)
784 {
785 struct __vpiArray*obj = new __vpiArray;
786
787 obj->signed_flag = signed_flag;
788
789 // Assume increasing addresses.
790 if (last_addr >= first_addr) {
791 obj->swap_addr = false;
792 } else {
793 obj->swap_addr = true;
794 int tmp = last_addr;
795 last_addr = first_addr;
796 first_addr = tmp;
797 }
798 assert(last_addr >= first_addr);
799 unsigned array_count = last_addr+1-first_addr;
800
801 // For now, treat all arrays as memories. This is not quite
802 // correct, as arrays are arrays with memories a special case.
803 obj->scope = vpip_peek_current_scope();
804 obj->name = vpip_name_string(name);
805 obj->array_count = array_count;
806
807 obj->first_addr.set_value(first_addr);
808 obj->last_addr .set_value(last_addr);
809
810 // Start off now knowing if we are nets or variables.
811 obj->nets = 0;
812 obj->vals4 = 0;
813 obj->vals = 0;
814 obj->vals_width = 0;
815 obj->vals_words = 0;
816
817 // Initialize (clear) the read-ports list.
818 obj->ports_ = 0;
819 obj->vpi_callbacks = 0;
820
821 /* Add this symbol to the array_symbols table for later lookup. */
822 if (!array_table)
823 array_table = new symbol_map_s<struct __vpiArray>;
824
825 assert(!array_find(label));
826 array_table->sym_set_value(label, obj);
827
828 /* Add this into the table of VPI objects. This is used for
829 contexts that try to look up VPI objects in
830 general. (i.e. arguments to vpi_task calls.) */
831 compile_vpi_symbol(label, obj);
832
833 /* Blindly attach to the scope as an object. */
834 vpip_attach_to_current_scope(obj);
835
836 return obj;
837 }
838
alias_word(unsigned long addr,vpiHandle word,int msb_,int lsb_)839 void __vpiArray::alias_word(unsigned long addr, vpiHandle word, int msb_, int lsb_)
840 {
841 assert(msb.get_value() == msb_);
842 assert(lsb.get_value() == lsb_);
843 assert(addr < get_size());
844 assert(nets);
845 nets[addr] = word;
846 }
847
attach_word(unsigned addr,vpiHandle word)848 void __vpiArray::attach_word(unsigned addr, vpiHandle word)
849 {
850 assert(addr < get_size());
851 assert(nets);
852 nets[addr] = word;
853
854 if (struct __vpiSignal*sig = dynamic_cast<__vpiSignal*>(word)) {
855 vvp_net_t*net = sig->node;
856 assert(net);
857 vvp_vpi_callback*fun = dynamic_cast<vvp_vpi_callback*>(net->fil);
858 assert(fun);
859 fun->attach_as_word(this, addr);
860 sig->is_netarray = 1;
861 sig->within.parent = this;
862 sig->id.index = new __vpiDecConst(addr + first_addr.get_value());
863 // Now we know the data type, update the array signed_flag.
864 signed_flag = sig->signed_flag;
865 return;
866 }
867
868 if (struct __vpiRealVar*sig = dynamic_cast<__vpiRealVar*>(word)) {
869 vvp_net_t*net = sig->net;
870 assert(net);
871 vvp_vpi_callback*fun = dynamic_cast<vvp_vpi_callback*>(net->fil);
872 assert(fun);
873 fun->attach_as_word(this, addr);
874 sig->is_netarray = 1;
875 sig->within.parent = this;
876 sig->id.index = new __vpiDecConst(addr + first_addr.get_value());
877 // Now we know the data type, update the array signed_flag.
878 signed_flag = true;
879 return;
880 }
881 }
882
compile_var_array(char * label,char * name,int last,int first,int msb,int lsb,char signed_flag)883 void compile_var_array(char*label, char*name, int last, int first,
884 int msb, int lsb, char signed_flag)
885 {
886 vpiHandle obj = vpip_make_array(label, name, first, last,
887 signed_flag != 0);
888
889 struct __vpiArray*arr = dynamic_cast<__vpiArray*>(obj);
890
891 /* Make the words. */
892 arr->vals_width = labs(msb-lsb) + 1;
893 if (vpip_peek_current_scope()->is_automatic()) {
894 arr->vals4 = new vvp_vector4array_aa(arr->vals_width,
895 arr->get_size());
896 } else {
897 arr->vals4 = new vvp_vector4array_sa(arr->vals_width,
898 arr->get_size());
899 }
900 arr->msb.set_value(msb);
901 arr->lsb.set_value(lsb);
902
903 count_var_arrays += 1;
904 count_var_array_words += arr->get_size();
905
906 free(label);
907 delete[] name;
908 }
909
compile_var2_array(char * label,char * name,int last,int first,int msb,int lsb,bool signed_flag)910 void compile_var2_array(char*label, char*name, int last, int first,
911 int msb, int lsb, bool signed_flag)
912 {
913 vpiHandle obj = vpip_make_array(label, name, first, last, signed_flag);
914
915 struct __vpiArray*arr = dynamic_cast<__vpiArray*>(obj);
916
917 /* Make the words. */
918 arr->msb.set_value(msb);
919 arr->lsb.set_value(lsb);
920 arr->vals_width = labs(msb-lsb) + 1;
921
922 assert(! arr->nets);
923 if (lsb == 0 && msb == 7 && signed_flag) {
924 arr->vals = new vvp_darray_atom<int8_t>(arr->get_size());
925 } else if (lsb == 0 && msb == 7 && !signed_flag) {
926 arr->vals = new vvp_darray_atom<uint8_t>(arr->get_size());
927 } else if (lsb == 0 && msb == 15 && signed_flag) {
928 arr->vals = new vvp_darray_atom<int16_t>(arr->get_size());
929 } else if (lsb == 0 && msb == 15 && !signed_flag) {
930 arr->vals = new vvp_darray_atom<uint16_t>(arr->get_size());
931 } else if (lsb == 0 && msb == 31 && signed_flag) {
932 arr->vals = new vvp_darray_atom<int32_t>(arr->get_size());
933 } else if (lsb == 0 && msb == 31 && !signed_flag) {
934 arr->vals = new vvp_darray_atom<uint32_t>(arr->get_size());
935 } else if (lsb == 0 && msb == 63 && signed_flag) {
936 arr->vals = new vvp_darray_atom<int64_t>(arr->get_size());
937 } else if (lsb == 0 && msb == 63 && !signed_flag) {
938 arr->vals = new vvp_darray_atom<uint64_t>(arr->get_size());
939 } else {
940 arr->vals = new vvp_darray_vec2(arr->get_size(), arr->vals_width);
941 }
942 count_var_arrays += 1;
943 count_var_array_words += arr->get_size();
944
945 free(label);
946 delete[] name;
947 }
948
compile_real_array(char * label,char * name,int last,int first)949 void compile_real_array(char*label, char*name, int last, int first)
950 {
951 vpiHandle obj = vpip_make_array(label, name, first, last, true);
952
953 struct __vpiArray*arr = dynamic_cast<__vpiArray*>(obj);
954
955 /* Make the words. */
956 arr->vals = new vvp_darray_real(arr->get_size());
957 arr->vals_width = 1;
958
959 count_real_arrays += 1;
960 count_real_array_words += arr->get_size();
961
962 free(label);
963 delete[] name;
964 }
965
compile_string_array(char * label,char * name,int last,int first)966 void compile_string_array(char*label, char*name, int last, int first)
967 {
968 vpiHandle obj = vpip_make_array(label, name, first, last, true);
969
970 struct __vpiArray*arr = dynamic_cast<__vpiArray*>(obj);
971
972 /* Make the words. */
973 arr->vals = new vvp_darray_string(arr->get_size());
974 arr->vals_width = 1;
975
976 count_real_arrays += 1;
977 count_real_array_words += arr->get_size();
978
979 free(label);
980 delete[] name;
981 }
982
compile_object_array(char * label,char * name,int last,int first)983 void compile_object_array(char*label, char*name, int last, int first)
984 {
985 vpiHandle obj = vpip_make_array(label, name, first, last, true);
986
987 struct __vpiArray*arr = dynamic_cast<__vpiArray*>(obj);
988
989 /* Make the words. */
990 arr->vals = new vvp_darray_object(arr->get_size());
991 arr->vals_width = 1;
992
993 count_real_arrays += 1;
994 count_real_array_words += arr->get_size();
995
996 free(label);
997 delete[] name;
998 }
999
compile_net_array(char * label,char * name,int last,int first)1000 void compile_net_array(char*label, char*name, int last, int first)
1001 {
1002 // At this point we don't know the array data type, so we
1003 // initialise signed_flag to false. This will be corrected
1004 // (if necessary) when we attach words to the array.
1005 vpiHandle obj = vpip_make_array(label, name, first, last, false);
1006
1007 struct __vpiArray*arr = dynamic_cast<__vpiArray*>(obj);
1008 arr->nets = (vpiHandle*)calloc(arr->get_size(), sizeof(vpiHandle));
1009
1010 count_net_arrays += 1;
1011 count_net_array_words += arr->get_size();
1012
1013 free(label);
1014 delete[] name;
1015 }
1016
1017 class vvp_fun_arrayport : public vvp_net_fun_t {
1018
1019 public:
1020 explicit vvp_fun_arrayport(vvp_array_t mem, vvp_net_t*net);
1021 explicit vvp_fun_arrayport(vvp_array_t mem, vvp_net_t*net, long addr);
1022 ~vvp_fun_arrayport();
1023
1024 virtual void check_word_change(unsigned long addr) = 0;
1025
1026 protected:
1027 vvp_array_t arr_;
1028 vvp_net_t *net_;
1029 unsigned long addr_;
1030
1031 friend void array_attach_port(vvp_array_t, vvp_fun_arrayport*);
1032 friend void __vpiArray::word_change(unsigned long);
1033 vvp_fun_arrayport*next_;
1034 };
1035
vvp_fun_arrayport(vvp_array_t mem,vvp_net_t * net)1036 vvp_fun_arrayport::vvp_fun_arrayport(vvp_array_t mem, vvp_net_t*net)
1037 : arr_(mem), net_(net), addr_(0)
1038 {
1039 next_ = 0;
1040 }
1041
vvp_fun_arrayport(vvp_array_t mem,vvp_net_t * net,long addr)1042 vvp_fun_arrayport::vvp_fun_arrayport(vvp_array_t mem, vvp_net_t*net, long addr)
1043 : arr_(mem), net_(net), addr_(addr)
1044 {
1045 next_ = 0;
1046 }
1047
~vvp_fun_arrayport()1048 vvp_fun_arrayport::~vvp_fun_arrayport()
1049 {
1050 }
1051
1052 class vvp_fun_arrayport_sa : public vvp_fun_arrayport {
1053
1054 public:
1055 explicit vvp_fun_arrayport_sa(vvp_array_t mem, vvp_net_t*net);
1056 explicit vvp_fun_arrayport_sa(vvp_array_t mem, vvp_net_t*net, long addr);
1057 ~vvp_fun_arrayport_sa();
1058
1059 void check_word_change(unsigned long addr);
1060
1061 void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
1062 vvp_context_t);
1063
1064 private:
1065 };
1066
vvp_fun_arrayport_sa(vvp_array_t mem,vvp_net_t * net)1067 vvp_fun_arrayport_sa::vvp_fun_arrayport_sa(vvp_array_t mem, vvp_net_t*net)
1068 : vvp_fun_arrayport(mem, net)
1069 {
1070 }
1071
vvp_fun_arrayport_sa(vvp_array_t mem,vvp_net_t * net,long addr)1072 vvp_fun_arrayport_sa::vvp_fun_arrayport_sa(vvp_array_t mem, vvp_net_t*net, long addr)
1073 : vvp_fun_arrayport(mem, net, addr)
1074 {
1075 }
1076
~vvp_fun_arrayport_sa()1077 vvp_fun_arrayport_sa::~vvp_fun_arrayport_sa()
1078 {
1079 }
1080
recv_vec4(vvp_net_ptr_t port,const vvp_vector4_t & bit,vvp_context_t)1081 void vvp_fun_arrayport_sa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
1082 vvp_context_t)
1083 {
1084 bool addr_valid_flag;
1085
1086 switch (port.port()) {
1087
1088 case 0: // Address input
1089 addr_valid_flag = vector4_to_value(bit, addr_);
1090 if (! addr_valid_flag)
1091 addr_ = arr_->get_size();
1092 if (vpi_array_is_real(arr_))
1093 port.ptr()->send_real(arr_->get_word_r(addr_), 0);
1094 else
1095 port.ptr()->send_vec4(arr_->get_word(addr_), 0);
1096
1097 break;
1098
1099 default:
1100 fprintf(stdout, "XXXX write ports not implemented.\n");
1101 assert(0);
1102 }
1103 }
1104
check_word_change(unsigned long addr)1105 void vvp_fun_arrayport_sa::check_word_change(unsigned long addr)
1106 {
1107 if (addr != addr_) return;
1108
1109 if (vpi_array_is_real(arr_)) {
1110 net_->send_real(arr_->get_word_r(addr_), 0);
1111 } else {
1112 net_->send_vec4(arr_->get_word(addr_), 0);
1113 }
1114 }
1115
1116 class vvp_fun_arrayport_aa : public vvp_fun_arrayport, public automatic_hooks_s {
1117
1118 public:
1119 explicit vvp_fun_arrayport_aa(vvp_array_t mem, vvp_net_t*net);
1120 explicit vvp_fun_arrayport_aa(vvp_array_t mem, vvp_net_t*net, long addr);
1121 ~vvp_fun_arrayport_aa();
1122
1123 void alloc_instance(vvp_context_t context);
1124 void reset_instance(vvp_context_t context);
1125 #ifdef CHECK_WITH_VALGRIND
1126 void free_instance(vvp_context_t context);
1127 #endif
1128
1129 void check_word_change(unsigned long addr);
1130
1131 void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
1132 vvp_context_t context);
1133
1134 private:
1135 void check_word_change_(unsigned long addr, vvp_context_t context);
1136
1137 __vpiScope*context_scope_;
1138 unsigned context_idx_;
1139 };
1140
vvp_fun_arrayport_aa(vvp_array_t mem,vvp_net_t * net)1141 vvp_fun_arrayport_aa::vvp_fun_arrayport_aa(vvp_array_t mem, vvp_net_t*net)
1142 : vvp_fun_arrayport(mem, net)
1143 {
1144 context_scope_ = vpip_peek_context_scope();
1145 context_idx_ = vpip_add_item_to_context(this, context_scope_);
1146 }
1147
vvp_fun_arrayport_aa(vvp_array_t mem,vvp_net_t * net,long addr)1148 vvp_fun_arrayport_aa::vvp_fun_arrayport_aa(vvp_array_t mem, vvp_net_t*net, long addr)
1149 : vvp_fun_arrayport(mem, net, addr)
1150 {
1151 context_scope_ = vpip_peek_context_scope();
1152 context_idx_ = vpip_add_item_to_context(this, context_scope_);
1153 }
1154
~vvp_fun_arrayport_aa()1155 vvp_fun_arrayport_aa::~vvp_fun_arrayport_aa()
1156 {
1157 }
1158
alloc_instance(vvp_context_t context)1159 void vvp_fun_arrayport_aa::alloc_instance(vvp_context_t context)
1160 {
1161 unsigned long*addr = new unsigned long;
1162 vvp_set_context_item(context, context_idx_, addr);
1163
1164 *addr = addr_;
1165 }
1166
reset_instance(vvp_context_t context)1167 void vvp_fun_arrayport_aa::reset_instance(vvp_context_t context)
1168 {
1169 unsigned long*addr = static_cast<unsigned long*>
1170 (vvp_get_context_item(context, context_idx_));
1171
1172 *addr = addr_;
1173 }
1174
1175 #ifdef CHECK_WITH_VALGRIND
free_instance(vvp_context_t context)1176 void vvp_fun_arrayport_aa::free_instance(vvp_context_t context)
1177 {
1178 unsigned long*addr = static_cast<unsigned long*>
1179 (vvp_get_context_item(context, context_idx_));
1180 delete addr;
1181 }
1182 #endif
1183
recv_vec4(vvp_net_ptr_t port,const vvp_vector4_t & bit,vvp_context_t context)1184 void vvp_fun_arrayport_aa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
1185 vvp_context_t context)
1186 {
1187 if (context) {
1188 unsigned long*addr = static_cast<unsigned long*>
1189 (vvp_get_context_item(context, context_idx_));
1190
1191 bool addr_valid_flag;
1192
1193 switch (port.port()) {
1194
1195 case 0: // Address input
1196 addr_valid_flag = vector4_to_value(bit, *addr);
1197 if (! addr_valid_flag) *addr = arr_->get_size();
1198 if (vpi_array_is_real(arr_)) {
1199 port.ptr()->send_real(arr_->get_word_r(*addr),
1200 context);
1201 } else {
1202 port.ptr()->send_vec4(arr_->get_word(*addr),
1203 context);
1204 }
1205 break;
1206
1207 default:
1208 fprintf(stdout, "XXXX write ports not implemented.\n");
1209 assert(0);
1210 }
1211 } else {
1212 context = context_scope_->live_contexts;
1213 while (context) {
1214 recv_vec4(port, bit, context);
1215 context = vvp_get_next_context(context);
1216 }
1217 }
1218 }
1219
check_word_change_(unsigned long addr,vvp_context_t context)1220 void vvp_fun_arrayport_aa::check_word_change_(unsigned long addr,
1221 vvp_context_t context)
1222 {
1223 unsigned long*port_addr = static_cast<unsigned long*>
1224 (vvp_get_context_item(context, context_idx_));
1225
1226 if (addr != *port_addr)
1227 return;
1228
1229 if (vpi_array_is_real(arr_)) {
1230 net_->send_real(arr_->get_word_r(addr), context);
1231 } else {
1232 net_->send_vec4(arr_->get_word(addr), context);
1233 }
1234 }
1235
check_word_change(unsigned long addr)1236 void vvp_fun_arrayport_aa::check_word_change(unsigned long addr)
1237 {
1238 if (arr_->get_scope()->is_automatic()) {
1239 assert(vthread_get_wt_context());
1240 check_word_change_(addr, vthread_get_wt_context());
1241 } else {
1242 vvp_context_t context = context_scope_->live_contexts;
1243 while (context) {
1244 check_word_change_(addr, context);
1245 context = vvp_get_next_context(context);
1246 }
1247 }
1248 }
1249
array_attach_port(vvp_array_t array,vvp_fun_arrayport * fun)1250 static void array_attach_port(vvp_array_t array, vvp_fun_arrayport*fun)
1251 {
1252 assert(fun->next_ == 0);
1253 fun->next_ = array->ports_;
1254 array->ports_ = fun;
1255 if (!array->get_scope()->is_automatic()) {
1256 /* propagate initial values for variable arrays */
1257 if (array->vals4) {
1258 vvp_vector4_t tmp(array->vals_width, BIT4_X);
1259 schedule_init_propagate(fun->net_, tmp);
1260 }
1261 if (array->vals) {
1262 schedule_init_propagate(fun->net_, 0.0);
1263 }
1264 }
1265 }
1266
1267 class array_word_value_callback : public value_callback {
1268 public:
array_word_value_callback(p_cb_data data)1269 inline explicit array_word_value_callback(p_cb_data data)
1270 : value_callback(data)
1271 { }
1272
1273 public:
1274 long word_addr;
1275 };
1276
word_change(unsigned long addr)1277 void __vpiArray::word_change(unsigned long addr)
1278 {
1279 for (vvp_fun_arrayport*cur = ports_; cur; cur = cur->next_)
1280 cur->check_word_change(addr);
1281
1282 // Run callbacks attached to the array itself.
1283 struct __vpiCallback *next = vpi_callbacks;
1284 struct __vpiCallback *prev = 0;
1285
1286 while (next) {
1287 array_word_value_callback*cur = dynamic_cast<array_word_value_callback*>(next);
1288 next = cur->next;
1289
1290 // Skip callbacks that are not for me. -1 is for every element.
1291 if (cur->word_addr != (long)addr && cur->word_addr != -1) {
1292 prev = cur;
1293 continue;
1294 }
1295
1296 // For whole array callbacks we need to set the index.
1297 if (cur->word_addr == -1) {
1298 cur->cb_data.index = (PLI_INT32) ((int)addr +
1299 first_addr.get_value());
1300 }
1301
1302 if (cur->cb_data.cb_rtn != 0) {
1303 if (cur->test_value_callback_ready()) {
1304 if (cur->cb_data.value) {
1305 if (vpi_array_is_real(this)) {
1306 double val = 0.0;
1307 if (addr < vals->get_size())
1308 vals->get_word(addr, val);
1309 vpip_real_get_value(val, cur->cb_data.value);
1310 } else {
1311 vpip_vec4_get_value(vals4->get_word(addr),
1312 vals_width,
1313 signed_flag,
1314 cur->cb_data.value);
1315 }
1316 }
1317
1318 callback_execute(cur);
1319 }
1320
1321 prev = cur;
1322
1323 } else if (prev == 0) {
1324
1325 vpi_callbacks = next;
1326 cur->next = 0;
1327 delete cur;
1328
1329 } else {
1330 assert(prev->next == cur);
1331 prev->next = next;
1332 cur->next = 0;
1333 delete cur;
1334 }
1335 }
1336 }
1337
1338 class array_resolv_list_t : public resolv_list_s {
1339
1340 public:
array_resolv_list_t(char * lab)1341 explicit array_resolv_list_t(char*lab) : resolv_list_s(lab) {
1342 array = 0;
1343 }
1344
1345 vvp_array_t*array;
1346 bool resolve(bool mes);
1347
1348 private:
1349 };
1350
resolve(bool mes)1351 bool array_resolv_list_t::resolve(bool mes)
1352 {
1353 *array = array_find(label());
1354 if (*array == 0) {
1355 assert(!mes);
1356 return false;
1357 }
1358 return true;
1359 }
1360
1361 class array_port_resolv_list_t : public resolv_list_s {
1362
1363 public:
1364 explicit array_port_resolv_list_t(char* lab, bool use_addr__,
1365 long addr__);
1366
1367 vvp_net_t*ptr;
1368 bool use_addr;
1369 long addr;
1370 bool resolve(bool mes);
1371
1372 private:
1373 };
1374
array_port_resolv_list_t(char * lab,bool use_addr__,long addr__)1375 array_port_resolv_list_t::array_port_resolv_list_t(char *lab, bool use_addr__,
1376 long addr__)
1377 : resolv_list_s(lab), use_addr(use_addr__), addr(addr__)
1378 {
1379 ptr = new vvp_net_t;
1380 }
1381
resolve(bool mes)1382 bool array_port_resolv_list_t::resolve(bool mes)
1383 {
1384 vvp_array_t mem = array_find(label());
1385 if (mem == 0) {
1386 assert(mem || !mes);
1387 return false;
1388 }
1389
1390 vvp_fun_arrayport*fun;
1391 if (use_addr)
1392 if (vpip_peek_current_scope()->is_automatic())
1393 fun = new vvp_fun_arrayport_aa(mem, ptr, addr);
1394 else
1395 fun = new vvp_fun_arrayport_sa(mem, ptr, addr);
1396 else
1397 if (vpip_peek_current_scope()->is_automatic())
1398 fun = new vvp_fun_arrayport_aa(mem, ptr);
1399 else
1400 fun = new vvp_fun_arrayport_sa(mem, ptr);
1401 ptr->fun = fun;
1402
1403 array_attach_port(mem, fun);
1404
1405 return true;
1406 }
1407
1408 class array_word_part_callback : public array_word_value_callback {
1409 public:
1410 explicit array_word_part_callback(p_cb_data data);
1411 ~array_word_part_callback();
1412
1413 bool test_value_callback_ready(void);
1414
1415 private:
1416 char*value_bits_;
1417 };
1418
array_word_part_callback(p_cb_data data)1419 array_word_part_callback::array_word_part_callback(p_cb_data data)
1420 : array_word_value_callback(data)
1421 {
1422 // Get the initial value of the part, to use as a reference.
1423 struct __vpiArrayVthrAPV*apvword = dynamic_cast<__vpiArrayVthrAPV*>(data->obj);
1424 s_vpi_value tmp_value;
1425 tmp_value.format = vpiBinStrVal;
1426 apvword->vpi_get_value(&tmp_value);
1427
1428 value_bits_ = new char[apvword->part_wid+1];
1429
1430 memcpy(value_bits_, tmp_value.value.str, apvword->part_wid);
1431 value_bits_[apvword->part_wid] = 0;
1432 }
1433
~array_word_part_callback()1434 array_word_part_callback::~array_word_part_callback()
1435 {
1436 delete[]value_bits_;
1437 }
1438
test_value_callback_ready(void)1439 bool array_word_part_callback::test_value_callback_ready(void)
1440 {
1441 struct __vpiArrayVthrAPV*apvword = dynamic_cast<__vpiArrayVthrAPV*>(cb_data.obj);
1442 assert(apvword);
1443
1444 // Get a reference value that can be used to compare with an
1445 // updated value.
1446 s_vpi_value tmp_value;
1447 tmp_value.format = vpiBinStrVal;
1448 apvword->vpi_get_value(&tmp_value);
1449
1450 if (memcmp(value_bits_, tmp_value.value.str, apvword->part_wid) == 0)
1451 return false;
1452
1453 memcpy(value_bits_, tmp_value.value.str, apvword->part_wid);
1454 return true;
1455
1456 }
1457
vpip_array_word_change(p_cb_data data)1458 value_callback*vpip_array_word_change(p_cb_data data)
1459 {
1460 struct __vpiArray*parent = 0;
1461 array_word_value_callback*cbh = 0;
1462 if (struct __vpiArrayWord*word = array_var_word_from_handle(data->obj)) {
1463 parent = (__vpiArray*) word->get_parent();
1464 unsigned addr = word->get_index();
1465 cbh = new array_word_value_callback(data);
1466 cbh->word_addr = addr;
1467
1468 } else if (struct __vpiArrayVthrA*tword = dynamic_cast<__vpiArrayVthrA*>(data->obj)) {
1469 parent = tword->array;
1470 cbh = new array_word_value_callback(data);
1471 cbh->word_addr = tword->address;
1472
1473 } else if (struct __vpiArrayVthrAPV*apvword = dynamic_cast<__vpiArrayVthrAPV*>(data->obj)) {
1474 parent = apvword->array;
1475 cbh = new array_word_part_callback(data);
1476 cbh->word_addr = apvword->word_sel;
1477 }
1478
1479 assert(cbh);
1480 assert(parent);
1481 cbh->next = parent->vpi_callbacks;
1482 parent->vpi_callbacks = cbh;
1483
1484 return cbh;
1485 }
1486
vpip_array_change(p_cb_data data)1487 value_callback* vpip_array_change(p_cb_data data)
1488 {
1489 array_word_value_callback*cbh = new array_word_value_callback(data);
1490 assert(data->obj);
1491
1492 struct __vpiArray*arr = dynamic_cast<__vpiArray*>(data->obj);
1493 cbh->word_addr = -1; // This is a callback for every element.
1494 cbh->next = arr->vpi_callbacks;
1495 arr->vpi_callbacks = cbh;
1496 return cbh;
1497 }
1498
compile_array_port(char * label,char * array,char * addr)1499 void compile_array_port(char*label, char*array, char*addr)
1500 {
1501 array_port_resolv_list_t*resolv_mem
1502 = new array_port_resolv_list_t(array, false, 0);
1503
1504 define_functor_symbol(label, resolv_mem->ptr);
1505 free(label);
1506 // Connect the port-0 input as the address.
1507 input_connect(resolv_mem->ptr, 0, addr);
1508
1509 resolv_submit(resolv_mem);
1510 }
1511
compile_array_port(char * label,char * array,long addr)1512 void compile_array_port(char*label, char*array, long addr)
1513 {
1514 array_port_resolv_list_t*resolv_mem
1515 = new array_port_resolv_list_t(array, true, addr);
1516
1517 define_functor_symbol(label, resolv_mem->ptr);
1518 free(label);
1519
1520 resolv_submit(resolv_mem);
1521 }
1522
compile_array_alias(char * label,char * name,char * src)1523 void compile_array_alias(char*label, char*name, char*src)
1524 {
1525 vvp_array_t mem = array_find(src);
1526 assert(mem);
1527
1528 struct __vpiArray*obj = new __vpiArray;
1529
1530 obj->scope = vpip_peek_current_scope();
1531 obj->name = vpip_name_string(name);
1532 obj->array_count = mem->array_count;
1533 obj->signed_flag = mem->signed_flag;
1534
1535 // Need to set an accurate range of addresses.
1536 obj->first_addr = mem->first_addr;
1537 obj->last_addr = mem->last_addr;
1538 obj->swap_addr = mem->swap_addr;
1539
1540 obj->msb = mem->msb;
1541 obj->lsb = mem->lsb;
1542
1543 // Share the words with the source array.
1544 obj->nets = mem->nets;
1545 obj->vals4 = mem->vals4;
1546 obj->vals = mem->vals;
1547 obj->vals_width = mem->vals_width;
1548 obj->vals_words = mem->vals_words;
1549
1550 obj->ports_ = 0;
1551 obj->vpi_callbacks = 0;
1552
1553 assert(array_table);
1554 assert(!array_find(label));
1555 array_table->sym_set_value(label, obj);
1556
1557 compile_vpi_symbol(label, obj);
1558 vpip_attach_to_current_scope(obj);
1559
1560 free(label);
1561 free(name);
1562 free(src);
1563 }
1564
1565 /*
1566 * &A<label,addr>
1567 * This represents a VPI handle for an addressed array. This comes
1568 * from expressions like "label[addr]" where "label" is the array and
1569 * "addr" is the canonical address of the desired word.
1570 */
vpip_make_vthr_A(char * label,unsigned addr)1571 vpiHandle vpip_make_vthr_A(char*label, unsigned addr)
1572 {
1573 struct __vpiArrayVthrA*obj = new __vpiArrayVthrA;
1574
1575 array_resolv_list_t*resolv_mem
1576 = new array_resolv_list_t(label);
1577
1578 resolv_mem->array = &obj->array;
1579 resolv_submit(resolv_mem);
1580
1581 obj->address_handle = 0;
1582 obj->address = addr;
1583
1584 return obj;
1585 }
1586
1587 /*
1588 * &A<label,symbol>
1589 * This represents a VPI handle for an addressed word, where the
1590 * word address is calculated from the VPI object that symbol
1591 * represents. The expression that leads to this looks like label[symbol].
1592 */
vpip_make_vthr_A(char * label,char * symbol)1593 vpiHandle vpip_make_vthr_A(char*label, char*symbol)
1594 {
1595 struct __vpiArrayVthrA*obj = new __vpiArrayVthrA;
1596
1597 array_resolv_list_t*resolv_mem
1598 = new array_resolv_list_t(label);
1599
1600 resolv_mem->array = &obj->array;
1601 resolv_submit(resolv_mem);
1602
1603 obj->address_handle = 0;
1604 compile_vpi_lookup(&obj->address_handle, symbol);
1605 obj->address = 0;
1606
1607 return obj;
1608 }
1609
vpip_make_vthr_A(char * label,vpiHandle handle)1610 vpiHandle vpip_make_vthr_A(char*label, vpiHandle handle)
1611 {
1612 struct __vpiArrayVthrA*obj = new __vpiArrayVthrA;
1613
1614 array_resolv_list_t*resolv_mem
1615 = new array_resolv_list_t(label);
1616
1617 resolv_mem->array = &obj->array;
1618 resolv_submit(resolv_mem);
1619
1620 obj->address_handle = handle;
1621 obj->address = 0;
1622
1623 return obj;
1624 }
1625
vpip_make_vthr_APV(char * label,unsigned index,unsigned bit,unsigned wid)1626 vpiHandle vpip_make_vthr_APV(char*label, unsigned index, unsigned bit, unsigned wid)
1627 {
1628 struct __vpiArrayVthrAPV*obj = new __vpiArrayVthrAPV;
1629
1630 array_resolv_list_t*resolv_mem
1631 = new array_resolv_list_t(label);
1632
1633 resolv_mem->array = &obj->array;
1634 resolv_submit(resolv_mem);
1635
1636 obj->word_sel = index;
1637 obj->part_bit = bit;
1638 obj->part_wid = wid;
1639
1640 return obj;
1641 }
1642
compile_array_cleanup(void)1643 void compile_array_cleanup(void)
1644 {
1645 delete array_table;
1646 array_table = 0;
1647 }
1648
1649 #ifdef CHECK_WITH_VALGRIND
memory_delete(vpiHandle item)1650 void memory_delete(vpiHandle item)
1651 {
1652 struct __vpiArray*arr = (struct __vpiArray*) item;
1653 if (arr->vals_words) delete [] (arr->vals_words-1);
1654
1655 // if (arr->vals4) {}
1656 // Delete the individual words?
1657 // constant_delete(handle)?
1658 delete arr->vals4;
1659
1660 // if (arr->vals) {}
1661 // Delete the individual words?
1662 // constant_delete(handle)?
1663 delete arr->vals;
1664
1665 if (arr->nets) {
1666 for (unsigned idx = 0; idx < arr->get_size(); idx += 1) {
1667 if (struct __vpiSignal*sig =
1668 dynamic_cast<__vpiSignal*>(arr->nets[idx])) {
1669 // Delete the individual words?
1670 constant_delete(sig->id.index);
1671 /* These should only be the real words. */
1672 } else {
1673 assert(arr->nets[idx]->get_type_code() ==
1674 vpiRealVar);
1675 struct __vpiRealVar *sigr = (struct __vpiRealVar *)
1676 arr->nets[idx];
1677 constant_delete(sigr->id.index);
1678 // Why are only the real words still here?
1679 delete arr->nets[idx];
1680 }
1681 }
1682 free(arr->nets);
1683 }
1684
1685 while (arr->vpi_callbacks) {
1686 struct __vpiCallback*tmp = arr->vpi_callbacks->next;
1687 delete arr->vpi_callbacks;
1688 arr->vpi_callbacks = tmp;
1689 }
1690
1691 delete arr;
1692 }
1693
A_delete(vpiHandle item)1694 void A_delete(vpiHandle item)
1695 {
1696 struct __vpiArrayVthrA*obj = (struct __vpiArrayVthrA*) item;
1697 if (obj->address_handle) {
1698 switch (obj->address_handle->get_type_code()) {
1699 case vpiMemoryWord:
1700 if (vpi_get(_vpiFromThr, obj->address_handle) == _vpi_at_A) {
1701 A_delete(obj->address_handle);
1702 }
1703 break;
1704 case vpiPartSelect:
1705 assert(vpi_get(_vpiFromThr, obj->address_handle) ==
1706 _vpi_at_PV);
1707 PV_delete(obj->address_handle);
1708 break;
1709 }
1710 }
1711
1712 delete obj;
1713 }
1714
APV_delete(vpiHandle item)1715 void APV_delete(vpiHandle item)
1716 {
1717 struct __vpiArrayVthrAPV*obj = (struct __vpiArrayVthrAPV*) item;
1718 delete obj;
1719 }
1720 #endif
1721