From f847b61333de18891f1fce03b5536219962cd939 Mon Sep 17 00:00:00 2001 From: stefan schippers Date: Tue, 25 Jul 2023 23:33:46 +0200 Subject: [PATCH] Gerard upates for Xschem <--> BeSpice TCP communication --- src/hilight.c | 173 +++++++++++++++++-------------------------------- src/xschem.tcl | 36 ++++++++-- 2 files changed, 88 insertions(+), 121 deletions(-) diff --git a/src/hilight.c b/src/hilight.c index 502c4afb..de4f7f86 100644 --- a/src/hilight.c +++ b/src/hilight.c @@ -264,6 +264,30 @@ void incr_hilight_color(void) xctx->hilight_color = (xctx->hilight_color + 1) % (xctx->n_active_layers * cadlayers); } +static void set_rawfile_for_bespice() +{ + char raw_file[PATH_MAX]; + char netlist_file[PATH_MAX]; + tcleval("file tail [file rootname [xschem get schname 0]].raw"); + my_strncpy(raw_file, tclresult(), S(raw_file)); + tcleval("file tail [file rootname [xschem get schname 0]].spice"); + my_strncpy(netlist_file, tclresult(), S(netlist_file)); + + /* (1) make sure that the raw file has been opened */ + tclvareval("puts $bespice_server_getdata(sock) ", + "{open_file \"", raw_file, "\"}", + NULL); + /* (2) create curves for electrically equivalent nodes (pins of spice subcircuits) */ + tclvareval("puts $bespice_server_getdata(sock) ", + "{create_equivalent_nets \"", raw_file, "\" \"", netlist_file, "\"}", + NULL); + /* (3) make sure that the raw file is used for commands plotting voltages and currents + this is important if more than one file has been opened. */ + tclvareval("puts $bespice_server_getdata(sock) ", + "{use_file_for_link_to_schematic \"", raw_file, "\"}", + NULL); +} + /* print all highlight signals which are not ports (in/out/inout). */ void create_plot_cmd(void) { @@ -310,6 +334,7 @@ void create_plot_cmd(void) } if(viewer == GAW) tcleval("setup_tcp_gaw"); if(tclresult()[0] == '0') return; + if(viewer == BESPICE) set_rawfile_for_bespice(); idx = 1; first = 1; for(i=0;ixcolor_array[c].red>>8, xctx->xcolor_array[c].green>>8, xctx->xcolor_array[c].blue>>8); my_strdup(_ALLOC_ID_, &t, tok); my_strdup2(_ALLOC_ID_, &p, (entry->path)+1); - if(simtype == 0 ) { /* spice */ - tclvareval( + /* bespice command syntax : + add_voltage_on_spice_node_to_plot
[] + plot name is "*" => automatic + section name is empty => automatic or user defined + */ + tclvareval( "puts $bespice_server_getdata(sock) ", - "{set_curve_style \"", - rawfile, - "\" \"v(", strtolower(p), strtolower(t), - ")\" \"solid_line\" \"no symbol\" 1 ", - color_str, "}", + "{add_voltage_on_spice_node_to_plot * \"\" \"", + p, t, "\" 0 ", color_str, "}", NULL); - tclvareval( - "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; - } - tclvareval( - "puts $bespice_server_getdata(sock) ", - "{set_curve_style \"", - rawfile, - "\" \"", strtoupper(p), strtoupper(t), - "\" \"solid_line\" \"no symbol\" 1 ", - color_str, "}", - NULL); - tclvareval( - "puts $bespice_server_getdata(sock) ", - "{add_curve_to_plot \"", rawfile, "\" \"", strtoupper(p), strtoupper(t), - "\" \"\"}", - NULL); - } my_free(_ALLOC_ID_, &p); my_free(_ALLOC_ID_, &t); } @@ -950,10 +951,9 @@ static void send_net_to_bespice(int simtype, const char *node) 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)); + set_rawfile_for_bespice(); + if(!node || !node[0]) return; tok = node; node_entry = bus_node_hash_lookup(tok, "", XLOOKUP, 0, "", "", "", ""); @@ -961,46 +961,22 @@ static void send_net_to_bespice(int simtype, const char *node) 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", xctx->xcolor_array[c].red>>8, xctx->xcolor_array[c].green>>8, + sprintf(color_str, "#%02x%02x%02x", xctx->xcolor_array[c].red>>8, xctx->xcolor_array[c].green>>8, xctx->xcolor_array[c].blue>>8); expanded_tok = expandlabel(tok, &tok_mult); my_strdup2(_ALLOC_ID_, &p, xctx->sch_path[xctx->currsch]+1); for(k=1; k<=tok_mult; ++k) { my_strdup(_ALLOC_ID_, &t, find_nth(expanded_tok, ",", k)); - if(simtype == 0 ) { /* spice */ - tclvareval( - "puts $bespice_server_getdata(sock) ", - "{set_curve_style \"", - rawfile, - "\" \"v(", strtolower(p), strtolower(t), - ")\" \"solid_line\" \"no symbol\" 1 ", - color_str, "}", - NULL); - tclvareval( - "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; - } - tclvareval( - "puts $bespice_server_getdata(sock) ", - "{set_curve_style \"", - rawfile, - "\" \"", strtoupper(p), strtoupper(t), - "\" \"solid_line\" \"no symbol\" 1 ", - color_str, "}", - NULL); - tclvareval( - "puts $bespice_server_getdata(sock) ", - "{add_curve_to_plot \"", rawfile, "\" \"", strtoupper(p), strtoupper(t), - "\" \"\"}", - NULL); - } + /* bespice command syntax : + add_voltage_on_spice_node_to_plot
[] + plot name is "*" => automatic + section name is empty => automatic or user defined + */ + tclvareval( + "puts $bespice_server_getdata(sock) ", + "{add_voltage_on_spice_node_to_plot * \"\" \"", + p, t, "\" 0 ", color_str, "}", + NULL); } my_free(_ALLOC_ID_, &p); my_free(_ALLOC_ID_, &t); @@ -1101,60 +1077,29 @@ static void send_current_to_bespice(int simtype, const char *node) 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)); + set_rawfile_for_bespice(); if(!node || !node[0]) return; tok = node; /* c = PINLAYER; */ c = get_color(xctx->hilight_color); - sprintf(color_str, "%d %d %d", xctx->xcolor_array[c].red>>8, xctx->xcolor_array[c].green>>8, + sprintf(color_str, "#%02x%02x%02x", xctx->xcolor_array[c].red>>8, xctx->xcolor_array[c].green>>8, xctx->xcolor_array[c].blue>>8); expanded_tok = expandlabel(tok, &tok_mult); my_strdup2(_ALLOC_ID_, &p, xctx->sch_path[xctx->currsch]+1); for(k=1; k<=tok_mult; ++k) { my_strdup(_ALLOC_ID_, &t, find_nth(expanded_tok, ",", k)); - if(!simtype) { /* spice */ - tclvareval( - "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); - tclvareval( - "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; - } - - tclvareval( - "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); - tclvareval( - "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); - } + /* bespice command syntax : + add_current_through_spice_device_to_plot
[] + plot name is "*" => automatic + section name is empty => automatic or user defined + */ + tclvareval( + "puts $bespice_server_getdata(sock) ", + "{add_current_through_spice_device_to_plot * \"\" \"", + p, t, "\" 0 ", color_str, "}", + NULL); } my_free(_ALLOC_ID_, &p); my_free(_ALLOC_ID_, &t); diff --git a/src/xschem.tcl b/src/xschem.tcl index 7e14aecd..80991cb7 100644 --- a/src/xschem.tcl +++ b/src/xschem.tcl @@ -1027,6 +1027,8 @@ proc set_sim_defaults {{reset {}}} { set_ne sim(spicewave,2,fg) 0 set_ne sim(spicewave,2,st) 0 + # A server communicating with bespice wave was set up in the function setup_tcp_bespice(). + # This server is listening on port $bespice_listen_port. set_ne sim(spicewave,3,cmd) {$env(HOME)/analog_flavor_eval/bin/bspwave --socket localhost $bespice_listen_port "$n.raw" } set sim(spicewave,3,name) {Bespice wave} set_ne sim(spicewave,3,fg) 0 @@ -1287,6 +1289,8 @@ proc xschem_getdata {sock} { unset xschem_server_getdata(res,$sock) } +# this function is called as soon as bespice wave connects to the communication server listening on $bespice_listen_port +# it makes sure the communication over the socket connection is possible proc bespice_server {sock addr port} { global bespice_server_getdata if { ![info exists bespice_server_getdata(sock)] } { @@ -1295,6 +1299,8 @@ proc bespice_server {sock addr port} { set bespice_server_getdata(addr,$sock) [list $addr $port] set bespice_server_getdata(sock) [list $sock] fileevent $sock readable [list bespice_getdata $sock] + # this informs bespice wave that it receives it's instructions from xschem. Some features will be adjusted for that. + puts $bespice_server_getdata(sock) "set_customer_specialization xschem" } } @@ -6492,14 +6498,30 @@ proc setup_tcp_xschem { {port_number {}} } { proc setup_tcp_bespice {} { global bespice_listen_port bespice_server_getdata if { [info exists bespice_listen_port] && ($bespice_listen_port ne {}) } { - if {[catch {socket -server bespice_server $bespice_listen_port} err]} { - puts "setup_tcp_bespice: problems listening to TCP port: $bespice_listen_port" - puts $err - return 0 - } else { - set bespice_server_getdata(server) $err + # We will attempt to open port $bespice_listen_port ... $bespice_listen_port + 1000 this should succeed ... + # We need to make this attempt as several instances of xschem / bespice might be running. + # Each of these instances needs it's own server listening on a dedicated port. + # The variable $bespice_listen_port is passed to bespice wave when the application is started in the function "set_sim_defaults()". + set port $bespice_listen_port + set last_port [expr $port + 1000] + while { $port < $last_port } { + if {[catch {socket -server bespice_server $port} err]} { + # failed => increment port + incr port + } else { + # succeded => set $bespice_listen_port and socket connection for communication + puts "setup_tcp_bespice: success : listening to TCP port: $port" + set bespice_server_getdata(server) $err + set bespice_listen_port $port + return 1 + } } - } + puts "setup_tcp_bespice: problems listening to TCP port: $bespice_listen_port ... $last_port" + puts $err + return 0 + } + # bespice_listen_port not defined, nothing to do + puts "setup_tcp_bespice: the functionallity was not set up as the variable \$bespice_listen_port hasn't been defined in your xschemrc file." return 1 }