From cd6deb0bf90166202a9f83d5df3128bbe9455713 Mon Sep 17 00:00:00 2001 From: Stefan Schippers Date: Sun, 31 Dec 2023 20:33:08 +0100 Subject: [PATCH] xschem raw_read: allow specifying t1 and t2 to load only a portion of simulation file --- .../tutorial_ngspice_backannotation.html | 9 --- src/callback.c | 4 +- src/draw.c | 24 +++---- src/save.c | 66 ++++++++++++++----- src/scheduler.c | 53 ++++++++------- src/xinit.c | 2 +- src/xschem.h | 7 +- xschem_library/examples/cmos_example.sch | 8 ++- 8 files changed, 105 insertions(+), 68 deletions(-) diff --git a/doc/xschem_man/tutorial_ngspice_backannotation.html b/doc/xschem_man/tutorial_ngspice_backannotation.html index 9246ac3c..f830894b 100644 --- a/doc/xschem_man/tutorial_ngspice_backannotation.html +++ b/doc/xschem_man/tutorial_ngspice_backannotation.html @@ -27,15 +27,6 @@ p{padding: 15px 30px 10px;}

-

CONFIGURATION

-

- Open your xschemrc file (usually ~/.xschem/xschemrc), go to the end of the file, - Ensure the following tcl file is appended to the list of scripts loaded on startup by Xschem: -

-#### list of tcl files to preload.
-lappend tcl_files ${XSCHEM_SHAREDIR}/ngspice_backannotate.tcl
- 
-

SETUP

