Added various procedures to select flat / hierarchical instances and re-route a terminal to a different net. reroute_inst -> change a pin connection, reroute_net -> change net updating all connected components. "xschem instances_to_net", "xschem instance_nodemap", "xschem instance_pin_coord" new query commands added. "xschem get expandlabel node" renamed to "xschem expandlabel node".

This commit is contained in:
Stefan Frederik 2020-11-26 03:46:55 +01:00
parent 01077ea162
commit 7a7868318b
5 changed files with 284 additions and 65 deletions

View File

@ -61,9 +61,11 @@ void display_hilights(char **str)
for(i=0;i<HASHSIZE;i++) {
entry = hilight_table[i];
while(entry) {
if(!first) my_strcat(93, str, ",");
my_strcat(562, str, entry->path+1);
if(!first) my_strcat(93, str, " ");
my_strcat(943, str,"{");
my_strcat(1190, str, entry->path+1);
my_strcat(1160, str, entry->token);
my_strcat(562, str,"}");
first = 0;
entry = entry->next;
}
@ -725,8 +727,8 @@ int hilight_netname(const char *name)
if(ret && !bus_hilight_lookup(name, hilight_color, XINSERT)) {
hilight_nets=1;
if(incr_hilight) hilight_color++;
redraw_hilights();
}
redraw_hilights();
return ret;
}

View File

