diff --git a/src/save.c b/src/save.c index 6da3c78e..46f7b5ae 100644 --- a/src/save.c +++ b/src/save.c @@ -1245,43 +1245,19 @@ void pop_undo(int redo) #endif /* ifndef IN_MEMORY_UNDO */ -static int Gcurrent_sym=0; -int CmpSchBbox(const void *a, const void *b) -{ - char *labela, *labelb; - const char *name; - Box *boxa = (Box*)a; - Box *boxb = (Box*)b; - int i, aa = -1, bb = -1; - labela=NULL; labelb=NULL; - my_strdup(658, &labela, get_tok_value(boxa->prop_ptr, "name", 0)); - my_strdup(659, &labelb, get_tok_value(boxb->prop_ptr, "name", 0)); - for (i = 0; i < instdef[Gcurrent_sym].rects[PINLAYER]; ++i) - { - name = get_tok_value(instdef[Gcurrent_sym].boxptr[PINLAYER][i].prop_ptr, "name", 0); - if (!strcmp(name, labela)) {aa = i;} - if (!strcmp(name, labelb)) {bb = i;} - if (aa>=0 && bb>=0) break; - } - my_free(896, &labela); - my_free(897, &labelb); - return(aa-bb); -} - - /* given a 'symname' component instantiation in a LCC schematic instance * get the type attribute from symbol global properties. * first look in already loaded symbols else inspect symbol file - * do not load in symname, just get the type */ -void get_symbol_type(const char *symname, char **type) + * do not load all symname data, just get the type + * return symbol type in type pointer or "" if no type or no symbol found + * if pintable given (!=NULL) hash all symbol pins */ +void get_sym_type(const char *symname, char **type, struct int_hashentry **pintable) { - int i; + int i, c, n = 0; char name[PATH_MAX]; FILE *fd; char tag[1]; - char *globalprop=NULL; int found = 0; - if(!strcmp(file_version,"1.0")) { my_strncpy(name, abs_sym_path(symname, ".sym"), S(name)); } else { @@ -1296,14 +1272,23 @@ void get_symbol_type(const char *symname, char **type) break; } } + /* hash pins to get LCC schematic have same order as corresponding symbol */ + if(found && pintable) for(c = 0; c < instdef[i].rects[PINLAYER]; c++) { + int_hash_lookup(pintable, get_tok_value(instdef[i].boxptr[PINLAYER][c].prop_ptr, "name", 0), c, XINSERT); + } if( !found ) { + dbg(1, "get_sym_type(): open file %s, pintable %s\n",name, pintable ? "set" : "null"); /* ... if not found open file and look for 'type' into the global attributes. */ if((fd=fopen(name,"r"))==NULL) { - dbg(1, "get_symbol_type(): Symbol not found: %s\n",name); + dbg(1, "get_sym_type(): Symbol not found: %s\n",name); my_strdup2(1162, type, ""); } else { - while(!found) { + char *globalprop=NULL; + Box box; + + box.prop_ptr = NULL; + while(1) { if(fscanf(fd," %c",tag)==EOF) break; switch(tag[0]) { case 'G': @@ -1317,6 +1302,21 @@ void get_symbol_type(const char *symname, char **type) my_strdup2(1165, type, get_tok_value(globalprop, "type", 0)); if(type[0]) found = 1; break; + case 'B': + fscanf(fd, "%d",&c); + if(c>=cadlayers) { + fprintf(errfp,"FATAL: box layer > defined cadlayers, increase cadlayers\n"); + tcleval( "exit"); + } + fscanf(fd, "%lf %lf %lf %lf ",&box.x1, &box.y1, &box.x2, &box.y2); + load_ascii_string( &box.prop_ptr, fd); + dbg(1, "get_sym_type(): %s box.prop_ptr=%s\n", symname, box.prop_ptr); + if (pintable && c == PINLAYER) { + /* hash pins to get LCC schematic have same order as corresponding symbol */ + int_hash_lookup(pintable, get_tok_value(box.prop_ptr, "name", 0), n++, XINSERT); + dbg(1, "get_sym_type() : hashing %s\n", get_tok_value(box.prop_ptr, "name", 0)); + } + break; default: if( tag[0] == '{' ) ungetc(tag[0], fd); read_record(tag[0], fd, 1); @@ -1325,26 +1325,71 @@ void get_symbol_type(const char *symname, char **type) read_line(fd, 0); /* discard any remaining characters till (but not including) newline */ } my_free(1166, &globalprop); + my_free(1167, &box.prop_ptr); fclose(fd); } } - dbg(1, "get_symbol_type(): symbol=%s --> type=%s\n", symname, *type); + dbg(1, "get_sym_type(): symbol=%s --> type=%s\n", symname, *type); +} + + +/* given a .sch file used as instance in LCC schematics, order its pin + * as in corresponding .sym file if it exists */ +void align_sch_pins_with_sym(const char *name, int pos) +{ + char *ptr; + char symname[PATH_MAX]; + char *symtype = NULL; + const char *pinname; + int i, fail = 0; + struct int_hashentry *pintable[HASHSIZE]; + + if ((ptr = strrchr(name, '.')) && !strcmp(ptr, ".sch")) { + my_strncpy(symname, add_ext(name, ".sym"), S(symname)); + for(i = 0; i < HASHSIZE; i++) pintable[i] = NULL; + /* hash all symbol pins with their position into pintable hash*/ + get_sym_type(symname, &symtype, pintable); + if(symtype[0]) { /* found a .sym for current .sch LCC instance */ + Box *box = NULL; + box = (Box *) my_malloc(1168, sizeof(Box) * instdef[pos].rects[PINLAYER]); + dbg(1, "align_sch_pins_with_sym(): symbol: %s\n", symname); + for(i=0; i < instdef[pos].rects[PINLAYER]; i++) { + struct int_hashentry *entry; + pinname = get_tok_value(instdef[pos].boxptr[PINLAYER][i].prop_ptr, "name", 0); + entry = int_hash_lookup(pintable, pinname, 0 , XLOOKUP); + if(!entry) { + dbg(0, " align_sch_pins_with_sym(): warning: pin mismatch between %s and %s : %s\n", name, symname, pinname); + fail = 1; + break; + } + box[entry->value] = instdef[pos].boxptr[PINLAYER][i]; /* box[] is the pin array ordered as in symbol */ + dbg(1, "align_sch_pins_with_sym(): i=%d, pin name=%s entry->value=%d\n", i, pinname, entry->value); + } + if(!fail) { + for(i=0; i < instdef[pos].rects[PINLAYER]; i++) { /* copy box[] ordererd array to LCC schematic instance */ + instdef[pos].boxptr[PINLAYER][i] = box[i]; + } + } + free_int_hash(pintable); + my_free(1169, &box); + } + my_free(1170, &symtype); + } } /* replace i/o/iopin instances of LCC schematics with symbol pins (boxes on PINLAYER layer) */ void add_pinlayer_boxes(int *lastr, Box **bb, const char *symtype, char *prop_ptr, double inst_x0, double inst_y0) { - int i, save; const char *label; char *pin_label = NULL; + i = lastr[PINLAYER]; my_realloc(652, &bb[PINLAYER], (i + 1) * sizeof(Box)); bb[PINLAYER][i].x1 = inst_x0 - 2.5; bb[PINLAYER][i].x2 = inst_x0 + 2.5; bb[PINLAYER][i].y1 = inst_y0 - 2.5; bb[PINLAYER][i].y2 = inst_y0 + 2.5; RECTORDER(bb[PINLAYER][i].x1, bb[PINLAYER][i].y1, bb[PINLAYER][i].x2, bb[PINLAYER][i].y2); bb[PINLAYER][i].prop_ptr = NULL; - label = get_tok_value(prop_ptr, "lab", 0); save = strlen(label)+30; pin_label = my_malloc(315, save); @@ -1359,12 +1404,9 @@ void add_pinlayer_boxes(int *lastr, Box **bb, const char *symtype, char *prop_pt my_strdup(463, &bb[PINLAYER][i].prop_ptr, pin_label); bb[PINLAYER][i].dash = 0; bb[PINLAYER][i].sel = 0; - /* add to symbol pins remaining attributes from schematic pins, except name= and lab= */ - my_strdup(157, &pin_label, get_sym_template(prop_ptr, "lab")); /* remove name=... and lab=... */ my_strcat(159, &bb[PINLAYER][i].prop_ptr, pin_label); - my_free(900, &pin_label); lastr[PINLAYER]++; } @@ -1390,6 +1432,75 @@ void use_lcc_pins(int level, char *symtype, char (*filename)[PATH_MAX]) } } +void calc_symbol_bbox(int pos) +{ + int c, i, count = 0; + Box boundbox, tmp; + + boundbox.x1 = boundbox.x2 = boundbox.y1 = boundbox.y2 = 0; + for(c=0;c x2) x2 = instdef[pos].polygonptr[c][i].x[k]; + if(k==0 || instdef[pos].polygonptr[c][i].y[k] > y2) y2 = instdef[pos].polygonptr[c][i].y[k]; + } + tmp.x1=x1;tmp.y1=y1;tmp.x2=x2;tmp.y2=y2; + updatebbox(count,&boundbox,&tmp); + } + } +/* +* do not include symbol text in bounding box, since text length +* is variable from one instance to another due to '@' variable expansions +* +* for(i=0;i exit */ if(fscanf(lcc[level].fd," %c",tag)==EOF) { if (level) { - dbg(1, "load_sym_def(): fclose1, level=%d, fd=%p\n", level, lcc[level].fd); + dbg(1, "l_s_d(): fclose1, level=%d, fd=%p\n", level, lcc[level].fd); fclose(lcc[level].fd); my_free(898, &lcc[level].prop_ptr); my_free(899, &lcc[level].symname); @@ -1564,7 +1665,6 @@ int load_sym_def(const char *name, FILE *embed_fd) ll[c][i].prop_ptr=NULL; load_ascii_string( &ll[c][i].prop_ptr, lcc[level].fd); dbg(2, "l_d_s(): loaded line: ptr=%lx\n", (unsigned long)ll[c]); - if(!strcmp(get_tok_value(ll[c][i].prop_ptr,"bus", 0), "true") ) ll[c][i].bus = 1; else @@ -1666,8 +1766,6 @@ int load_sym_def(const char *name, FILE *embed_fd) } else aa[c][i].dash = 0; aa[c][i].sel = 0; - - dbg(2, "l_d_s(): loaded arc: ptr=%lx\n", (unsigned long)aa[c]); lasta[c]++; break; @@ -1721,33 +1819,26 @@ int load_sym_def(const char *name, FILE *embed_fd) } tt[i].prop_ptr=NULL; load_ascii_string(&tt[i].prop_ptr, lcc[level].fd); - if(level > 0 && symtype && !strcmp(symtype, "label")) { char lay[30]; my_snprintf(lay, S(lay), " layer=%d", WIRELAYER); my_strcat(1163, &tt[i].prop_ptr, lay); } - - dbg(1, "l_d_s(): loaded text : t=%s p=%s\n", tt[i].txt_ptr, tt[i].prop_ptr); - + dbg(1, "l_d_s(): loaded text : t=%s p=%s\n", tt[i].txt_ptr, tt[i].prop_ptr ? tt[i].prop_ptr : "NULL"); my_strdup(351, &tt[i].font, get_tok_value(tt[i].prop_ptr, "font", 0)); - str = get_tok_value(tt[i].prop_ptr, "hcenter", 0); tt[i].hcenter = strcmp(str, "true") ? 0 : 1; str = get_tok_value(tt[i].prop_ptr, "vcenter", 0); tt[i].vcenter = strcmp(str, "true") ? 0 : 1; - str = get_tok_value(tt[i].prop_ptr, "layer", 0); if(str[0]) tt[i].layer = atoi(str); else tt[i].layer = -1; - tt[i].flags = 0; str = get_tok_value(tt[i].prop_ptr, "slant", 0); tt[i].flags |= strcmp(str, "oblique") ? 0 : TEXT_OBLIQUE; tt[i].flags |= strcmp(str, "italic") ? 0 : TEXT_ITALIC; str = get_tok_value(tt[i].prop_ptr, "weight", 0); tt[i].flags |= strcmp(str, "bold") ? 0 : TEXT_BOLD; - lastt++; break; case 'N': /* store wires as lines on layer WIRELAYER. */ @@ -1793,13 +1884,11 @@ int load_sym_def(const char *name, FILE *embed_fd) endfile = 1; continue; } - dbg(1, "load_sym_def(): call get_symbol_type(), symname=%s\n", symname); - + dbg(1, "l_s_d(): call get_sym_type(), symname=%s\n", symname); /* get symbol type by looking into list of loaded symbols or (if not found) by * opening/closing the symbol file and getting the 'type' attribute from global symbol attributes */ - get_symbol_type(symname, &symtype); - dbg(1, "load_sym_def(): level=%d, symname=%s symtype=%s\n", level, symname, symtype); - + get_sym_type(symname, &symtype, NULL); + dbg(1, "l_s_d(): level=%d, symname=%s symtype=%s\n", level, symname, symtype); if( /* add here symbol types not to consider when loading schematic-as-symbol instances */ !strcmp(symtype, "logo") || !strcmp(symtype, "netlist_commands") || @@ -1813,31 +1902,29 @@ int load_sym_def(const char *name, FILE *embed_fd) !strcmp(symtype, "verilog_preprocessor") || !strcmp(symtype, "timescale") ) break; - - /* add PINLAYER boxes (symbol pins) at schematic i/o/iopin coordinates. */ if (level==0 && (!strcmp(symtype, "ipin") || !strcmp(symtype, "opin") || !strcmp(symtype, "iopin"))) { add_pinlayer_boxes(lastr, bb, symtype, prop_ptr, inst_x0, inst_y0); } /* build symbol filename to be loaded */ if (!strcmp(file_version, "1.0")) { - my_strncpy(name4, abs_sym_path(symname, ".sym"), S(name4)); + my_strncpy(sympath, abs_sym_path(symname, ".sym"), S(sympath)); } else { - my_strncpy(name4, abs_sym_path(symname, ""), S(name4)); + my_strncpy(sympath, abs_sym_path(symname, ""), S(sympath)); } /* replace i/o/iopin.sym filename with better looking (for LCC symbol) pins */ - use_lcc_pins(level, symtype, &name4); + use_lcc_pins(level, symtype, &sympath); - if ((fd_tmp = fopen(name4, "r")) == NULL) { - fprintf(errfp, "load_sym_def(): unable to open file to read schematic: %s\n", name4); + if ((fd_tmp = fopen(sympath, "r")) == NULL) { + fprintf(errfp, "l_s_d(): unable to open file to read schematic: %s\n", sympath); } else { if (level+1 >= max_level) { my_realloc(653, &lcc, (max_level + 1) * sizeof(struct Lcc)); max_level++; } - dbg(1, "load_sym_def(): fopen2(%s), level=%d, fd=%p\n", name4, level, fd_tmp); + dbg(1, "l_s_d(): fopen2(%s), level=%d, fd=%p\n", sympath, level, fd_tmp); ++level; incremented_level = 1; lcc[level].fd = fd_tmp; @@ -1863,7 +1950,7 @@ int load_sym_def(const char *name, FILE *embed_fd) } my_strdup(654, &lcc[level].prop_ptr, prop_ptr); my_strdup(657, &lcc[level].symname, symname); - dbg(1, "level incremented: level=%d, symname=%s, prop_ptr = %s name4=%s\n", level, symname, prop_ptr, name4); + dbg(1, "level incremented: level=%d, symname=%s, prop_ptr = %s sympath=%s\n", level, symname, prop_ptr, sympath); } break; case '[': @@ -1895,7 +1982,7 @@ int load_sym_def(const char *name, FILE *embed_fd) read_line(lcc[level].fd, 0); /* discard any remaining characters till (but not including) newline */ } if(!embed_fd) { - dbg(1, "load_sym_def(): fclose2, level=%d, fd=%p\n", level, lcc[0].fd); + dbg(1, "l_s_d(): fclose2, level=%d, fd=%p\n", level, lcc[0].fd); fclose(lcc[0].fd); } if(embed_fd || strstr(name, ".xschem_embedded_")) { @@ -1917,69 +2004,12 @@ int load_sym_def(const char *name, FILE *embed_fd) } instdef[lastinstdef].texts = lastt; instdef[lastinstdef].txtptr = tt; - - - boundbox.x1 = boundbox.x2 = boundbox.y1 = boundbox.y2 = 0; - for(c=0;c x2) x2 = pp[c][i].x[k]; - if(k==0 || pp[c][i].y[k] > y2) y2 = pp[c][i].y[k]; - } - tmp.x1=x1;tmp.y1=y1;tmp.x2=x2;tmp.y2=y2; - updatebbox(count,&boundbox,&tmp); - } - } -/* -* do not include symbol text in bounding box, since text length -* is variable from one instance to another due to '@' variable replacement -* -* for(i=0;i save) remove_symbol(lastinstdef - 1); /* if previous match_symbol() caused a symbol to be loaded unload it now */ - } recursion_counter--; return 1; } diff --git a/src/spice_netlist.c b/src/spice_netlist.c index 113936b2..2c95e66e 100644 --- a/src/spice_netlist.c +++ b/src/spice_netlist.c @@ -515,3 +515,88 @@ void free_hash(struct hashentry **table) table[i] = free_hash_entry( table[i] ); } } + +/* GENERIC PURPOSE INT HASH TABLE */ + + +/* token value what ... what ... + * -------------------------------------------------------------------------- + * "whatever" "whatever" XINSERT insert in hash table if not in. + * if already present update value if not NULL, + * return entry address. + * "whatever" "whatever" XINSERT_NOREPLACE same as XINSERT but do not replace existing value + * return NULL if not found. + * "whatever" "whatever" XLOOKUP lookup in hash table,return entry addr. + * return NULL if not found + * "whatever" "whatever" XDELETE delete entry if found,return NULL + */ +struct int_hashentry *int_hash_lookup(struct int_hashentry **table, const char *token, const int value, int what) +{ + unsigned int hashcode, index; + struct int_hashentry *entry, *saveptr, **preventry; + int s ; + + if(token==NULL) return NULL; + hashcode=hash(token); + index=hashcode % HASHSIZE; + entry=table[index]; + preventry=&table[index]; + while(1) + { + if( !entry ) /* empty slot */ + { + if(what==XINSERT || what == XINSERT_NOREPLACE) /* insert data */ + { + s=sizeof( struct int_hashentry ); + entry=(struct int_hashentry *)my_malloc(659, s); + entry->next=NULL; + entry->token=NULL; + my_strdup(658, &entry->token, token); + entry->value = value; + entry->hash=hashcode; + *preventry=entry; + } + return NULL; /* if element inserted return NULL since it was not in table */ + } + if( entry -> hash==hashcode && strcmp(token,entry->token)==0 ) /* found a matching token */ + { + if(what==XDELETE) /* remove token from the hash table ... */ + { + saveptr=entry->next; + my_free(896, &entry->token); + my_free(897, &entry); + *preventry=saveptr; + } + else if(what == XINSERT ) { + entry->value = value; + } + return entry; /* found matching entry, return the address */ + } + preventry=&entry->next; /* descend into the list. */ + entry = entry->next; + } +} + +static struct int_hashentry *free_int_hash_entry(struct int_hashentry *entry) +{ + struct int_hashentry *tmp; + while( entry ) { + tmp = entry -> next; + my_free(1171, &(entry->token)); + my_free(1172, &entry); + entry = tmp; + } + return NULL; +} + + +void free_int_hash(struct int_hashentry **table) +{ + int i; + + for(i=0;i