Select the 'STIMULI' code block (click on it) and edit its attributes (press q or diff --git a/src/callback.c b/src/callback.c index 3f408b05..867e5d5b 100644 --- a/src/callback.c +++ b/src/callback.c @@ -527,7 +527,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int my_strdup2(_ALLOC_ID_, &rawfile, get_tok_value(r->prop_ptr, "rawfile", 0)); my_strdup2(_ALLOC_ID_, &sim_type, get_tok_value(r->prop_ptr, "sim_type", 0)); - if(rawfile[0] && sim_type[0]) switched = extra_rawfile(2, rawfile, sim_type); + if(rawfile[0] && sim_type[0]) switched = extra_rawfile(2, rawfile, sim_type, -1.0, -1.0); my_free(_ALLOC_ID_, &rawfile); my_free(_ALLOC_ID_, &sim_type); @@ -549,7 +549,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int xx1 = pp - delta / 2.0; xx2 = pp + delta / 2.0; - if(switched) extra_rawfile(5, NULL, NULL); /* switch back to previous raw file */ + if(switched) extra_rawfile(5, NULL, NULL, -1.0, -1.0); /* switch back to previous raw file */ } else if(button == Button3 && (xctx->ui_state & GRAPHPAN) && !xctx->graph_left && !xctx->graph_top) { diff --git a/src/draw.c b/src/draw.c index 7ab3efd9..8f1cded9 100644 --- a/src/draw.c +++ b/src/draw.c @@ -2077,7 +2077,7 @@ int graph_fullxzoom(int i, Graph_ctx *gr, int dataset) my_strdup2(_ALLOC_ID_, &custom_rawfile, get_tok_value(r->prop_ptr,"rawfile",0)); my_strdup2(_ALLOC_ID_, &sim_type, get_tok_value(r->prop_ptr,"sim_type",0)); if((i == xctx->graph_master) && custom_rawfile[0]) { - extra_rawfile(1, custom_rawfile, sim_type[0] ? sim_type : xctx->raw->sim_type); + extra_rawfile(1, custom_rawfile, sim_type[0] ? sim_type : xctx->raw->sim_type, -1.0, -1.0); } idx = get_raw_index(find_nth(get_tok_value(r->prop_ptr, "sweep", 0), ", ", "\"", 0, 1)); dbg(1, "graph_fullxzoom(): sweep idx=%d\n", idx); @@ -2088,7 +2088,7 @@ int graph_fullxzoom(int i, Graph_ctx *gr, int dataset) my_strdup2(_ALLOC_ID_, &sim_type, get_tok_value(xctx->rect[GRIDLAYER][xctx->graph_master].prop_ptr,"sim_type",0)); if(custom_rawfile[0]) { - extra_rawfile(1, custom_rawfile, sim_type[0] ? sim_type : xctx->raw->sim_type); + extra_rawfile(1, custom_rawfile, sim_type[0] ? sim_type : xctx->raw->sim_type, -1.0, -1.0); } } @@ -2119,7 +2119,7 @@ int graph_fullxzoom(int i, Graph_ctx *gr, int dataset) my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x1", dtoa(xx1))); my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "x2", dtoa(xx2))); - if(sch_waves_loaded()!= -1 && custom_rawfile[0]) extra_rawfile(5, NULL, NULL); + if(sch_waves_loaded()!= -1 && custom_rawfile[0]) extra_rawfile(5, NULL, NULL, -1.0, -1.0); my_free(_ALLOC_ID_, &custom_rawfile); my_free(_ALLOC_ID_, &sim_type); @@ -2175,7 +2175,7 @@ int graph_fullyzoom(xRect *r, Graph_ctx *gr, int graph_dataset) char str_extra_idx[30]; if(sch_waves_loaded() != -1 && custom_rawfile[0]) { - extra_rawfile(1, custom_rawfile, sim_type[0] ? sim_type : xctx->raw->sim_type); + extra_rawfile(1, custom_rawfile, sim_type[0] ? sim_type : xctx->raw->sim_type, -1.0, -1.0); } raw = xctx->raw; @@ -2194,7 +2194,7 @@ int graph_fullyzoom(xRect *r, Graph_ctx *gr, int graph_dataset) sim_type[0] ? sim_type : xctx->raw->sim_type); dbg(1, "node_rawfile=|%s| node_sim_type=|%s|\n", node_rawfile, node_sim_type); if(node_rawfile && node_rawfile[0]) { - extra_rawfile(1, node_rawfile, node_sim_type); + extra_rawfile(1, node_rawfile, node_sim_type, -1.0, -1.0); raw = xctx->raw; } my_free(_ALLOC_ID_, &node_rawfile); @@ -2298,7 +2298,7 @@ int graph_fullyzoom(xRect *r, Graph_ctx *gr, int graph_dataset) } if(save_extra_idx != -1) { my_snprintf(str_extra_idx, S(str_extra_idx), "%d", save_extra_idx); - extra_rawfile(2, str_extra_idx, NULL); + extra_rawfile(2, str_extra_idx, NULL, -1.0, -1.0); raw = xctx->raw; } @@ -3191,7 +3191,7 @@ int find_closest_wave(int i, Graph_ctx *gr) my_strdup2(_ALLOC_ID_, &custom_rawfile, get_tok_value(r->prop_ptr,"rawfile",0)); my_strdup2(_ALLOC_ID_, &sim_type, get_tok_value(r->prop_ptr,"sim_type",0)); if(sch_waves_loaded()!= -1 && custom_rawfile[0]) { - extra_rawfile(1, custom_rawfile, sim_type[0] ? sim_type : xctx->raw->sim_type); + extra_rawfile(1, custom_rawfile, sim_type[0] ? sim_type : xctx->raw->sim_type, -1.0, -1.0); } raw = xctx->raw; @@ -3303,7 +3303,7 @@ int find_closest_wave(int i, Graph_ctx *gr) dbg(0, "closest dataset=%d\n", closest_dataset); if(express) my_free(_ALLOC_ID_, &express); - if(sch_waves_loaded()!= -1 && custom_rawfile[0]) extra_rawfile(5, NULL, NULL); + if(sch_waves_loaded()!= -1 && custom_rawfile[0]) extra_rawfile(5, NULL, NULL, -1.0, -1.0); my_free(_ALLOC_ID_, &custom_rawfile); my_free(_ALLOC_ID_, &sim_type); @@ -3394,7 +3394,7 @@ void draw_graph(int i, const int flags, Graph_ctx *gr, void *ct) char str_extra_idx[30]; if(sch_waves_loaded()!= -1 && custom_rawfile[0]) { - extra_rawfile(1, custom_rawfile, sim_type[0] ? sim_type : xctx->raw->sim_type); + extra_rawfile(1, custom_rawfile, sim_type[0] ? sim_type : xctx->raw->sim_type, -1.0, -1.0); } raw = xctx->raw; @@ -3420,7 +3420,7 @@ void draw_graph(int i, const int flags, Graph_ctx *gr, void *ct) sim_type[0] ? sim_type : xctx->raw->sim_type); dbg(1, "node_rawfile=|%s| node_sim_type=|%s|\n", node_rawfile, node_sim_type); if(node_rawfile && node_rawfile[0]) { - extra_rawfile(1, node_rawfile, node_sim_type); + extra_rawfile(1, node_rawfile, node_sim_type, -1.0, -1.0); raw = xctx->raw; } my_free(_ALLOC_ID_, &node_rawfile); @@ -3606,14 +3606,14 @@ void draw_graph(int i, const int flags, Graph_ctx *gr, void *ct) } if(save_extra_idx != -1) { my_snprintf(str_extra_idx, S(str_extra_idx), "%d", save_extra_idx); - extra_rawfile(2, str_extra_idx, NULL); + extra_rawfile(2, str_extra_idx, NULL, -1.0, -1.0); raw = xctx->raw; } } /* while( (ntok = my_strtok_r(nptr, "\n\t ", "", 0, &saven)) ) */ if(ntok_copy) my_free(_ALLOC_ID_, &ntok_copy); if(express) my_free(_ALLOC_ID_, &express); - /* if(sch_waves_loaded()!= -1 && custom_rawfile[0]) extra_rawfile(5, NULL, NULL); */ + /* if(sch_waves_loaded()!= -1 && custom_rawfile[0]) extra_rawfile(5, NULL, NULL, -1.0, -1.0); */ my_free(_ALLOC_ID_, &custom_rawfile); my_free(_ALLOC_ID_, &sim_type); my_free(_ALLOC_ID_, &node); diff --git a/src/save.c b/src/save.c index efd4ddab..6fd95706 100644 --- a/src/save.c +++ b/src/save.c @@ -391,32 +391,62 @@ void transpose_matrix(double *a, int r, int c) */ static void read_binary_block(FILE *fd, Raw *raw, int ac) { - int p, v; + int i, p, v; double *tmp; int offset = 0; + #ifdef __unix__ + long filepos; + #else + __int3264 filepos; + #endif + int npoints; + if(!raw) { dbg(0, "read_binary_block() no raw struct allocated\n"); return; } + /* read buffer */ + tmp = my_calloc(_ALLOC_ID_, raw->nvars, (sizeof(double *) )); + + /* if sweep1 and sweep2 are given calculate actual npoints that will be loaded */ + npoints = raw->npoints[raw->datasets]; + if(!(raw->sweep1 == raw->sweep2 && raw->sweep1 == -1.0)) { + double sweepvar; + npoints = 0; + filepos = xftell(fd); /* store file pointer position */ + for(p = 0; p < raw->npoints[raw->datasets]; p++) { + if(fread(tmp, sizeof(double) , raw->nvars, fd) != raw->nvars) { + dbg(0, "Warning: binary block is not of correct size\n"); + } + sweepvar = tmp[0]; + if(sweepvar < raw->sweep1 || sweepvar >= raw->sweep2) continue; + else npoints++; + } + xfseek(fd, filepos, SEEK_SET); /* rewind file pointer */ + } for(p = 0 ; p < raw->datasets; p++) { offset += raw->npoints[p]; } - - /* read buffer */ - tmp = my_calloc(_ALLOC_ID_, raw->nvars, (sizeof(double *) )); /* allocate storage for binary block, add one data column for custom data plots */ if(!raw->values) raw->values = my_calloc(_ALLOC_ID_, raw->nvars + 1, sizeof(SPICE_DATA *)); for(p = 0 ; p <= raw->nvars; p++) { my_realloc(_ALLOC_ID_, - &raw->values[p], (offset + raw->npoints[raw->datasets]) * sizeof(SPICE_DATA)); + &raw->values[p], (offset + npoints) * sizeof(SPICE_DATA)); } /* read binary block */ - for(p = 0; p < raw->npoints[raw->datasets]; p++) { + p = 0; + for(i = 0; i < raw->npoints[raw->datasets]; i++) { if(fread(tmp, sizeof(double) , raw->nvars, fd) != raw->nvars) { dbg(0, "Warning: binary block is not of correct size\n"); } + + if(!(raw->sweep1 == raw->sweep2 && raw->sweep1 == -1.0)) { + double sweepvar = tmp[0]; + if(sweepvar < raw->sweep1 || sweepvar >= raw->sweep2) continue; + } + /* assign to xschem struct, memory aligned per variable, for cache locality */ if(ac) { for(v = 0; v < raw->nvars; v += 2) { /*AC analysis: calculate magnitude */ @@ -436,7 +466,9 @@ static void read_binary_block(FILE *fd, Raw *raw, int ac) else for(v = 0; v < raw->nvars; v++) { raw->values[v][offset + p] = (SPICE_DATA)tmp[v]; } + p++; } + raw->npoints[raw->datasets] = npoints; /* if sweeep1 and sweep2 are given less points are read */ my_free(_ALLOC_ID_, &tmp); } @@ -492,7 +524,7 @@ static int read_dataset(FILE *fd, Raw **rawptr, const char *type) "Use binary format in ngspice (set filetype=binary)\n"); tcleval("alert_ {read_dataset(): ASCII raw files can not be read. " "Use binary format in ngspice (set filetype=binary)}"); - extra_rawfile(3, NULL, NULL); + extra_rawfile(3, NULL, NULL, -1.0, -1.0); free_rawfile(rawptr, 0); exit_status = 0; goto read_dataset_done; @@ -563,7 +595,7 @@ static int read_dataset(FILE *fd, Raw **rawptr, const char *type) n = sscanf(line, "No. of Data Rows : %d", &npoints); if(n < 1) { dbg(0, "read_dataset(): WAARNING: malformed raw file, aborting\n"); - extra_rawfile(3, NULL, NULL); + extra_rawfile(3, NULL, NULL, -1.0, -1.0); free_rawfile(rawptr, 0); exit_status = 0; goto read_dataset_done; @@ -592,7 +624,7 @@ static int read_dataset(FILE *fd, Raw **rawptr, const char *type) if(n < 1) { dbg(0, "read_dataset(): WAARNING: malformed raw file, aborting\n"); - extra_rawfile(3, NULL, NULL); + extra_rawfile(3, NULL, NULL, -1.0, -1.0); free_rawfile(rawptr, 0); exit_status = 0; goto read_dataset_done; @@ -605,7 +637,7 @@ static int read_dataset(FILE *fd, Raw **rawptr, const char *type) n = sscanf(line, "No. Points: %d", &npoints); if(n < 1) { dbg(0, "read_dataset(): WAARNING: malformed raw file, aborting\n"); - extra_rawfile(3, NULL, NULL); + extra_rawfile(3, NULL, NULL, -1.0, -1.0); free_rawfile(rawptr, 0); exit_status = 0; goto read_dataset_done; @@ -628,7 +660,7 @@ static int read_dataset(FILE *fd, Raw **rawptr, const char *type) n = sscanf(line, "%d %s", &i, varname); /* read index and name of saved waveform */ if(n < 2) { dbg(0, "read_dataset(): WAARNING: malformed raw file, aborting\n"); - extra_rawfile(3, NULL, NULL); + extra_rawfile(3, NULL, NULL, -1.0, -1.0); free_rawfile(rawptr, 0); exit_status = 0; goto read_dataset_done; @@ -738,7 +770,7 @@ char *base64_from_file(const char *f, size_t *length) return b64s; } -int raw_read_from_attr(Raw **rawptr, const char *type) +int raw_read_from_attr(Raw **rawptr, const char *type, double sweep1, double sweep2) { int res = 0; unsigned char *s; @@ -767,7 +799,7 @@ int raw_read_from_attr(Raw **rawptr, const char *type) fwrite(s, decoded_length, 1, fd); fclose(fd); my_free(_ALLOC_ID_, &s); - res = raw_read(tmp_filename, rawptr, type); + res = raw_read(tmp_filename, rawptr, type, sweep1, sweep2); unlink(tmp_filename); } else { dbg(0, "read_rawfile_from_attr(): failed to open file %s for reading\n", tmp_filename); @@ -778,7 +810,7 @@ int raw_read_from_attr(Raw **rawptr, const char *type) } /* read a ngspice raw file (with data portion in binary format) */ -int raw_read(const char *f, Raw **rawptr, const char *type) +int raw_read(const char *f, Raw **rawptr, const char *type, double sweep1, double sweep2) { int res = 0; FILE *fd; @@ -797,6 +829,8 @@ int raw_read(const char *f, Raw **rawptr, const char *type) raw = *rawptr; raw->level = -1; raw->annot_p = -1; + raw->sweep1 = sweep1; + raw->sweep2 = sweep2; raw->annot_sweep_idx = -1; int_hash_init(&raw->table, HASHSIZE); @@ -844,7 +878,7 @@ int raw_read(const char *f, Raw **rawptr, const char *type) * what == 5: switch back to previous * return 1 if sucessfull, 0 otherwise */ -int extra_rawfile(int what, const char *file, const char *type) +int extra_rawfile(int what, const char *file, const char *type, double sweep1, double sweep2) { int i; int ret = 1; @@ -872,7 +906,7 @@ int extra_rawfile(int what, const char *file, const char *type) Raw *save; save = xctx->raw; xctx->raw = NULL; - read_ret = raw_read(f, &xctx->raw, type); + read_ret = raw_read(f, &xctx->raw, type, sweep1, sweep2); if(read_ret) { xctx->extra_raw_arr[xctx->extra_raw_n] = xctx->raw; xctx->extra_prev_idx = xctx->extra_idx; diff --git a/src/scheduler.c b/src/scheduler.c index 9abe39b5..4f9d01d3 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -283,9 +283,9 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg } tclsetboolvar("live_cursor2_backannotate", 1); /* clear all raw files */ - extra_rawfile(3, NULL, NULL); + extra_rawfile(3, NULL, NULL, -1.0, -1.0); free_rawfile(&xctx->raw, 1); - raw_read(f, &xctx->raw, "op"); + raw_read(f, &xctx->raw, "op", -1.0, -1.0); if(level >= 0) { xctx->raw->level = level; my_strdup2(_ALLOC_ID_, &xctx->raw->schname, xctx->sch[level]); @@ -3360,32 +3360,32 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg int ret = 0; if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;} if(argc > 3 && !strcmp(argv[2], "read")) { - if(argc > 4) ret = extra_rawfile(1, argv[3], argv[4]); - else ret = extra_rawfile(1, argv[3], NULL); + if(argc > 4) ret = extra_rawfile(1, argv[3], argv[4], -1.0, -1.0); + else ret = extra_rawfile(1, argv[3], NULL, -1.0, -1.0); Tcl_SetResult(interp, my_itoa(ret), TCL_VOLATILE); } else if(argc > 2 && !strcmp(argv[2], "switch")) { if(argc > 4) { - ret = extra_rawfile(2, argv[3], argv[4]); + ret = extra_rawfile(2, argv[3], argv[4], -1.0, -1.0); } else if(argc > 3) { - ret = extra_rawfile(2, argv[3], NULL); + ret = extra_rawfile(2, argv[3], NULL, -1.0, -1.0); } else { - ret = extra_rawfile(2, NULL, NULL); + ret = extra_rawfile(2, NULL, NULL, -1.0, -1.0); } update_op(); Tcl_SetResult(interp, my_itoa(ret), TCL_VOLATILE); } else if(argc > 2 && !strcmp(argv[2], "info")) { - ret = extra_rawfile(4, NULL, NULL); + ret = extra_rawfile(4, NULL, NULL, -1.0, -1.0); } else if(argc > 2 && !strcmp(argv[2], "switch_back")) { - ret = extra_rawfile(5, NULL, NULL); + ret = extra_rawfile(5, NULL, NULL, -1.0, -1.0); update_op(); Tcl_SetResult(interp, my_itoa(ret), TCL_VOLATILE); } else if(argc > 2 && !strcmp(argv[2], "clear")) { if(argc > 4) { - ret = extra_rawfile(3, argv[3], argv[4]); + ret = extra_rawfile(3, argv[3], argv[4], -1.0, -1.0); } else if(argc > 3) { - ret = extra_rawfile(3, argv[3], NULL); + ret = extra_rawfile(3, argv[3], NULL, -1.0, -1.0); } else { - ret = extra_rawfile(3, NULL, NULL); + ret = extra_rawfile(3, NULL, NULL, -1.0, -1.0); } Tcl_SetResult(interp, my_itoa(ret), TCL_VOLATILE); } else { @@ -3399,7 +3399,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg else if(!strcmp(argv[1], "raw_clear")) { if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;} - extra_rawfile(3, NULL, NULL); /* unload additional raw files */ + extra_rawfile(3, NULL, NULL, -1.0, -1.0); /* unload additional raw files */ free_rawfile(&xctx->raw, 1); /* unload base (current) raw file */ Tcl_ResetResult(interp); } @@ -3499,7 +3499,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg } } - /* raw_read [file] [sim] + /* raw_read [file] [sim] [sweep1 sweep2] * If a raw file is already loaded delete from memory * else load specified file and analysis 'sim' (dc, ac, tran, op, ...) * If 'sim' not specified load first section found in raw file. */ @@ -3511,19 +3511,24 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg /* * if(sch_waves_loaded() >= 0) { * tcleval("array unset ngspice::ngspice_data"); - * extra_rawfile(3, NULL, NULL); + * extra_rawfile(3, NULL, NULL, -1.0, -1.0); * free_rawfile(&xctx->raw, 1); * } else */ if(argc > 2) { + double sweep1 = -1.0, sweep2 = -1.0; tcleval("array unset ngspice::ngspice_data"); - extra_rawfile(3, NULL, NULL); + extra_rawfile(3, NULL, NULL, -1.0, -1.0); free_rawfile(&xctx->raw, 0); my_snprintf(f, S(f),"regsub {^~/} {%s} {%s/}", argv[2], home_dir); tcleval(f); my_strncpy(f, tclresult(), S(f)); - if(argc > 3) res = raw_read(f, &xctx->raw, argv[3]); - else res = raw_read(f, &xctx->raw, NULL); + if(argc > 5) { + sweep1 = atof(argv[4]); + sweep2 = atof(argv[5]); + } + if(argc > 3) res = raw_read(f, &xctx->raw, argv[3], sweep1, sweep2); + else res = raw_read(f, &xctx->raw, NULL, -1.0, -1.0); if(sch_waves_loaded() >= 0) { draw(); } @@ -3541,13 +3546,13 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg { if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;} if(sch_waves_loaded() >= 0) { - extra_rawfile(3, NULL, NULL); + extra_rawfile(3, NULL, NULL, -1.0, -1.0); free_rawfile(&xctx->raw, 1); } else { - extra_rawfile(3, NULL, NULL); + extra_rawfile(3, NULL, NULL, -1.0, -1.0); free_rawfile(&xctx->raw, 0); - if(argc > 2) raw_read_from_attr(&xctx->raw, argv[2]); - else raw_read_from_attr(&xctx->raw, NULL); + if(argc > 2) raw_read_from_attr(&xctx->raw, argv[2], -1.0, -1.0); + else raw_read_from_attr(&xctx->raw, NULL, -1.0, -1.0); if(sch_waves_loaded() >= 0) { draw(); } @@ -4926,13 +4931,13 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg char f[PATH_MAX + 100]; if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;} if(sch_waves_loaded() >= 0) { - extra_rawfile(3, NULL, NULL); + extra_rawfile(3, NULL, NULL, -1.0, -1.0); free_rawfile(&xctx->raw, 1); } else if(argc > 2) { my_snprintf(f, S(f),"regsub {^~/} {%s} {%s/}", argv[2], home_dir); tcleval(f); my_strncpy(f, tclresult(), S(f)); - extra_rawfile(3, NULL, NULL); + extra_rawfile(3, NULL, NULL, -1.0, -1.0); free_rawfile(&xctx->raw, 0); table_read(f); if(sch_waves_loaded() >= 0) { diff --git a/src/xinit.c b/src/xinit.c index 7021f257..517c2136 100644 --- a/src/xinit.c +++ b/src/xinit.c @@ -689,7 +689,7 @@ static void delete_schematic_data(int delete_pixmap) escape_chars(NULL); sanitize(NULL); is_generator(NULL); - extra_rawfile(3, NULL, NULL); + extra_rawfile(3, NULL, NULL, -1.0, -1.0); free_rawfile(&xctx->raw, 0); statusmsg("", 1); /* clear allocated string */ record_global_node(2, NULL, NULL); /* delete global node array */ diff --git a/src/xschem.h b/src/xschem.h index d7842c02..dee64246 100644 --- a/src/xschem.h +++ b/src/xschem.h @@ -782,6 +782,7 @@ typedef struct { * holds the name of the top schematic from which the raw file was loaded */ char *schname; int level; /* hierarchy level where raw file has been read */ + double sweep1, sweep2; } Raw; @@ -1219,7 +1220,7 @@ extern int filter_data(const char *din, const size_t ilen, char **dout, size_t *olen, const char *cmd); extern int embed_rawfile(const char *rawfile); extern int read_rawfile_from_attr(const char *b64s, size_t length, const char *type); -extern int raw_read_from_attr(Raw **rawptr, const char *type); +extern int raw_read_from_attr(Raw **rawptr, const char *type, double sweep1, double sweep2); extern char *base64_from_file(const char *f, size_t *length); extern int set_rect_flags(xRect *r); extern int set_text_flags(xText *t); @@ -1234,8 +1235,8 @@ extern unsigned char *ascii85_encode(const unsigned char *data, const size_t inp extern int get_raw_index(const char *node); extern void free_rawfile(Raw **rawptr, int dr); extern int update_op(); -extern int extra_rawfile(int what, const char *f, const char *type); -extern int raw_read(const char *f, Raw **rawptr, const char *type); +extern int extra_rawfile(int what, const char *f, const char *type, double sweep1, double sweep2); +extern int raw_read(const char *f, Raw **rawptr, const char *type, double sweep1, double sweep2); extern int table_read(const char *f); extern double get_raw_value(int dataset, int idx, int point); extern int plot_raw_custom_data(int sweep_idx, int first, int last, const char *ntok); diff --git a/xschem_library/examples/cmos_example.sch b/xschem_library/examples/cmos_example.sch index 12788e99..e83c8d85 100644 --- a/xschem_library/examples/cmos_example.sch +++ b/xschem_library/examples/cmos_example.sch @@ -303,7 +303,7 @@ tclcommand="xschem annotate_op $\{netlist_dir\}/cmos_example_ngspice.raw" C {launcher.sym} 700 -110 0 0 {name=h2 descr="View raw file" tclcommand="textwindow $netlist_dir/cmos_example_ngspice.raw"} -C {ngspice_get_value.sym} 620 -160 0 0 {name=r5 node=i(@$\{path\}m1[id]) +C {ngspice_get_value.sym} 610 -180 0 0 {name=r5 node=i(@$\{path\}m1[id]) descr="I="} C {launcher.sym} 475 -695 0 0 {name=h3 descr="Load NGSPICE waveforms (ctrl-left-click)" @@ -406,3 +406,9 @@ xschem raw switch; xschem redraw" } C {ngspice_get_value.sym} 210 -200 0 1 {name=r1 node=i(@$\{path\}m3[id]) descr="I="} +C {ngspice_get_value.sym} 470 -230 0 1 {name=r2 node=@$\{path\}m4[gm] +descr="gm="} +C {ngspice_get_value.sym} 720 -230 0 0 {name=r3 node=@$\{path\}m5[gm] +descr="gm="} +C {ngspice_get_value.sym} 610 -130 0 0 {name=r4 node=@$\{path\}m1[gm] +descr="gm="}