@ -451,6 +451,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
else if(!strcmp(argv[1],"set_modify"))
{
if(argc == 3 && argv[2][0] == '0') set_modify(0);
set_modify(1);
Tcl_ResetResult(interp);
}
@ -748,6 +749,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
}
}
/* xschem instance_net inst pin */
} else if(!strcmp(argv[1],"instance_net")) {
int no_of_pins, i, p, mult;
const char *str_ptr=NULL;
@ -780,7 +782,9 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
for(n=0; n < lastselected; n++) {
if(selectedgroup[n].type == ELEMENT) {
i = selectedgroup[n].n;
my_strcat(645, &res, xctx->inst[i].instname);
my_strcat(1191, &res, "{");
my_strcat(1192, &res, xctx->inst[i].instname);
my_strcat(645, &res, "}");
if(n < lastselected-1) my_strcat(646, &res, " ");
}
}
@ -806,29 +810,13 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
}
if(!strcmp(argv[2],"instance") && argc==4) {
char *endptr;
int i,found=0;
int n;
n=strtol(argv[3], &endptr, 10);
/* 20171006 find by instance name */
for(i=0;i<xctx->instances;i++) {
if(!strcmp(xctx->inst[i].instname, argv[3])) {
select_element(i, SELECTED, 0, 0);
found=1;
break;
}
int i;
/* find by instance name or number*/
i = get_instance(argv[3]);
if(i >= 0) {
select_element(i, SELECTED, 0, 0);
}
if(!found && !(endptr == argv[3]) && n<xctx->instances && n >= 0) {
select_element(n, SELECTED, 0, 0);
found = 1;
}
if(!found) {
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, "xschem select instance: instance not found", NULL);
return TCL_ERROR;
}
Tcl_SetResult(interp, (i >= 0) ? "1" : "0" , TCL_STATIC);
}
else if(!strcmp(argv[2],"wire") && argc==4) {
int n=atol(argv[3]);
@ -843,6 +831,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
drawtempline(gc[SELLAYER], END, 0.0, 0.0, 0.0, 0.0);
} else if(!strcmp(argv[1],"instance")) {
if(argc==7)
/* pos sym_name x y rot flip prop draw first */
place_symbol(-1, argv[2], atof(argv[3]), atof(argv[4]), atoi(argv[5]), atoi(argv[6]),NULL, 3, 1);
else if(argc==8)
place_symbol(-1, argv[2], atof(argv[3]), atof(argv[4]), atoi(argv[5]), atoi(argv[6]), argv[7], 3, 1);
@ -1434,6 +1423,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
else if(!strcmp(argv[1],"select_hilight_net"))
{
select_hilight_net();
Tcl_ResetResult(interp);
}
else if(!strcmp(argv[1],"unhilight"))
{
@ -1609,13 +1599,164 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
const char *pin;
pin = get_tok_value((xctx->inst[i].ptr+ xctx->sym)->rect[PINLAYER][p].prop_ptr,"name",0);
if(!pin[0]) pin = "--ERROR--";
my_strcat(376, &pins, pin);
my_strcat(376, &pins, "{");
my_strcat(523, &pins, pin);
my_strcat(533, &pins, "}");
if(p< no_of_pins-1) my_strcat(377, &pins, " ");
}
Tcl_AppendResult(interp, pins, NULL);
my_free(926, &pins);
my_free(1195, &pins);
}
/* xschem instance_pin_coord m12 pinnumber 2
* xschem instance_pin_coord m12 name p
* returns pin_name x y */
else if(!strcmp(argv[1],"instance_pin_coord")) {
xSymbol *symbol;
xRect *rct;
int flip, rot;
double x0,y0, pinx0, piny0;
char num[60];
int p, i, no_of_pins;
if(argc < 5) {
Tcl_SetResult(interp,
"xschem instance_pin_coord requires an instance, a pin attribute and a value", TCL_STATIC);
return TCL_ERROR;
}
i = get_instance(argv[2]);
if(i < 0) {
Tcl_SetResult(interp,"", TCL_STATIC);
return TCL_OK;
}
x0 = xctx->inst[i].x0;
y0 = xctx->inst[i].y0;
rot = xctx->inst[i].rot;
flip = xctx->inst[i].flip;
symbol = xctx->sym + xctx->inst[i].ptr;
no_of_pins= symbol->rects[PINLAYER];
rct=symbol->rect[PINLAYER];
for(p = 0;p < no_of_pins; p++) {
const char *pin;
pin = get_tok_value(rct[p].prop_ptr,argv[3],0);
if(!strcmp(pin, argv[4])) break;
}
if(p >= no_of_pins) {
Tcl_SetResult(interp,"", TCL_STATIC);
return TCL_OK;
}
pinx0 = (rct[p].x1+rct[p].x2)/2;
piny0 = (rct[p].y1+rct[p].y2)/2;
ROTATION(rot, flip, 0.0, 0.0, pinx0, piny0, pinx0, piny0);
pinx0 += x0;
piny0 += y0;
my_snprintf(num, S(num), "{%s} %g %g", get_tok_value(rct[p].prop_ptr, "name", 2), pinx0, piny0);
Tcl_SetResult(interp, num, TCL_STATIC);
}
/* xschem instances_to_net PLUS */
else if(!strcmp(argv[1],"instances_to_net")) {
xSymbol *symbol;
xRect *rct;
int flip, rot;
double x0,y0, pinx0, piny0;
char num[40];
char *pins = NULL;
int p, i, no_of_pins;
prepare_netlist_structs(0);
if(argc < 3) {
Tcl_SetResult(interp,"xschem instances_to_net requires a net name argument", TCL_STATIC);
return TCL_ERROR;
}
for(i = 0;i < xctx->instances; i++) {
x0 = xctx->inst[i].x0;
y0 = xctx->inst[i].y0;
rot = xctx->inst[i].rot;
flip = xctx->inst[i].flip;
symbol = xctx->sym + xctx->inst[i].ptr;
no_of_pins= symbol->rects[PINLAYER];
rct=symbol->rect[PINLAYER];
for(p = 0;p < no_of_pins; p++) {
const char *pin;
pin = get_tok_value(rct[p].prop_ptr,"name",0);
if(!pin[0]) pin = "--ERROR--";
if(xctx->inst[i].node[p] && !strcmp(xctx->inst[i].node[p], argv[2]) &&
!IS_LABEL_SH_OR_PIN( (xctx->inst[i].ptr+xctx->sym)->type )) {
my_strcat(534, &pins, "{ {");
my_strcat(535, &pins, xctx->inst[i].instname);
my_strcat(536, &pins, "} {");
my_strcat(537, &pins, pin);
pinx0 = (rct[p].x1+rct[p].x2)/2;
piny0 = (rct[p].y1+rct[p].y2)/2;
ROTATION(rot, flip, 0.0, 0.0, pinx0, piny0, pinx0, piny0);
pinx0 += x0;
piny0 += y0;
my_strcat(538, &pins, "} {");
my_snprintf(num, S(num), "%g", pinx0);
my_strcat(539, &pins, num);
my_strcat(540, &pins, "} {");
my_snprintf(num, S(num), "%g", piny0);
my_strcat(541, &pins, num);
my_strcat(542, &pins, "} } ");
}
}
Tcl_AppendResult(interp, pins ? pins : "", NULL);
my_free(926, &pins);
}
}
else if(argc == 3 && !strcmp(argv[1],"expandlabel")) {
int tmp, llen;
char *result=NULL;
const char *l;
l = expandlabel(argv[2], &tmp);
llen = strlen(l);
result = my_malloc(378, llen + 30);
my_snprintf(result, llen + 30, "%s %d", l, tmp);
Tcl_AppendResult(interp, result, NULL);
my_free(927, &result);
}
/* xschem instance_nodemap [instance_name] */
else if(!strcmp(argv[1],"instance_nodemap")) {
char *pins = NULL;
int p, i, no_of_pins;
int inst = -1;
prepare_netlist_structs(0);
if(argc>=3) inst = get_instance(argv[2]);
for(i=0;i<xctx->instances;i++) {
if(inst>=0 && i != inst) continue;
my_strcat(573, &pins, "{ {");
my_strcat(574, &pins, xctx->inst[i].instname);
my_strcat(575, &pins, "} ");
no_of_pins= (xctx->inst[i].ptr+ xctx->sym)->rects[PINLAYER];
for(p=0;p<no_of_pins;p++) {
const char *pin;
pin = get_tok_value((xctx->inst[i].ptr+ xctx->sym)->rect[PINLAYER][p].prop_ptr,"name",0);
if(!pin[0]) pin = "--ERROR--";
if(argc>=4 && strcmp(argv[3], pin)) continue;
my_strcat(576, &pins, "{ ");
my_strcat(655, &pins, "{");
my_strcat(662, &pins, pin);
my_strcat(663, &pins, "} {");
my_strcat(664, &pins, xctx->inst[i].node[p] ? xctx->inst[i].node[p] : "");
my_strcat(665, &pins, "} ");
my_strcat(1155, &pins, "} ");
}
my_strcat(1188, &pins, "} ");
Tcl_AppendResult(interp, pins, NULL);
my_free(1189, &pins);
}
}
/*
* ********** xschem get subcommands
*/
@ -1641,18 +1782,6 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
Tcl_AppendResult(interp, xctx->sch_path[x], NULL);
}
}
else if(argc == 4 && !strcmp(argv[1],"get") && !strcmp(argv[2],"expandlabel")) {
int tmp, llen;
char *result=NULL;
const char *l;
l = expandlabel(argv[3], &tmp);
llen = strlen(l);
result = my_malloc(378, llen + 30);
my_snprintf(result, llen + 30, "%s %d", l, tmp);
Tcl_AppendResult(interp, result, NULL);
my_free(927, &result);
}
else if(!strcmp(argv[1],"get") && argc==3)
{
if(!strcmp(argv[2],"incr_hilight")) {

View File

@ -651,34 +651,122 @@ proc xschem_server {sock addr port} {
fileevent $sock readable [list xschem_getdata $sock]
}
## given a hierarchical net name x1.xamp.netname go down in the hierarchy and
## highlight the specified net.
proc probe_net {net} {
xschem unselect_all
xschem set no_draw 1
## given a path (x1.x2.m4) descend into x1.x2 and return m4 whether m4 found or not
proc descend_hierarchy {path {redraw 1}} {
# return to top level if not already there
xschem set no_draw 1
while { [xschem get currsch] } { xschem go_back }
while { [regexp {\.} $net] } {
set inst $net
regsub {\..*} $inst {} inst
regsub {[^.]+\.} $net {} net
while { [regexp {\.} $path] } {
xschem unselect_all
set inst $path
regsub {\..*} $inst {} inst ;# take 1st path component: xlev1[3].xlev2.m3 -> xlev1[3]
regsub {[^.]+\.} $path {} path ;# take remaining path: xlev1[3].xlev2.m3 -> xlev2.m3
xschem search exact 1 name $inst
set full_inst [split [lindex [xschem get expandlabel [xschem selected_set]] 0] {,}]
set instnum [expr [lsearch -exact $full_inst $inst] + 1]
# puts "$full_inst --> $instnum"
# handle vector instances: xlev1[3:0] -> xlev1[3],xlev1[2],xlev1[1],xlev1[0]
# descend into the right one
set inst_list [split [lindex [xschem expandlabel [lindex [xschem selected_set] 0 ] ] 0] {,}]
set instnum [expr [lsearch -exact $inst_list $inst] + 1]
xschem descend $instnum
# set a [lindex [split [lindex [xschem get expandlabel {xrdec[31:0]}] 0] ,] 3]
}
set res [xschem hilight_netname $net]
if {$res==0 && [regexp {^net[0-9]+$} $net]} {
set res [xschem hilight_netname \#$net]
}
xschem set no_draw 0
xschem redraw
return $res
if {$redraw} {xschem redraw}
return $path
}
## given a hierarchical instname name (x1.xamp.m1) go down in the hierarchy and
## select the specified instance (m1).
## this search assumes it is given from the top of hierarchy
proc select_inst {fullinst {redraw 1 } } {
xschem set no_draw 1
set inst [descend_hierarchy $fullinst 0]
set res [xschem select instance $inst]
# if nothing found return to top
if {!$res} {
while { [xschem get currsch] } { xschem go_back }
}
xschem set no_draw 0
if {$redraw} {xschem redraw}
if {$res} {return $inst} else { return {} }
}
proc pin_label {} {
if { [file exists [abs_sym_path devices/lab_pin.sym]] } {
return {devices/lab_pin.sym}
}
return {lab_pin.sym}
}
## given a hierarchical net name x1.xamp.netname go down in the hierarchy and
## highlight the specified net.
## this search assumes it is given from the top of hierarchy
proc probe_net {fullnet {redraw 1} } {
xschem set no_draw 1
set net [descend_hierarchy $fullnet 0]
set res [xschem hilight_netname $net]
if {$res==0 && [regexp {^net[0-9]+$} $net]} {
set net \#$net
set res [xschem hilight_netname $net]
}
if {!$res} {
while { [xschem get currsch] } { xschem go_back }
}
xschem set no_draw 0
if {$redraw} {xschem redraw}
if {$res} {return $net} else { return {} }
}
proc reroute_inst {fullinst pinattr pinval newnet} {
if { [regexp {\.} $fullinst] } { set hier 1 } else { set hier 0 }
set res [descend_hierarchy $fullinst 0]
if {$res ne {} } {
set coord [xschem instance_pin_coord $res $pinattr $pinval]
if { $coord eq {} } {
while { [xschem get currsch] } { xschem go_back }
return 0
}
set pinname [lindex $coord 0]
set x [expr [lindex $coord 1] - 10 ]
set y [expr [lindex $coord 2] - 10 ]
set oldnet [xschem instance_net $res $pinname]
regsub {.*\.} $newnet {} newnet
if { $oldnet eq $newnet } {
while { [xschem get currsch] } { xschem go_back }
puts "Warning: netlist patch already done? "
return 0
}
xschem instance [pin_label] $x $y 0 0 [list name=l1 lab=$newnet]
xschem hilight_netname $newnet
xschem select instance $res
xschem hilight_netname $oldnet
if {$hier} { xschem save}
xschem redraw
return 1
}
return 0
}
## put $new net labels close to pins on all elements connected to $old
proc reroute_net {old new} {
xschem push_undo
xschem set no_undo 1
xschem clear_hilights
probe_net $old
set old_nopath [regsub {.*\.} $old {}]
set new_nopath [regsub {.*\.} $new {}]
set devlist [xschem instances_to_net $old_nopath]
foreach i $devlist {
set instname [lindex $i 0]
set x [expr [lindex $i 2] - 10]
set y [expr [lindex $i 3] - 10]
xschem instance [pin_label] $x $y 0 0 [list name=l1 lab=$new_nopath]
xschem select instance $instname
}
xschem hilight_netname $new_nopath
xschem set no_undo 0
}
proc simulate {{callback {}}} {

View File

@ -164,7 +164,7 @@ C {code.sym} 160 -190 0 0 {name=MODELS value=".model Q2N3904 NPN(Is=6.734f Xti
"}
C {code_shown.sym} 320 -180 0 0 {name=COMMANDS
value=".SAVE ALL
*.OP
* .OP
.AC DEC 20 1Hz 100MegHz
* .DC Vinput 0 5 .01
* .DC Vinput 1 2 .0

View File

@ -34,7 +34,7 @@ N 920 -710 920 -520 { lab=VCC_FIVE}
N 170 -710 310 -710 { lab=VCC_UNREG}
N 170 -630 310 -630 { lab=VSSA}
N 820 -710 920 -710 { lab=VCC_FIVE}
N 230 -740 230 -710 { lab=VCC_UNREG}
N 260 -740 260 -710 { lab=VCC_UNREG}
C {conn_3x1.sym} 300 -360 0 0 {name=C1}
C {opin.sym} 1010 -300 0 0 {name=p0 lab=VOUT}
C {lab_wire.sym} 810 -360 0 0 {name=l9 lab=G}
@ -82,5 +82,5 @@ C {reg.sch} -120 -520 0 0 {name=x2}
C {ipin.sym} 170 -710 0 0 {name=p3 lab=VCC_UNREG}
C {ipin.sym} 170 -630 0 0 {name=p1 lab=VSSA}
C {lab_wire.sym} 690 -520 0 0 {name=l4 lab=VCC_FIVE}
C {diode.sym} 230 -770 0 0 {name=D1 model=D1N914 area=1 device=D1N914 footprint=acy(300)}
C {vdd.sym} 230 -800 0 0 {name=l5 lab=VCC}
C {diode.sym} 260 -770 0 1 {name=D1 model=D1N914 area=1 device=D1N914 footprint=acy(300)}
C {vdd.sym} 260 -800 0 0 {name=l5 lab=VCC}