From b25bd1d06d048257cd7311488f83d7743c6eca9d Mon Sep 17 00:00:00 2001 From: Stefan Frederik Date: Wed, 6 Jan 2021 03:01:14 +0100 Subject: [PATCH] saving to file made 4x faster, this implies less latency due to undo buffer savings on freaking big schematics. --- src/paste.c | 12 +++- src/save.c | 164 +++++++++++++++++++++++------------------------- src/scheduler.c | 2 +- src/select.c | 6 +- src/token.c | 8 +-- src/xinit.c | 2 +- src/xschem.h | 1 + 7 files changed, 97 insertions(+), 98 deletions(-) diff --git a/src/paste.c b/src/paste.c index 6f02ed56..fe418ecc 100644 --- a/src/paste.c +++ b/src/paste.c @@ -199,13 +199,21 @@ void merge_inst(int k,FILE *fd) { int i; char *prop_ptr=NULL; - + char *tmp = NULL; xInstance *ptr; i=xctx->instances; check_inst_storage(); ptr=xctx->inst; ptr[i].name=NULL; - load_ascii_string(&ptr[i].name,fd); + load_ascii_string(&tmp, fd); + /* avoid as much as possible calls to rel_sym_path (slow) */ + #ifdef __unix__ + if(tmp[0] == '/') my_strdup(755, &ptr[i].name, rel_sym_path(tmp)); + else my_strdup(755, &ptr[i].name,tmp); + #else + my_strdup(755, &ptr[i].name, rel_sym_path(tmp)); + #endif + my_free(756, &tmp); if(fscanf(fd, "%lf %lf %hd %hd",&ptr[i].x0, &ptr[i].y0,&ptr[i].rot, &ptr[i].flip) < 4) { fprintf(errfp,"WARNING: missing fields for INSTANCE object, ignoring.\n"); read_line(fd, 0); diff --git a/src/save.c b/src/save.c index 06bde458..b6527f42 100644 --- a/src/save.c +++ b/src/save.c @@ -175,17 +175,36 @@ void updatebbox(int count, xRect *boundbox, xRect *tmp) } } -void save_ascii_string(const char *ptr, FILE *fd) +void save_ascii_string(const char *ptr, FILE *fd, int newline) { - int i=0; - int c; - fputc('{',fd); - while( ptr && (c=ptr[i++]) ) - { - if( c=='\\' || c=='{' || c=='}') fputc('\\',fd); - fputc(c,fd); - } - fputc('}',fd); + int c, len, strbuf_pos = 0; + static char *strbuf = NULL; + static int strbuf_size=0; + + + if(ptr == NULL) { + if( fd == NULL) { /* used to clear static data */ + my_free(139, &strbuf); + strbuf_size = 0; + return; + } + if(newline) fputs("{}\n", fd); + else fputs("{}", fd); + return; + } + len = strlen(ptr) + CADCHUNKALLOC; + if(strbuf_size < len ) my_realloc(140, &strbuf, (strbuf_size = len)); + + strbuf[strbuf_pos++] = '{'; + while( (c = *ptr++) ) { + if(strbuf_pos > strbuf_size - 6) my_realloc(525, &strbuf, (strbuf_size += CADCHUNKALLOC)); + if( c=='\\' || c=='{' || c=='}') strbuf[strbuf_pos++] = '\\'; + strbuf[strbuf_pos++] = c; + } + strbuf[strbuf_pos++] = '}'; + if(newline) strbuf[strbuf_pos++] = '\n'; + strbuf[strbuf_pos] = '\0'; + fwrite(strbuf, 1, strbuf_pos, fd); } void save_embedded_symbol(xSymbol *s, FILE *fd) @@ -194,8 +213,7 @@ void save_embedded_symbol(xSymbol *s, FILE *fd) fprintf(fd, "v {xschem version=%s file_version=%s}\n", XSCHEM_VERSION, XSCHEM_FILE_VERSION); fprintf(fd, "G "); - save_ascii_string(s->prop_ptr,fd); - fputc('\n' ,fd); + save_ascii_string(s->prop_ptr,fd, 1); fprintf(fd, "V {}\n"); fprintf(fd, "S {}\n"); fprintf(fd, "E {}\n"); @@ -207,8 +225,7 @@ void save_embedded_symbol(xSymbol *s, FILE *fd) { fprintf(fd, "L %d %.16g %.16g %.16g %.16g ", c,ptr[i].x1, ptr[i].y1,ptr[i].x2, ptr[i].y2 ); - save_ascii_string(ptr[i].prop_ptr,fd); - fputc('\n' ,fd); + save_ascii_string(ptr[i].prop_ptr,fd, 1); } } for(c=0;ctexts;i++) @@ -240,12 +255,11 @@ void save_embedded_symbol(xSymbol *s, FILE *fd) xText *ptr; ptr = s->text; fprintf(fd, "T "); - save_ascii_string(ptr[i].txt_ptr,fd); + save_ascii_string(ptr[i].txt_ptr,fd, 0); fprintf(fd, " %.16g %.16g %hd %hd %.16g %.16g ", ptr[i].x0, ptr[i].y0, ptr[i].rot, ptr[i].flip, ptr[i].xscale, ptr[i].yscale); - save_ascii_string(ptr[i].prop_ptr,fd); - fputc('\n' ,fd); + save_ascii_string(ptr[i].prop_ptr,fd, 1); } for(c=0;cinst; + oldversion = !strcmp(xctx->file_version, "1.0"); for(i=0;isymbols;i++) xctx->sym[i].flags &=~EMBEDDED; for(i=0;iinstances;i++) { - fprintf(fd, "C "); - - if(!strcmp(xctx->file_version, "1.0")) { + fputs("C ", fd); + if(oldversion) { my_strdup(57, &tmp, add_ext(ptr[i].name, ".sym")); - save_ascii_string(rel_sym_path(tmp), fd); + save_ascii_string(tmp, fd, 0); + my_free(882, &tmp); } else { - save_ascii_string(rel_sym_path(ptr[i].name), fd); + save_ascii_string(ptr[i].name, fd, 0); } - my_free(882, &tmp); fprintf(fd, " %.16g %.16g %hd %hd ",ptr[i].x0, ptr[i].y0, ptr[i].rot, ptr[i].flip ); - save_ascii_string(ptr[i].prop_ptr,fd); - fputc('\n' ,fd); + save_ascii_string(ptr[i].prop_ptr,fd, 1); if( !strcmp(get_tok_value(ptr[i].prop_ptr, "embed", 0), "true") ) { /* && !(xctx->sym[ptr[i].ptr].flags & EMBEDDED)) { */ fprintf(fd, "[\n"); @@ -305,8 +317,7 @@ void save_wire(FILE *fd) { fprintf(fd, "N %.16g %.16g %.16g %.16g ",ptr[i].x1, ptr[i].y1, ptr[i].x2, ptr[i].y2); - save_ascii_string(ptr[i].prop_ptr,fd); - fputc('\n' ,fd); + save_ascii_string(ptr[i].prop_ptr,fd, 1); } } @@ -318,12 +329,11 @@ void save_text(FILE *fd) for(i=0;itexts;i++) { fprintf(fd, "T "); - save_ascii_string(ptr[i].txt_ptr,fd); + save_ascii_string(ptr[i].txt_ptr,fd, 0); fprintf(fd, " %.16g %.16g %hd %hd %.16g %.16g ", ptr[i].x0, ptr[i].y0, ptr[i].rot, ptr[i].flip, ptr[i].xscale, ptr[i].yscale); - save_ascii_string(ptr[i].prop_ptr,fd); - fputc('\n' ,fd); + save_ascii_string(ptr[i].prop_ptr,fd, 1); } } @@ -340,8 +350,7 @@ void save_polygon(FILE *fd) for(j=0;jget_tok_size; if(ty && !strcmp(xctx->sch[xctx->currsch] + strlen(xctx->sch[xctx->currsch]) - 4,".sym") ) { fprintf(fd, "G {}\nK "); - save_ascii_string(xctx->schvhdlprop,fd); - fputc('\n', fd); + save_ascii_string(xctx->schvhdlprop,fd, 1); } else { fprintf(fd, "G "); - save_ascii_string(xctx->schvhdlprop,fd); - fputc('\n', fd); + save_ascii_string(xctx->schvhdlprop,fd, 1); fprintf(fd, "K "); - save_ascii_string(xctx->schsymbolprop,fd); - fputc('\n', fd); + save_ascii_string(xctx->schsymbolprop,fd, 1); } } else { fprintf(fd, "G "); - save_ascii_string(xctx->schvhdlprop,fd); - fputc('\n', fd); + save_ascii_string(xctx->schvhdlprop,fd, 1); fprintf(fd, "K "); - save_ascii_string(xctx->schsymbolprop,fd); - fputc('\n', fd); + save_ascii_string(xctx->schsymbolprop,fd, 1); } fprintf(fd, "V "); - save_ascii_string(xctx->schverilogprop,fd); - fputc('\n', fd); + save_ascii_string(xctx->schverilogprop,fd, 1); fprintf(fd, "S "); - save_ascii_string(xctx->schprop,fd); - fputc('\n', fd); + save_ascii_string(xctx->schprop,fd, 1); fprintf(fd, "E "); - save_ascii_string(xctx->schtedaxprop,fd); - fputc('\n', fd); + save_ascii_string(xctx->schtedaxprop,fd, 1); save_line(fd); save_box(fd); @@ -530,22 +528,23 @@ static void load_inst(int k, FILE *fd) char name[PATH_MAX]; char *tmp = NULL; - dbg(3, "load_inst(): start\n"); i=xctx->instances; check_inst_storage(); load_ascii_string(&tmp, fd); if(!tmp) return; - dbg(1, "load_inst(): tmp=%s\n", tmp); my_strncpy(name, tmp, S(name)); dbg(1, "load_inst(): 1: name=%s\n", name); if(!strcmp(xctx->file_version,"1.0") ) { - dbg(1, "load_inst(): add_ext(name,\".sym\") = %s\n", add_ext(name, ".sym") ); my_strncpy(name, add_ext(name, ".sym"), S(name)); } xctx->inst[i].name=NULL; - my_strdup2(56, &xctx->inst[i].name, name); - dbg(1, "load_inst(): 2: name=%s\n", name); - + /* avoid as much as possible calls to rel_sym_path (slow) */ + #ifdef __unix__ + if(name[0] == '/') my_strdup2(56, &xctx->inst[i].name, rel_sym_path(name)); + else my_strdup2(762, &xctx->inst[i].name, name); + #else + my_strdup2(56, &xctx->inst[i].name, rel_sym_path(name)); + #endif if(fscanf(fd, "%lf %lf %hd %hd", &xctx->inst[i].x0, &xctx->inst[i].y0, &xctx->inst[i].rot, &xctx->inst[i].flip) < 4) { fprintf(errfp,"WARNING: missing fields for INSTANCE object, ignoring.\n"); @@ -2164,8 +2163,7 @@ void create_sch_from_sym(void) fprintf(fd, "C {%s} %.16g %.16g %.16g %.16g ", generic_pin, x, 20.0*(ypos++), 0.0, 0.0 ); else fprintf(fd, "C {%s} %.16g %.16g %.16g %.16g ", generic_pin2, x, 20.0*(ypos++), 0.0, 0.0 ); - save_ascii_string(str, fd); - fputc('\n' ,fd); + save_ascii_string(str, fd, 1); } /* for(i) */ npin = ptr->rects[PINLAYER]; rct = ptr->rect[PINLAYER]; @@ -2191,8 +2189,7 @@ void create_sch_from_sym(void) fprintf(fd, "C {%s} %.16g %.16g %.16g %.16g ", pinname[j], x, 20.0*(ypos++), 0.0, 0.0); else fprintf(fd, "C {%s} %.16g %.16g %.16g %.16g ", pinname2[j], x, 20.0*(ypos++), 0.0, 0.0); - save_ascii_string(str, fd); - fputc('\n' ,fd); + save_ascii_string(str, fd, 1); } /* if() */ } /* for(i) */ } /* for(j) */ @@ -2367,27 +2364,24 @@ void save_selection(int what) { case xTEXT: fprintf(fd, "T "); - save_ascii_string(xctx->text[n].txt_ptr,fd); + save_ascii_string(xctx->text[n].txt_ptr,fd, 0); fprintf(fd, " %.16g %.16g %hd %hd %.16g %.16g ", xctx->text[n].x0, xctx->text[n].y0, xctx->text[n].rot, xctx->text[n].flip, xctx->text[n].xscale, xctx->text[n].yscale); - save_ascii_string(xctx->text[n].prop_ptr,fd); - fputc('\n' ,fd); + save_ascii_string(xctx->text[n].prop_ptr,fd, 1); break; case ARC: fprintf(fd, "A %d %.16g %.16g %.16g %.16g %.16g ", c, xctx->arc[c][n].x, xctx->arc[c][n].y, xctx->arc[c][n].r, xctx->arc[c][n].a, xctx->arc[c][n].b); - save_ascii_string(xctx->arc[c][n].prop_ptr,fd); - fputc('\n' ,fd); + save_ascii_string(xctx->arc[c][n].prop_ptr,fd, 1); break; case xRECT: fprintf(fd, "B %d %.16g %.16g %.16g %.16g ", c,xctx->rect[c][n].x1, xctx->rect[c][n].y1,xctx->rect[c][n].x2, xctx->rect[c][n].y2); - save_ascii_string(xctx->rect[c][n].prop_ptr,fd); - fputc('\n' ,fd); + save_ascii_string(xctx->rect[c][n].prop_ptr,fd, 1); break; case POLYGON: @@ -2395,31 +2389,27 @@ void save_selection(int what) for(k=0; kpoly[c][n].points; k++) { fprintf(fd, "%.16g %.16g ", xctx->poly[c][n].x[k], xctx->poly[c][n].y[k]); } - save_ascii_string(xctx->poly[c][n].prop_ptr,fd); - fputc('\n' ,fd); + save_ascii_string(xctx->poly[c][n].prop_ptr,fd, 1); break; case WIRE: fprintf(fd, "N %.16g %.16g %.16g %.16g ",xctx->wire[n].x1, xctx->wire[n].y1, xctx->wire[n].x2, xctx->wire[n].y2); - save_ascii_string(xctx->wire[n].prop_ptr,fd); - fputc('\n' ,fd); + save_ascii_string(xctx->wire[n].prop_ptr,fd, 1); break; case LINE: fprintf(fd, "L %d %.16g %.16g %.16g %.16g ", c,xctx->line[c][n].x1, xctx->line[c][n].y1, xctx->line[c][n].x2, xctx->line[c][n].y2 ); - save_ascii_string(xctx->line[c][n].prop_ptr,fd); - fputc('\n' ,fd); + save_ascii_string(xctx->line[c][n].prop_ptr,fd, 1); break; case ELEMENT: fprintf(fd, "C "); - save_ascii_string(xctx->inst[n].name,fd); + save_ascii_string(xctx->inst[n].name,fd, 0); fprintf(fd, " %.16g %.16g %hd %hd ",xctx->inst[n].x0, xctx->inst[n].y0, xctx->inst[n].rot, xctx->inst[n].flip ); - save_ascii_string(xctx->inst[n].prop_ptr,fd); - fputc('\n' ,fd); + save_ascii_string(xctx->inst[n].prop_ptr,fd, 1); break; default: diff --git a/src/scheduler.c b/src/scheduler.c index 3043197f..11ad8914 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -1916,7 +1916,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg delete_inst_node(inst); /* 20180208 fix crashing bug: delete node info if changing symbol */ /* if number of pins is different we must delete these data *before* */ /* changing ysmbol, otherwise i might end up deleting non allocated data. */ - my_strdup(369, &xctx->inst[inst].name,symbol); + my_strdup(369, &xctx->inst[inst].name, rel_sym_path(symbol)); xctx->inst[inst].ptr=sym_number; bbox(ADD, xctx->inst[inst].x1, xctx->inst[inst].y1, xctx->inst[inst].x2, xctx->inst[inst].y2); diff --git a/src/select.c b/src/select.c index f94b4907..920ef148 100644 --- a/src/select.c +++ b/src/select.c @@ -184,9 +184,9 @@ void symbol_bbox(int i, double *x1,double *y1, double *x2, double *y2) sym_flip = flip; sym_rot = rot; text = (xctx->inst[i].ptr+ xctx->sym)->text[j]; - dbg(2, "symbol_bbox(): instance %d text n: %d text str=%s\n", i,j, text.txt_ptr? text.txt_ptr:"NULL"); + /* dbg(2, "symbol_bbox(): instance %d text n: %d text str=%s\n", i,j, text.txt_ptr? text.txt_ptr:"NULL"); */ tmp_txt = translate(i, text.txt_ptr); - dbg(2, "symbol_bbox(): translated text: %s\n", tmp_txt); + /* dbg(2, "symbol_bbox(): translated text: %s\n", tmp_txt); */ ROTATION(rot, flip, 0.0,0.0,text.x0, text.y0,text_x0,text_y0); #if HAS_CAIRO==1 customfont=set_text_custom_font(&text); @@ -202,7 +202,7 @@ void symbol_bbox(int i, double *x1,double *y1, double *x2, double *y2) if(yy1<*y1) *y1=yy1; if(xx2>*x2) *x2=xx2; if(yy2>*y2) *y2=yy2; - dbg(2, "symbol_bbox(): instance=%d text=%d %.16g %.16g %.16g %.16g\n",i,j, *x1, *y1, *x2, *y2); + /* dbg(2, "symbol_bbox(): instance=%d text=%d %.16g %.16g %.16g %.16g\n",i,j, *x1, *y1, *x2, *y2); */ } } diff --git a/src/token.c b/src/token.c index 56d12fdd..145f01ae 100644 --- a/src/token.c +++ b/src/token.c @@ -461,7 +461,7 @@ const char *get_tok_value(const char *s,const char *tok, int with_quotes) return ""; } xctx->get_tok_value_size = xctx->get_tok_size = 0; - dbg(2, "get_tok_value(): looking for <%s> in <%s>\n",tok,s); + /* dbg(2, "get_tok_value(): looking for <%s> in <%s>\n",tok,s); */ if( size == 0 ) { sizetok = size = CADCHUNKALLOC; my_realloc(454, &result, size); @@ -503,7 +503,7 @@ const char *get_tok_value(const char *s,const char *tok, int with_quotes) /* report back also token size, useful to check if requested token exists */ xctx->get_tok_size = token_pos; } - dbg(2, "get_tok_value(): token=%s\n", token); + /* dbg(2, "get_tok_value(): token=%s\n", token);*/ token_pos=0; } } else if(state==TOK_END) { @@ -2784,7 +2784,7 @@ const char *translate(int inst, const char* s) else if(state==TOK_SEP) { token[token_pos]='\0'; - dbg(2, "translate(): token=%s\n", token); + /* dbg(2, "translate(): token=%s\n", token);*/ /* if spiceprefix==0 and token == @spiceprefix then set empty value */ if(!spiceprefix && !strcmp(token, "@spiceprefix")) { @@ -2804,7 +2804,7 @@ const char *translate(int inst, const char* s) } else { /* no definition found -> subst with token without leading $ */ tmp=token_pos -1 ; /* we need token_pos -1 chars, ( strlen(token+1) ) , excluding leading '$' */ STR_ALLOC(&result, tmp + result_pos, &size); - dbg(2, "translate(): token=%s, token_pos = %d\n", token, token_pos); + /* dbg(2, "translate(): token=%s, token_pos = %d\n", token, token_pos); */ memcpy(result+result_pos, token + 1, tmp+1); } result_pos+=tmp; diff --git a/src/xinit.c b/src/xinit.c index 4e82546f..3d1c3cf1 100644 --- a/src/xinit.c +++ b/src/xinit.c @@ -604,7 +604,7 @@ void xwin_exit(void) translate2(NULL, 0, NULL); /* clear static data in function */ subst_token(NULL, NULL, NULL); /* clear static data in function */ find_nth(NULL, '\0', 0); /* clear static data in function */ - + save_ascii_string(NULL, NULL, 0); /* clear static data in function */ dbg(1, "xwin_exit(): removing font\n"); for(i=0;i<127;i++) my_free(1140, &character[i]); diff --git a/src/xschem.h b/src/xschem.h index 4f1907c6..8ce9b0f2 100644 --- a/src/xschem.h +++ b/src/xschem.h @@ -852,6 +852,7 @@ extern int samefile(const char *fa, const char *fb); extern void saveas(const char *f, int type); extern const char *get_file_path(char *f); extern int save(int confirm); +extern void save_ascii_string(const char *ptr, FILE *fd, int newline); extern struct hilight_hashentry *bus_hilight_lookup(const char *token, int value, int what) ; extern struct hilight_hashentry *hilight_lookup(const char *token, int value, int what); extern int name_strcmp(char *s, char *d) ;