compare schematics does not require to save schematic 1, so a comparison with the saved version of itself is possible, showing the differences after editing.

This commit is contained in:
Stefan Frederik 2022-08-26 15:29:10 +02:00
parent 5100803673
commit 3c980ce956
2 changed files with 177 additions and 131 deletions

View File

@ -1046,127 +1046,6 @@ void prepare_netlist_structs(int for_netlist)
/* propagate_hilights(1, 0, XINSERT_NOREPLACE);*/
}
int compare_schematics(const char *f)
{
Int_hashentry *table1[HASHSIZE], *table2[HASHSIZE];
Int_hashentry *found;
char *s = NULL;
int i;
size_t l;
char current_sch[PATH_MAX];
int ret=0; /* ret==0 means no differences found */
save(0);
if(f == NULL) {
tcleval("load_file_dialog {Schematic to compare with} .sch.sym INITIALLOADDIR");
if(tclresult()[0]) my_strncpy(xctx->sch_to_compare, tclresult(), S(xctx->sch_to_compare));
else my_strncpy(xctx->sch_to_compare, "", S(xctx->sch_to_compare));
} else if(f[0] != '\0') {
my_strncpy(xctx->sch_to_compare, f, S(xctx->sch_to_compare));
}
if(!xctx->sch_to_compare[0]) {
dbg(0, "compare_schematics() schematic to compare with not set\n");
return -1;
}
memset(table1, 0, HASHSIZE * sizeof(Int_hashentry *));
memset(table2, 0, HASHSIZE * sizeof(Int_hashentry *));
my_strncpy(current_sch, abs_sym_path(xctx->current_name, ""), S(current_sch));
/* HASH SCHEMATIC 1 */
for(i = 0; i < xctx->instances; i++) {
l = 1024 + strlen(xctx->inst[i].prop_ptr ? xctx->inst[i].prop_ptr : "");
my_realloc(1534, &s, l);
my_snprintf(s, l, "C %s %g %g %d %d %s", xctx->inst[i].name,
xctx->inst[i].x0, xctx->inst[i].y0, xctx->inst[i].rot, xctx->inst[i].flip,
xctx->inst[i].prop_ptr ? xctx->inst[i].prop_ptr : "");
int_hash_lookup(table1, s, i, XINSERT_NOREPLACE);
}
for(i=0;i<xctx->wires;i++)
{
l =1024 + strlen(xctx->wire[i].prop_ptr ? xctx->wire[i].prop_ptr : "");
my_realloc(1535, &s, l);
my_snprintf(s, l, "N %g %g %g %g", xctx->wire[i].x1, xctx->wire[i].y1,
xctx->wire[i].x2, xctx->wire[i].y2);
int_hash_lookup(table1, s, i, XINSERT_NOREPLACE);
}
clear_all_hilights();
unselect_all(1);
remove_symbols();
xctx->no_draw = 1;
load_schematic(1, xctx->sch_to_compare, 1);
/* HASH SCHEMATIC 2 , CHECK SCHEMATIC 2 WITH SCHEMATIC 1 */
for(i = 0; i < xctx->instances; i++) {
l = 1024 + strlen(xctx->inst[i].prop_ptr ? xctx->inst[i].prop_ptr : "");
my_realloc(1534, &s, l);
my_snprintf(s, l, "C %s %g %g %d %d %s", xctx->inst[i].name,
xctx->inst[i].x0, xctx->inst[i].y0, xctx->inst[i].rot, xctx->inst[i].flip,
xctx->inst[i].prop_ptr ? xctx->inst[i].prop_ptr : "");
int_hash_lookup(table2, s, i, XINSERT_NOREPLACE);
found = int_hash_lookup(table1, s, i, XLOOKUP);
if(!found) {
dbg(1, "schematic 2 instance %d: %s mismatch or not found in schematic 1\n", i,
xctx->inst[i].instname ? xctx->inst[i].instname : "");
select_element(i,SELECTED, 1, 1);
ret = 1;
}
}
for(i=0;i<xctx->wires;i++)
{
l =1024 + strlen(xctx->wire[i].prop_ptr ? xctx->wire[i].prop_ptr : "");
my_realloc(1535, &s, l);
my_snprintf(s, l, "N %g %g %g %g", xctx->wire[i].x1, xctx->wire[i].y1,
xctx->wire[i].x2, xctx->wire[i].y2);
int_hash_lookup(table2, s, i, XINSERT_NOREPLACE);
found = int_hash_lookup(table1, s, i, XLOOKUP);
if(!found) {
dbg(1, "schematic 2 net %d: %s mismatch or not found in schematic 1\n", i,
xctx->wire[i].prop_ptr ? xctx->wire[i].prop_ptr : "");
select_wire(i, SELECTED, 1);
ret = 1;
}
}
if(ret) {
rebuild_selected_array();
draw_selection(xctx->gc[PINLAYER], 0);
}
unselect_all(0);
load_schematic(1, current_sch, 1);
xctx->no_draw = 0;
/* CHECK SCHEMATIC 1 WITH SCHEMATIC 2*/
for(i = 0; i < xctx->instances; i++) {
l = 1024 + strlen(xctx->inst[i].prop_ptr ? xctx->inst[i].prop_ptr : "");
my_realloc(1536,&s, l);
my_snprintf(s, l, "C %s %g %g %d %d %s", xctx->inst[i].name,
xctx->inst[i].x0, xctx->inst[i].y0, xctx->inst[i].rot, xctx->inst[i].flip,
xctx->inst[i].prop_ptr ? xctx->inst[i].prop_ptr : "");
found = int_hash_lookup(table2, s, i, XLOOKUP);
if(!found) {
select_element(i,SELECTED, 1, 1);
ret = 1;
}
}
for(i=0;i<xctx->wires;i++)
{
l = 1024 + strlen(xctx->wire[i].prop_ptr ? xctx->wire[i].prop_ptr : "");
my_realloc(1537, &s, l);
my_snprintf(s, l, "N %g %g %g %g", xctx->wire[i].x1, xctx->wire[i].y1,
xctx->wire[i].x2, xctx->wire[i].y2);
found = int_hash_lookup(table2, s, i, XLOOKUP);
if(!found) {
select_wire(i, SELECTED, 1);
ret = 1;
}
}
int_hash_free(table1);
int_hash_free(table2);
rebuild_selected_array();
draw_selection(xctx->gc[SELLAYER], 0);
my_free(1531, &s);
return ret;
}
int warning_overlapped_symbols()
{
int i;

View File

@ -633,7 +633,7 @@ static void alloc_xschem_data(const char *top_path, const char *win_path)
xctx->time_last_modify = 0;
}
static void delete_schematic_data(void)
static void delete_schematic_data(int delete_pixmap)
{
dbg(1, "delete_schematic_data()\n");
unselect_all(1);
@ -645,7 +645,7 @@ static void delete_schematic_data(void)
clear_all_hilights(); /* data structs for hilighting nets/instances */
get_unnamed_node(0, 0, 0); /* net### enumerator used for netlisting */
clear_drawing();
if(has_x) {
if(has_x && delete_pixmap) {
resetwin(0, 1, 1, 0, 0); /* delete preview pixmap, delete cairo surfaces */
free_gc();
}
@ -657,6 +657,170 @@ static void delete_schematic_data(void)
free_xschem_data(); /* delete the xctx struct */
}
int compare_schematics(const char *f)
{
Int_hashentry *table1[HASHSIZE], *table2[HASHSIZE];
Int_hashentry *found;
char *s = NULL;
int i;
size_t l;
int ret=0; /* ret==0 means no differences found */
Xschem_ctx *save_xctx;
memset(table1, 0, HASHSIZE * sizeof(Int_hashentry *));
memset(table2, 0, HASHSIZE * sizeof(Int_hashentry *));
/* set filename of schematic to compare */
if(f == NULL) {
tcleval("load_file_dialog {Schematic to compare with} .sch.sym INITIALLOADDIR");
if(tclresult()[0]) my_strncpy(xctx->sch_to_compare, tclresult(), S(xctx->sch_to_compare));
else my_strncpy(xctx->sch_to_compare, "", S(xctx->sch_to_compare));
} else if(f[0] != '\0') {
my_strncpy(xctx->sch_to_compare, f, S(xctx->sch_to_compare));
}
if(!xctx->sch_to_compare[0]) {
dbg(0, "compare_schematics() schematic to compare with not set\n");
return -1;
}
/* HASH SCHEMATIC 1 */
for(i = 0; i < xctx->instances; i++) {
l = 1024 + strlen(xctx->inst[i].prop_ptr ? xctx->inst[i].prop_ptr : "");
my_realloc(1534, &s, l);
my_snprintf(s, l, "C %s %g %g %d %d %s", xctx->inst[i].name,
xctx->inst[i].x0, xctx->inst[i].y0, xctx->inst[i].rot, xctx->inst[i].flip,
xctx->inst[i].prop_ptr ? xctx->inst[i].prop_ptr : "");
int_hash_lookup(table1, s, i, XINSERT_NOREPLACE);
}
for(i=0;i<xctx->wires;i++)
{
l =1024 + strlen(xctx->wire[i].prop_ptr ? xctx->wire[i].prop_ptr : "");
my_realloc(1535, &s, l);
my_snprintf(s, l, "N %g %g %g %g", xctx->wire[i].x1, xctx->wire[i].y1,
xctx->wire[i].x2, xctx->wire[i].y2);
int_hash_lookup(table1, s, i, XINSERT_NOREPLACE);
}
/* save old xctx and create new xctx for compare schematic */
save_xctx = xctx;
xctx = NULL;
alloc_xschem_data("", ".drw");
xctx->netlist_type = CAD_SPICE_NETLIST;
tclsetvar("netlist_type","spice");
init_pixdata(); /* populate xctx->fill_type array that is used in create_gc() to set fill styles */
/* draw in same window */
xctx->window = save_xctx->window;
/* copy filename from saved schematic ctx */
my_strncpy(xctx->sch_to_compare, save_xctx->sch_to_compare, S(xctx->sch_to_compare));
set_snap(0); /* set default value specified in xschemrc as 'snap' else CADSNAP */
set_grid(0); /* set default value specified in xschemrc as 'grid' else CADGRID */
create_gc();
enable_layers();
build_colors(0.0, 0.0);
/* copy graphic context data from schematic 1 */
xctx->areax1 = save_xctx->areax1;
xctx->areax2 = save_xctx->areax2;
xctx->areay1 = save_xctx->areay1;
xctx->areay2 = save_xctx->areay2;
xctx->areaw = save_xctx->areaw;
xctx->areah = save_xctx->areah;
xctx->xrect[0].x = save_xctx->xrect[0].x;
xctx->xrect[0].y = save_xctx->xrect[0].y;
xctx->xrect[0].width = save_xctx->xrect[0].width;
xctx->xrect[0].height = save_xctx->xrect[0].height;
xctx->save_pixmap = save_xctx->save_pixmap;
xctx->gctiled = save_xctx->gctiled;
xctx->cairo_ctx = save_xctx->cairo_ctx;
xctx->cairo_save_ctx = save_xctx->cairo_save_ctx;
/* set identical viewport */
xctx->zoom = save_xctx->zoom;
xctx->mooz = save_xctx->mooz;
xctx->xorigin = save_xctx->xorigin;
xctx->yorigin = save_xctx->yorigin;
/* Load schematic 2 for comparing */
load_schematic(1, xctx->sch_to_compare, 0); /* last param to 0, do not alter window title */
/* HASH SCHEMATIC 2 , CHECK SCHEMATIC 2 WITH SCHEMATIC 1 */
for(i = 0; i < xctx->instances; i++) {
l = 1024 + strlen(xctx->inst[i].prop_ptr ? xctx->inst[i].prop_ptr : "");
my_realloc(1534, &s, l);
my_snprintf(s, l, "C %s %g %g %d %d %s", xctx->inst[i].name,
xctx->inst[i].x0, xctx->inst[i].y0, xctx->inst[i].rot, xctx->inst[i].flip,
xctx->inst[i].prop_ptr ? xctx->inst[i].prop_ptr : "");
int_hash_lookup(table2, s, i, XINSERT_NOREPLACE);
found = int_hash_lookup(table1, s, i, XLOOKUP);
if(!found) {
dbg(1, "schematic 2 instance %d: %s mismatch or not found in schematic 1\n", i,
xctx->inst[i].instname ? xctx->inst[i].instname : "");
select_element(i,SELECTED, 1, 1);
ret = 1;
}
}
for(i=0;i<xctx->wires;i++)
{
l =1024 + strlen(xctx->wire[i].prop_ptr ? xctx->wire[i].prop_ptr : "");
my_realloc(1535, &s, l);
my_snprintf(s, l, "N %g %g %g %g", xctx->wire[i].x1, xctx->wire[i].y1,
xctx->wire[i].x2, xctx->wire[i].y2);
int_hash_lookup(table2, s, i, XINSERT_NOREPLACE);
found = int_hash_lookup(table1, s, i, XLOOKUP);
if(!found) {
dbg(1, "schematic 2 net %d: %s mismatch or not found in schematic 1\n", i,
xctx->wire[i].prop_ptr ? xctx->wire[i].prop_ptr : "");
select_wire(i, SELECTED, 1);
ret = 1;
}
}
/* draw mismatches in red */
if(ret) {
rebuild_selected_array();
draw_selection(xctx->gc[PINLAYER], 0);
}
unselect_all(0);
/* delete compare schematic data */
delete_schematic_data(0); /* do not delete save_pixmap */
/* restore schematic 1 */
xctx = save_xctx;
/* CHECK SCHEMATIC 1 WITH SCHEMATIC 2*/
for(i = 0; i < xctx->instances; i++) {
l = 1024 + strlen(xctx->inst[i].prop_ptr ? xctx->inst[i].prop_ptr : "");
my_realloc(1536,&s, l);
my_snprintf(s, l, "C %s %g %g %d %d %s", xctx->inst[i].name,
xctx->inst[i].x0, xctx->inst[i].y0, xctx->inst[i].rot, xctx->inst[i].flip,
xctx->inst[i].prop_ptr ? xctx->inst[i].prop_ptr : "");
found = int_hash_lookup(table2, s, i, XLOOKUP);
if(!found) {
select_element(i,SELECTED, 1, 1);
ret = 1;
}
}
for(i=0;i<xctx->wires;i++)
{
l = 1024 + strlen(xctx->wire[i].prop_ptr ? xctx->wire[i].prop_ptr : "");
my_realloc(1537, &s, l);
my_snprintf(s, l, "N %g %g %g %g", xctx->wire[i].x1, xctx->wire[i].y1,
xctx->wire[i].x2, xctx->wire[i].y2);
found = int_hash_lookup(table2, s, i, XLOOKUP);
if(!found) {
select_wire(i, SELECTED, 1);
ret = 1;
}
}
int_hash_free(table1);
int_hash_free(table2);
rebuild_selected_array();
draw_selection(xctx->gc[SELLAYER], 0);
my_free(1531, &s);
return ret;
}
static void xwin_exit(void)
{
int i;
@ -666,7 +830,7 @@ static void xwin_exit(void)
return;
}
tcleval("catch { ngspice::resetdata }"); /* remove ngspice annotation data if any */
delete_schematic_data();
delete_schematic_data(1);
if(has_x) {
Tk_DestroyWindow(mainwindow);
#ifdef __unix__
@ -952,7 +1116,7 @@ void preview_window(const char *what, const char *win_path, const char *fname)
xctx = preview_xctx;
if(!current_file || strcmp(fname, current_file) ) {
if(current_file) {
delete_schematic_data();
delete_schematic_data(1);
}
my_strdup(117, &current_file, fname);
xctx = NULL; /* reset for preview */
@ -974,7 +1138,7 @@ void preview_window(const char *what, const char *win_path, const char *fname)
dbg(1, "preview_window() destroy\n");
xctx = preview_xctx;
if(current_file) {
delete_schematic_data();
delete_schematic_data(1);
preview_xctx = NULL;
}
@ -1299,7 +1463,7 @@ static void destroy_window(int *window_count, const char *win_path)
/* set saved ctx to main window if current is to be destroyed */
if(savectx == xctx) savectx = save_xctx[0];
tclvareval("winfo toplevel ", win_path, NULL);
delete_schematic_data();
delete_schematic_data(1);
save_xctx[n] = NULL;
Tk_DestroyWindow(Tk_NameToWindow(interp, window_path[n], mainwindow));
tclvareval("destroy ", tclresult(), NULL);
@ -1352,7 +1516,7 @@ static void destroy_tab(int *window_count, const char *win_path)
tclvareval("delete_ctx ", win_path, NULL);
tclvareval("delete_tab ", win_path, NULL);
xctx = save_xctx[n];
delete_schematic_data();
delete_schematic_data(1);
save_xctx[n] = NULL;
my_strncpy(window_path[n], "", S(window_path[n]));
/* delete Tcl context of deleted schematic window */
@ -1360,7 +1524,10 @@ static void destroy_tab(int *window_count, const char *win_path)
if(*window_count == 0) tcleval(".menubar.view.menu entryconfigure 21 -state normal");
}
xctx = save_xctx[0]; /* restore main (.drw) schematic */
resetwin(1, 0, 0, 0, 0); /* create pixmap. resetwin(create_pixmap, clear_pixmap, force, w, h) */
/* seems unnecessary; previous tab save_pixmap was not deleted */
/* resetwin(1, 0, 0, 0, 0); */ /* create pixmap. resetwin(create_pixmap, clear_pixmap, force, w, h) */
tclvareval("restore_ctx ", xctx->current_win_path, " ; housekeeping_ctx", NULL);
set_modify(-1); /* sets window title */
draw();
@ -1397,7 +1564,7 @@ static void destroy_all_windows(int *window_count)
Tcl_ResetResult(interp);
if(close) {
tclvareval("winfo toplevel ", window_path[i], NULL);
delete_schematic_data();
delete_schematic_data(1);
/* set saved ctx to main window if previous is about to be destroyed */
if(savectx == save_xctx[i]) savectx = save_xctx[0];
save_xctx[i] = NULL;
@ -1444,7 +1611,7 @@ static void destroy_all_tabs(int *window_count)
/* delete Tcl context of deleted schematic window */
tclvareval("delete_ctx ", window_path[i], NULL);
tclvareval("delete_tab ", window_path[i], NULL);
delete_schematic_data();
delete_schematic_data(1);
/* set saved ctx to main window if previous is about to be destroyed */
if(savectx == save_xctx[i]) savectx = save_xctx[0];
save_xctx[i] = NULL;