diff --git a/doc/xschem_man/component_property_syntax.html b/doc/xschem_man/component_property_syntax.html index 02766223..b7c63a3a 100644 --- a/doc/xschem_man/component_property_syntax.html +++ b/doc/xschem_man/component_property_syntax.html @@ -129,10 +129,13 @@ name="mchanged_name" model=\"nmos\" w="20u" l="3u" m="10"

If set to true the #n:net_name symbol attributes will display the net names attached to pin terminals. the n is a pin number or name.

  • place
  • -

    This - place=end attribute is only valid only for netlist_commands type symbols, and tells +

    The place=end attribute is only valid only for netlist_commands type symbols, and tells XSCHEM that this component must be netlisted last. This is necessary for some spice commands that need to be placed after the rest of the netlist.

    +

    The place=header attribute is only valid only for netlist_commands type symbols + and spice netlisting mode, it tells XSCHEM that this component must be netlisted in the very first + part of a spice netlist. This is necessary for some spice commands + that need to be placed before the rest of the netlist.

  • spice_ignore
  • This tells XSCHEM that for SPICE netlist this component will be completely ignored.

  • verilog_ignore
  • diff --git a/doc/xschem_man/xschem_man.html b/doc/xschem_man/xschem_man.html index 4827d149..8350a83d 100644 --- a/doc/xschem_man/xschem_man.html +++ b/doc/xschem_man/xschem_man.html @@ -66,6 +66,7 @@
  • [Video] Run a Verilog simulation with XSCHEM and icarus Verilog
  • [Video] See logic propagation of nets live in xschem without using a backend simulator
  • [Video] Probe xschem nets into the GAW waveform viewer
  • +
  • [Video] Probe xschem nets into the BESPICE waveform viewer
  • [Video] Creating a symbol
  • [Video] Instantiating schematics instead of symbols (LCC, Local Custom Cell)
  • [Video] Using more schematic views of a symbol to do simulation at different abstraction levels
  • diff --git a/src/callback.c b/src/callback.c index 98d82f28..d227c669 100644 --- a/src/callback.c +++ b/src/callback.c @@ -455,7 +455,7 @@ int callback(int event, int mx, int my, KeySym key, break; } if(key == 'J' && state==ShiftMask) { - create_plot_cmd(NGSPICE); + create_plot_cmd(); break; } if(key == '$' && ( state == ShiftMask) ) /* toggle pixmap saving */ @@ -991,11 +991,30 @@ int callback(int event, int mx, int my, KeySym key, if(!big) bbox(END , 0.0 , 0.0 , 0.0 , 0.0); break; } - if(key=='g' && state==Mod1Mask) { /* highlight net and send to gaw viewer */ + if(key=='g' && state==Mod1Mask) { /* highlight net and send to viewer */ + int tool = 0; + int exists = 0; + char *tool_name = NULL; + char str[200]; + if(xctx->semaphore >= 2) break; - enable_drill=0; - hilight_net(GAW); - redraw_hilights(0); + tcleval("info exists sim"); + if(tclresult()[0] == '1') exists = 1; + enable_drill = 0; + if(exists) { + tool = atol(tclgetvar("sim(spicewave,default)")); + my_snprintf(str, S(str), "sim(spicewave,%d,name)", tool); + my_strdup(1271, &tool_name, tclgetvar(str)); + dbg(1,"callback(): tool_name=%s\n", tool_name); + if(strstr(tool_name, "Gaw")) tool=GAW; + else if(strstr(tool_name, "Bespice")) tool=BESPICE; + if(tool) { + hilight_net(tool); + redraw_hilights(0); + } + my_free(1272, &tool_name); + } + Tcl_ResetResult(interp); break; } if(key=='g' && state==0) /* half snap factor */ diff --git a/src/hilight.c b/src/hilight.c index d6be5fbc..087c9ca6 100644 --- a/src/hilight.c +++ b/src/hilight.c @@ -125,17 +125,41 @@ void incr_hilight_color(void) } /* print all highlight signals which are not ports (in/out/inout). */ -void create_plot_cmd(int viewer) +void create_plot_cmd(void) { int i, c, idx, first; struct hilight_hashentry *entry; struct node_hashentry *node_entry; char *tok; char plotfile[PATH_MAX]; - char color_str[18]; + char color_str[30]; FILE *fd = NULL; char *str = NULL; + int viewer = 0; + int exists = 0; + char *viewer_name = NULL; + char tcl_str[200]; + char rawfile[PATH_MAX]; + int simtype; + tcleval("sim_is_xyce"); + simtype = atoi( tclresult() ); + tcleval("file tail [file rootname [xschem get schname 0]].raw"); + my_strncpy(rawfile, tclresult(), S(rawfile)); + tcleval("info exists sim"); + if(tclresult()[0] == '1') exists = 1; + enable_drill = 0; + if(exists) { + viewer = atol(tclgetvar("sim(spicewave,default)")); + my_snprintf(tcl_str, S(tcl_str), "sim(spicewave,%d,name)", viewer); + my_strdup(1269, &viewer_name, tclgetvar(tcl_str)); + dbg(1,"create_plot_cmd(): viewer_name=%s\n", viewer_name); + if(strstr(viewer_name, "Gaw")) viewer=GAW; + else if(strstr(viewer_name, "Bespice")) viewer=BESPICE; + else if(strstr(viewer_name, "Ngspice")) viewer=NGSPICE; + my_free(1270, &viewer_name); + } + if(!exists || !viewer) return; my_snprintf(plotfile, S(plotfile), "%s/xplot", netlist_dir); if(viewer == NGSPICE) { if(!(fd = fopen(plotfile, "w"))) { @@ -157,10 +181,10 @@ void create_plot_cmd(int viewer) if(node_entry && !strcmp(xctx->sch_path[xctx->currsch], entry->path) && (node_entry->d.port == 0 || !strcmp(entry->path, ".") )) { c = get_color(entry->value); - sprintf(color_str, "%02x/%02x/%02x", - xcolor_array[c].red>>8, xcolor_array[c].green>>8, xcolor_array[c].blue>>8); idx++; if(viewer == NGSPICE) { + sprintf(color_str, "%02x/%02x/%02x", + xcolor_array[c].red>>8, xcolor_array[c].green>>8, xcolor_array[c].blue>>8); if(idx > 9) { idx = 2; fprintf(fd, str); @@ -180,10 +204,66 @@ void create_plot_cmd(int viewer) } if(viewer == GAW) { char *t=NULL, *p=NULL; + sprintf(color_str, "%02x%02x%02x", + xcolor_array[c].red>>8, xcolor_array[c].green>>8, xcolor_array[c].blue>>8); + my_strdup(1273, &t, tok); + my_strdup2(1274, &p, (entry->path)+1); + if(simtype == 0 ) { /* spice */ + Tcl_VarEval(interp, "puts $gaw_fd {copyvar v(", strtolower(p), strtolower(t), + ") sel #", color_str, "}\nvwait gaw_fd\n", NULL); + } else { /* Xyce */ + char *c=p; + while(*c){ + if(*c == '.') *c = ':'; /* Xyce uses : as path separator */ + c++; + } + Tcl_VarEval(interp, "puts $gaw_fd {copyvar ", strtoupper(p), strtoupper(t), + " sel #", color_str, "}\nvwait gaw_fd\n", NULL); + } + my_free(1275, &p); + my_free(1276, &t); + } + if(viewer == BESPICE) { + char *t=NULL, *p=NULL; + sprintf(color_str, "%d %d %d", + xcolor_array[c].red>>8, xcolor_array[c].green>>8, xcolor_array[c].blue>>8); my_strdup(241, &t, tok); my_strdup2(245, &p, (entry->path)+1); - Tcl_VarEval(interp, "puts $gaw_fd {copyvar v(", strtolower(p), strtolower(t), - ") sel #", color_str, "}\nvwait gaw_fd\n", NULL); + + if(simtype == 0 ) { /* spice */ + Tcl_VarEval(interp, + "puts $bespice_server_getdata(sock) ", + "{set_curve_style \"", + rawfile, + "\" \"v(", strtolower(p), strtolower(t), + ")\" \"solid_line\" \"no symbol\" 1 ", + color_str, "}", + NULL); + Tcl_VarEval(interp, + "puts $bespice_server_getdata(sock) ", + "{add_curve_to_plot \"", rawfile, "\" \"v(", strtolower(p), strtolower(t), + ")\" \"\"}", + NULL); + } else { /* Xyce */ + char *c=p; + while(*c){ + if(*c == '.') *c = ':'; /* Xyce uses : as path separator */ + c++; + } + Tcl_VarEval(interp, + "puts $bespice_server_getdata(sock) ", + "{set_curve_style \"", + rawfile, + "\" \"", strtoupper(p), strtoupper(t), + "\" \"solid_line\" \"no symbol\" 1 ", + color_str, "}", + NULL); + Tcl_VarEval(interp, + "puts $bespice_server_getdata(sock) ", + "{add_curve_to_plot \"", rawfile, "\" \"", strtoupper(p), strtoupper(t), + "\" \"\"}", + NULL); + } my_free(759, &p); my_free(760, &t); } @@ -750,6 +830,70 @@ int hilight_netname(const char *name) return node_entry ? 1 : 0; } +static void send_net_to_bespice(int simtype, const char *node) +{ + int c, k, tok_mult; + struct node_hashentry *node_entry; + const char *expanded_tok; + const char *tok; + char color_str[30]; + char rawfile[PATH_MAX]; + + tcleval("file tail [file rootname [xschem get schname 0]].raw"); + my_strncpy(rawfile, tclresult(), S(rawfile)); + if(!node || !node[0]) return; + tok = node; + node_entry = bus_hash_lookup(tok, "", XLOOKUP, 0, "", "", "", ""); + if(tok[0] == '#') tok++; + if(node_entry && (node_entry->d.port == 0 || !strcmp(xctx->sch_path[xctx->currsch], ".") )) { + char *t=NULL, *p=NULL; + c = get_color(xctx->hilight_color); + sprintf(color_str, "%d %d %d", xcolor_array[c].red>>8, xcolor_array[c].green>>8, + xcolor_array[c].blue>>8); + expanded_tok = expandlabel(tok, &tok_mult); + for(k=1; k<=tok_mult; k++) { + my_strdup(1277, &t, find_nth(expanded_tok, ',', k)); + my_strdup2(1278, &p, xctx->sch_path[xctx->currsch]+1); + if(simtype == 0 ) { /* spice */ + Tcl_VarEval(interp, + "puts $bespice_server_getdata(sock) ", + "{set_curve_style \"", + rawfile, + "\" \"v(", strtolower(p), strtolower(t), + ")\" \"solid_line\" \"no symbol\" 1 ", + color_str, "}", + NULL); + Tcl_VarEval(interp, + "puts $bespice_server_getdata(sock) ", + "{add_curve_to_plot \"", rawfile, "\" \"v(", strtolower(p), strtolower(t), + ")\" \"\"}", + NULL); + } else { /* Xyce */ + char *c=p; + while(*c){ + if(*c == '.') *c = ':'; /* Xyce uses : as path separator */ + c++; + } + Tcl_VarEval(interp, + "puts $bespice_server_getdata(sock) ", + "{set_curve_style \"", + rawfile, + "\" \"", strtoupper(p), strtoupper(t), + "\" \"solid_line\" \"no symbol\" 1 ", + color_str, "}", + NULL); + Tcl_VarEval(interp, + "puts $bespice_server_getdata(sock) ", + "{add_curve_to_plot \"", rawfile, "\" \"", strtoupper(p), strtoupper(t), + "\" \"\"}", + NULL); + } + } + my_free(1279, &p); + my_free(1280, &t); + } +} + static void send_net_to_gaw(int simtype, const char *node) { int c, k, tok_mult; @@ -790,6 +934,72 @@ static void send_net_to_gaw(int simtype, const char *node) } } +static void send_current_to_bespice(int simtype, const char *node) +{ + int c, k, tok_mult; + const char *expanded_tok; + const char *tok; + char color_str[30]; + char *t=NULL, *p=NULL; + char rawfile[PATH_MAX]; + + tcleval("file tail [file rootname [xschem get schname 0]].raw"); + my_strncpy(rawfile, tclresult(), S(rawfile)); + + if(!node || !node[0]) return; + tok = node; + /* c = PINLAYER; */ + c = get_color(xctx->hilight_color); + sprintf(color_str, "%d %d %d", xcolor_array[c].red>>8, xcolor_array[c].green>>8, + xcolor_array[c].blue>>8); + expanded_tok = expandlabel(tok, &tok_mult); + for(k=1; k<=tok_mult; k++) { + my_strdup(1281, &t, find_nth(expanded_tok, ',', k)); + my_strdup2(1282, &p, xctx->sch_path[xctx->currsch]+1); + if(!simtype) { /* spice */ + Tcl_VarEval(interp, + "puts $bespice_server_getdata(sock) ", + "{set_curve_style \"", + rawfile, + "\" \"i(", xctx->currsch>0 ? "v." : "", + strtolower(p), strtolower(t), + ")\" \"solid_line\" \"no symbol\" 1 ", + color_str, "}", + NULL); + Tcl_VarEval(interp, + "puts $bespice_server_getdata(sock) ", + "{add_curve_to_plot \"", rawfile, "\" \"i(", xctx->currsch>0 ? "v." : "", + strtolower(p), strtolower(t), + ")\" \"\"}", + NULL); + } else { /* Xyce */ + char *c=p; + while(*c){ + if(*c == '.') *c = ':'; /* Xyce uses : as path separator */ + c++; + } + + Tcl_VarEval(interp, + "puts $bespice_server_getdata(sock) ", + "{set_curve_style \"", + rawfile, + "\" \"", xctx->currsch>0 ? "V:" : "", + strtoupper(p), strtoupper( xctx->currsch>0 ? t+1 : t), "#branch", + "\" \"solid_line\" \"no symbol\" 1 ", + color_str, "}", + NULL); + Tcl_VarEval(interp, + "puts $bespice_server_getdata(sock) ", + "{add_curve_to_plot \"", rawfile, "\" \"", xctx->currsch>0 ? "V:" : "", + strtoupper(p), strtoupper( xctx->currsch>0 ? t+1 : t), "#branch", + "\" \"\"}", + NULL); + } + } + my_free(1283, &p); + my_free(1284, &t); +} + static void send_current_to_gaw(int simtype, const char *node) { int c, k, tok_mult; @@ -800,7 +1010,8 @@ static void send_current_to_gaw(int simtype, const char *node) if(!node || !node[0]) return; tok = node; - c = PINLAYER; + /* c = PINLAYER; */ + c = get_color(xctx->hilight_color); sprintf(color_str, "%02x%02x%02x", xcolor_array[c].red>>8, xcolor_array[c].green>>8, xcolor_array[c].blue>>8); expanded_tok = expandlabel(tok, &tok_mult); @@ -1282,7 +1493,7 @@ void logic_set(int value, int num) } -void hilight_net(int to_waveform) +void hilight_net(int viewer) { int i, n; char *type; @@ -1299,7 +1510,8 @@ void hilight_net(int to_waveform) case WIRE: /* sets xctx->hilight_nets=1 */ if(!bus_hilight_lookup(xctx->wire[n].node, xctx->hilight_color, XINSERT_NOREPLACE)) { - if(to_waveform == GAW) send_net_to_gaw(sim_is_xyce, xctx->wire[n].node); + if(viewer == GAW) send_net_to_gaw(sim_is_xyce, xctx->wire[n].node); + if(viewer == BESPICE) send_net_to_bespice(sim_is_xyce, xctx->wire[n].node); if(incr_hilight) incr_hilight_color(); } break; @@ -1308,18 +1520,20 @@ void hilight_net(int to_waveform) if( type && xctx->inst[n].node && IS_LABEL_SH_OR_PIN(type) ) { /* instance must have a pin! */ /* sets xctx->hilight_nets=1 */ if(!bus_hilight_lookup(xctx->inst[n].node[0], xctx->hilight_color, XINSERT_NOREPLACE)) { - if(to_waveform == GAW) send_net_to_gaw(sim_is_xyce, xctx->inst[n].node[0]); + if(viewer == GAW) send_net_to_gaw(sim_is_xyce, xctx->inst[n].node[0]); + if(viewer == BESPICE) send_net_to_bespice(sim_is_xyce, xctx->inst[n].node[0]); if(incr_hilight) incr_hilight_color(); } } else { dbg(1, "hilight_net(): setting hilight flag on inst %d\n",n); xctx->hilight_nets=1; xctx->inst[n].color = xctx->hilight_color; + if(type && (!strcmp(type, "current_probe") || !strcmp(type, "vsource")) ) { + if(viewer == GAW) send_current_to_gaw(sim_is_xyce, xctx->inst[n].instname); + if(viewer == BESPICE) send_current_to_bespice(sim_is_xyce, xctx->inst[n].instname); + } if(incr_hilight) incr_hilight_color(); } - if(type && (!strcmp(type, "current_probe") || !strcmp(type, "vsource")) ) { - if(to_waveform == GAW) send_current_to_gaw(sim_is_xyce, xctx->inst[n].instname); - } break; default: break; diff --git a/src/scheduler.c b/src/scheduler.c index d4e0ba02..8e0c523d 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -295,15 +295,8 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg else if(!strcmp(argv[1],"create_plot_cmd") ) { cmd_found = 1; - if(argc>2) { - if(!strcmp(argv[2], "gaw")) { - create_plot_cmd(GAW); - } else { - create_plot_cmd(NGSPICE); - } - } else { - create_plot_cmd(NGSPICE); - } + create_plot_cmd(); + Tcl_ResetResult(interp); } else if(!strcmp(argv[1],"cut")) @@ -2130,13 +2123,30 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg my_free(453, &res); } - else if(!strcmp(argv[1],"send_to_gaw")) + else if(!strcmp(argv[1],"send_to_viewer")) { + int viewer = 0; + int exists = 0; + char *viewer_name = NULL; + char tcl_str[200]; + cmd_found = 1; + tcleval("info exists sim"); + if(tclresult()[0] == '1') exists = 1; enable_drill = 0; - hilight_net(GAW); - /* draw_hilight_net(1); */ - redraw_hilights(0); + if(exists) { + viewer = atol(tclgetvar("sim(spicewave,default)")); + my_snprintf(tcl_str, S(tcl_str), "sim(spicewave,%d,name)", viewer); + my_strdup(1267, &viewer_name, tclgetvar(tcl_str)); + dbg(1,"send_to_viewer: viewer_name=%s\n", viewer_name); + if(strstr(viewer_name, "Gaw")) viewer=GAW; + else if(strstr(viewer_name, "Bespice")) viewer=BESPICE; + if(viewer) { + hilight_net(viewer); + redraw_hilights(0); + } + my_free(1268, &viewer_name); + } Tcl_ResetResult(interp); } diff --git a/src/xschem.h b/src/xschem.h index 81efb20b..3899dfed 100644 --- a/src/xschem.h +++ b/src/xschem.h @@ -223,6 +223,7 @@ extern char win_temp_dir[PATH_MAX]; /* viewers xschem can generate plot commands for */ #define NGSPICE 1 #define GAW 2 +#define BESPICE 3 /* some useful primes */ /* 109, 163, 251, 367, 557, 823, 1237, 1861, 2777, 4177, 6247, 9371, 14057 */ @@ -836,7 +837,7 @@ extern double timer(int start); extern void enable_layers(void); extern void set_snap(double); extern void set_grid(double); -extern void create_plot_cmd(int viewer); +extern void create_plot_cmd(void); extern void set_modify(int mod); extern void dbg(int level, char *fmt, ...); extern void here(int i); diff --git a/src/xschem.tcl b/src/xschem.tcl index b29f044d..9ea251a9 100644 --- a/src/xschem.tcl +++ b/src/xschem.tcl @@ -461,9 +461,7 @@ proc set_sim_defaults {} { set_ne sim(spicewave,0,fg) 0 set_ne sim(spicewave,0,st) 0 - set_ne sim(spicewave,1,cmd) {echo load "$n.raw" > .spiceinit - $terminal -e ngspice - rm .spiceinit} + set_ne sim(spicewave,1,cmd) {$terminal -e ngspice} set_ne sim(spicewave,1,name) {Ngpice Viewer} set_ne sim(spicewave,1,fg) 0 set_ne sim(spicewave,1,st) 0 @@ -474,7 +472,7 @@ proc set_sim_defaults {} { set_ne sim(spicewave,2,st) 0 set_ne sim(spicewave,3,cmd) {$env(HOME)/analog_flavor_eval/bin/bspwave --socket localhost $bespice_listen_port "$n.raw" } - set_ne sim(spicewave,3,name) {bespice wave} + set_ne sim(spicewave,3,name) {Bespice wave} set_ne sim(spicewave,3,fg) 0 set_ne sim(spicewave,3,st) 0 # number of configured spice wave viewers, and default one @@ -676,6 +674,19 @@ proc simconf_add {tool} { incr sim($tool,n) } +proc bespice_getdata {sock} { + global bespice_server_getdata + if {[eof $sock] || [catch {gets $sock bespice_server_getdata(line,$sock)}]} { + close $sock + puts "Close $bespice_server_getdata(addr,$sock)" + unset bespice_server_getdata(addr,$sock) + unset bespice_server_getdata(line,$sock) + unset bespice_server_getdata(sock) + } else { + puts "bespice --> $bespice_server_getdata(line,$sock)" + } +} + proc xschem_getdata {sock} { global xschem_server_getdata if {[eof $sock] || [catch {gets $sock xschem_server_getdata(line,$sock)}]} { @@ -692,6 +703,18 @@ proc xschem_getdata {sock} { } } +proc bespice_server {sock addr port} { + global bespice_server_getdata + if { ![info exists bespice_server_getdata(sock)] } { + puts "Accept $sock from $addr port $port" + fconfigure $sock -buffering line + set bespice_server_getdata(addr,$sock) [list $addr $port] + set bespice_server_getdata(sock) [list $sock] + fileevent $sock readable [list bespice_getdata $sock] + } +} + + proc xschem_server {sock addr port} { global xschem_server_getdata puts "Accept $sock from $addr port $port" @@ -4186,8 +4209,8 @@ if { ( $::OS== "Windows" || [string length [lindex [array get env DISPLAY] 1] ] -command "xschem hilight drill" -accelerator {Ctrl+Shift+K} .menubar.hilight.menu add command -label {Highlight selected net/pins} \ -command "xschem hilight" -accelerator K - .menubar.hilight.menu add command -label {Send selected net/pins to GAW} \ - -command "xschem send_to_gaw" -accelerator Alt+G + .menubar.hilight.menu add command -label {Send selected net/pins to Viewer} \ + -command "xschem send_to_viewer" -accelerator Alt+G .menubar.hilight.menu add command -label {Select hilight nets / pins} -command "xschem select_hilight_net" \ -accelerator Alt+K .menubar.hilight.menu add command -label {Un-highlight all net/pins} \ @@ -4232,9 +4255,8 @@ if { ( $::OS== "Windows" || [string length [lindex [array get env DISPLAY] 1] ] } .menubar.simulation.menu add command -label {Edit Netlist} \ -command {edit_netlist [file tail [xschem get schname]]} - .menubar.simulation.menu add command -label {Send highlighted nets to GAW} -command {xschem create_plot_cmd gaw} - .menubar.simulation.menu add command -label {Create Ngspice 'xplot' file} \ - -command {xschem create_plot_cmd ngspice} -accelerator Shift+J + .menubar.simulation.menu add command -label {Send highlighted nets to viewer} \ + -command {xschem create_plot_cmd} -accelerator Shift+J .menubar.simulation.menu add checkbutton -label "Forced stop tcl scripts" -variable tclstop .menubar.simulation.menu add separator .menubar.simulation.menu add checkbutton -label "LVS netlist: Top level is a .subckt" -variable top_subckt @@ -4320,3 +4342,10 @@ if { [info exists xschem_listen_port] && ($xschem_listen_port ne {}) } { } } +if { [info exists bespice_listen_port] && ($bespice_listen_port ne {}) } { + if {[catch {socket -server bespice_server $bespice_listen_port} err]} { + puts "problems listening to TCP port: $bespice_listen_port" + puts $err + } +} + diff --git a/src/xschemrc b/src/xschemrc index 4e6f26ae..d919537f 100644 --- a/src/xschemrc +++ b/src/xschemrc @@ -290,7 +290,7 @@ #### BESPICE WAVE SOCKET CONNECTION ########################################################################### #### set bespice wave listening port; default: not enabled -set bespice_listen_port 2022 +# set bespice_listen_port 2022 ########################################################################### #### UTILE SPICE STIMULI DESCRIPTION LANGUAGE AND TRANSLATOR