fix measure data in multiple sweep/wraps graphs

This commit is contained in:
Stefan Frederik 2022-01-05 17:38:01 +01:00
parent 4a705de9d0
commit 09d8474a2c
7 changed files with 160 additions and 137 deletions

View File

@ -258,7 +258,7 @@ void toggle_only_probes()
}
#ifdef __unix__
void new_window(const char *cell, int symbol)
void new_xschem_process(const char *cell, int symbol)
{
char f[PATH_MAX]; /* overflow safe 20161122 */
struct stat buf;
@ -266,9 +266,9 @@ void new_window(const char *cell, int symbol)
pid_t pid2;
int status;
dbg(1, "new_window(): executable: %s, cell=%s, symbol=%d\n", xschem_executable, cell, symbol);
dbg(1, "new_xschem_process(): executable: %s, cell=%s, symbol=%d\n", xschem_executable, cell, symbol);
if(stat(xschem_executable,&buf)) {
fprintf(errfp, "new_window(): executable not found\n");
fprintf(errfp, "new_xschem_process(): executable not found\n");
return;
}
@ -300,24 +300,24 @@ void new_window(const char *cell, int symbol)
}
} else {
/* error */
fprintf(errfp, "new_window(): fork error 1\n");
fprintf(errfp, "new_xschem_process(): fork error 1\n");
tcleval("exit");
}
} else {
/* error */
fprintf(errfp, "new_window(): fork error 2\n");
fprintf(errfp, "new_xschem_process(): fork error 2\n");
tcleval("exit");
}
}
#else
void new_window(const char* cell, int symbol)
void new_xschem_process(const char* cell, int symbol)
{
char cmd_line[2 * PATH_MAX + 100];
struct stat buf;
dbg(1, "new_window(): executable: %s, cell=%s, symbol=%d\n", xschem_executable, cell, symbol);
dbg(1, "new_xschem_process(): executable: %s, cell=%s, symbol=%d\n", xschem_executable, cell, symbol);
if (stat(xschem_executable, &buf)) {
fprintf(errfp, "new_window(): executable not found\n");
fprintf(errfp, "new_xschem_process(): executable not found\n");
return;
}
/* According to Stackoverflow, system should be avoided because it's resource heavy
@ -966,11 +966,11 @@ void symbol_in_new_window(void)
rebuild_selected_array();
if(xctx->lastsel !=1 || xctx->sel_array[0].type!=ELEMENT)
{
new_window(xctx->sch[xctx->currsch],1);
new_xschem_process(xctx->sch[xctx->currsch],1);
}
else
{
new_window(abs_sym_path(xctx->inst[xctx->sel_array[0].n].name, ""),1);
new_xschem_process(abs_sym_path(xctx->inst[xctx->sel_array[0].n].name, ""),1);
}
}
@ -983,8 +983,8 @@ void schematic_in_new_window(void)
rebuild_selected_array();
if(xctx->lastsel !=1 || xctx->sel_array[0].type!=ELEMENT)
{
/* new_window("", 0); */
new_window(xctx->sch[xctx->currsch], 0); /* 20111007 duplicate current schematic if no inst selected */
/* new_xschem_process("", 0); */
new_xschem_process(xctx->sch[xctx->currsch], 0); /* 20111007 duplicate current schematic if no inst selected */
return;
}
else
@ -1009,7 +1009,7 @@ void schematic_in_new_window(void)
my_strncpy(filename, add_ext(abs_sym_path(xctx->inst[xctx->sel_array[0].n].name, ""), ".sch"), S(filename));
}
new_window(filename, 0);
new_xschem_process(filename, 0);
}
}

View File

