/* Copyright (c) 1992, 1993 Regents of the University of California All rights reserved. Use and copying of this software and preparation of derivative works based upon this software are permitted. However, any distribution of this software or derivative works must include the above copyright notice. This software is made available AS IS, and neither the Electronics Research Laboratory or the Universify of California make any warranty about the software, its performance or its conformity to any specification. Author: Szu-Tsung Cheng, stcheng@ic.Berkeley.EDU 10/92 10/93 $Header: /projects/development/hsv/CVSRepository/vl2mv/src/parser/util.c,v 1.4 2009/03/09 20:25:57 fabio Exp $ */ #include #include "util.h" #include "st.h" #include "list.h" #include "array.h" #include "set.h" #include "vl_defs.h" #include "vl_types.h" #include "vlr_int.h" #include "verilog_yacc.h" #include "vl_create.h" #include "vl_write.h" #include "vl_write_util.h" #include "verilog.h" void chk_error(str) char *str; { fprintf(stderr, "internal utility error:%s\n", str); vl_exit(ERR_CHK); } char *chk_malloc(unsigned n) { char *retval; if ((retval=(char*)malloc((n==0)?1:n)) == NIL(char)) chk_error("can't allocate memory "); memset(retval, 0, n); return retval; } void vl_chk_free(lsGeneric p) { free((char *)p); } char* vlStrdup(char *str) { char *retval; unsigned length; length = strlen(str)+1; retval = (char*)chk_malloc(length); strcpy(retval, str); return retval; } void compile_error(char* str) { extern int yylineno; if (yylineno >=0) fprintf(stderr, "line %d %s\n", yylineno, str); else fprintf(stderr, "%s\n", str); vl_exit(ERR_COMPILE); } void semantic_error(char *str) { fprintf(stderr, "semantic error: %s\n", str); vl_exit(ERR_SEMANTIC); } void internal_error(char *str) { fprintf(stderr, "internal error: %s\n", str); vl_exit(ERR_INTERNAL); } void Translate_Warning(char *str) { fprintf(stderr, "%s, translation might be imprecise\n", str); vl_exit(ERR_SEMANTIC); } void Translate_Notice(char *str) { fprintf(stderr, "%s\n", str); } int drive_strength(int strength0, int strength1) { int retval = -1; switch(strength0) { case YYSUPPLY0: switch(strength1) { case YYSUPPLY1:retval = Supply1Supply0; break; case YYSTRONG1:retval = Strong1Supply0; break; case YYPULL1: retval = Pull1Supply0; break; case YYWEAK1: retval = Weak1Supply0; break; case YYHIGHZ1: retval = HighZ1Supply0; break; default: compile_error("illegal strength0/strength1"); } break; case YYSTRONG0: switch(strength1) { case YYSUPPLY1:retval = Supply1Strong0; break; case YYSTRONG1:retval = Strong1Strong0; break; case YYPULL1: retval = Pull1Strong0; break; case YYWEAK1: retval = Weak1Strong0; break; case YYHIGHZ1: retval = HighZ1Strong0; break; default: compile_error("illegal strength0/strength1"); } break; case YYPULL0: switch(strength1) { case YYSUPPLY1:retval = Supply1Pull0; break; case YYSTRONG1:retval = Strong1Pull0; break; case YYPULL1: retval = Pull1Pull0; break; case YYWEAK1: retval = Weak1Pull0; break; case YYHIGHZ1: retval = HighZ1Pull0; break; default: compile_error("illegal strength0/strength1"); } break; case YYWEAK0: switch(strength1) { case YYSUPPLY1:retval = Supply1Weak0; break; case YYSTRONG1:retval = Strong1Weak0; break; case YYPULL1: retval = Pull1Weak0; break; case YYWEAK1: retval = Weak1Weak0; break; case YYHIGHZ1: retval = HighZ1Weak0; break; default: compile_error("illegal strength0/strength1"); } break; case YYHIGHZ0: switch(strength1) { case YYSUPPLY1:retval = Supply1HighZ0; break; case YYSTRONG1:retval = Strong1HighZ0; break; case YYPULL1: retval = Pull1HighZ0; break; case YYWEAK1: retval = Weak1HighZ0; break; case YYHIGHZ1: retval = HighZ1HighZ0; break; default: compile_error("illegal strength0/strength1"); } break; default: compile_error("illegal strength0/strength1"); } return retval; } void insert_instances(lsList inst_list, void *inst_master) { lsHandle handle; extern int Warn_DuplicateInst; if (vl_currentModule == NIL(vl_module)) { compile_error("instantiate mod/prim/gate not within module"); } else { lsGen gen; typestruct *mpg; for (gen = lsStart(inst_list); lsNext(gen, (lsGeneric*)&mpg, &handle) != LS_NOMORE; ) { if (((vl_mod_prim_inst*)mpg)->name) { if (st_lookup(vl_currentModule->inst_st, ((vl_mod_prim_inst*)mpg)->name->name, (char**)&mpg)) { if (Warn_DuplicateInst) { char buf[MAXSTRLEN]; sprintf(buf, "%s:%s:Duplicated instance name", vl_currentModule->name->name, ((vl_mod_prim_inst*)mpg)->name->name); Translate_Notice(buf); } } st_insert(vl_currentModule->inst_st, ((vl_mod_prim_inst*)mpg)->name->name, (char*)mpg); ((vl_mod_prim_inst*)mpg)->name->mpg_master_exp = inst_master; } } (void) lsFinish(gen); } } void collect_latch(char *name) { extern int rst_ckt; extern int in_reset_stmt; vl_id_range *id_sym, *latch_sym; blif_latch *latch; char latch_name[MAXSTRLEN]; if (!st_lookup(vl_currentModule->latch_st, name, (char**)&latch)) { if (!st_lookup(vl_currentModule->sig_st, name, (char**)&id_sym)) { char buf[MAXSTRLEN]; yylineno = -1; sprintf(buf, "%s %s", name, "undefined and used as latch"); compile_error(buf); id_sym = vl_create_id_range(name, NIL(vl_range)); st_insert(vl_currentModule->sig_st, name, (char*)id_sym); } sprintf(latch_name, "%s%s", name, SEP_LATCH); latch_sym = vl_copy_id_range(id_sym); latch_sym->flags = id_sym->flags; latch_sym->syndrome_expr_list = lsCreate(); latch_sym->initial = lsCreate(); free(latch_sym->name); latch_sym->name = vlStrdup(latch_name); st_insert(vl_currentModule->sig_st, vlStrdup(latch_name), (char*)latch_sym); latch = create_latch(id_sym, NIL(vl_term), NIL(vl_term)); latch->flags |= (rst_ckt || in_reset_stmt) ? NBASSIGN_IN_INITIAL : NBASSIGN_IN_ALWAYS; st_insert(vl_currentModule->latch_st, name, (char*)latch); } else { latch->flags |= (rst_ckt || in_reset_stmt) ? NBASSIGN_IN_INITIAL : NBASSIGN_IN_ALWAYS; } } void collect_quasi(char *name) { vl_id_range *id_sym, *quasi_sym; int dummy; char quasi_name[MAXSTRLEN]; if (!st_lookup(vl_currentModule->quasi_st, name, (char**)&dummy)) { if (!st_lookup(vl_currentModule->sig_st, name, (char**)&id_sym)) { char buf[MAXSTRLEN]; yylineno = -1; sprintf(buf, "%s undefined and used as lhs of quasi-continuous assignment", name); compile_error(buf); id_sym = vl_create_id_range(name, NIL(vl_range)); st_insert(vl_currentModule->sig_st, name, (char*)id_sym); } sprintf(quasi_name, "%s%s", name, SEP_QUASI); quasi_sym = vl_copy_id_range(id_sym); quasi_sym->flags = id_sym->flags; quasi_sym->syndrome_expr_list = lsCreate(); free(quasi_sym->name); quasi_sym->name = vlStrdup(quasi_name); st_insert(vl_currentModule->sig_st, vlStrdup(quasi_name), (char*)quasi_sym); st_insert(vl_currentModule->quasi_st, name, (char*)0); } } void extract_delay_strength(lsList delay_strength, vl_delay **delay, int *strength) { int head, tail; switch (lsLength(delay_strength)) { case 0: break; case 1: lsFirstItem(delay_strength, (lsGeneric*)&head, 0); if (head & LEAST_SB) *delay = (vl_delay*)(head & (~LEAST_SB)); else *strength = (head >> 2); break; case 2: lsFirstItem(delay_strength, (lsGeneric*)&head, 0); lsLastItem(delay_strength, (lsGeneric*)&tail, 0); if (head & LEAST_SB || !(tail & LEAST_SB)) compile_error("mod/prim/gate illegal drive_strength | delay"); *strength = (head >> 2); *delay = (vl_delay*)(tail & (~LEAST_SB)); break; default: compile_error("too many drive_strength | delay"); } } void associate_symbolic_value(vl_lval *lval, vl_expr *expr) { vl_id_range *id_sym; char *mbody; extern char last_macro[]; extern st_table *macros; if (expr->type==IntExpr || expr->type==BitExpr) if (*last_macro && lval->type!=ConcatExpr) { if (st_lookup(vl_currentModule->sig_st, lval->name->name, (char**)&id_sym)) { if (!st_lookup(id_sym->symbolic_values, last_macro, &mbody)) { st_lookup(macros, last_macro, &mbody); st_insert(id_sym->symbolic_values, vlStrdup(last_macro), vlStrdup(mbody)); } } } } void dup_info_var_in_st(st_table *vars) { st_generator *gen; char *key; var_info *cur_var; gen = st_init_gen(vars); while (st_gen(gen, &key, (char**)&cur_var)) { st_insert(vars, key, (char*)copy_var_info(cur_var)); } st_free_gen(gen); } void reset_cond_list_in_st(st_table *vars) { st_generator *gen; char *key; var_info *cur_var; gen = st_init_gen(vars); while (st_gen(gen, &key, (char**)&cur_var)) { lsDestroy(cur_var->cond_list,0); cur_var->cond_list = lsCreate(); } st_free_gen(gen); } int data_width(vl_expr *expr) { int retval = 0, v; switch(expr->type) { case IntExpr: for (retval=0, v=expr->u.intval; v>0; v >>= 1) retval++; break; case RealExpr: for (retval=0, v=(int)expr->u.realval; v>0; v >>= 1) retval++; break; case BitExpr: break; } return retval; } char *strappend(char *str1, char *str2) { char *retval; strcat(str1, str2); retval = str1 + strlen(str2); return retval; } char *strappendS(char *str1, char *str2) { strcat(str1, str2); strcat(str1, " "); return (str1 + strlen(str2)+1); } char *WRT_BLIF_DC(FILE *file) { char *retval; retval = vlStrdup(new_termname()); fprintf(file, ".names %s\n-\n", retval); return retval; } char *WRT_BLIF_MV_DC(FILE *file, lsList domain) { char *retval; lsGen enum_gen; lsHandle enum_handle; vl_enumerator *enum_elt; int i; retval = vlStrdup(new_termname()); fprintf(file, ".mv %s %d ", retval, lsLength(domain)); for (enum_gen=lsStart(domain), i=0; lsNext(enum_gen,(lsGeneric*)&enum_elt,&enum_handle)!=LS_NOMORE; i++) { fprintf(file, "%s ", enum_elt->name); } lsFinish(enum_gen); fprintf(file, "\n"); fprintf(file, ".names %s\n-\n", retval); return retval; } char *WRT_BLIF_GND(FILE *file) { char *retval; retval = vlStrdup(new_termname()); fprintf(file, ".names %s\n", retval); fprintf(file, "0\n"); return retval; } char *WRT_BLIF_SUP(file) FILE *file; { char *retval; retval = vlStrdup(new_termname()); fprintf(file, ".names %s\n", retval); fprintf(file, "1\n"); return retval; } vl_term *true_term(file) FILE *file; { vl_term *retval; retval = vl_create_term(vl_create_id_range(vlStrdup(new_termname()),NIL(vl_range)), 0, -1); fprintf(file, ".names %s\n", retval->name->name); fprintf(file, "1\n"); return retval; } vl_term *false_term(file) FILE *file; { vl_term *retval; retval = vl_create_term(vl_create_id_range(vlStrdup(new_termname()),NIL(vl_range)), 0, -1); fprintf(file, ".names %s\n", retval->name->name); fprintf(file, "0\n"); return retval; } int ptrcmp(ptr1, ptr2) const char *ptr1; const char *ptr2; { if (ptr1==ptr2) return 0; if (ptr1 < ptr2) return -1; if (ptr1 > ptr2) return 1; return 0; } int ptrhash(key, modulus) char *key; int modulus; { return ((int)key % modulus); } int declcmp(char *ptr1, char *ptr2) { int l1, l2; int r1, r2; l1 = vl_eval_expr(get_decl_range_left(ptr1)); r1 = vl_eval_expr(get_decl_range_right(ptr1)); l2 = vl_eval_expr(get_decl_range_left(ptr2)); r2 = vl_eval_expr(get_decl_range_right(ptr2)); if (l1==l2 && r1==r2) return 0; else return 1; } int declhash(key, modulus) char *key; int modulus; { return ((int)key % modulus); } int str_matchtail(char *str, char *pat) { char *cp; if (strlen(str) < strlen(pat)) return 0; cp = &str[strlen(str)-strlen(pat)]; return !strcmp(cp, pat); } char *strip_char (str, ch) char *str; char *ch; { char *cp; if (strlen(str) >= strlen(ch)) { cp = &str[strlen(str)-strlen(ch)]; if (!strcmp(cp,ch)) *cp = '\0'; } return str; } FILE *open_file(name, mode) char *name; char *mode; { FILE *retval; retval = fopen(name, mode); if (!retval) { char msg[MAXSTRLEN]; sprintf(msg, "can't open file %s", name); chk_error(msg); } return retval; } void close_file(file) FILE *file; { fclose(file); } char *num_to_binstr(num, width) int num, width; { static char retval[MAXSTRLEN]; int i; for (i=0; i> 1); } retval[width] = '\0'; return retval; } int min_bit_width(a) int a; { int retval; int largest_num; for (retval=1, largest_num=1; largest_num < a; largest_num = (largest_num << 1) | 1) retval++; return retval; } st_table *st_union(st1, st2) st_table *st1; st_table *st2; { st_generator *gen; char *key; var_info *vinfo, *vinfo1; gen = st_init_gen(st2); while (st_gen(gen, &key, (char**)&vinfo)) { if (!st_lookup(st1, key, (char**)&vinfo1)) { st_insert(st1, key, (char*)vinfo); } } st_free_gen(gen); return st1; } char *sys_lib_encode(type, widthi, widtho) int type; int widthi, widtho; { static char retval[MAXSTRLEN]; if (type == LIBplus || type == LIBminus) { sprintf(retval, "%s%s_%d_%d", HSIS_LIB_HEADER, SYS_LIB_NAME(type), widthi, widtho); } else { sprintf(retval, "%s%s_%d", HSIS_LIB_HEADER,SYS_LIB_NAME(type),widthi); } return retval; } char *lib_encode(type, width) int type; int width; { static char retval[MAXSTRLEN]; sprintf(retval, "%s%d", LIB_NAME(type), width); return retval; } char *gen_lib_encode(type, args) int type; lsList args; { static char retval[MAXSTRLEN]; char *arg; int i; lsGen gen; lsHandle handle; sprintf(retval, "%s%s", LIB_NAME(type), SEP_LTRANGE); for (gen=lsStart(args), i=0; lsNext(gen,(lsGeneric*)&arg,&handle)!=LS_NOMORE; i++) { strcat(retval, arg); if (i < lsLength(args)-1) strcat(retval, SEP_GATEPIN); } strcat(retval, SEP_RTRANGE); lsFinish(gen); return retval; } int ipower(base, power) int base; int power; { register int i, retval; for (retval=1, i=0; i0) { st_generator *gen; char *key; vl_id_range *id_sym; gen = st_init_gen(undefined); while (st_gen(gen, &key, (char**)&id_sym)) { fprintf(stderr, "undefined module/primitive: %s\n", key); } st_free_gen(gen); vl_exit(1); } } char *basename(filename) char *filename; { char *retval; int i; retval = vlStrdup(filename); for (i=strlen(retval)-1; i>0 && retval[i] != '/'; i--) if (retval[i] == '.') { retval[i]='\0'; break; } return retval; } char *extname(char *filename) { char *retval; retval = vlStrdup(filename); return retval; } int gcd(int u, int v) { int t; while (u > 0) { if (u < v) { t = u; u = v; v = t; } u = u-v; } return v; } int lcm(int u, int v) { return ( u * v / gcd(u,v)); }