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 # include "compile.h"
21 # include "vpi_priv.h"
22 # include "symbols.h"
23 # include "statistics.h"
24 # include "config.h"
25 #ifdef CHECK_WITH_VALGRIND
26 # include "vvp_cleanup.h"
27 #endif
28 # include <vector>
29 # include <cstring>
30 # include <cstdlib>
31 # include <cassert>
32 # include "ivl_alloc.h"
33
34 using namespace std;
35
36 static vector<vpiHandle> vpip_root_table;
37
vpip_make_root_iterator(void)38 vpiHandle vpip_make_root_iterator(void)
39 {
40 return vpip_make_iterator(vpip_root_table.size(),
41 &vpip_root_table[0], false);
42 }
43
vpip_make_root_iterator(__vpiHandle ** & table,unsigned & ntable)44 void vpip_make_root_iterator(__vpiHandle**&table, unsigned&ntable)
45 {
46 table = &vpip_root_table[0];
47 ntable = vpip_root_table.size();
48 }
49
50 #ifdef CHECK_WITH_VALGRIND
51 void port_delete(__vpiHandle*handle);
52
53 /* Class definitions need to be cleaned up at the end. */
54 static class_type **class_list = 0;
55 static unsigned class_list_count = 0;
56
delete_sub_scopes(__vpiScope * scope)57 static void delete_sub_scopes(__vpiScope *scope)
58 {
59 for (unsigned idx = 0; idx < scope->intern.size(); idx += 1) {
60 vpiHandle item = (scope->intern)[idx];
61 __vpiScope*lscope = static_cast<__vpiScope*>(item);
62 switch(item->get_type_code()) {
63 case vpiFunction:
64 case vpiTask:
65 contexts_delete(lscope);
66 case vpiModule:
67 case vpiGenScope:
68 case vpiNamedBegin:
69 case vpiNamedFork:
70 case vpiClassTypespec:
71 delete_sub_scopes(lscope);
72 vthreads_delete(lscope);
73 delete item;
74 break;
75 case vpiMemory:
76 case vpiNetArray:
77 memory_delete(item);
78 break;
79 case vpiModPath:
80 /* The destination ModPath is cleaned up later. */
81 delete item;
82 break;
83 case vpiNamedEvent:
84 named_event_delete(item);
85 break;
86 case vpiNet:
87 case vpiReg:
88 case vpiIntegerVar:
89 case vpiLongIntVar:
90 case vpiShortIntVar:
91 case vpiIntVar:
92 case vpiByteVar:
93 case vpiBitVar:
94 signal_delete(item);
95 break;
96 case vpiParameter:
97 parameter_delete(item);
98 break;
99 case vpiRealVar:
100 real_delete(item);
101 break;
102 case vpiEnumTypespec:
103 enum_delete(item);
104 break;
105 case vpiPort:
106 port_delete(item);
107 break;
108 case vpiStringVar:
109 string_delete(item);
110 break;
111 case vpiClassVar:
112 class_delete(item);
113 break;
114 case vpiArrayVar:
115 switch(item->vpi_get(vpiArrayType)) {
116 case vpiQueueArray:
117 queue_delete(item);
118 break;
119 case vpiDynamicArray:
120 darray_delete(item);
121 break;
122 default:
123 fprintf(stderr, "Need support for array type: %d\n",
124 item->vpi_get(vpiArrayType));
125 assert(0);
126 break;
127 }
128 break;
129 default:
130 fprintf(stderr, "Need support for type: %d\n",
131 item->get_type_code());
132 assert(0);
133 break;
134 }
135 }
136 scope->intern.clear();
137
138 /* Save any class definitions to clean up later. */
139 map<std::string, class_type*>::iterator citer;
140 for (citer = scope->classes.begin();
141 citer != scope->classes.end(); ++ citer ) {
142 class_list_count += 1;
143 class_list = (class_type **) realloc(class_list,
144 class_list_count*sizeof(class_type **));
145 class_list[class_list_count-1] = citer->second;
146 }
147 }
148
root_table_delete(void)149 void root_table_delete(void)
150 {
151 for (unsigned idx = 0; idx < vpip_root_table.size(); idx += 1) {
152 __vpiScope *scope = static_cast<__vpiScope *>
153 (vpip_root_table[idx]);
154 vthreads_delete(scope);
155 delete_sub_scopes(scope);
156 delete scope;
157 }
158 vpip_root_table.clear();
159
160 /* Clean up all the class definitions. */
161 for (unsigned idx = 0; idx < class_list_count; idx += 1) {
162 class_def_delete(class_list[idx]);
163 }
164 free(class_list);
165 class_list = 0;
166 class_list_count = 0;
167 }
168 #endif
169
construct_scope_fullname(__vpiScope * ref,char * buf)170 static void construct_scope_fullname(__vpiScope*ref, char*buf)
171 {
172 if (ref->scope) {
173 construct_scope_fullname(ref->scope, buf);
174 strcat(buf, ".");
175 }
176
177 strcat(buf, ref->scope_name());
178 }
179
scope_get_type(int code)180 static const char* scope_get_type(int code)
181 {
182 switch (code) {
183 case vpiModule:
184 return "vpiModule";
185 case vpiGenScope:
186 return "vpiGenScope";
187 case vpiFunction:
188 return "vpiFunction";
189 case vpiTask:
190 return "vpiTask";
191 case vpiNamedBegin:
192 return "vpiNamedBegin";
193 case vpiNamedFork:
194 return "vpiNamedFork";
195 default:
196 fprintf(stderr, "VPI error: invalid scope type code %d.\n", code);
197 return NULL;
198 }
199 }
200
scope_get_str(int code,vpiHandle obj)201 static char* scope_get_str(int code, vpiHandle obj)
202 {
203 __vpiScope*ref = dynamic_cast<__vpiScope*>(obj);
204 assert(ref);
205
206 char buf[4096]; // XXX is a fixed buffer size really reliable?
207 const char *p=0;
208 switch (code) {
209 case vpiDefFile:
210 p = file_names[ref->def_file_idx];
211 break;
212
213 case vpiFile:
214 p = file_names[ref->file_idx];
215 break;
216
217 case vpiFullName:
218 buf[0] = 0;
219 construct_scope_fullname(ref, buf);
220 p = buf;
221 break;
222
223 case vpiName:
224 p = ref->scope_name();
225 break;
226
227 case vpiDefName:
228 p = ref->scope_def_name();
229 break;
230
231 case vpiType:
232 p = scope_get_type(code);
233 break;
234
235 default:
236 fprintf(stderr, "VPI error: invalid scope string code %d.\n", code);
237 return NULL;
238 }
239 return simple_set_rbuf_str(p);
240 }
241
scope_get_handle(int code,vpiHandle obj)242 static vpiHandle scope_get_handle(int code, vpiHandle obj)
243 {
244 __vpiScope*rfp = dynamic_cast<__vpiScope*>(obj);
245 assert(rfp);
246
247 switch (code) {
248
249 case vpiScope:
250 return rfp->scope;
251
252 case vpiModule:
253 return rfp->scope;
254 }
255
256 return 0;
257 }
258
259 /* compares vpiType's considering object classes */
compare_types(int code,int type)260 static int compare_types(int code, int type)
261 {
262 /* NOTE: The Verilog VPI does not for any object support
263 vpiScope as an iterator parameter, so it is used here as a
264 means to scan everything in the *current* scope. */
265 if (code == vpiScope)
266 return 1;
267
268 if (code == type)
269 return 1;
270
271 if ( code == vpiInternalScope &&
272 (type == vpiModule ||
273 type == vpiGenScope ||
274 type == vpiFunction ||
275 type == vpiTask ||
276 type == vpiNamedBegin ||
277 type == vpiNamedFork) )
278 return 1;
279
280 if ( code == vpiVariables &&
281 (type == vpiIntegerVar ||
282 type == vpiBitVar ||
283 type == vpiByteVar ||
284 type == vpiShortIntVar ||
285 type == vpiIntVar ||
286 type == vpiLongIntVar ||
287 type == vpiTimeVar ||
288 type == vpiRealVar))
289 return 1;
290
291 return 0;
292 }
293
module_iter_subset(int code,__vpiScope * ref)294 static vpiHandle module_iter_subset(int code, __vpiScope*ref)
295 {
296 unsigned mcnt = 0, ncnt = 0;
297 vpiHandle*args;
298
299 for (unsigned idx = 0 ; idx < ref->intern.size() ; idx += 1)
300 if (compare_types(code, ref->intern[idx]->get_type_code()))
301 mcnt += 1;
302
303 if (mcnt == 0)
304 return 0;
305
306 args = (vpiHandle*)calloc(mcnt, sizeof(vpiHandle));
307 for (unsigned idx = 0 ; idx < ref->intern.size() ; idx += 1)
308 if (compare_types(code, ref->intern[idx]->get_type_code()))
309 args[ncnt++] = ref->intern[idx];
310
311 assert(ncnt == mcnt);
312
313 return vpip_make_iterator(mcnt, args, true);
314 }
315
316 /*
317 * This function implements the vpi_iterate method for vpiModule and
318 * similar objects. The vpi_iterate allows the user to iterate over
319 * things that are contained in the scope object, by generating an
320 * iterator for the requested set of items.
321 */
module_iter(int code,vpiHandle obj)322 static vpiHandle module_iter(int code, vpiHandle obj)
323 {
324 __vpiScope*ref = dynamic_cast<__vpiScope*>(obj);
325 assert(ref);
326
327 return module_iter_subset(code, ref);
328 }
329
330
__vpiScope(const char * nam,const char * tnam,bool auto_flag)331 __vpiScope::__vpiScope(const char*nam, const char*tnam, bool auto_flag)
332 : is_automatic_(auto_flag)
333 {
334 name_ = vpip_name_string(nam);
335 tname_ = vpip_name_string(tnam? tnam : "");
336 }
337
vpi_get(int code)338 int __vpiScope::vpi_get(int code)
339 {
340 switch (code) {
341 case vpiCellInstance:
342 return is_cell? 1 : 0;
343
344 case vpiDefLineNo:
345 return def_lineno;
346
347 case vpiLineNo:
348 return lineno;
349
350 case vpiTimeUnit:
351 return time_units;
352
353 case vpiTimePrecision:
354 return time_precision;
355
356 case vpiTopModule:
357 return 0x0 == scope;
358
359 case vpiAutomatic:
360 return is_automatic_? 1 : 0;
361 }
362
363 return vpiUndefined;
364 }
365
366
vpi_get_str(int code)367 char*__vpiScope::vpi_get_str(int code)
368 { return scope_get_str(code, this); }
369
vpi_handle(int code)370 vpiHandle __vpiScope::vpi_handle(int code)
371 { return scope_get_handle(code, this); }
372
vpi_iterate(int code)373 vpiHandle __vpiScope::vpi_iterate(int code)
374 { return module_iter(code, this); }
375
376
377 class vpiScopeModule : public __vpiScope {
378 public:
vpiScopeModule(const char * nam,const char * tnam)379 inline vpiScopeModule(const char*nam, const char*tnam)
380 : __vpiScope(nam,tnam,false) { }
get_type_code(void) const381 int get_type_code(void) const { return vpiModule; }
382 };
383
384 struct vpiScopePackage : public __vpiScope {
vpiScopePackagevpiScopePackage385 inline vpiScopePackage(const char*nam, const char*tnam)
386 : __vpiScope(nam,tnam) { }
get_type_codevpiScopePackage387 int get_type_code(void) const { return vpiPackage; }
388 };
389
390 struct vpiScopeTask : public __vpiScope {
vpiScopeTaskvpiScopeTask391 inline vpiScopeTask(const char*nam, const char*tnam)
392 : __vpiScope(nam,tnam) { }
get_type_codevpiScopeTask393 int get_type_code(void) const { return vpiTask; }
394 };
395
396 struct vpiScopeTaskAuto : public __vpiScope {
vpiScopeTaskAutovpiScopeTaskAuto397 inline vpiScopeTaskAuto(const char*nam, const char*tnam)
398 : __vpiScope(nam,tnam,true) { }
get_type_codevpiScopeTaskAuto399 int get_type_code(void) const { return vpiTask; }
400 };
401
402 struct vpiScopeBegin : public __vpiScope {
vpiScopeBeginvpiScopeBegin403 inline vpiScopeBegin(const char*nam, const char*tnam)
404 : __vpiScope(nam,tnam,false) { }
get_type_codevpiScopeBegin405 int get_type_code(void) const { return vpiNamedBegin; }
406 };
407
408 class vpiScopeBeginAuto : public __vpiScope {
409 public:
vpiScopeBeginAuto(const char * nam,const char * tnam)410 inline vpiScopeBeginAuto(const char*nam, const char*tnam)
411 : __vpiScope(nam,tnam,true) { }
get_type_code(void) const412 int get_type_code(void) const { return vpiNamedBegin; }
413 };
414
415 struct vpiScopeGenerate : public __vpiScope {
vpiScopeGeneratevpiScopeGenerate416 inline vpiScopeGenerate(const char*nam, const char*tnam)
417 : __vpiScope(nam,tnam) { }
get_type_codevpiScopeGenerate418 int get_type_code(void) const { return vpiGenScope; }
419 };
420
421 struct vpiScopeFork : public __vpiScope {
vpiScopeForkvpiScopeFork422 inline vpiScopeFork(const char*nam, const char*tnam)
423 : __vpiScope(nam,tnam,false) { }
get_type_codevpiScopeFork424 int get_type_code(void) const { return vpiNamedFork; }
425 };
426
427 class vpiScopeForkAuto : public __vpiScope {
428 public:
vpiScopeForkAuto(const char * nam,const char * tnam)429 inline vpiScopeForkAuto(const char*nam, const char*tnam)
430 : __vpiScope(nam,tnam,true) { }
get_type_code(void) const431 int get_type_code(void) const { return vpiNamedFork; }
432 };
433
434 struct vpiScopeClass : public __vpiScope {
vpiScopeClassvpiScopeClass435 inline vpiScopeClass(const char*nam, const char*tnam)
436 : __vpiScope(nam,tnam) { }
get_type_codevpiScopeClass437 int get_type_code(void) const { return vpiClassTypespec; }
438 };
439
440 /*
441 * The current_scope is a compile time concept. As the vvp source is
442 * compiled, items that have scope are placed in the current
443 * scope. The ".scope" directives select the scope that is current.
444 */
445 static __vpiScope*current_scope = 0;
446
vpip_attach_to_scope(__vpiScope * scope,vpiHandle obj)447 void vpip_attach_to_scope(__vpiScope*scope, vpiHandle obj)
448 {
449 assert(scope);
450 scope->intern.push_back(obj);
451 }
452
453 /*
454 * When the compiler encounters a scope declaration, this function
455 * creates and initializes a __vpiScope object with the requested name
456 * and within the addressed parent. The label is used as a key in the
457 * symbol table and the name is used to construct the actual object.
458 */
459 void
compile_scope_decl(char * label,char * type,char * name,char * tname,char * parent,long file_idx,long lineno,long def_file_idx,long def_lineno,long is_cell)460 compile_scope_decl(char*label, char*type, char*name, char*tname,
461 char*parent, long file_idx, long lineno,
462 long def_file_idx, long def_lineno, long is_cell)
463 {
464 count_vpi_scopes += 1;
465 char vec_type;
466 char sign_flag;
467 unsigned wid;
468
469 __vpiScope*scope;
470 if (strcmp(type,"module") == 0) {
471 scope = new vpiScopeModule(name, tname);
472 } else if ( sscanf(type, "function.vec%c.%c%u", &vec_type, &sign_flag, &wid) == 3 ) {
473 int type_code;
474 if (sign_flag=='s') {
475 type_code = vpiSizedSignedFunc;
476 } else if (sign_flag=='u') {
477 type_code = vpiSizedFunc;
478 } else if (sign_flag=='i') {
479 type_code = vpiIntFunc;
480 } else {
481 assert(0);
482 type_code = vpiSizedFunc;
483 }
484 vvp_bit4_t init_val = vec_type == '4' ? BIT4_X : BIT4_0;
485 scope = new vpiScopeFunction(name, tname, false, type_code, wid, init_val);
486
487 } else if ( sscanf(type, "autofunction.vec%c.%c%u", &vec_type, &sign_flag, &wid) == 3 ) {
488 int type_code;
489 switch (sign_flag) {
490 case 's':
491 type_code = vpiSizedSignedFunc;
492 break;
493 case 'u':
494 type_code = vpiSizedFunc;
495 break;
496 default:
497 assert(0);
498 type_code = vpiSizedFunc;
499 break;
500 }
501 vvp_bit4_t init_val = vec_type == '4' ? BIT4_X : BIT4_0;
502 scope = new vpiScopeFunction(name, tname, true, type_code, wid, init_val);
503
504 } else if (strcmp(type,"function.obj") == 0) {
505 scope = new vpiScopeFunction(name, tname, false, vpiSizedFunc, 0, BIT4_0);
506 } else if (strcmp(type,"autofunction.obj") == 0) {
507 scope = new vpiScopeFunction(name, tname, true, vpiSizedFunc, 0, BIT4_0);
508 } else if (strcmp(type,"function.real") == 0) {
509 scope = new vpiScopeFunction(name, tname, false, vpiRealFunc, 0, BIT4_0);
510 } else if (strcmp(type,"autofunction.real") == 0) {
511 scope = new vpiScopeFunction(name, tname, true, vpiRealFunc, 0, BIT4_0);
512 } else if (strcmp(type,"function.str") == 0) {
513 scope = new vpiScopeFunction(name, tname, false, vpiOtherFunc, 0, BIT4_0);
514 } else if (strcmp(type,"autofunction.str") == 0) {
515 scope = new vpiScopeFunction(name, tname, true, vpiOtherFunc, 0, BIT4_0);
516 } else if (strcmp(type,"function.void") == 0) {
517 scope = new vpiScopeFunction(name, tname, false, vpiOtherFunc, 0, BIT4_0);
518 } else if (strcmp(type,"autofunction.void") == 0) {
519 scope = new vpiScopeFunction(name, tname, true, vpiOtherFunc, 0, BIT4_0);
520 } else if (strcmp(type,"task") == 0) {
521 scope = new vpiScopeTask(name, tname);
522 } else if (strcmp(type,"autotask") == 0) {
523 scope = new vpiScopeTaskAuto(name, tname);
524 } else if (strcmp(type,"fork") == 0) {
525 scope = new vpiScopeFork(name, tname);
526 } else if (strcmp(type,"autofork") == 0) {
527 scope = new vpiScopeForkAuto(name, tname);
528 } else if (strcmp(type,"begin") == 0) {
529 scope = new vpiScopeBegin(name, tname);
530 } else if (strcmp(type,"autobegin") == 0) {
531 scope = new vpiScopeBeginAuto(name, tname);
532 } else if (strcmp(type,"generate") == 0) {
533 scope = new vpiScopeGenerate(name, tname);
534 } else if (strcmp(type,"package") == 0) {
535 scope = new vpiScopePackage(name, tname);
536 } else if (strcmp(type,"class") == 0) {
537 scope = new vpiScopeClass(name, tname);
538 } else {
539 scope = new vpiScopeModule(name, tname);
540 assert(0);
541 }
542
543 scope->file_idx = (unsigned) file_idx;
544 scope->lineno = (unsigned) lineno;
545 scope->def_file_idx = (unsigned) def_file_idx;
546 scope->def_lineno = (unsigned) def_lineno;
547 scope->item = 0;
548 scope->nitem = 0;
549 scope->live_contexts = 0;
550 scope->free_contexts = 0;
551
552 if (is_cell) scope->is_cell = true;
553 else scope->is_cell = false;
554
555 current_scope = scope;
556
557 compile_vpi_symbol(label, scope);
558
559 free(label);
560 free(type);
561 delete[] name;
562 delete[] tname;
563
564 if (parent) {
565 static vpiHandle obj;
566 compile_vpi_lookup(&obj, parent);
567 assert(obj);
568 __vpiScope*sp = dynamic_cast<__vpiScope*>(obj);
569 vpip_attach_to_scope(sp, scope);
570 scope->scope = dynamic_cast<__vpiScope*>(obj);
571
572 /* Inherit time units and precision from the parent scope. */
573 scope->time_units = sp->time_units;
574 scope->time_precision = sp->time_precision;
575
576 } else {
577 scope->scope = 0x0;
578
579 vpip_root_table.push_back(scope);
580
581 /* Root scopes inherit time_units and precision from the
582 system precision. */
583 scope->time_units = vpip_get_time_precision();
584 scope->time_precision = vpip_get_time_precision();
585 }
586 }
587
compile_scope_recall(char * symbol)588 void compile_scope_recall(char*symbol)
589 {
590 /* A __vpiScope starts with a __vpiHandle structure so this is
591 a safe cast. We need the (void*) to avoid a dereferenced
592 type punned pointer warning from some gcc compilers. */
593 compile_vpi_lookup((vpiHandle*)(void*)¤t_scope, symbol);
594 assert(current_scope);
595 }
596
597 /*
598 * This function handles the ".timescale" directive in the vvp
599 * source. It sets in the current scope the specified units value.
600 */
compile_timescale(long units,long precision)601 void compile_timescale(long units, long precision)
602 {
603 assert(current_scope);
604 current_scope->time_units = units;
605 current_scope->time_precision = precision;
606 }
607
vpip_peek_current_scope(void)608 __vpiScope* vpip_peek_current_scope(void)
609 {
610 return current_scope;
611 }
612
vpip_attach_to_current_scope(vpiHandle obj)613 void vpip_attach_to_current_scope(vpiHandle obj)
614 {
615 vpip_attach_to_scope(current_scope, obj);
616 }
617
vpip_peek_context_scope(void)618 __vpiScope* vpip_peek_context_scope(void)
619 {
620 __vpiScope*scope = current_scope;
621
622 /* A context is allocated for each automatic task or function.
623 Storage for nested scopes (named blocks) is allocated in
624 the parent context. */
625 while (scope->scope && scope->scope->is_automatic())
626 scope = scope->scope;
627
628 return scope;
629 }
630
vpip_add_item_to_context(automatic_hooks_s * item,__vpiScope * scope)631 unsigned vpip_add_item_to_context(automatic_hooks_s*item,
632 __vpiScope*scope)
633 {
634 assert(scope);
635 assert(scope->is_automatic());
636
637 unsigned idx = scope->nitem++;
638
639 if (scope->item == 0)
640 scope->item = (automatic_hooks_s**)
641 malloc(sizeof(automatic_hooks_s*));
642 else
643 scope->item = (automatic_hooks_s**)
644 realloc(scope->item, sizeof(automatic_hooks_s*)*scope->nitem);
645
646 scope->item[idx] = item;
647
648 /* Offset the context index by 2 to leave space for the list links. */
649 return 2 + idx;
650 }
651
652
653 class vpiPortInfo : public __vpiHandle {
654 public:
655 vpiPortInfo( __vpiScope *parent,
656 unsigned index,
657 int vpi_direction,
658 unsigned width,
659 const char *name );
660 ~vpiPortInfo();
661
get_type_code(void) const662 int get_type_code(void) const { return vpiPort; }
663
664 int vpi_get(int code);
665 char* vpi_get_str(int code);
666 vpiHandle vpi_handle(int code);
667
668 private:
669 __vpiScope *parent_;
670 unsigned index_;
671 int direction_;
672 unsigned width_;
673 const char *name_;
674 };
675
vpiPortInfo(__vpiScope * parent,unsigned index,int vpi_direction,unsigned width,const char * name)676 vpiPortInfo::vpiPortInfo( __vpiScope *parent,
677 unsigned index,
678 int vpi_direction,
679 unsigned width,
680 const char *name ) :
681 parent_(parent),
682 index_(index),
683 direction_(vpi_direction),
684 width_(width),
685 name_(name)
686 {
687 }
688
~vpiPortInfo()689 vpiPortInfo::~vpiPortInfo()
690 {
691 delete[] name_;
692 }
693
694 #ifdef CHECK_WITH_VALGRIND
port_delete(__vpiHandle * handle)695 void port_delete(__vpiHandle *handle)
696 {
697 delete dynamic_cast<vpiPortInfo *>(handle);
698 }
699 #endif
700
vpi_get(int code)701 int vpiPortInfo::vpi_get(int code)
702 {
703 switch( code ) {
704
705 case vpiDirection :
706 return direction_;
707 case vpiPortIndex :
708 return index_;
709 case vpiSize :
710 return width_;
711 default :
712 return vpiUndefined;
713 }
714
715 }
716
717
vpi_get_str(int code)718 char *vpiPortInfo::vpi_get_str(int code)
719 {
720 switch( code ) {
721 case vpiName :
722 return simple_set_rbuf_str(name_);
723 default :
724 return NULL;
725 }
726
727 }
728
729
vpi_handle(int code)730 vpiHandle vpiPortInfo::vpi_handle(int code)
731 {
732
733 switch (code) {
734
735 case vpiParent:
736 case vpiScope:
737 case vpiModule:
738 return parent_;
739 default :
740 break;
741 }
742
743 return 0;
744 }
745
746
747 /* Port info is meta-data to allow vpi queries of the port signature of modules for
748 * code-generators etc. There are no actual nets corresponding to instances of module ports
749 * as elaboration directly connects nets connected through module ports.
750 */
compile_port_info(unsigned index,int vpi_direction,unsigned width,const char * name)751 void compile_port_info( unsigned index, int vpi_direction, unsigned width, const char *name )
752 {
753 vpiHandle obj = new vpiPortInfo( vpip_peek_current_scope(),
754 index, vpi_direction, width, name );
755 vpip_attach_to_current_scope(obj);
756 }
757