infix_interface xschemrc variable (default=1) can be set to 0 to disable infix (need to click a point after bindkey); disable warnings from graphs with autoload=1 if no raw file or matching analysis found; add m parameter (multiplicity) to bsource.sym, cmos_example.sch; remove dependency on external model file, use ngspice provided mos model 8 bsim3 models.

This commit is contained in:
stefan schippers 2025-01-17 17:15:48 +01:00
parent c57c49fde8
commit ac8db614c0
9 changed files with 221 additions and 90 deletions

View File

@ -2186,6 +2186,7 @@ int callback(const char *winpath, int event, int mx, int my, KeySym key,
XKeyboardState kbdstate;
#endif
int draw_xhair = tclgetboolvar("draw_crosshair");
int infix_interface = tclgetboolvar("infix_interface");
int rstate; /* (reduced state, without ShiftMask) */
/* this fix uses an alternative method for getting mouse coordinates on KeyPress/KeyRelease
@ -2727,10 +2728,17 @@ int rstate; /* (reduced state, without ShiftMask) */
{
int prev_state = xctx->ui_state;
if(xctx->semaphore >= 2) break;
start_wire(xctx->mousex_snap, xctx->mousey_snap);
if(prev_state == STARTWIRE) {
tcleval("set constr_mv 0" );
xctx->constr_mv=0;
if(infix_interface) {
start_wire(xctx->mousex_snap, xctx->mousey_snap);
if(prev_state == STARTWIRE) {
tcleval("set constr_mv 0" );
xctx->constr_mv=0;
}
} else {
xctx->last_command = 0;
xctx->ui_state |= MENUSTART;
xctx->ui_state2 = MENUSTARTWIRE;
}
break;
}
@ -2772,10 +2780,15 @@ int rstate; /* (reduced state, without ShiftMask) */
{
if(xctx->semaphore >= 2) break;
dbg(1, "callback(): start polygon\n");
xctx->mx_double_save=xctx->mousex_snap;
xctx->my_double_save=xctx->mousey_snap;
xctx->last_command = 0;
new_polygon(PLACE, xctx->mousex_snap, xctx->mousey_snap);
if(infix_interface) {
xctx->mx_double_save=xctx->mousex_snap;
xctx->my_double_save=xctx->mousey_snap;
xctx->last_command = 0;
new_polygon(PLACE, xctx->mousex_snap, xctx->mousey_snap);
} else {
xctx->ui_state |= MENUSTART;
xctx->ui_state2 = MENUSTARTPOLYGON;
}
break;
}
if(key=='P' && rstate == 0) /* pan, other way to. */
@ -2924,10 +2937,16 @@ int rstate; /* (reduced state, without ShiftMask) */
if(key=='r' /* && !xctx->ui_state */ && rstate==0) /* start rect */
{
dbg(1, "callback(): start rect\n");
xctx->mx_double_save=xctx->mousex_snap;
xctx->my_double_save=xctx->mousey_snap;
xctx->last_command = 0;
new_rect(PLACE,xctx->mousex_snap, xctx->mousey_snap);
if(xctx->semaphore >= 2) break;
if(infix_interface) {
xctx->mx_double_save=xctx->mousex_snap;
xctx->my_double_save=xctx->mousey_snap;
xctx->last_command = 0;
new_rect(PLACE,xctx->mousex_snap, xctx->mousey_snap);
} else {
xctx->ui_state |= MENUSTART;
xctx->ui_state2 = MENUSTARTRECT;
}
break;
}
if(key=='V' && rstate == ControlMask) /* toggle spice/vhdl netlist */
@ -3097,19 +3116,29 @@ int rstate; /* (reduced state, without ShiftMask) */
if(key=='C' /* && !xctx->ui_state */ && rstate == 0) /* place arc */
{
if(xctx->semaphore >= 2) break;
xctx->mx_double_save=xctx->mousex_snap;
xctx->my_double_save=xctx->mousey_snap;
xctx->last_command = 0;
new_arc(PLACE, 180., xctx->mousex_snap, xctx->mousey_snap);
if(infix_interface) {
xctx->mx_double_save=xctx->mousex_snap;
xctx->my_double_save=xctx->mousey_snap;
xctx->last_command = 0;
new_arc(PLACE, 180., xctx->mousex_snap, xctx->mousey_snap);
} else {
xctx->ui_state |= MENUSTART;
xctx->ui_state2 = MENUSTARTARC;
}
break;
}
if(key=='C' /* && !xctx->ui_state */ && rstate == ControlMask) /* place circle */
{
if(xctx->semaphore >= 2) break;
xctx->mx_double_save=xctx->mousex_snap;
xctx->my_double_save=xctx->mousey_snap;
xctx->last_command = 0;
new_arc(PLACE, 360., xctx->mousex_snap, xctx->mousey_snap);
if(infix_interface) {
xctx->mx_double_save=xctx->mousex_snap;
xctx->my_double_save=xctx->mousey_snap;
xctx->last_command = 0;
new_arc(PLACE, 360., xctx->mousex_snap, xctx->mousey_snap);
} else {
xctx->ui_state |= MENUSTART;
xctx->ui_state2 = MENUSTARTCIRCLE;
}
break;
}
if(key=='O' && rstate == ControlMask ) /* load most recent tile */
@ -3419,10 +3448,17 @@ int rstate; /* (reduced state, without ShiftMask) */
if(key=='l' /* && !xctx->ui_state */ && rstate == 0) /* start line */
{
int prev_state = xctx->ui_state;
start_line(xctx->mousex_snap, xctx->mousey_snap);
if(prev_state == STARTLINE) {
tcleval("set constr_mv 0" );
xctx->constr_mv=0;
if(xctx->semaphore >= 2) break;
if(infix_interface) {
start_line(xctx->mousex_snap, xctx->mousey_snap);
if(prev_state == STARTLINE) {
tcleval("set constr_mv 0" );
xctx->constr_mv=0;
}
} else {
xctx->last_command = 0;
xctx->ui_state |= MENUSTART;
xctx->ui_state2 = MENUSTARTLINE;
}
break;
}

View File

@ -3827,7 +3827,8 @@ void draw_graph(int i, const int flags, Graph_ctx *gr, void *ct)
clear_cairo_surface(xctx->cairo_ctx, gr->sx1, gr->sy1, sw, sh);
#endif
autoload = !strboolcmp(get_tok_value(r->prop_ptr,"autoload", 0), "1");
if(autoload == 0) autoload = 2; /* 2: switch */
if(autoload == 0) autoload = 2; /* 2: switch */
else if(autoload == 1) autoload = 33; /* 1: read, 32: no_warning */
/* graph box, gridlines and axes */
draw_graph_grid(gr, ct);
/* get data to plot */

View File

@ -590,7 +590,7 @@ static void read_raw_data_block(int binary, FILE *fd, Raw *raw, int ac)
* 157 i(v1) current
* Binary:
*/
static int read_dataset(FILE *fd, Raw **rawptr, const char *type)
static int read_dataset(FILE *fd, Raw **rawptr, const char *type, int no_warning)
{
int variables = 0, i, done_points = 0;
char *line = NULL, *varname = NULL, *lowerline = NULL;
@ -716,7 +716,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, -1.0, -1.0);
/* free_rawfile(rawptr, 0); */
/* free_rawfile(rawptr, 0, 0); */
exit_status = 0;
goto read_dataset_done;
}
@ -749,7 +749,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, -1.0, -1.0);
/* free_rawfile(rawptr, 0); */
/* free_rawfile(rawptr, 0, 0); */
exit_status = 0;
goto read_dataset_done;
}
@ -763,7 +763,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, -1.0, -1.0);
/* free_rawfile(rawptr, 0); */
/* free_rawfile(rawptr, 0, 0); */
exit_status = 0;
goto read_dataset_done;
}
@ -786,7 +786,7 @@ static int read_dataset(FILE *fd, Raw **rawptr, const char *type)
if(n < 2) {
dbg(0, "read_dataset(): WAARNING: malformed raw file, aborting\n");
extra_rawfile(3, NULL, NULL, -1.0, -1.0);
/* free_rawfile(rawptr, 0); */
/* free_rawfile(rawptr, 0, 0); */
exit_status = 0;
goto read_dataset_done;
}
@ -838,7 +838,7 @@ static int read_dataset(FILE *fd, Raw **rawptr, const char *type)
/* no analysis was found: delete */
if(exit_status != 1) {
free_rawfile(rawptr, 0);
free_rawfile(rawptr, 0, no_warning);
}
read_dataset_done:
if(line) my_free(_ALLOC_ID_, &line);
@ -851,18 +851,22 @@ static int read_dataset(FILE *fd, Raw **rawptr, const char *type)
return exit_status;
}
void free_rawfile(Raw **rawptr, int dr)
void free_rawfile(Raw **rawptr, int dr, int no_warning)
{
int i;
Raw *raw;
if(!rawptr || !*rawptr) {
dbg(0, "free_rawfile(): no raw file to clear\n");
if(!no_warning) {
dbg(0, "free_rawfile(): no raw file to clear\n");
}
if(dr) draw();
return;
}
raw = *rawptr;
dbg(0, "free_rawfile(): clearing data\n");
if(!no_warning) {
dbg(0, "free_rawfile(): clearing data\n");
}
if(raw->names) {
for(i = 0 ; i < raw->nvars; ++i) {
my_free(_ALLOC_ID_, &raw->names[i]);
@ -954,7 +958,7 @@ int raw_read_from_attr(Raw **rawptr, const char *type, double sweep1, double swe
fwrite(s, decoded_length, 1, fd);
fclose(fd);
my_free(_ALLOC_ID_, &s);
res = raw_read(tmp_filename, rawptr, type, sweep1, sweep2);
res = raw_read(tmp_filename, rawptr, type, 0, sweep1, sweep2);
unlink(tmp_filename);
} else {
dbg(0, "raw_read_from_attr(): failed to open file %s for reading\n", tmp_filename);
@ -995,7 +999,7 @@ int raw_add_vector(const char *varname, const char *expr, int sweep_idx)
}
/* read a ngspice raw file (with data portion in binary format) */
int raw_read(const char *f, Raw **rawptr, const char *type, double sweep1, double sweep2)
int raw_read(const char *f, Raw **rawptr, const char *type, int no_warning, double sweep1, double sweep2)
{
int res = 0;
FILE *fd;
@ -1021,7 +1025,7 @@ int raw_read(const char *f, Raw **rawptr, const char *type, double sweep1, doubl
int_hash_init(&raw->table, HASHSIZE);
fd = fopen(f, fopen_read_mode);
if(fd) {
if((res = read_dataset(fd, rawptr, type)) == 1) {
if((res = read_dataset(fd, rawptr, type, no_warning)) == 1) {
int i;
set_modify(-2); /* clear text floater caches */
my_strdup2(_ALLOC_ID_, &raw->rawfile, f);
@ -1035,8 +1039,10 @@ int raw_read(const char *f, Raw **rawptr, const char *type, double sweep1, doubl
dbg(0, "points=%d, vars=%d, datasets=%d sim_type=%s\n",
raw->allpoints, raw->nvars, raw->datasets, raw->sim_type ? raw->sim_type : "<NULL>");
} else {
/* free_rawfile(rawptr, 0); */ /* do not free: already done in read_dataset()->extra_rawfile() */
dbg(0, "raw_read(): no useful data found\n");
/* free_rawfile(rawptr, 0, 0); */ /* do not free: already done in read_dataset()->extra_rawfile() */
if(!no_warning) {
dbg(0, "raw_read(): no useful data found\n");
}
}
fclose(fd);
if(has_x) {
@ -1050,7 +1056,9 @@ int raw_read(const char *f, Raw **rawptr, const char *type, double sweep1, doubl
}
return res;
}
dbg(0, "raw_read(): failed to open file %s for reading\n", f);
if(!no_warning) {
dbg(0, "raw_read(): failed to open file %s for reading\n", f);
}
return 0;
}
@ -1168,6 +1176,7 @@ int new_rawfile(const char *name, const char *type, const char *sweepvar,
* what == 3: remove a raw file. If no filename given remove all
* what == 4: print info
* what == 5: switch back to previous
* if bit 5 (32) of what is set do not issue warnings
* return 1 if sucessfull, 0 otherwise
*/
int extra_rawfile(int what, const char *file, const char *type, double sweep1, double sweep2)
@ -1175,11 +1184,13 @@ int extra_rawfile(int what, const char *file, const char *type, double sweep1, d
int i;
int ret = 1;
char f[PATH_MAX];
int no_warning = what & 32;
what &= 0xf; /* remove warning bit */
if(type && !type[0]) type = NULL; /* empty string as type will be considered NULL */
dbg(1, "extra_rawfile(): what=%d, file=%s, type=%s\n",
what, file ? file : "<NULL>", type ? type : "<NULL>");
dbg(1, "extra_rawfile(): what=%d, no_warning=%d, file=%s, type=%s\n",
what, no_warning, file ? file : "<NULL>", type ? type : "<NULL>");
if(what == 0) return 0;
/* if not already done insert base raw file (if there is one) into xctx->extra_raw_arr[0] */
if(xctx->raw && xctx->extra_raw_n == 0) {
@ -1208,7 +1219,9 @@ int extra_rawfile(int what, const char *file, const char *type, double sweep1, d
xctx->extra_raw_n++;
} else {
ret = 0; /* not found so did not switch */
dbg(0, "extra_rawfile() read: %s not found or no \"%s\" analysis\n", f, type);
if(!no_warning) {
dbg(0, "extra_rawfile() read: %s not found or no \"%s\" analysis\n", f, type);
}
if(xctx->extra_raw_n) { /* only restore if raw wiles were not deleted due to a failure in read_raw() */
xctx->raw = save; /* restore */
xctx->extra_prev_idx = xctx->extra_idx;
@ -1239,7 +1252,7 @@ int extra_rawfile(int what, const char *file, const char *type, double sweep1, d
Raw *save;
save = xctx->raw;
xctx->raw = NULL;
read_ret = raw_read(f, &xctx->raw, type, sweep1, sweep2);
read_ret = raw_read(f, &xctx->raw, type, no_warning, sweep1, sweep2);
if(read_ret) {
dbg(1, "extra_rawfile(): read %s %s, switch to it. raw->sim_type=%s\n", f,
type ? type : "<NULL>", xctx->raw->sim_type ? xctx->raw->sim_type : "<NULL>");
@ -1249,7 +1262,9 @@ int extra_rawfile(int what, const char *file, const char *type, double sweep1, d
xctx->extra_raw_n++;
} else {
ret = 0; /* not found so did not switch */
dbg(0, "extra_rawfile() read: %s not found or no \"%s\" analysis\n", f, type ? type : "<unspecified>");
if(!no_warning) {
dbg(0, "extra_rawfile() read: %s not found or no \"%s\" analysis\n", f, type ? type : "<unspecified>");
}
if(xctx->extra_raw_n) { /* only restore if raw wiles were not deleted due to a failure in read_raw() */
xctx->raw = save; /* restore */
xctx->extra_prev_idx = xctx->extra_idx;
@ -1290,7 +1305,9 @@ int extra_rawfile(int what, const char *file, const char *type, double sweep1, d
xctx->extra_prev_idx = xctx->extra_idx;
xctx->extra_idx = i;
} else {
dbg(0, "extra_rawfile() switch: %s not found or no %s analysis\n", f, type ? type : "<NULL>");
if(!no_warning) {
dbg(0, "extra_rawfile() switch: %s not found or no %s analysis\n", f, type ? type : "<NULL>");
}
ret = 0;
}
} else { /* switch to next */
@ -1310,7 +1327,7 @@ int extra_rawfile(int what, const char *file, const char *type, double sweep1, d
if(!file) { /* clear all */
if(xctx->extra_raw_n == 0) ret = 0;
for(i = 0; i < xctx->extra_raw_n; i++) {
free_rawfile(&xctx->extra_raw_arr[i], 0);
free_rawfile(&xctx->extra_raw_arr[i], 0, no_warning);
}
tcleval("array unset ngspice::ngspice_data");
xctx->raw = NULL;
@ -1327,11 +1344,11 @@ int extra_rawfile(int what, const char *file, const char *type, double sweep1, d
!strcmp(xctx->extra_raw_arr[i]->rawfile, f) &&
!strcmp(xctx->extra_raw_arr[i]->sim_type, type)
) {
free_rawfile(&xctx->extra_raw_arr[i], 0);
free_rawfile(&xctx->extra_raw_arr[i], 0, no_warning);
found++;
continue;
} else if( !(type && type[0]) && !strcmp(xctx->extra_raw_arr[i]->rawfile, f)) {
free_rawfile(&xctx->extra_raw_arr[i], 0);
free_rawfile(&xctx->extra_raw_arr[i], 0, no_warning);
found++;
continue;
}

View File

@ -4163,7 +4163,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
{
if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
extra_rawfile(3, NULL, NULL, -1.0, -1.0); /* unload additional raw files */
/* free_rawfile(&xctx->raw, 1); */ /* unload base (current) raw file */
/* free_rawfile(&xctx->raw, 1, 0); */ /* unload base (current) raw file */
draw();
Tcl_ResetResult(interp);
}
@ -4183,14 +4183,14 @@ 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, -1.0, -1.0);
* free_rawfile(&xctx->raw, 1);
* free_rawfile(&xctx->raw, 1, 0);
* } else
*/
if(argc > 2) {
double sweep1 = -1.0, sweep2 = -1.0;
tcleval("array unset ngspice::ngspice_data");
extra_rawfile(3, NULL, NULL, -1.0, -1.0);
/* free_rawfile(&xctx->raw, 0); */
/* free_rawfile(&xctx->raw, 0, 0); */
my_snprintf(f, S(f),"regsub {^~/} {%s} {%s/}", argv[2], home_dir);
tcleval(f);
my_strncpy(f, tclresult(), S(f));
@ -4198,8 +4198,8 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
sweep1 = atof_spice(argv[4]);
sweep2 = atof_spice(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(argc > 3) res = raw_read(f, &xctx->raw, argv[3], 0, sweep1, sweep2);
else res = raw_read(f, &xctx->raw, NULL, 0, -1.0, -1.0);
if(sch_waves_loaded() >= 0) {
draw();
}
@ -4218,11 +4218,11 @@ 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, -1.0, -1.0);
/* free_rawfile(&xctx->raw, 1); */
/* free_rawfile(&xctx->raw, 1, 0); */
draw();
} else {
extra_rawfile(3, NULL, NULL, -1.0, -1.0);
/* free_rawfile(&xctx->raw, 0); */
/* free_rawfile(&xctx->raw, 0, 0); */
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) {
@ -5763,14 +5763,14 @@ 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, -1.0, -1.0);
/* free_rawfile(&xctx->raw, 1); */
/* free_rawfile(&xctx->raw, 1, 0); */
draw();
} 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, -1.0, -1.0);
/* free_rawfile(&xctx->raw, 0); */
/* free_rawfile(&xctx->raw, 0, 0); */
table_read(f);
if(sch_waves_loaded() >= 0) {
draw();

View File

@ -1270,10 +1270,10 @@ extern char *base64_encode(const unsigned char *data, const size_t input_length,
extern unsigned char *ascii85_encode(const unsigned char *data, const size_t input_length, size_t *output_length);
extern int raw_get_pos(const char *node, double value, int dset, int from_start, int to_end);
extern int get_raw_index(const char *node, Int_hashentry **entry_ret);
extern void free_rawfile(Raw **rawptr, int dr);
extern void free_rawfile(Raw **rawptr, int dr, int no_warning);
extern int update_op();
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 raw_read(const char *f, Raw **rawptr, const char *type, int no_warning, 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, const char *yname);

View File

@ -7603,7 +7603,7 @@ set tctx::global_list {
graph_logy graph_private_cursor graph_rainbow graph_schname graph_sel_color graph_sel_wave
graph_selected graph_sort graph_unlocked graph_use_ctrl_key
hide_empty_graphs hide_symbols tctx::hsize
incr_hilight incremental_select infowindow_text intuitive_interface
incr_hilight incremental_select infix_interface infowindow_text intuitive_interface
keep_symbols launcher_default_program
light_colors line_width live_cursor2_backannotate local_netlist_dir lvs_ignore
lvs_netlist measure_text netlist_dir netlist_show netlist_type no_ask_save
@ -9060,6 +9060,7 @@ set_ne big_grid_points 0
set_ne draw_grid_axes 1
set_ne persistent_command 0
set_ne intuitive_interface 1
set_ne infix_interface 1
set_ne autotrim_wires 0
set_ne compare_sch 0
set_ne disable_unique_names 0

View File

@ -201,6 +201,11 @@
#### default: 0
# set persistent_command 1
#### if set to 0 users must click a point after hitting a command key
#### like 'w(ire)', 'l(ine)' and so on.
#### default is 1 (hitting the command key sets also the first point).
# set infix_interface 0
#### if set to 1 allow click & drag objects in the schematic
#### to move them without keyboard commands ('m')
#### default: enabled (1)

View File

@ -21,8 +21,8 @@ v {xschem version=3.4.6 file_version=1.2
}
G {}
K {type=source
format="@name @pinlist @VAR = @FUNC "
template="name=B1 VAR=I FUNC=\\"pwl(V(plus,minus),0,0, 1,10m, 2, 100m)\\""}
format="@name @pinlist @VAR = @FUNC m=@m"
template="name=B1 VAR=I FUNC=\\"'pwl(V(plus,minus),0,0, 1,10m, 2, 100m)'\\" m=1"}
V {}
S {}
E {}

File diff suppressed because one or more lines are too long