/* * alias vs normal symbol adding */ static void alias_vs_normal_symadd(struct vcdsymbol *v, struct vcdsymbol *root_v) { if(!root_v) { if((v->vartype==V_INTEGER)||(v->vartype==V_REAL)) { v->ltsym = lxt2_wr_symbol_add(lt, v->name, 0, v->msi, v->lsi, (v->vartype==V_INTEGER)?LXT2_WR_SYM_F_INTEGER:((v->vartype==V_REAL)?LXT2_WR_SYM_F_DOUBLE:LXT2_WR_SYM_F_BITS)); } else { char buf[65537]; if(v->msi==v->lsi) { sprintf(buf, "%s[%d]", v->name, v->msi); } else { sprintf(buf, "%s[%d:%d]", v->name, v->msi, v->lsi); } v->ltsym = lxt2_wr_symbol_add(lt, buf, 0, v->msi, v->lsi, (v->vartype==V_INTEGER)?LXT2_WR_SYM_F_INTEGER:((v->vartype==V_REAL)?LXT2_WR_SYM_F_DOUBLE:LXT2_WR_SYM_F_BITS)); } } else { if((v->vartype==V_INTEGER)||(v->vartype==V_REAL)) { lxt2_wr_symbol_alias(lt, root_v->name, v->name, v->msi, v->lsi); } else { char bufold[65537], buf[65537]; if(v->msi==v->lsi) { sprintf(bufold, "%s[%d]", root_v->name, root_v->msi); sprintf(buf, "%s[%d]", v->name, v->msi); } else { sprintf(bufold, "%s[%d:%d]", root_v->name, root_v->msi, root_v->lsi); sprintf(buf, "%s[%d:%d]", v->name, v->msi, v->lsi); } lxt2_wr_symbol_alias(lt, bufold, buf, v->msi, v->lsi); } } }
static void scan_item(unsigned depth, vpiHandle item, int skip) { struct t_cb_data cb; struct vcd_info* info; const char* name; const char* ident; int nexus_id; /* list of types to iterate upon */ int i; static int types[] = { /* Value */ vpiNet, vpiReg, vpiVariables, /* Scope */ vpiFunction, vpiModule, vpiNamedBegin, vpiNamedFork, vpiTask, -1 }; switch (vpi_get(vpiType, item)) { case vpiMemoryWord: if (vpi_get(vpiConstantSelect, item) == 0) { /* Turn a non-constant array word select into a * constant word select. */ vpiHandle array = vpi_handle(vpiParent, item); PLI_INT32 idx = vpi_get(vpiIndex, item); item = vpi_handle_by_index(array, idx); } case vpiIntegerVar: case vpiBitVar: case vpiByteVar: case vpiShortIntVar: case vpiIntVar: case vpiLongIntVar: case vpiTimeVar: case vpiReg: case vpiNet: /* An array word is implicitly escaped so look for an * escaped identifier that this could conflict with. */ if (vpi_get(vpiType, item) == vpiMemoryWord && vpi_handle_by_name(vpi_get_str(vpiFullName, item), 0)) { vpi_printf("LXT2 warning: dumping array word %s will " "conflict with an escaped identifier.\n", vpi_get_str(vpiFullName, item)); } if (skip || vpi_get(vpiAutomatic, item)) break; name = vpi_get_str(vpiName, item); nexus_id = vpi_get(_vpiNexusId, item); if (nexus_id) { ident = find_nexus_ident(nexus_id); } else { ident = 0; } if (!ident) { char*tmp = create_full_name(name); ident = strdup_sh(&name_heap, tmp); free(tmp); if (nexus_id) set_nexus_ident(nexus_id, ident); info = new_vcd_info(); info->item = item; info->sym = lxt2_wr_symbol_add(dump_file, ident, 0 /* array rows */, vpi_get(vpiLeftRange, item), vpi_get(vpiRightRange, item), LXT2_WR_SYM_F_BITS); info->dmp_next = 0; cb.time = 0; cb.user_data = (char*)info; cb.value = NULL; cb.obj = item; cb.reason = cbValueChange; cb.cb_rtn = variable_cb_1; info->cb = vpi_register_cb(&cb); } else { char *n = create_full_name(name); lxt2_wr_symbol_alias(dump_file, ident, n, vpi_get(vpiSize, item)-1, 0); free(n); } break; case vpiRealVar: if (skip || vpi_get(vpiAutomatic, item)) break; name = vpi_get_str(vpiName, item); { char*tmp = create_full_name(name); ident = strdup_sh(&name_heap, tmp); free(tmp); } info = new_vcd_info(); info->item = item; info->sym = lxt2_wr_symbol_add(dump_file, ident, 0 /* array rows */, vpi_get(vpiSize, item)-1, 0, LXT2_WR_SYM_F_DOUBLE); info->dmp_next = 0; cb.time = 0; cb.user_data = (char*)info; cb.value = NULL; cb.obj = item; cb.reason = cbValueChange; cb.cb_rtn = variable_cb_1; info->cb = vpi_register_cb(&cb); break; case vpiModule: case vpiNamedBegin: case vpiTask: case vpiFunction: case vpiNamedFork: if (depth > 0) { int nskip; vpiHandle argv; const char* fullname = vpi_get_str(vpiFullName, item); #if 0 vpi_printf("LXT2 info: scanning scope %s, %u levels\n", fullname, depth); #endif nskip = vcd_scope_names_test(fullname); if (!nskip) vcd_scope_names_add(fullname); else vpi_printf("LXT2 warning: ignoring signals in " "previously scanned scope %s\n", fullname); name = vpi_get_str(vpiName, item); push_scope(name); for (i=0; types[i]>0; i++) { vpiHandle hand; argv = vpi_iterate(types[i], item); while (argv && (hand = vpi_scan(argv))) { scan_item(depth-1, hand, nskip); } } pop_scope(); } break; default: vpi_printf("LXT2 warning: $dumpvars: Unsupported parameter " "type (%s)\n", vpi_get_str(vpiType, item)); } }
static void vcd_parse(void) { int tok; for(;;) { switch(get_token()) { case T_COMMENT: sync_end("COMMENT:"); break; case T_DATE: sync_end("DATE:"); break; case T_VERSION: sync_end("VERSION:"); break; case T_TIMEZERO: { int vtok=get_token(); if((vtok==T_END)||(vtok==T_EOF)) break; time_zero=atoi_64(yytext); lxt2_wr_set_timezero(lt, time_zero); sync_end(NULL); } break; case T_TIMESCALE: { int vtok; int i; char prefix=' '; int timelogadjust = 0; vtok=get_token(); if((vtok==T_END)||(vtok==T_EOF)) break; time_scale=atoi_64(yytext); if(!time_scale) time_scale=1; else if (time_scale == 10) timelogadjust = +1; else if (time_scale == 100) timelogadjust = +2; for(i=0;i<yylen;i++) { if((yytext[i]<'0')||(yytext[i]>'9')) { prefix=yytext[i]; break; } } if(prefix==' ') { vtok=get_token(); if((vtok==T_END)||(vtok==T_EOF)) break; prefix=yytext[0]; } switch(prefix) { case 's': case ' ': lxt2_wr_set_timescale(lt, 0+timelogadjust); break; case 'm': lxt2_wr_set_timescale(lt, -3+timelogadjust); break; case 'u': lxt2_wr_set_timescale(lt, -6+timelogadjust); break; case 'n': lxt2_wr_set_timescale(lt, -9+timelogadjust); break; case 'p': lxt2_wr_set_timescale(lt, -12+timelogadjust); break; case 'f': lxt2_wr_set_timescale(lt, -15+timelogadjust); break; default: /* unknown */ lxt2_wr_set_timescale(lt, -9+timelogadjust); break; } sync_end(NULL); } break; case T_SCOPE: T_GET; T_GET; if(tok==T_STRING) { struct slist *s; s=(struct slist *)calloc_2(1,sizeof(struct slist)); s->len=yylen; s->str=(char *)malloc_2(yylen+1); strcpy(s->str,yytext); if(slistcurr) { slistcurr->next=s; slistcurr=s; } else { slistcurr=slistroot=s; } build_slisthier(); DEBUG(fprintf(stderr, "SCOPE: %s\n",slisthier)); } sync_end(NULL); break; case T_UPSCOPE: if(slistroot) { struct slist *s; s=slistroot; if(!s->next) { free_2(s->str); free_2(s); slistroot=slistcurr=NULL; } else for(;;) { if(!s->next->next) { free_2(s->next->str); free_2(s->next); s->next=NULL; slistcurr=s; break; } s=s->next; } build_slisthier(); DEBUG(fprintf(stderr, "SCOPE: %s\n",slisthier)); } sync_end(NULL); break; case T_VAR: { int vtok; struct vcdsymbol *v=NULL; var_prevch=0; if(varsplit) { free_2(varsplit); varsplit=NULL; } vtok=get_vartoken(1); if(vtok>V_PORT) goto bail; v=(struct vcdsymbol *)calloc_2(1,sizeof(struct vcdsymbol)); v->vartype=vtok; v->msi=v->lsi=vcd_explicit_zero_subscripts; /* indicate [un]subscripted status */ if(vtok==V_PORT) { vtok=get_vartoken(1); if(vtok==V_STRING) { v->size=atoi_64(yytext); if(!v->size) v->size=1; } else if(vtok==V_LB) { vtok=get_vartoken(1); if(vtok==V_END) goto err; if(vtok!=V_STRING) goto err; v->msi=atoi_64(yytext); vtok=get_vartoken(0); if(vtok==V_RB) { v->lsi=v->msi; v->size=1; } else { if(vtok!=V_COLON) goto err; vtok=get_vartoken(0); if(vtok!=V_STRING) goto err; v->lsi=atoi_64(yytext); vtok=get_vartoken(0); if(vtok!=V_RB) goto err; if(v->msi>v->lsi) { v->size=v->msi-v->lsi+1; } else { v->size=v->lsi-v->msi+1; } } } else goto err; vtok=get_strtoken(); if(vtok==V_END) goto err; v->id=(char *)malloc_2(yylen+1); strcpy(v->id, yytext); v->nid=vcdid_hash(yytext,yylen); if(v->nid < vcd_minid) vcd_minid = v->nid; if(v->nid > vcd_maxid) vcd_maxid = v->nid; vtok=get_vartoken(0); if(vtok!=V_STRING) goto err; if(slisthier_len) { v->name=(char *)malloc_2(slisthier_len+1+yylen+1); strcpy(v->name,slisthier); strcpy(v->name+slisthier_len,vcd_hier_delimeter); strcpy(v->name+slisthier_len+1,yytext); } else { v->name=(char *)malloc_2(yylen+1); strcpy(v->name,yytext); } } else /* regular vcd var, not an evcd port var */ { vtok=get_vartoken(1); if(vtok==V_END) goto err; v->size=atoi_64(yytext); vtok=get_strtoken(); if(vtok==V_END) goto err; v->id=(char *)malloc_2(yylen+1); strcpy(v->id, yytext); v->nid=vcdid_hash(yytext,yylen); if(v->nid < vcd_minid) vcd_minid = v->nid; if(v->nid > vcd_maxid) vcd_maxid = v->nid; vtok=get_vartoken(0); if(vtok!=V_STRING) goto err; if(slisthier_len) { v->name=(char *)malloc_2(slisthier_len+1+yylen+1); strcpy(v->name,slisthier); strcpy(v->name+slisthier_len,vcd_hier_delimeter); strcpy(v->name+slisthier_len+1,yytext); } else { v->name=(char *)malloc_2(yylen+1); strcpy(v->name,yytext); } vtok=get_vartoken(1); if(vtok==V_END) goto dumpv; if(vtok!=V_LB) goto err; vtok=get_vartoken(0); if(vtok!=V_STRING) goto err; v->msi=atoi_64(yytext); vtok=get_vartoken(0); if(vtok==V_RB) { v->lsi=v->msi; goto dumpv; } if(vtok!=V_COLON) goto err; vtok=get_vartoken(0); if(vtok!=V_STRING) goto err; v->lsi=atoi_64(yytext); vtok=get_vartoken(0); if(vtok!=V_RB) goto err; } dumpv: if(v->size == 0) { v->vartype = V_REAL; } /* MTI fix */ if(v->vartype==V_REAL) { v->size=1; /* override any data we parsed in */ v->msi=v->lsi=0; } else if((v->size>1)&&(v->msi<=0)&&(v->lsi<=0)) { if(v->vartype==V_EVENT) { v->size=1; } else { /* any criteria for the direction here? */ v->msi=v->size-1; v->lsi=0; } } else if((v->msi>v->lsi)&&((v->msi-v->lsi+1)!=v->size)) { if(v->vartype!=V_EVENT) goto err; v->size=v->msi-v->lsi+1; } else if((v->lsi>=v->msi)&&((v->lsi-v->msi+1)!=v->size)) { if(v->vartype!=V_EVENT) goto err; v->size=v->msi-v->lsi+1; } /* initial conditions */ v->value=(char *)malloc_2(v->size+1); v->value[v->size]=0; v->narray=(struct Node **)calloc_2(v->size,sizeof(struct Node *)); { int i; for(i=0;i<v->size;i++) { v->value[i]='x'; v->narray[i]=(struct Node *)calloc_2(1,sizeof(struct Node)); v->narray[i]->head.time=-1; v->narray[i]->head.v.val=1; } } if(v->vartype==V_EVENT) { struct queuedevent *q; v->ev=q=(struct queuedevent *)calloc_2(1,sizeof(struct queuedevent)); q->sym=v; q->last_event_time=-1; q->next=queuedevents; queuedevents=q; } if(!vcdsymroot) { vcdsymroot=vcdsymcurr=v; } else { vcdsymcurr->next=v; vcdsymcurr=v; } numsyms++; #if 0 if((v->vartype==V_INTEGER)||(v->vartype==V_REAL)) { v->ltsym = lxt2_wr_symbol_add(lt, v->name, 0, v->msi, v->lsi, (v->vartype==V_INTEGER)?LXT2_WR_SYM_F_INTEGER:((v->vartype==V_REAL)?LXT2_WR_SYM_F_DOUBLE:LXT2_WR_SYM_F_BITS)); } else { char buf[65537]; if(v->msi==v->lsi) { sprintf(buf, "%s[%d]", v->name, v->msi); } else { sprintf(buf, "%s[%d:%d]", v->name, v->msi, v->lsi); } v->ltsym = lxt2_wr_symbol_add(lt, buf, 0, v->msi, v->lsi, (v->vartype==V_INTEGER)?LXT2_WR_SYM_F_INTEGER:((v->vartype==V_REAL)?LXT2_WR_SYM_F_DOUBLE:LXT2_WR_SYM_F_BITS)); } #endif DEBUG(fprintf(stderr,"VAR %s %d %s %s[%d:%d]\n", vartypes[v->vartype], v->size, v->id, v->name, v->msi, v->lsi)); goto bail; err: if(v) { if(v->name) free_2(v->name); if(v->id) free_2(v->id); if(v->value) free_2(v->value); free_2(v); } bail: if(vtok!=V_END) sync_end(NULL); break; } case T_ENDDEFINITIONS: if(!header_over) { header_over=1; /* do symbol table management here */ create_sorted_table(); if((!sorted)&&(!indexed)) { fprintf(stderr, "No symbols in VCD file..nothing to do!\n"); exit(1); } } break; case T_STRING: if(header_over) { /* catchall for events when header over */ if(yytext[0]=='#') { TimeType t_time; t_time=atoi_64(yytext+1); if(start_time<0) { start_time=t_time; } if(t_time < current_time) /* avoid backtracking time counts which can happen on malformed files */ { t_time = current_time; } current_time=t_time; if(end_time<t_time) end_time=t_time; /* in case of malformed vcd files */ lxt2_wr_set_time64(lt, current_time); DEBUG(fprintf(stderr,"#"TTFormat"\n",t_time)); } else { parse_valuechange(); } } break; case T_DUMPALL: /* dump commands modify vals anyway so */ case T_DUMPPORTSALL: break; /* just loop through.. */ case T_DUMPOFF: case T_DUMPPORTSOFF: dumping_off=1; lxt2_wr_set_dumpoff(lt); break; case T_DUMPON: case T_DUMPPORTSON: dumping_off=0; lxt2_wr_set_dumpon(lt); break; case T_DUMPVARS: case T_DUMPPORTS: if(current_time<0) { start_time=current_time=end_time=0; /* lxt2_wr_set_time(lt, current_time); */ } break; case T_VCDCLOSE: sync_end("VCDCLOSE:"); break; /* next token will be '#' time related followed by $end */ case T_END: /* either closure for dump commands or */ break; /* it's spurious */ case T_UNKNOWN_KEY: sync_end(NULL); /* skip over unknown keywords */ break; case T_EOF: return; default: DEBUG(fprintf(stderr,"UNKNOWN TOKEN\n")); } } }
/************************************************* lxt2_add - add object to file ************************************************/ static void lxt2_add( handle object, int depth ) { int real = 0; int event = 0; int flags; int msb; int lsb; info_p info; handle block; handle term; static int filter[] = { accIntegerVar, accNamedEvent, accNet, accRealVar, accRegister, accTimeVar, 0 }; switch( acc_fetch_type(object) ) { case accNamedEvent: flags = LXT2_WR_SYM_F_BITS; event = 1; break; case accRealVar: flags = LXT2_WR_SYM_F_DOUBLE; real = 1; break; case accIntegerVar: case accNet: case accPort: case accReg: case accTimeVar: case accParameter: flags = LXT2_WR_SYM_F_BITS; break; case accStatement: case accTask: case accModule: term = null; while(1) { term = acc_next( filter, object, term ); if( term == null ) { break; } lxt2_add( term, depth ); } if( depth == 1 ) { return; } block = null; while(1) { block = acc_next_child( object, block ); if( block == null ) { break; } lxt2_add( block, (depth==0) ? 0 : depth-1 ); } return; default: return; } info = (info_p)malloc( sizeof(info_t) ); if( !info ) { tf_error( "cannot allocate memory" ); tf_dofinish(); return; } info->object = object; info->name = strdup( acc_fetch_fullname(object) ); info->next = lxt.objectList; lxt.objectList = info; info->sequence = lxt.sequence; info->event = event; info->real = real; info->updateNext = 0; if( real ) { info->symbol = lxt2_wr_symbol_add( lxt.t, info->name, 0, 0, 0, flags ); } else if( event ) { info->symbol = lxt2_wr_symbol_add( lxt.t, info->name, 0, 0, 0, flags ); } else { acc_fetch_range( object, &msb, &lsb ); #if DEBUG io_printf( "lxt2_add: %s [ %d : %d ]\n", info->name, msb, lsb ); #endif info->symbol = lxt2_wr_symbol_add( lxt.t, info->name, 0, msb, lsb, flags ); } acc_vcl_add( object, lxt2_changed, (char*)info, vcl_verilog_logic ); #if DEBUG io_printf( "lxt2_recordvars: adding %p %s\n", info->symbol, info->name ); #endif }