`Alt-e` does a true descend sub-schematic and opens it in another window

This commit is contained in:
stefan schippers 2023-11-20 17:53:28 +01:00
parent d4cde62870
commit 8d155af82f
8 changed files with 158 additions and 43 deletions

View File

@ -510,16 +510,6 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
@ -596,6 +586,9 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
if '3' argument is given combine '1' and '2' </pre>
<li><kbd> copy</kbd></li><pre>
Copy selection to clipboard </pre>
<li><kbd> copy_hierarchy to from</kbd></li><pre>
Copy hierarchy info from tab/window "from" to tab/window "to"
Example: xschem copy_hierarchy .drw .x1.drw </pre>
<li><kbd> copy_objects [deltax deltay [rot flip]]</kbd></li><pre>
if deltax and deltay (and optionally rot and flip) are given copy selection
to specified offset, otherwise start a GUI copy operation </pre>
@ -699,6 +692,7 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
<li><kbd> header_text </kbd> header metadata (license info etc) present in schematic </li>
<li><kbd> infowindow_text </kbd> ERC messages </li>
<li><kbd> instances </kbd> number of instances in schematic </li>
<li><kbd> last_created_window </kbd> return win_path of last created tab or window </li>
<li><kbd> lastsel </kbd> number of selected objects </li>
<li><kbd> line_width </kbd> get line width </li>
<li><kbd> lines </kbd> (xschem get lines n) number of lines on layer 'n' </li>
@ -783,6 +777,8 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
('inst' can be an instance name or instance number)
('pin' can be a pin name or pin number)</pre>
<li><kbd> get_sch_from_sym inst</kbd></li><pre>
get schematic associated with instance 'inst' </pre>
<li><kbd> get_tok str tok [with_quotes]</kbd></li><pre>
get value of token 'tok' in string 'str'
'with_quotes' (default:0) is an integer passed to get_tok_value() </pre>
@ -1052,7 +1048,7 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
what = read | clear | info | switch | switch_back
Load /clear / switch additional raw files </pre>
<li><kbd> raw_clear </kbd></li><pre>
Delete loaded simulation raw file </pre>
Unload all simulation raw files </pre>
<li><kbd> raw_query loaded|value|index|values|datasets|vars|list </kbd></li><pre>
xschem raw_query list: get list of saved simulation variables
xschem raw_query vars: get number of simulation variables
@ -1140,13 +1136,14 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
List a 2-item list of all pins and directions of current schematic
Example: xschem sch_pinlist
--&gt; {PLUS} {in} {OUT} {out} {MINUS} {in} {VCC} {inout} {VSS} {inout}</pre>
<li><kbd> schematic_in_new_window [new_process] [nodraw]</kbd></li><pre>
<li><kbd> schematic_in_new_window [new_process] [nodraw] [force]</kbd></li><pre>
When a symbol is selected edit corresponding schematic
in a new tab/window if not already open.
If nothing selected open another window of the second
schematic (issues a warning).
if 'new_process' is given start a new xschem process
if 'nodraw' is given do not draw loaded schematic </pre>
if 'nodraw' is given do not draw loaded schematic
returns '1' if a new schematic was opened, 0 otherwise </pre>
<li><kbd> search regex|exact select tok val [match_case]</kbd></li><pre>
Search instances / wires / rects / texts with attribute string containing 'tok'
and value 'val'
@ -1422,6 +1419,18 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"

View File