@ -26,12 +26,11 @@ static int waves_selected(int event, int key, int state, int button)
{
int i;
int is_inside = 0, skip = 0;
if(xctx->ui_state & STARTPAN2) skip = 1;
if(xctx->ui_state & (STARTPAN2 | STARTSELECT | STARTMOVE | STARTCOPY)) skip = 1;
if(state & Mod1Mask) skip = 1;
if(event == MotionNotify && (state & Button2Mask)) skip = 1;
if(event == ButtonPress && button == Button2) skip = 1;
if(event == ButtonRelease && button == Button2) skip = 1;
if(xctx->ui_state & STARTSELECT) skip = 1;
if(!skip) for(i=0; i< xctx->rects[GRIDLAYER]; i++) {
xRect *r;
@ -2108,7 +2107,7 @@ int callback(const char *winpath, int event, int mx, int my, KeySym key,
}
if(key=='x' && state == 0 ) /* new cad session */
{
new_window(NULL ,0);
new_xschem_process(NULL ,0);
break;
}
if((key=='#') && !(state & ControlMask) )

View File

@ -1883,7 +1883,7 @@ static void draw_graph_bus_points(const char *ntok, int n_bits, int *idx_arr,
double ylow = DW_Y(c + wy2 * s2); /* swapped as xschem Y coordinates are top-bottom */
double yhigh = DW_Y(c + wy1 * s2);
char busval[1024], old_busval[1024];
double xval, xval_old;
double xval=0.0, xval_old=0.0;
double ydelta = fabs(yhigh - ylow);
double labsize = 0.015 * ydelta;
double charwidth = labsize * 38.0;
@ -2078,7 +2078,7 @@ static void draw_graph_grid(
* 4: draw x-cursor2
* 8: all drawing, if not set do only XCopyArea / x-cursor if specified
*/
void draw_graph(int c, int i, int flags)
void draw_graph(int c, int i, const int flags)
{
/* container box */
double rx1, ry1, rx2, ry2, rw/*, rh */;
@ -2113,6 +2113,10 @@ void draw_graph(int c, int i, int flags)
char *bus_msb = NULL;
int wcnt = 0, idx;
int dataset = -1;
int measure_p = -1;
double measure_xx;
double measure_prev_x;
/* container (embedding rectangle) coordinates */
rx1 = r->x1;
@ -2165,15 +2169,21 @@ void draw_graph(int c, int i, int flags)
/* plot single dataset */
val = get_tok_value(r->prop_ptr,"dataset",0);
if(val[0]) dataset = atoi(val);
if(dataset >= xctx->graph_datasets) dataset = xctx->graph_datasets - 1;
/* this can not be done as a single dataset may have multiple sweep variable
* wraps to beginning as in multiple dc sims
* if(dataset >= xctx->graph_datasets) dataset = xctx->graph_datasets - 1;
*/
/* set margins */
calc_graph_area(c, i, digital, &x1, &y1, &x2, &y2, &marginx, &marginy);
txtsizelab = marginy * 0.009;
tmp = (x2 - x1) * 0.00036;
tmp = (x2 - x1) * 0.00044;
if(tmp < txtsizelab) txtsizelab = tmp;
/* digtxtsizelab = txtsizelab * 0.85 * fabs( (wy2 - wy1) / (ypos2 - ypos1)); */
digtxtsizelab = 0.300 * fabs( (wy2 - wy1) / (ypos2 - ypos1));
if(flags & 2)
digtxtsizelab = 0.300 * fabs( (wy2 - wy1) / (ypos2 - ypos1));
else
digtxtsizelab = 0.400 * fabs( (wy2 - wy1) / (ypos2 - ypos1));
/* cache coefficients for faster graph --> xschem coord transformations */
cx = (x2 - x1) / (wx2 - wx1);
dx = x1 - wx1 * cx;
@ -2272,8 +2282,9 @@ void draw_graph(int c, int i, int flags)
double xx;
double start;
double end;
int n_bits;
int n_bits = 1, wrap;
int *idx_arr = NULL;
int sweepvar_wrap = 0; /* incremented on new dataset or sweep variable wrap */
XPoint *point = NULL;
ofs = 0;
@ -2284,27 +2295,27 @@ void draw_graph(int c, int i, int flags)
idx_arr = get_bus_idx_array(ntok, &n_bits); /* idx_arr allocated by function, must free! */
}
/* loop through all datasets found in raw file */
bbox(START, 0.0, 0.0, 0.0, 0.0);
bbox(ADD,x1, y1, x2, y2);
bbox(SET, 0.0, 0.0, 0.0, 0.0);
for(dset = 0 ; dset < xctx->graph_datasets; dset++) {
if(dataset == -1 || dset == dataset) {
double prev_x, prev_prev_x;
int cnt=0;
first = last = -1;
poly_npoints = 0;
my_realloc(1401, &point, xctx->graph_npoints[dset] * sizeof(XPoint));
/* Process "npoints" simulation items
* p loop split repeated 2 timed (for x and y points) to preserve cache locality */
prev_prev_x = prev_x = 0;
last = ofs;
for(p = ofs ; p < ofs + xctx->graph_npoints[dset]; p++) {
xx = xctx->graph_values[sweep_idx][p];
if(first != -1) { /* there is something to plot ... */
if(xx > end || xx < start || /* ... and we ran out of graph area ... */
((sweep_idx == 0 && cnt > 1) && /* ... or sweep variable changed direction */
SIGN(xx - prev_x) != SIGN(prev_x - prev_prev_x) ) ) {
double prev_x, prev_prev_x;
int cnt=0;
first = last = -1;
poly_npoints = 0;
my_realloc(1401, &point, xctx->graph_npoints[dset] * sizeof(XPoint));
/* Process "npoints" simulation items
* p loop split repeated 2 timed (for x and y points) to preserve cache locality */
prev_prev_x = prev_x = 0;
last = ofs;
for(p = ofs ; p < ofs + xctx->graph_npoints[dset]; p++) {
xx = xctx->graph_values[sweep_idx][p];
wrap = (sweep_idx == 0 && cnt > 1 && SIGN(xx - prev_x) != SIGN(prev_x - prev_prev_x));
if(first != -1) { /* there is something to plot ... */
if(xx > end || xx < start || /* ... and we ran out of graph area ... */
wrap) { /* ... or sweep variable changed direction */
if(dataset == -1 || dataset == sweepvar_wrap) {
/* clipping everything outside graph area */
bbox(START, 0.0, 0.0, 0.0, 0.0);
bbox(ADD,x1, y1, x2, y2);
bbox(SET, 0.0, 0.0, 0.0, 0.0);
/* get y-axis points */
if(bus_msb) {
if(digital) {
@ -2316,76 +2327,39 @@ void draw_graph(int c, int i, int flags)
draw_graph_points(idx, first, last, scy, sdy, dscy, dsdy, point, wave_color,
digital, wcnt, n_nodes, wy1, wy2, ypos1, ypos2);
}
bbox(END, 0.0, 0.0, 0.0, 0.0);
poly_npoints = 0;
first = -1;
cnt = 0;
}
}
if(xx >= start && xx <= end) {
if(first == -1) first = p;
/* Build poly x array. Translate from graph coordinates to screen coords */
point[poly_npoints].x = S_X(xx); /* CLIP(S_X(xx), xctx->areax1, xctx->areax2); */
if(flags & 2 && p > ofs) { /* cursor1: show measurements on analog nodes in graph */
if(SIGN(xx - xctx->graph_cursor1_x) != SIGN(prev_x - xctx->graph_cursor1_x)) {
double yy1 = xctx->graph_values[idx][p-1];
double dy = xctx->graph_values[idx][p] - yy1;
double dx = xx - prev_x;
double yy = yy1 + dy / dx * (xctx->graph_cursor1_x - prev_x);
char *fmt1, *fmt2;
if(SIGN(wy1) != SIGN(wy2) && fabs(yy) < 1e-4 * fabs(wy2 - wy1)) yy = 0.0;
if(yy != 0.0 && fabs(yy * unity) < 1.0e-3) {
fmt1="%.2e";
fmt2="%.2e%c";
} else {
fmt1="%.4g";
fmt2="%.4g%c";
}
/* draw node values in graph */
bbox(START, 0.0, 0.0, 0.0, 0.0);
bbox(ADD, rx1, ry1, rx2, ry2);
bbox(SET_INSIDE, 0.0, 0.0, 0.0, 0.0);
if(!bus_msb) {
if(unity != 1.0) my_snprintf(tmpstr, S(tmpstr), fmt2, yy * unity, unity_suffix);
else my_snprintf(tmpstr, S(tmpstr), fmt1, yy);
} else {
get_bus_value(n_bits, idx_arr, p, tmpstr, wy1, wy2);
}
if(!bus_msb && !digital) {
draw_string(wave_color, NOW, tmpstr, 0, 0, 0, 0,
rx1 + 2 + rw / n_nodes * wcnt, ry1 + txtsizelab * 60,
txtsizelab * 0.8, txtsizelab * 0.8);
dbg(1, "node: %s, x=%g, value=%g\n", ntok, xx, yy);
}
else if(digital) {
double xt = x1 - 10 * txtsizelab;
double deltag = wy2 - wy1;
double s1 = DIG_NWAVES; /* 1/DIG_NWAVES waveforms fit in graph if unscaled vertically */
double s2 = DIG_SPACE; /* (DIG_NWAVES - DIG_SPACE) spacing between traces */
double yt = s1 * (double)(n_nodes - wcnt) * deltag - (wy1 - deltag * 0.4) * s2;
if(yt <= ypos2 && yt >= ypos1) {
draw_string(wave_color, NOW, tmpstr, 2, 0, 0, 0,
xt, DW_Y(yt) + digtxtsizelab * 50, digtxtsizelab * 0.8, digtxtsizelab * 0.8);
}
}
bbox(END, 0.0, 0.0, 0.0, 0.0);
}
}
last = p;
poly_npoints++;
prev_prev_x = prev_x;
prev_x = xx;
cnt++;
poly_npoints = 0;
first = -1;
}
}
if(first != -1) {
/* clipping everything outside graph area */
bbox(START, 0.0, 0.0, 0.0, 0.0);
bbox(ADD,x1, y1, x2, y2);
bbox(SET, 0.0, 0.0, 0.0, 0.0);
if(wrap) {
sweepvar_wrap++;
cnt = 0;
}
if(xx >= start && xx <= end) {
if(first == -1) first = p;
/* Build poly x array. Translate from graph coordinates to screen coords */
point[poly_npoints].x = S_X(xx);
if(dataset == -1 || dataset == sweepvar_wrap)
if(measure_p == -1 && flags & 2 && cnt) { /* cursor1: show measurements on nodes in graph */
if(SIGN(xx - xctx->graph_cursor1_x) != SIGN(prev_x - xctx->graph_cursor1_x)) {
measure_p = p;
measure_xx = xx;
measure_prev_x = prev_x;
}
} /* if(measure_p == -1 && flags & 2 && p > ofs) */
last = p;
poly_npoints++;
cnt++;
} /* if(xx >= start && xx <= end) */
prev_prev_x = prev_x;
prev_x = xx;
} /* for(p = ofs ; p < ofs + xctx->graph_npoints[dset]; p++) */
if(first != -1) {
/* clipping everything outside graph area */
if(dataset == -1 || dataset == sweepvar_wrap) {
/* get y-axis points */
if(bus_msb) {
if(digital) {
@ -2397,24 +2371,73 @@ void draw_graph(int c, int i, int flags)
draw_graph_points(idx, first, last, scy, sdy, dscy, dsdy, point, wave_color,
digital, wcnt, n_nodes, wy1, wy2, ypos1, ypos2);
}
bbox(END, 0.0, 0.0, 0.0, 0.0);
}
} /* if(dataset == -1 || dset == dataset) */
}
/* offset pointing to next dataset */
ofs += xctx->graph_npoints[dset];
sweepvar_wrap++;
} /* for(dset...) */
bbox(END, 0.0, 0.0, 0.0, 0.0);
/* show values of signals if cursor1 active */
if(measure_p >= 0) {
double yy1 = xctx->graph_values[idx][measure_p-1];
double dy = xctx->graph_values[idx][measure_p] - yy1;
double dx = measure_xx - measure_prev_x;
double yy = yy1 + dy / dx * (xctx->graph_cursor1_x - measure_prev_x);
char *fmt1, *fmt2;
if(SIGN0(wy1) != SIGN0(wy2) && fabs(yy) < 1e-4 * fabs(wy2 - wy1)) yy = 0.0;
if(yy != 0.0 && fabs(yy * unity) < 1.0e-3) {
fmt1="%.2e";
fmt2="%.2e%c";
} else {
fmt1="%.4g";
fmt2="%.4g%c";
}
/* draw node values in graph */
bbox(START, 0.0, 0.0, 0.0, 0.0);
bbox(ADD, rx1, ry1, rx2, ry2);
bbox(SET_INSIDE, 0.0, 0.0, 0.0, 0.0);
if(!bus_msb) {
if(unity != 1.0) my_snprintf(tmpstr, S(tmpstr), fmt2, yy * unity, unity_suffix);
else my_snprintf(tmpstr, S(tmpstr), fmt1, yy);
} else {
get_bus_value(n_bits, idx_arr, measure_p, tmpstr, wy1, wy2);
}
if(!bus_msb && !digital) {
draw_string(wave_color, NOW, tmpstr, 0, 0, 0, 0,
rx1 + 2 + rw / n_nodes * wcnt, ry1 + txtsizelab * 60,
txtsizelab * 0.8, txtsizelab * 0.8);
dbg(1, "node: %s, x=%g, value=%g\n", ntok, measure_xx, yy);
}
else if(digital) {
double xt = x1 - 10 * txtsizelab;
double deltag = wy2 - wy1;
double s1 = DIG_NWAVES; /* 1/DIG_NWAVES waveforms fit in graph if unscaled vertically */
double s2 = DIG_SPACE; /* (DIG_NWAVES - DIG_SPACE) spacing between traces */
double yt = s1 * (double)(n_nodes - wcnt) * deltag - (wy1 - deltag * 0.4) * s2;
if(yt <= ypos2 && yt >= ypos1) {
draw_string(wave_color, NOW, tmpstr, 2, 0, 0, 0,
xt, DW_Y(yt) + digtxtsizelab * 50, digtxtsizelab * 0.8, digtxtsizelab * 0.8);
}
}
bbox(END, 0.0, 0.0, 0.0, 0.0);
} /* if(measure_p >= 0) */
my_free(1403, &point);
if(idx_arr) my_free(1455, &idx_arr);
} /* if( (idx = get_raw_index(bus_msb ? bus_msb : ntok)) != -1 ) */
wcnt++;
if(bus_msb) my_free(1453, &bus_msb);
} /* while( (ntok = my_strtok_r(nptr, "\n\t ", &saven)) ) */
my_free(1391, &node);
my_free(1392, &color);
my_free(1408, &sweep);
}
if(flags & 2) { /* cursor1 */
} /* if(flags & 8) */
if((flags & 2) && (flags & 8)) { /* cursor1 */
double xx = W_X(xctx->graph_cursor1_x);
double tx1, ty1, tx2, ty2;
int tmp;
@ -2433,7 +2456,7 @@ void draw_graph(int c, int i, int flags)
draw_string(1, NOW, tmpstr, 2, flip, 0, 0, xx + xoffs, ry2-1, txtsize, txtsize);
}
}
if(flags & 4) { /* cursor2 */
if((flags & 4) && (flags & 8)) { /* cursor2 */
double xx = W_X(xctx->graph_cursor2_x);
double tx1, ty1, tx2, ty2;
int tmp;
@ -2453,7 +2476,7 @@ void draw_graph(int c, int i, int flags)
}
}
if((flags & 6) == 6) { /* difference between cursors */
if((flags & 2) && (flags & 4) && (flags & 8)) { /* difference between cursors */
int tmp;
double txtsize = txtsizex;
double tx1, ty1, tx2, ty2;

View File

@ -1714,16 +1714,16 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
else if(!strcmp(argv[1],"new_symbol_window"))
{
cmd_found = 1;
if(argc==2) new_window("",1);
else new_window(argv[2],1);
if(argc==2) new_xschem_process("",1);
else new_xschem_process(argv[2],1);
Tcl_ResetResult(interp);
}
else if(!strcmp(argv[1],"new_window"))
{
cmd_found = 1;
if(argc==2) new_window("",0);
else new_window(argv[2],0);
if(argc==2) new_xschem_process("",0);
else new_xschem_process(argv[2],0);
Tcl_ResetResult(interp);
}
}

View File

@ -1342,7 +1342,7 @@ void print_tedax_subckt(FILE *fd, int symbol)
int no_of_pins=0;
my_strdup(460, &format, get_tok_value(xctx->sym[symbol].prop_ptr,"format",2));
if( (format==NULL) ) {
if( format==NULL ) {
my_free(473, &format);
return; /* no format */
}
@ -1450,7 +1450,7 @@ void print_spice_subckt(FILE *fd, int symbol)
int no_of_pins=0;
my_strdup(103, &format, get_tok_value(xctx->sym[symbol].prop_ptr,"format",2));
if( (format==NULL) ) {
if( format==NULL ) {
my_free(1012, &format);
return; /* no format */
}

View File

@ -311,7 +311,8 @@ extern char win_temp_dir[PATH_MAX];
strcmp(type,"show_label") && strcmp(type,"iopin")))
#define IS_LABEL_OR_PIN(type) (!(strcmp(type,"label") && strcmp(type,"ipin") && strcmp(type,"opin") && strcmp(type,"iopin")))
#define IS_PIN(type) (!(strcmp(type,"ipin") && strcmp(type,"opin") && strcmp(type,"iopin")))
#define SIGN(x) ( (x) < 0 ? -1 : (x) > 0 ? 1 : 0)
#define SIGN(x) ( (x) < 0 ? -1 : 1)
#define SIGN0(x) ( (x) < 0 ? -1 : (x) > 0 ? 1 : 0)
/* floor not needed? screen coordinates always positive <<<< */
/* #define X_TO_SCREEN(x) ( floor(((x)+xctx->xorigin)* xctx->mooz) ) */
@ -983,7 +984,7 @@ extern void select_all(void);
extern void change_linewidth(double w);
extern void schematic_in_new_window(void);
extern void symbol_in_new_window(void);
extern void new_window(const char *cell, int symbol);
extern void new_xschem_process(const char *cell, int symbol);
extern void ask_new_file(void);
extern int samefile(const char *fa, const char *fb);
extern void saveas(const char *f, int type);

View File

@ -19,7 +19,7 @@ L 4 370 -580 560 -580 {dash=3}
L 4 1420 -730 1440 -750 {dash=3}
L 4 1420 -770 1420 -730 {dash=3}
L 4 1420 -770 1440 -750 {dash=3}
L 4 1300 -750 1420 -750 {dash=3}
L 4 1350 -750 1420 -750 {dash=3}
B 2 750 -490 1410 -260 {flags=3
y1 = -0.0578106
y2 = 3.04806
@ -30,18 +30,18 @@ divx=6
node="v(a) v(zz) v(zzz)"
color="4 6 8"
sweep="v(a)"}
B 2 30 -930 500 -720 {flags=3
B 2 10 -930 570 -700 {flags=3
y1 = -0.0578112
y2 = 3.04806
divy = 6
x1=-0.0713896
x2=3.06704
x1=0.242453
x2=3.38088
divx=6
node="v(a) v(z)"
color="4 6 8"
sweep="v(z) v(a)"}
P 4 5 560 -700 560 -510 1350 -510 1350 -700 560 -700 {dash=3}
P 4 5 770 -920 770 -730 1300 -730 1300 -920 770 -920 {dash=3}
P 4 5 820 -920 820 -730 1350 -730 1350 -920 820 -920 {dash=3}
T {These 2 instances are equivalent} 290 -280 0 0 0.4 0.4 {}
T {Example of using a schematic as a component instance
instead of the usual symbol. LCC: Local Custom Cell.
@ -50,11 +50,11 @@ LCC schematic instantiation show actual parameters
in the schematic instance.} 570 -680 0 0 0.5 0.5 {}
T {LCC schematics can be nested
If only .sch is used there is
no need for a .sym file at all} 790 -880 0 0 0.6 0.6 {}
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 {}
T {Butterfly diagram
of a cmos latch} 510 -940 0 0 0.4 0.4 {layer=8}
of a cmos latch} 620 -950 0 0 0.4 0.4 {layer=8}
N 410 -100 410 -80 {lab=HALF}
N 410 -190 430 -190 {lab=ZZZ}
N 410 -190 410 -160 {lab=ZZZ}
@ -65,8 +65,8 @@ N 700 -490 700 -240 {lab=ZZ}
N 700 -240 1450 -240 {lab=ZZ}
N 320 -190 410 -190 {lab=ZZZ}
N 330 -490 420 -490 {lab=ZZ}
N 620 -850 620 -760 { lab=Z}
N 540 -850 540 -760 { lab=A}
N 730 -860 730 -770 { lab=Z}
N 650 -860 650 -770 { lab=A}
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}
@ -164,10 +164,10 @@ C {cmos_inv.sch} 140 -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}
C {lab_pin.sym} 540 -760 0 0 {name=p14 lab=A}
C {cmos_inv.sym} 580 -850 0 1 {name=Xinv3 WN=3u WP=5u LLN=3u LLP=3u}
C {lab_pin.sym} 620 -760 0 1 {name=p2 lab=Z}
C {cmos_inv.sym} 580 -760 0 0 {name=Xinv1 WN=3u WP=5u LLN=3u LLP=3u}
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
descr="Select arrow and
Ctrl-Left-Click to load/unload waveforms"