From 09a373954f704fe93a9d7b23f6e7b523bd3ca654 Mon Sep 17 00:00:00 2001 From: stefan schippers Date: Fri, 26 May 2023 11:56:52 +0200 Subject: [PATCH] initial implementation of portmap feature: from sub-schematics resolve hierarchic name of schematic nets connected to I/O pins (go to the upper level recursively until resolved) --- src/actions.c | 65 +++++++++++++++++++++++++++++++++++++------------ src/hilight.c | 10 +++++--- src/save.c | 7 ++++-- src/scheduler.c | 21 ++++++++++++++-- src/xinit.c | 4 +++ src/xschem.h | 1 + 6 files changed, 85 insertions(+), 23 deletions(-) diff --git a/src/actions.c b/src/actions.c index c3730622..4245a98c 100644 --- a/src/actions.c +++ b/src/actions.c @@ -530,6 +530,7 @@ void ask_new_file(void) remove_symbols(); load_schematic(1, f, 1, 1); tclvareval("update_recent_file {", f, "}", NULL); + if(xctx->portmap[xctx->currsch].table) str_hash_free(&xctx->portmap[xctx->currsch]); my_strdup(_ALLOC_ID_, &xctx->sch_path[xctx->currsch],"."); xctx->sch_path_hash[xctx->currsch] = 0; xctx->sch_inst_number[xctx->currsch] = 1; @@ -1602,11 +1603,11 @@ void get_sch_from_sym(char *filename, xSymbol *sym, int inst) int descend_schematic(int instnumber) { - const char *str; + char *str = NULL; char filename[PATH_MAX]; int inst_mult, inst_number; int save_ok = 0; - int n = 0; + int i, n = 0; rebuild_selected_array(); if(xctx->lastsel !=1 || xctx->sel_array[0].type!=ELEMENT) { @@ -1655,17 +1656,13 @@ int descend_schematic(int instnumber) dbg(1, "descend_schematic(): selected instname=%s\n", xctx->inst[n].instname); if(xctx->inst[n].instname && xctx->inst[n].instname[0]) { - str=expandlabel(xctx->inst[n].instname, &inst_mult); + my_strdup2(_ALLOC_ID_, &str, expandlabel(xctx->inst[n].instname, &inst_mult)); } else { - str = ""; + my_strdup2(_ALLOC_ID_, &str, ""); inst_mult = 1; } - my_strdup(_ALLOC_ID_, &xctx->sch_path[xctx->currsch+1], xctx->sch_path[xctx->currsch]); - xctx->sch_path_hash[xctx->currsch+1] =0; - my_strdup(_ALLOC_ID_, &xctx->hier_attr[xctx->currsch].prop_ptr, - xctx->inst[n].prop_ptr); - my_strdup(_ALLOC_ID_, &xctx->hier_attr[xctx->currsch].templ, - get_tok_value((xctx->inst[n].ptr+ xctx->sym)->prop_ptr, "template", 0)); + prepare_netlist_structs(0); + inst_number = 1; if(inst_mult > 1) { /* on multiple instances ask where to descend, to correctly evaluate the hierarchy path you descend to */ @@ -1677,8 +1674,7 @@ int descend_schematic(int instnumber) inum = tclresult(); dbg(1, "descend_schematic(): inum=%s\n", inum); if(!inum[0]) { - my_free(_ALLOC_ID_, &xctx->sch_path[xctx->currsch+1]); - xctx->sch_path_hash[xctx->currsch+1] =0; + my_free(_ALLOC_ID_, &str); return 0; } inst_number=atoi(inum); @@ -1689,11 +1685,48 @@ int descend_schematic(int instnumber) /* any invalid number->descend to leftmost inst */ if(inst_number <1 || inst_number > inst_mult) inst_number = 1; } + + my_strdup(_ALLOC_ID_, &xctx->sch_path[xctx->currsch+1], xctx->sch_path[xctx->currsch]); + xctx->sch_path_hash[xctx->currsch+1] =0; + if(xctx->portmap[xctx->currsch + 1].table) str_hash_free(&xctx->portmap[xctx->currsch + 1]); + str_hash_init(&xctx->portmap[xctx->currsch + 1], HASHSIZE); + + for(i = 0; i < xctx->sym[xctx->inst[n].ptr].rects[PINLAYER]; i++) { + const char *pin_name = get_tok_value(xctx->sym[xctx->inst[n].ptr].rect[PINLAYER][i].prop_ptr,"name",0); + char *pin_node = NULL, *net_node = NULL; + int k, mult, net_mult; + char *single_p = NULL, *single_n = NULL; + + if(!pin_name[0]) continue; + if(!xctx->inst[n].node[i]) continue; + + my_strdup2(_ALLOC_ID_, &pin_node, expandlabel(pin_name, &mult)); + my_strdup2(_ALLOC_ID_, &net_node, expandlabel(xctx->inst[n].node[i], &net_mult)); + + for(k = 1; k<=mult; ++k) { + my_strdup2(_ALLOC_ID_, &single_p, find_nth(pin_node, ",", k)); + my_strdup2(_ALLOC_ID_, &single_n, + find_nth(net_node, ",", ((inst_number - 1) * mult + k - 1) % net_mult + 1)); + str_hash_lookup(&xctx->portmap[xctx->currsch + 1], single_p, single_n, XINSERT); + dbg(1, "descend_schematic(): %s: %s ->%s\n", xctx->inst[n].instname, single_p, single_n); + } + if(single_p) my_free(_ALLOC_ID_, &single_p); + if(single_n) my_free(_ALLOC_ID_, &single_n); + my_free(_ALLOC_ID_, &net_node); + my_free(_ALLOC_ID_, &pin_node); + } + + my_strdup(_ALLOC_ID_, &xctx->hier_attr[xctx->currsch].prop_ptr, + xctx->inst[n].prop_ptr); + my_strdup(_ALLOC_ID_, &xctx->hier_attr[xctx->currsch].templ, + get_tok_value((xctx->inst[n].ptr+ xctx->sym)->prop_ptr, "template", 0)); + dbg(1,"descend_schematic(): inst_number=%d\n", inst_number); my_strcat(_ALLOC_ID_, &xctx->sch_path[xctx->currsch+1], find_nth(str, ",", inst_number)); + my_free(_ALLOC_ID_, &str); dbg(1,"descend_schematic(): inst_number=%d\n", inst_number); my_strcat(_ALLOC_ID_, &xctx->sch_path[xctx->currsch+1], "."); - xctx->sch_inst_number[xctx->currsch+1] = inst_number; + xctx->sch_inst_number[xctx->currsch] = inst_number; dbg(1, "descend_schematic(): current path: %s\n", xctx->sch_path[xctx->currsch+1]); dbg(1, "descend_schematic(): inst_number=%d\n", inst_number); @@ -1703,7 +1736,6 @@ int descend_schematic(int instnumber) xctx->zoom_array[xctx->currsch].zoom=xctx->zoom; xctx->currsch++; hilight_child_pins(); - unselect_all(1); get_sch_from_sym(filename, xctx->inst[n].ptr+ xctx->sym, n); dbg(1, "descend_schematic(): filename=%s\n", filename); @@ -1756,6 +1788,9 @@ void go_back(int confirm) /* 20171006 add confirm */ from_embedded_sym=1; } my_strncpy(xctx->sch[xctx->currsch] , "", S(xctx->sch[xctx->currsch])); + if(xctx->portmap[xctx->currsch].table) str_hash_free(&xctx->portmap[xctx->currsch]); + + xctx->sch_path_hash[xctx->currsch] = 0; xctx->currsch--; save_modified = xctx->modified; /* we propagate modified flag (cleared by load_schematic */ /* by default) to parent schematic if going back from embedded symbol */ @@ -1765,7 +1800,7 @@ void go_back(int confirm) /* 20171006 add confirm */ /* if we are returning from a symbol created from a generator don't set modified flag on parent * as these symbols can not be edited / saved as embedded * xctx->sch_inst_number[xctx->currsch + 1] == -1 --> we came from an inst with no embed flag set */ - if(from_embedded_sym && xctx->sch_inst_number[xctx->currsch + 1] != -1) + if(from_embedded_sym && xctx->sch_inst_number[xctx->currsch] != -1) xctx->modified=save_modified; /* to force ask save embedded sym in parent schematic */ if(xctx->hilight_nets) { diff --git a/src/hilight.c b/src/hilight.c index d6a5f9d2..7217e293 100644 --- a/src/hilight.c +++ b/src/hilight.c @@ -493,7 +493,7 @@ void hilight_parent_pins(void) if(!xctx->hilight_nets) return; prepare_netlist_structs(0); i=xctx->previous_instance[xctx->currsch]; - inst_number = xctx->sch_inst_number[xctx->currsch+1]; + inst_number = xctx->sch_inst_number[xctx->currsch]; /* may be set to -1 by descend_symbol to notify we are * descending into a smbol from an instance with no embed flag set @@ -529,7 +529,7 @@ void hilight_parent_pins(void) bus_hilight_hash_lookup(find_nth(net_node, ",", ((inst_number - 1) * mult + k - 1) % net_mult + 1), 0, XDELETE); } - } + } } my_free(_ALLOC_ID_, &pin_node); my_free(_ALLOC_ID_, &net_node); @@ -545,10 +545,12 @@ void hilight_child_pins(void) int mult, net_mult, i, inst_number; i = xctx->previous_instance[xctx->currsch-1]; - if(!xctx->hilight_nets) return; + if(!xctx->hilight_nets) { + return; + } prepare_netlist_structs(0); rects = (xctx->inst[i].ptr+ xctx->sym)->rects[PINLAYER]; - inst_number = xctx->sch_inst_number[xctx->currsch]; + inst_number = xctx->sch_inst_number[xctx->currsch-1]; /* may be set to -1 by descend_symbol to notify we are * descending into a smbol from an instance with no embed flag set diff --git a/src/save.c b/src/save.c index 6ae9ff5b..e1b68d38 100644 --- a/src/save.c +++ b/src/save.c @@ -4076,6 +4076,9 @@ void descend_symbol(void) my_strdup(_ALLOC_ID_, &xctx->sch_path[xctx->currsch+1], xctx->sch_path[xctx->currsch]); my_strcat(_ALLOC_ID_, &xctx->sch_path[xctx->currsch+1], str); my_strcat(_ALLOC_ID_, &xctx->sch_path[xctx->currsch+1], "."); + if(xctx->portmap[xctx->currsch + 1].table) str_hash_free(&xctx->portmap[xctx->currsch + 1]); + str_hash_init(&xctx->portmap[xctx->currsch + 1], HASHSIZE); + xctx->sch_path_hash[xctx->currsch+1] = 0; my_free(_ALLOC_ID_, &str); @@ -4089,9 +4092,9 @@ void descend_symbol(void) /* use -1 to keep track we are descending into symbol from instance with no embed attr * we use this info to avoid asking to save parent schematic when returning from a symbol * created from a generator */ - xctx->sch_inst_number[xctx->currsch+1] = -1; + xctx->sch_inst_number[xctx->currsch] = -1; else - xctx->sch_inst_number[xctx->currsch+1] = 1; /* inst number we descend into. For symbol always 1 */ + xctx->sch_inst_number[xctx->currsch] = 1; /* inst number we descend into. For symbol always 1 */ xctx->previous_instance[xctx->currsch]=n; /* instance we are descending from */ /* store previous zoom area */ diff --git a/src/scheduler.c b/src/scheduler.c index bca49275..87d95a31 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -1950,6 +1950,8 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg load_schematic(load_symbols, f, undo_reset, !force); tclvareval("update_recent_file {", f, "}", NULL); my_strdup(_ALLOC_ID_, &xctx->sch_path[xctx->currsch], "."); + if(xctx->portmap[xctx->currsch].table) str_hash_free(&xctx->portmap[xctx->currsch]); + str_hash_init(&xctx->portmap[xctx->currsch], HASHSIZE); xctx->sch_path_hash[xctx->currsch] = 0; xctx->sch_inst_number[xctx->currsch] = 1; if(nofullzoom) draw(); @@ -2732,11 +2734,13 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg else if(!strcmp(argv[1], "rebuild_connectivity")) { int err = 0; + int n = 1; + if(argc > 2) n = atoi(argv[2]); xctx->prep_hash_inst=0; xctx->prep_hash_wires=0; xctx->prep_net_structs=0; xctx->prep_hi_structs=0; - err |= prepare_netlist_structs(1); + err |= prepare_netlist_structs(n); Tcl_SetResult(interp, my_itoa(err), TCL_VOLATILE); } @@ -3689,7 +3693,20 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg * testmode */ else if(!strcmp(argv[1], "test")) { + Str_hashentry *entry; + int level; Tcl_ResetResult(interp); + if(argc > 2) { + const char *node = argv[2]; + level = xctx->currsch; + while(level > 0) { + entry = str_hash_lookup(&xctx->portmap[level], node, NULL, XLOOKUP); + if(entry) node = entry->value; + else break; + level--; + } + Tcl_AppendResult(interp, node, NULL); + } } /* toggle_colorscheme @@ -4144,7 +4161,7 @@ int tclvareval(const char *script, ...) size = my_strcat(_ALLOC_ID_, &str, p); dbg(2, "tclvareval(): p=%s, str=%s, size=%d\n", p, str, size); } - dbg(1, "tclvareval(): script=%s, str=%s, size=%d\n", script, str ? str : "", size); + dbg(2, "tclvareval(): script=%s, str=%s, size=%d\n", script, str ? str : "", size); return_code = Tcl_EvalEx(interp, str, (int)size, TCL_EVAL_GLOBAL); va_end(args); if(return_code != TCL_OK) { diff --git a/src/xinit.c b/src/xinit.c index bd6cc0c3..3ebda545 100644 --- a/src/xinit.c +++ b/src/xinit.c @@ -349,6 +349,7 @@ static void free_xschem_data() my_free(_ALLOC_ID_, &xctx->maxl); my_free(_ALLOC_ID_, &xctx->sel_array); for(i=0;iportmap[i].table) str_hash_free(&xctx->portmap[i]); if(xctx->sch_path[i]) my_free(_ALLOC_ID_, &xctx->sch_path[i]); if(xctx->hier_attr[i].templ) my_free(_ALLOC_ID_, &xctx->hier_attr[i].templ); if(xctx->hier_attr[i].prop_ptr) my_free(_ALLOC_ID_, &xctx->hier_attr[i].prop_ptr); @@ -541,8 +542,11 @@ static void alloc_xschem_data(const char *top_path, const char *win_path) xctx->hier_attr[i].templ = NULL; xctx->hier_attr[i].symname = NULL; xctx->hier_attr[i].fd = NULL; + xctx->portmap[i].table = NULL; + xctx->portmap[i].size = 0; } my_strdup(_ALLOC_ID_, &xctx->sch_path[0],"."); + xctx->sch_inst_number[0] = 1; xctx->maxt=CADMAXTEXT; xctx->maxw=CADMAXWIRES; diff --git a/src/xschem.h b/src/xschem.h index 53c69741..161b21ec 100644 --- a/src/xschem.h +++ b/src/xschem.h @@ -837,6 +837,7 @@ typedef struct { char current_name[PATH_MAX]; char file_version[100]; char *sch_path[CADMAXHIER]; + Str_hashtable portmap[CADMAXHIER]; int sch_path_hash[CADMAXHIER]; /* cached hash of hierarchic schematic path for speed */ int sch_inst_number[CADMAXHIER]; /* inst number descended into in case of vector instances X1[5:0] */ int previous_instance[CADMAXHIER]; /* to remember the instance we came from when going up the hier. */