@ -1573,8 +1573,11 @@ void symbol_in_new_window(int new_process)
}
}
void copy_hierarchy_data(Xschem_ctx *from, Xschem_ctx *to)
int copy_hierarchy_data(const char *from_win_path, const char *to_win_path)
{
int n;
Xschem_ctx **save_xctx;
Xschem_ctx *from, *to;
char **sch;
char **sch_path;
int *sch_path_hash;
@ -1585,7 +1588,18 @@ void copy_hierarchy_data(Xschem_ctx *from, Xschem_ctx *to)
int i, j;
Str_hashentry **fromnext;
Str_hashentry **tonext;
if(!get_window_count()) { return 0; }
save_xctx = get_save_xctx();
n = get_tab_or_window_number(from_win_path);
if(n >= 0) {
from = save_xctx[n];
} else return 0;
n = get_tab_or_window_number(to_win_path);
if(n >= 0) {
to = save_xctx[n];
} else return 0;
sch = from->sch;
sch_path = from->sch_path;
sch_path_hash = from->sch_path_hash;
@ -1629,21 +1643,29 @@ void copy_hierarchy_data(Xschem_ctx *from, Xschem_ctx *to)
}
}
}
return 1;
}
/* 20111007 duplicate current schematic if no inst selected */
void schematic_in_new_window(int new_process, int dr)
/* 20111007 duplicate current schematic if no inst selected */
/* if force set to 1 force opening another new schematic even if already open */
int schematic_in_new_window(int new_process, int dr, int force)
{
char filename[PATH_MAX];
char win_path[WINDOW_PATH_SIZE];
rebuild_selected_array();
if(xctx->lastsel !=1 || xctx->sel_array[0].type!=ELEMENT) {
if(xctx->lastsel == 0) {
if(new_process) new_xschem_process(xctx->sch[xctx->currsch], 0);
else new_schematic("create", "noalert", xctx->sch[xctx->currsch], dr);
else new_schematic("create", force ? "noalert" : "", xctx->sch[xctx->currsch], dr);
return 1;
}
else {
else if(xctx->lastsel > 1) {
return 0;
}
else { /* xctx->lastsel == 1 */
if(xctx->inst[xctx->sel_array[0].n].ptr < 0 ) return 0;
if(!(xctx->inst[xctx->sel_array[0].n].ptr+ xctx->sym)->type) return 0;
if(xctx->sel_array[0].type != ELEMENT) return 0;
if( /* do not descend if not subcircuit */
(xctx->inst[xctx->sel_array[0].n].ptr+ xctx->sym)->type &&
strcmp(
(xctx->inst[xctx->sel_array[0].n].ptr+ xctx->sym)->type,
"subcircuit"
@ -1652,13 +1674,14 @@ void schematic_in_new_window(int new_process, int dr)
(xctx->inst[xctx->sel_array[0].n].ptr+ xctx->sym)->type,
"primitive"
)
) return;
) return 0;
get_sch_from_sym(filename, xctx->inst[xctx->sel_array[0].n].ptr+ xctx->sym, xctx->sel_array[0].n);
if(!check_loaded(filename, win_path)) {
if(force || !check_loaded(filename, win_path)) {
if(new_process) new_xschem_process(filename, 0);
else new_schematic("create", "noalert", filename, dr);
}
}
return 1;
}
void launcher(void)

View File

@ -1838,7 +1838,8 @@ int rstate; /* (reduced state, without ShiftMask) */
{
int save = xctx->semaphore;
xctx->semaphore--; /* so semaphore for current context wll be saved correctly */
schematic_in_new_window(0, 1);
/* schematic_in_new_window(0, 1, 0); */
tcleval("open_sub_schematic");
xctx->semaphore = save;
break;
}
@ -1847,7 +1848,7 @@ int rstate; /* (reduced state, without ShiftMask) */
{
int save = xctx->semaphore;
xctx->semaphore--; /* so semaphore for current context wll be saved correctly */
schematic_in_new_window(1, 1);
schematic_in_new_window(1, 1, 0);
xctx->semaphore = save;
break;
}

View File

@ -547,6 +547,20 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
Tcl_ResetResult(interp);
}
/* copy_hierarchy to from
* Copy hierarchy info from tab/window "from" to tab/window "to"
* Example: xschem copy_hierarchy .drw .x1.drw */
else if(!strcmp(argv[1], "copy_hierarchy"))
{
int ret = 0;
if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
if(argc > 3) {
ret = copy_hierarchy_data(argv[2], argv[3]);
}
Tcl_SetResult(interp, my_itoa(ret), TCL_VOLATILE);
}
/* copy_objects [deltax deltay [rot flip]]
* if deltax and deltay (and optionally rot and flip) are given copy selection
* to specified offset, otherwise start a GUI copy operation */
@ -1088,7 +1102,10 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
}
break;
case 'l':
if(!strcmp(argv[2], "lastsel")) { /* number of selected objects */
if(!strcmp(argv[2], "last_created_window")) { /* return win_path of last created tab or window */
Tcl_SetResult(interp, get_last_created_window(), TCL_VOLATILE);
}
else if(!strcmp(argv[2], "lastsel")) { /* number of selected objects */
if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
rebuild_selected_array();
Tcl_SetResult(interp, my_itoa(xctx->lastsel),TCL_VOLATILE);
@ -1561,6 +1578,27 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
}
}
/* get_sch_from_sym inst
* get schematic associated with instance 'inst' */
else if(!strcmp(argv[1], "get_sch_from_sym") )
{
int inst = -1;
char filename[PATH_MAX];
my_strncpy(filename, "", S(filename));
if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
if(argc > 2) {
if((inst = get_instance(argv[2])) < 0 ) {
Tcl_SetResult(interp, "xschem get_sch_from_sym: instance not found", TCL_STATIC);
return TCL_ERROR;
} else {
if( xctx->inst[inst].ptr >= 0 ) {
get_sch_from_sym(filename, xctx->inst[inst].ptr+ xctx->sym, inst);
}
}
}
Tcl_SetResult(interp, filename, TCL_VOLATILE);
}
/* get_tok str tok [with_quotes]
* get value of token 'tok' in string 'str'
* 'with_quotes' (default:0) is an integer passed to get_tok_value() */
@ -3197,12 +3235,12 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
}
/* raw_clear
* Delete loaded simulation raw file */
* Unload all simulation raw files */
else if(!strcmp(argv[1], "raw_clear"))
{
if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
extra_rawfile(3, NULL, NULL);
free_rawfile(&xctx->raw, 1);
extra_rawfile(3, NULL, NULL); /* unload additional raw files */
free_rawfile(&xctx->raw, 1); /* unload base (current) raw file */
Tcl_ResetResult(interp);
}
@ -3762,25 +3800,29 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
}
}
/* schematic_in_new_window [new_process] [nodraw]
/* schematic_in_new_window [new_process] [nodraw] [force]
* When a symbol is selected edit corresponding schematic
* in a new tab/window if not already open.
* If nothing selected open another window of the second
* schematic (issues a warning).
* if 'new_process' is given start a new xschem process
* if 'nodraw' is given do not draw loaded schematic */
* if 'nodraw' is given do not draw loaded schematic
* returns '1' if a new schematic was opened, 0 otherwise */
else if(!strcmp(argv[1], "schematic_in_new_window"))
{
int res = 0;
int new_process = 0;
int nodraw = 0;
int force = 0;
int i;
if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
for(i = 2; i < argc; i++) {
if(!strcmp(argv[i], "new_process")) new_process = 1;
if(!strcmp(argv[i], "nodraw")) nodraw = 1;
if(!strcmp(argv[i], "force")) force = 1;
}
schematic_in_new_window(new_process, !nodraw);
Tcl_ResetResult(interp);
res = schematic_in_new_window(new_process, !nodraw, force);
Tcl_SetResult(interp, my_itoa(res), TCL_VOLATILE);
}
/* search regex|exact select tok val [match_case]
@ -4764,8 +4806,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
del_object_table();
}
else if(argc > 2 && atoi(argv[2]) == 2) {
Xschem_ctx **save_xctx = get_save_xctx();
copy_hierarchy_data(save_xctx[0], save_xctx[1]);
copy_hierarchy_data(".drw", ".x1.drw");
}
else if(argc > 2 && atoi(argv[2]) == 3) {
Xschem_ctx **save_xctx = get_save_xctx();

View File

@ -42,6 +42,7 @@ static Xschem_ctx *save_xctx[MAX_NEW_WINDOWS]; /* save pointer to current schema
static char window_path[MAX_NEW_WINDOWS][WINDOW_PATH_SIZE];
/* ==0 if no additional windows/tabs, ==1 if one additional window/tab, ... */
static int window_count = 0;
static int last_created_window = -1;
/* ----------------------------------------------------------------------- */
/* EWMH message handling routines 20071027... borrowed from wmctrl code */
@ -94,6 +95,15 @@ char *get_window_path(int i)
return window_path[i];
}
char *get_last_created_window(void)
{
if(last_created_window >= 0) {
return window_path[last_created_window];
} else {
return "";
}
}
int get_window_count(void)
{
return window_count;
@ -1204,7 +1214,7 @@ void preview_window(const char *what, const char *win_path, const char *fname)
}
static int get_tab_or_window_number(const char *win_path)
int get_tab_or_window_number(const char *win_path)
{
int i, n = -1;
Xschem_ctx *ctx, **save_xctx = get_save_xctx();
@ -1522,7 +1532,7 @@ static void create_new_window(int *window_count, const char *noconfirm, const ch
n = -1;
for(i = 1; i < MAX_NEW_WINDOWS; ++i) { /* search 1st free slot */
if(save_xctx[i] == NULL) {
n = i;
last_created_window = n = i;
break;
}
}
@ -1627,6 +1637,7 @@ static void create_new_tab(int *window_count, const char *noconfirm, const char
dbg(0, "new_schematic(\"newtab\"...): no more free slots\n");
return;
}
last_created_window = i;
/* tcl code to create the tab button */
my_snprintf(nn, S(nn), "%d", i);
if(has_x) {
@ -1911,7 +1922,6 @@ static void destroy_all_tabs(int *window_count, int force)
int new_schematic(const char *what, const char *win_path, const char *fname, int dr)
{
int tabbed_interface;
tabbed_interface = tclgetboolvar("tabbed_interface");
dbg(1, "new_schematic(): current_win_path=%s, what=%s, win_path=%s\n", xctx->current_win_path, what, win_path);
if(!strcmp(what, "ntabs")) {

View File

@ -1260,8 +1260,8 @@ extern int check_lib(int what, const char *s);
extern int floaters_from_selected_inst();
extern void select_all(void);
extern void change_linewidth(double w);
extern void copy_hierarchy_data(Xschem_ctx *from, Xschem_ctx *to);
extern void schematic_in_new_window(int new_process, int dr);
extern int copy_hierarchy_data(const char *from_win_path, const char *to_win_path);
extern int schematic_in_new_window(int new_process, int dr, int force);
extern void symbol_in_new_window(int new_process);
extern void new_xschem_process(const char *cell, int symbol);
extern void ask_new_file(void);
@ -1456,9 +1456,11 @@ extern void mem_delete_undo(void);
extern void mem_clear_undo(void);
extern void load_schematic(int load_symbol, const char *fname, int reset_undo, int alert);
/* check if filename already in an open window/tab */
extern int get_tab_or_window_number(const char *win_path);
extern void swap_tabs(void);
extern void swap_windows(int dr);
extern int check_loaded(const char *f, char *win_path);
extern char *get_last_created_window(void);
extern char *get_window_path(int i);
extern int get_window_count(void);
extern Xschem_ctx **get_save_xctx(void);

View File

@ -2960,6 +2960,34 @@ proc save_file_dialog { msg ext global_initdir {initialf {}} {overwrt 1} } {
return $r
}
# opens indicated instance (or selected one) into a separate tab/window
# keeping the hierarchy path, as it was descended into (as with 'e' key).
proc open_sub_schematic {{inst {}} {inst_number 0}} {
set one_sel [expr {[xschem get lastsel] == 1}]
if { $inst eq {} && $one_sel} {
set inst [lindex [xschem selected_set] 0]
xschem unselect_all
} else {
set instlist {}
# get list of instances (instance names only)
foreach {i s t} [xschem instance_list] {lappend instlist $i}
# if provided $inst is not in the list return 0
if {[lsearch -exact $instlist $inst] == -1} {return 0}
}
# open a new top level in another window / tab
set schname [xschem get_sch_from_sym $inst]
set res [xschem schematic_in_new_window force]
# if successfull descend into indicated sub-schematic
if {$res} {
xschem new_schematic switch [xschem get last_created_window]
xschem select instance $inst fast
xschem descend
return 1
}
return 0
}
proc is_xschem_file {f} {
if { ![file exists $f] } { return 0
} elseif { [file isdirectory $f] } { return 0 }
@ -6854,7 +6882,8 @@ proc build_widgets { {topwin {} } } {
toolbar_add FileOpen "xschem load" "Open File" $topwin
$topwin.menubar.file.menu add command -label "Open schematic in new window/tab" \
-command "xschem schematic_in_new_window" -accelerator Alt+E
-command "open_sub_schematic" -accelerator Alt+E
# -command "xschem schematic_in_new_window" -accelerator Alt+E
$topwin.menubar.file.menu add command -label "Open symbol in new window/tab" \
-command "xschem symbol_in_new_window" -accelerator Alt+I

View File

@ -322,7 +322,7 @@ C {spice_probe.sym} 670 -1120 0 0 {name=p43 analysis=tran }
C {spice_probe.sym} 950 -1200 0 0 {name=p44 analysis=tran }
C {launcher.sym} 1000 -270 0 0 {name=h1
descr="Backannotate"
tclcommand="xschem annotate_op $netlist_dir/poweramp_op.raw"}
tclcommand="xschem annotate_op $netlist_dir/poweramp.raw"}
C {spice_probe.sym} 350 -1210 0 0 {name=p45 analysis=tran }
C {spice_probe.sym} 350 -1050 0 0 {name=p46 analysis=tran }
C {launcher.sym} 1145 -1165 0 0 {name=h5
@ -354,11 +354,11 @@ vvss vss 0 dc 0
.control
save all
op
write poweramp_op.raw
write poweramp.raw
set appendwrite
tran 2e-7 0.025 uic
* .FOUR 20k v(outm,outp)
* .probe i(*)
plot outp outm
save p(r*) p(v*)
write poweramp.raw
quit 0