annotation of voltage and currents in (nested) LCC instances

This commit is contained in:
Stefan Frederik 2022-10-16 13:08:52 +02:00
parent 0e6c35f598
commit 91ba5fd1d3
6 changed files with 187 additions and 42 deletions

View File

@ -52,7 +52,7 @@ xinit.c \
| sort -n \
| awk '{
if(n>0 && $1 <= prev) print ">>>>>>>>>>> ERROR >>>>>>>>> " $0
else if(n++>0 && $1 != prev+1) {
else if(n>0 && $1 != prev+1) {
if($1-1 > prev+1)
print ">>>>>>>>>>> FREE >>>>>>>>> " prev+1 ":" $1-1
else
@ -60,6 +60,7 @@ xinit.c \
print
} else print
n++
prev = $1
}
END{

View File

@ -2784,7 +2784,7 @@ int load_sym_def(const char *name, FILE *embed_fd)
symbols = xctx->symbols;
dbg(1, "l_s_d(): recursion_counter=%d, name=%s\n", recursion_counter, name);
recursion_counter++;
dbg(1, "l_s_d(): name=%s\n", name);
dbg(1, "l_s_d(): loading name=%s\n", name);
lcc=NULL;
my_realloc(647, &lcc, (level + 1) * sizeof(Lcc));
max_level = level + 1;
@ -3068,7 +3068,7 @@ int load_sym_def(const char *name, FILE *embed_fd)
tt[i].txt_ptr=NULL;
tt[i].font=NULL;
load_ascii_string(&tt[i].txt_ptr, lcc[level].fd);
dbg(1, "l_s_d(): txt1: tt[i].txt_ptr=%s, i=%d\n", tt[i].txt_ptr, i);
dbg(1, "l_s_d(): txt1: level=%d tt[i].txt_ptr=%s, i=%d\n", level, tt[i].txt_ptr, i);
if(fscanf(lcc[level].fd, "%lf %lf %hd %hd %lf %lf ",&tt[i].x0, &tt[i].y0, &tt[i].rot,
&tt[i].flip, &tt[i].xscale, &tt[i].yscale) < 6 ) {
fprintf(errfp,"l_s_d(): WARNING: missing fields for Text object, ignoring\n");
@ -3081,6 +3081,49 @@ int load_sym_def(const char *name, FILE *embed_fd)
rot = lcc[level].rot; flip = lcc[level].flip;
if (tmp) my_strdup(651, &tt[i].txt_ptr, tmp);
dbg(1, "l_s_d(): txt3: tt[i].txt_ptr=%s, i=%d\n", tt[i].txt_ptr, i);
/* allow annotation inside LCC instances. */
if(tt[i].txt_ptr && !strcmp(tt[i].txt_ptr, "@spice_get_voltage")) {
/* prop_ptr is the attribute string of last loaded LCC component */
const char *lab;
size_t new_size = 0;
char *path = NULL;
if(level > 1) { /* add parent LCC instance names (X1, Xinv etc) */
int i;
for(i = 1; i <level; i++) {
const char *instname = get_tok_value(lcc[i].prop_ptr, "name", 0);
my_strcat(1582, &path, instname);
my_strcat(1588, &path, ".");
}
}
if(path) new_size += strlen(path);
lab = get_tok_value(prop_ptr, "lab", 0);
new_size += xctx->tok_size + 21; /* @spice_get_voltage(<lab>) */
my_realloc(1587, &tt[i].txt_ptr, new_size);
my_snprintf(tt[i].txt_ptr, new_size, "@spice_get_voltage(%s%s)", path ? path : "", lab);
my_free(1589, &path);
dbg(1, " --> tt[i].txt_ptr=%s\n", tt[i].txt_ptr);
}
if(tt[i].txt_ptr && !strcmp(tt[i].txt_ptr, "@spice_get_current")) {
/* prop_ptr is the attribute string of last loaded LCC component */
const char *dev;
size_t new_size = 0;
char *path = NULL;
if(level > 1) { /* add parent LCC instance names (X1, Xinv etc) */
int i;
for(i = 1; i <level; i++) {
const char *instname = get_tok_value(lcc[i].prop_ptr, "name", 0);
my_strcat(1582, &path, instname);
my_strcat(1588, &path, ".");
}
}
if(path) new_size += strlen(path);
dev = get_tok_value(prop_ptr, "name", 0);
new_size += xctx->tok_size + 21; /* @spice_get_current(<dev>) */
my_realloc(1587, &tt[i].txt_ptr, new_size);
my_snprintf(tt[i].txt_ptr, new_size, "@spice_get_current(%s%s)", path ? path : "", dev);
my_free(1589, &path);
dbg(1, " --> tt[i].txt_ptr=%s\n", tt[i].txt_ptr);
}
ROTATION(rot, flip, 0.0, 0.0, tt[i].x0, tt[i].y0, rx1, ry1);
tt[i].x0 = lcc[level].x0 + rx1; tt[i].y0 = lcc[level].y0 + ry1;
tt[i].rot = (tt[i].rot + ((lcc[level].flip && (tt[i].rot & 1)) ?
@ -3143,13 +3186,13 @@ int load_sym_def(const char *name, FILE *embed_fd)
break;
case 'C':
load_ascii_string(&symname, lcc[level].fd);
dbg(1, "l_s_d(): C line: symname=%s\n", symname);
if (fscanf(lcc[level].fd, "%lf %lf %hd %hd", &inst_x0, &inst_y0, &inst_rot, &inst_flip) < 4) {
fprintf(errfp, "l_s_d(): WARNING: missing fields for COMPONENT object, ignoring\n");
read_line(lcc[level].fd, 0);
continue;
}
load_ascii_string(&prop_ptr, lcc[level].fd);
dbg(1, "l_s_d() component: level=%d, sym=%s, prop_ptr = %s\n", level, symname, prop_ptr);
if(level + 1 >=CADMAXHIER) {
fprintf(errfp, "l_s_d(): Symbol recursively instantiating symbol: max depth reached, skipping\n");
if(has_x) tcleval("alert_ {xSymbol recursively instantiating symbol: max depth reached, skipping} {} 1");
@ -3274,7 +3317,7 @@ int load_sym_def(const char *name, FILE *embed_fd)
if( tag[0] == '{' ) ungetc(tag[0], lcc[level].fd);
read_record(tag[0], lcc[level].fd, 0);
break;
}
} /* switch(tag[0]) */
/* if a 'C' line was encountered and level was incremented, rest of line must be read
with lcc[level-1].fd file pointer */
if(incremented_level)

View File

@ -3017,11 +3017,12 @@ const char *translate(int inst, const char* s)
if(pin_prop_ptr) net = get_tok_value(pin_prop_ptr, "lab", 0);
if(net == NULL || net[0] == '\0') net = net_name(inst,0, &multip, 0, 0);
len = strlen(path) + strlen(net) + 1;
dbg(1, "net=%s\n", net);
dbg(1, "translate() @spice_get_voltage: inst=%s\n", xctx->inst[inst].instname);
dbg(1, " net=%s, pin_prop_ptr=%s\n", net, pin_prop_ptr);
fqnet = my_malloc(1573, len);
my_snprintf(fqnet, len, "%s%s", path, net);
strtolower(fqnet);
dbg(1, "translate(): fqnet=%s start_level=%d\n", fqnet, start_level);
dbg(1, "translate() @spice_get_voltage: fqnet=%s start_level=%d\n", fqnet, start_level);
idx = get_raw_index(fqnet);
if(idx >= 0) {
val = xctx->graph_values[idx][xctx->graph_annotate_p];
@ -3069,12 +3070,12 @@ const char *translate(int inst, const char* s)
n = sscanf(token + 19, "%[^)]", net);
if(n == 1) {
strtolower(net);
len = strlen(path) + strlen(net) + 1;
len = strlen(path) + strlen(xctx->inst[inst].instname) + strlen(net) + 2;
dbg(1, "net=%s\n", net);
fqnet = my_malloc(1548, len);
my_snprintf(fqnet, len, "%s%s", path, net);
my_snprintf(fqnet, len, "%s%s.%s", path, xctx->inst[inst].instname, net);
strtolower(fqnet);
dbg(1, "translate(): fqnet=%s start_level=%d\n", fqnet, start_level);
dbg(1, "translate(): net=%s, fqnet=%s start_level=%d\n", net, fqnet, start_level);
idx = get_raw_index(fqnet);
if(idx >= 0) {
val = xctx->graph_values[idx][xctx->graph_annotate_p];
@ -3099,6 +3100,75 @@ const char *translate(int inst, const char* s)
}
}
}
else if(strncmp(token,"@spice_get_current(", 19)==0 )
{
int start_level; /* hierarchy level where waves were loaded */
if((start_level = sch_waves_loaded()) >= 0 && xctx->graph_annotate_p>=0) {
char *fqdev = NULL;
const char *path = xctx->sch_path[xctx->currsch] + 1;
char *dev = NULL;
size_t len;
int idx, n;
double val;
const char *valstr;
tmp = strlen(token) + 1;
if(path) {
int skip = 0;
/* skip path components that are above the level where raw file was loaded */
while(*path && skip < start_level) {
if(*path == '.') skip++;
path++;
}
dev = my_malloc(1550, tmp);
n = sscanf(token + 19, "%[^)]", dev);
if(n == 1) {
strtolower(dev);
len = strlen(path) + strlen(xctx->inst[inst].instname) +
strlen(dev) + 11; /* some extra chars for i(..) wrapper */
dbg(1, "dev=%s\n", dev);
fqdev = my_malloc(1556, len);
if(!sim_is_xyce) {
int prefix, vsource;
char *ptr = dev;
char *prefix_ptr = dev;
while(*ptr) { /* since dev is something like X1.X2.V2 find last . before V */
if(*ptr == '.') prefix_ptr = ptr + 1;
ptr++;
}
prefix = prefix_ptr[0]; /* character after last '.' */
dbg(1, "prefix=%c, path=%s\n", prefix, path);
vsource = (prefix == 'v') || (prefix == 'e');
if(vsource) my_snprintf(fqdev, len, "i(%c.%s%s.%s)", prefix, path, xctx->inst[inst].instname, dev);
else my_snprintf(fqdev, len, "i(@%c.%s%s.%s)", prefix, path, xctx->inst[inst].instname, dev);
} else {
my_snprintf(fqdev, len, "i(%s%s.%s)", path, xctx->inst[inst].instname, dev);
}
strtolower(fqdev);
dbg(1, "fqdev=%s\n", fqdev);
idx = get_raw_index(fqdev);
if(idx >= 0) {
val = xctx->graph_values[idx][xctx->graph_annotate_p];
}
if(idx < 0) {
valstr = "";
xctx->tok_size = 0;
len = 0;
} else {
valstr = dtoa_eng(val);
len = xctx->tok_size;
}
if(len) {
STR_ALLOC(&result, len + result_pos, &size);
memcpy(result+result_pos, valstr, len+1);
result_pos += len;
}
dbg(1, "inst %d, dev=%s, fqdev=%s idx=%d valstr=%s\n", inst, dev, fqdev, idx, valstr);
my_free(1557, &fqdev);
} /* if(n == 1) */
my_free(1551, &dev);
} /* if(path) */
} /* if((start_level = sch_waves_loaded()) >= 0 && xctx->graph_annotate_p>=0) */
}
else if(strcmp(token,"@spice_get_diff_voltage")==0 )
{
int start_level; /* hierarchy level where waves were loaded */
@ -3412,6 +3482,12 @@ const char *translate2(Lcc *lcc, int level, char* s)
memcpy(result + result_pos, token, tmp + 1);
result_pos += tmp;
}
else if (strncmp(token, "@spice_get_current", 18) == 0) { /* return unchanged */
tmp = strlen(token);
STR_ALLOC(&result, tmp + result_pos, &size);
memcpy(result + result_pos, token, tmp + 1);
result_pos += tmp;
}
else if (strcmp(token, "@symname") == 0) {
tmp_sym_name = lcc[level].symname ? get_cell(lcc[level].symname, 0) : "";
tmp = strlen(tmp_sym_name);

View File

@ -34,7 +34,7 @@ zzz"
color="4 6 8"
sweep="v(a)"
dataset=-1}
B 2 10 -930 570 -700 {flags=graph
B 2 10 -950 570 -720 {flags=graph
y1 = 0
y2 = 3
divy = 6
@ -58,7 +58,7 @@ T {LCC schematics can be nested
If only .sch is used there is
no need for a .sym file at all} 840 -880 0 0 0.6 0.6 {}
T {Select one or more graphs (and no other objects)
and use arrow keys to zoom / pan waveforms} 20 -980 0 0 0.3 0.3 {}
and use arrow keys to zoom / pan waveforms} 20 -1000 0 0 0.3 0.3 {}
T {Butterfly diagram
of a cmos latch} 620 -950 0 0 0.4 0.4 {layer=8}
N 410 -100 410 -80 {lab=HALF}
@ -67,12 +67,15 @@ N 410 -190 410 -160 {lab=ZZZ}
N 420 -400 420 -380 {lab=HALF}
N 420 -490 700 -490 {lab=ZZ}
N 420 -490 420 -460 {lab=ZZ}
N 700 -490 700 -240 {lab=ZZ}
N 700 -240 1450 -240 {lab=ZZ}
N 700 -240 1450 -240 {lab=#net1}
N 320 -190 410 -190 {lab=ZZZ}
N 330 -490 420 -490 {lab=ZZ}
N 730 -860 730 -770 { lab=Z}
N 650 -860 650 -770 { lab=A}
N 700 -320 700 -240 {
lab=#net1}
N 700 -490 700 -380 {
lab=ZZ}
C {vsource.sym} 50 -140 0 0 {name=V1 value="pwl 0 0 1u 0 5u 3"}
C {lab_pin.sym} 50 -170 0 0 {name=p4 lab=A}
C {lab_pin.sym} 50 -110 0 0 {name=p5 lab=0}
@ -158,7 +161,7 @@ C {lab_pin.sym} 410 -80 0 0 {name=p10 lab=HALF}
C {vsource.sym} 50 -340 0 0 {name=V3 value=1.5}
C {lab_pin.sym} 50 -370 0 0 {name=p11 lab=HALF}
C {lab_pin.sym} 50 -310 0 0 {name=p12 lab=0}
C {lab_pin.sym} 200 -490 0 0 {name=p13 lab=A}
C {lab_pin.sym} 120 -490 0 0 {name=p13 lab=A}
C {res.sym} 420 -430 0 0 {name=R2
value=20k
footprint=1206
@ -166,7 +169,7 @@ device=resistor
m=1}
C {lab_pin.sym} 420 -380 0 0 {name=p15 lab=HALF}
C {title.sym} 160 -30 0 0 {name=l1 author="Stefan Schippers"}
C {cmos_inv.sch} 140 -260 0 0 {name=Xinv WN=15u WP=45u LLN=3u LLP=3u}
C {cmos_inv.sch} 60 -260 0 0 {name=Xinv WN=15u WP=45u LLN=3u LLP=3u}
C {cmos_inv.sym} 280 -190 0 0 {name=Xinv2 WN=15u WP=45u LLN=3u LLP=3u}
C {bus_keeper.sch} 1200 60 0 0 {name=Xkeeper WN_FB=3u WP_FB=5u}
C {lab_pin.sym} 700 -490 0 1 {name=p1 lab=ZZ}
@ -174,10 +177,11 @@ C {lab_pin.sym} 650 -770 0 0 {name=p14 lab=A}
C {cmos_inv.sym} 690 -860 0 1 {name=Xinv3 WN=3u WP=5u LLN=3u LLP=3u}
C {lab_pin.sym} 730 -770 0 1 {name=p2 lab=Z}
C {cmos_inv.sym} 690 -770 0 0 {name=Xinv1 WN=3u WP=5u LLN=3u LLP=3u}
C {launcher.sym} 85 -1015 0 0 {name=h1
C {launcher.sym} 85 -1035 0 0 {name=h1
descr="Select arrow and
Ctrl-Left-Click to load/unload waveforms"
tclcommand="
xschem raw_read $netlist_dir/[file tail [file rootname [xschem get current_name]]].raw
"
}
C {ammeter.sym} 700 -350 0 1 {name=Vmeas}

View File

@ -1,4 +1,5 @@
v {xschem version=3.0.0 file_version=1.2 }
v {xschem version=3.1.0 file_version=1.2
}
G {}
K {type=subcircuit
format="@name @pinlist @symname WN_FB=@WN_FB WP_FB=@WP_FB"
@ -6,23 +7,24 @@ template="name=X1 WN_FB=1u WP_FB=2u"}
V {}
S {}
E {}
P 2 5 250 -880 250 -120 480 -120 480 -880 250 -880 {dash=5}
T {@name} 250 -915 0 0 0.5 0.5 {}
P 2 5 250 -930 250 -120 610 -120 610 -930 250 -930 {dash=5}
T {@name} 250 -965 0 0 0.5 0.5 {}
T {@symname} 253.75 -115 0 0 0.5 0.5 {}
N 250 -300 300 -300 {lab=A}
N 280 -680 300 -680 {lab=A}
N 280 -680 280 -300 {lab=A}
N 430 -300 450 -300 {lab=#net1}
N 450 -680 450 -300 {lab=#net1}
N 430 -680 450 -680 {lab=#net1}
N 350 -500 390 -500 { lab=GND}
N 280 -690 300 -690 {lab=A}
N 280 -690 280 -300 {lab=A}
N 510 -300 550 -300 {lab=Y}
N 550 -690 550 -300 {lab=Y}
N 510 -690 550 -690 {lab=Y}
N 550 -240 550 -200 { lab=GND}
C {cmos_inv.sch} 240 -70 0 0 {name=X2 WN=15u WP=45u LLN=3u LLP=3u}
C {cmos_inv.sch} 490 -450 0 1 {name=X1 WN=WN_FB WP=WP_FB LLN=3u LLP=3u}
C {cmos_inv.sch} 570 -460 0 1 {name=X1 WN=WN_FB WP=WP_FB LLN=3u LLP=3u}
C {iopin.sym} 250 -300 0 1 {name=p1 lab=A}
C {title.sym} 160 -30 0 0 {name=l1 author="Stefan Schippers"}
C {capa.sym} 420 -500 1 0 {name=C1
C {capa.sym} 550 -270 0 0 {name=C1
m=1
value=10f
footprint=1206
device="ceramic capacitor"}
C {gnd.sym} 350 -500 0 0 {name=l2 lab=GND}
C {gnd.sym} 550 -200 0 0 {name=l2 lab=0}
C {lab_pin.sym} 550 -550 0 0 {name=l3 sig_type=std_logic lab=Y}

View File

@ -1,4 +1,5 @@
v {xschem version=2.9.9 file_version=1.2 }
v {xschem version=3.1.0 file_version=1.2
}
G {}
K {type=subcircuit
function0="1 ~"
@ -8,22 +9,40 @@ template="name=X1 WN=15u WP=45u LLN=3u LLP=3u m=1"
V {}
S {}
E {}
A 15 90 -350 14.14213562373095 135 360 {dash=2}
P 2 5 60 -390 190 -390 190 -90 60 -90 60 -390 {dash=5}
T {@name} 60 -405 0 0 0.2 0.2 {}
A 15 90 -410 14.14213562373095 135 360 {dash=2}
P 2 5 60 -450 270 -450 270 -90 60 -90 60 -450 {dash=5}
T {@name} 60 -465 0 0 0.2 0.2 {}
T {@symname} 63.75 -85 0 0 0.2 0.2 {}
N 140 -260 140 -200 {lab=Z}
N 100 -290 100 -170 {lab=A}
N 60 -230 100 -230 {lab=A}
N 140 -230 190 -230 {lab=Z}
N 140 -340 140 -320 {lab=VDD}
N 80 -350 80 -170 {lab=A}
N 60 -230 80 -230 {lab=A}
N 140 -400 140 -380 {lab=VDD}
N 140 -140 140 -120 {lab=0}
C {opin.sym} 190 -230 0 0 {name=p2 lab=Z}
N 240 -230 270 -230 {
lab=Z}
N 140 -230 180 -230 {
lab=D}
N 140 -320 140 -290 {
lab=#net1}
N 140 -230 140 -200 {
lab=D}
N 80 -350 100 -350 {
lab=A}
N 80 -170 100 -170 {
lab=A}
C {opin.sym} 270 -230 0 0 {name=p2 lab=Z}
C {ipin.sym} 60 -230 0 0 {name=p1 lab=A goto=0}
C {vdd.sym} 140 -340 0 0 {name=l1 lab=VDD}
C {vdd.sym} 140 -400 0 0 {name=l1 lab=VDD}
C {lab_pin.sym} 140 -120 0 0 {name=l2 sig_type=std_logic lab=0}
C {pmos4.sym} 120 -290 0 0 {name=M2 model=p w=WP l=LLP m=1 net_name=true}
C {pmos4.sym} 120 -350 0 0 {name=M2 model=p w=WP l=LLP m=1 net_name=true}
C {nmos4.sym} 120 -170 0 0 {name=M1 model=n w=WN l=LLN m=1 net_name=true}
C {lab_pin.sym} 140 -170 0 1 {name=l3 sig_type=std_logic lab=0}
C {lab_pin.sym} 140 -290 0 1 {name=l4 sig_type=std_logic lab=VDD}
C {lab_pin.sym} 140 -350 0 1 {name=l4 sig_type=std_logic lab=VDD}
C {title.sym} 160 -30 0 0 {name=l5 author="Stefan Schippers"}
C {res.sym} 210 -230 1 0 {name=R1
value=1k
footprint=1206
device=resistor
m=1}
C {lab_pin.sym} 140 -220 0 1 {name=l6 sig_type=std_logic lab=D}
C {lab_pin.sym} 80 -320 0 1 {name=l7 sig_type=std_logic lab=A}
C {ammeter.sym} 140 -260 0 0 {name=V1}