From 9f368d32e52493eaedff4a467982d47156d21ea4 Mon Sep 17 00:00:00 2001 From: stefan schippers Date: Fri, 31 May 2024 09:07:56 +0200 Subject: [PATCH] sim_pinnumber attribute on schematic pins will be used for top level .subckt pin ordering if no corresponding symbol exists when creating a spice netlist --- src/save.c | 130 ++++++++++++++++++++++++++++++++------------ src/spice_netlist.c | 33 ++++++----- src/xschem.h | 8 ++- 3 files changed, 117 insertions(+), 54 deletions(-) diff --git a/src/save.c b/src/save.c index 3e46e07a..d3e13870 100644 --- a/src/save.c +++ b/src/save.c @@ -3019,6 +3019,100 @@ static void make_schematic(const char *schname) fclose(fd); } +static int order_changed; +static int pin_compare(const void *a, const void *b) +{ + int pinnumber_a, pinnumber_b; + const char *tmp; + int result; + + tmp = get_tok_value(((xRect *)a)->prop_ptr, "sim_pinnumber", 0); + pinnumber_a = tmp[0] ? atoi(tmp) : -1; + tmp = get_tok_value(((xRect *)b)->prop_ptr, "sim_pinnumber", 0); + pinnumber_b = tmp[0] ?atoi(tmp) : -1; + result = pinnumber_a < pinnumber_b ? -1 : pinnumber_a == pinnumber_b ? 0 : 1; + if(result >= 0) order_changed = 1; + return result; +} + +static int schpin_compare(const void *a, const void *b) +{ + int pinnumber_a, pinnumber_b; + int result; + + pinnumber_a = ((Sch_pin_record *) a)->pinnumber; + pinnumber_b = ((Sch_pin_record *) b)->pinnumber; + result = pinnumber_a < pinnumber_b ? -1 : pinnumber_a == pinnumber_b ? 0 : 1; + if(result >= 0) order_changed = 1; + return result; +} + + +static void sort_symbol_pins(xRect *pin_array, int npins, const char *name) +{ + int j, do_sort = 0; + const char *pinnumber; + order_changed = 0; + + if(npins > 0) do_sort = 1; /* no pins, no sort... */ + /* do not sort if some pins don't have pinnumber attribute */ + for(j = 0; j < npins; ++j) { + pinnumber = get_tok_value(pin_array[j].prop_ptr, "sim_pinnumber", 0); + if(!pinnumber[0]) do_sort = 0; + } + if(do_sort) { + qsort(pin_array, npins, sizeof(xRect), pin_compare); + if(order_changed) { + dbg(1, "Symbol %s has pinnumber attributes on pins. Pins will be sorted\n", name); + } + } +} + +/* Caller must free returned pointer (if not NULL) + * number of i/o ports found returned into npins */ +Sch_pin_record *sort_schematic_pins(int *npins) +{ + int i, do_sort = -1; + const char *pinnumber; + Sch_pin_record *pinnumber_list = NULL; + char *type; + int lvs_ignore = tclgetboolvar("lvs_ignore"); + + *npins = 0; + order_changed = 0; + for(i=0;iinstances; ++i) { + if(skip_instance(i, 1, lvs_ignore)) continue; + type = (xctx->inst[i].ptr + xctx->sym)->type; + if( type && IS_PIN(type)) { + (*npins)++; + } + } + pinnumber_list = my_malloc(_ALLOC_ID_, sizeof(Sch_pin_record) * *npins); + *npins = 0; + for(i=0;iinstances; ++i) { + if(skip_instance(i, 1, lvs_ignore)) continue; + type = (xctx->inst[i].ptr + xctx->sym)->type; + if( type && IS_PIN(type)) { + int n; + if(do_sort == -1) do_sort = 1; + pinnumber = get_tok_value(xctx->inst[i].prop_ptr, "sim_pinnumber", 0); + if(!pinnumber[0]) { + do_sort = 0; + n = 0; + } else { + n = atoi(pinnumber); + } + pinnumber_list[*npins].pinnumber = n; + pinnumber_list[*npins].n = i; + (*npins)++; + } + } + if(do_sort) { + qsort(pinnumber_list, *npins, sizeof(Sch_pin_record), schpin_compare); + } + return pinnumber_list; +} + /* ALWAYS call with absolute path in schname!!! */ /* return value: * 0 : did not save @@ -3796,42 +3890,6 @@ static void calc_symbol_bbox(int pos) xctx->sym[pos].maxy = boundbox.y2; } -static int order_changed; -static int pin_compare(const void *a, const void *b) -{ - int pinnumber_a, pinnumber_b; - const char *tmp; - int result; - - tmp = get_tok_value(((xRect *)a)->prop_ptr, "sim_pinnumber", 0); - pinnumber_a = tmp[0] ? atoi(tmp) : -1; - tmp = get_tok_value(((xRect *)b)->prop_ptr, "sim_pinnumber", 0); - pinnumber_b = tmp[0] ?atoi(tmp) : -1; - result = pinnumber_a < pinnumber_b ? -1 : pinnumber_a == pinnumber_b ? 0 : 1; - if(result >= 0) order_changed = 1; - return result; -} - -void sort_symbol_pins(xRect *pin_array, int npins, const char *name) -{ - int j, do_sort = 0; - const char *pinnumber; - order_changed = 0; - - if(npins > 0) do_sort = 1; /* no pins, no sort... */ - /* do not sort if some pins don't have pinnumber attribute */ - for(j = 0; j < npins; ++j) { - pinnumber = get_tok_value(pin_array[j].prop_ptr, "sim_pinnumber", 0); - if(!pinnumber[0]) do_sort = 0; - } - if(do_sort) { - qsort(pin_array, npins, sizeof(xRect), pin_compare); - if(order_changed) { - dbg(1, "Symbol %s has pinnumber attributes on pins. Pins will be sorted\n", name); - } - } -} - /* return 1 if http or https url * return 0 otherwise */ diff --git a/src/spice_netlist.c b/src/spice_netlist.c index d201fc28..63f4b1a1 100644 --- a/src/spice_netlist.c +++ b/src/spice_netlist.c @@ -172,7 +172,7 @@ static int spice_netlist(FILE *fd, int spice_stop ) { int err = 0; int i, flag = 0; - char *type=NULL; + const char *type; int top_sub; int lvs_ignore = tclgetboolvar("lvs_ignore"); @@ -185,7 +185,7 @@ static int spice_netlist(FILE *fd, int spice_stop ) for(i=0;iinstances; ++i) /* print first ipin/opin defs ... */ { if(skip_instance(i, 1, lvs_ignore)) continue; - my_strdup(_ALLOC_ID_, &type,(xctx->inst[i].ptr+ xctx->sym)->type); + type = (xctx->inst[i].ptr+ xctx->sym)->type; if( type && IS_PIN(type) ) { if(top_sub && !flag) { fprintf(fd, "*.PININFO "); @@ -206,7 +206,7 @@ static int spice_netlist(FILE *fd, int spice_stop ) for(i=0;iinstances; ++i) /* ... then print other lines */ { if(skip_instance(i, 1, lvs_ignore)) continue; - my_strdup(_ALLOC_ID_, &type,(xctx->inst[i].ptr+ xctx->sym)->type); + type = (xctx->inst[i].ptr+ xctx->sym)->type; if( type && !IS_LABEL_OR_PIN(type) ) { /* already done in global_spice_netlist */ @@ -242,7 +242,6 @@ static int spice_netlist(FILE *fd, int spice_stop ) } } } - my_free(_ALLOC_ID_, &type); } if(!spice_stop && !xctx->netlist_count) redraw_hilights(0); /* draw_hilight_net(1); */ return err; @@ -257,7 +256,7 @@ int global_spice_netlist(int global) /* netlister driver */ int multip; unsigned int *stored_flags; int i; - char *type=NULL; + const char *type; char *place=NULL; char netl_filename[PATH_MAX]; /* overflow safe 20161122 */ char tcl_cmd_netlist[PATH_MAX + 100]; /* 20081211 overflow safe 20161122 */ @@ -276,6 +275,8 @@ int global_spice_netlist(int global) /* netlister driver */ * top_symbol_name == 1: a symbol file matching schematic has been found. * top_symbol_name == 3: the found symbol has type=subcircuit and has ports */ int found_top_symbol = 0; + int npins = 0; /* top schematic number of i/o ports */ + Sch_pin_record *pinnumber_list = NULL; /* list of top sch i/o ports ordered wrt sim_pinnumber attr */ exit_code = 0; /* reset exit code */ split_f = tclgetboolvar("split_files"); @@ -314,7 +315,7 @@ int global_spice_netlist(int global) /* netlister driver */ for(i=0;iinstances; ++i) /* print netlist_commands of top level cell with 'place=header' property */ { if(skip_instance(i, 1, lvs_ignore)) continue; - my_strdup(_ALLOC_ID_, &type,(xctx->inst[i].ptr+ xctx->sym)->type); + type = (xctx->inst[i].ptr+ xctx->sym)->type; my_strdup(_ALLOC_ID_, &place,get_tok_value((xctx->inst[i].ptr+ xctx->sym)->prop_ptr,"place",0)); if( type && !strcmp(type,"netlist_commands") ) { if(!place) { @@ -340,6 +341,7 @@ int global_spice_netlist(int global) /* netlister driver */ top_sub = tclgetboolvar("lvs_netlist"); if(!top_sub) fprintf(fd,"**"); fprintf(fd,".subckt %s", get_cell(xctx->sch[xctx->currsch], 0)); + pinnumber_list = sort_schematic_pins(&npins); /* sort pins according to sim_pinnumber attr */ /* print top subckt ipin/opins */ my_strdup2(_ALLOC_ID_, &top_symbol_name, abs_sym_path(add_ext(xctx->current_name, ".sym"), "")); @@ -360,16 +362,14 @@ int global_spice_netlist(int global) /* netlister driver */ } my_free(_ALLOC_ID_, &top_symbol_name); if(found_top_symbol != 3) { - for(i=0;iinstances; ++i) { - if(skip_instance(i, 1, lvs_ignore)) continue; - my_strdup(_ALLOC_ID_, &type,(xctx->inst[i].ptr+ xctx->sym)->type); - if( type && IS_PIN(type)) { - str_tmp = expandlabel ( (xctx->inst[i].lab ? xctx->inst[i].lab : ""), &multip); - /*must handle invalid node names */ - fprintf(fd, " %s", str_tmp ? str_tmp : "(NULL)" ); - } + for(i=0;iinst[n].lab ? xctx->inst[n].lab : ""), &multip); + /*must handle invalid node names */ + fprintf(fd, " %s", str_tmp ? str_tmp : "(NULL)" ); } } + my_free(_ALLOC_ID_, &pinnumber_list); fprintf(fd,"\n"); err |= spice_netlist(fd, 0); @@ -379,7 +379,7 @@ int global_spice_netlist(int global) /* netlister driver */ and no place=header */ { if(skip_instance(i, 1, lvs_ignore)) continue; - my_strdup(_ALLOC_ID_, &type,(xctx->inst[i].ptr+ xctx->sym)->type); + type = (xctx->inst[i].ptr+ xctx->sym)->type; my_strdup(_ALLOC_ID_, &place,get_tok_value((xctx->inst[i].ptr+ xctx->sym)->prop_ptr,"place",0)); if( type && !strcmp(type,"netlist_commands") ) { if(!place) { @@ -534,7 +534,7 @@ int global_spice_netlist(int global) /* netlister driver */ for(i=0;iinstances; ++i) /* print netlist_commands of top level cell with 'place=end' property */ { if(skip_instance(i, 1, lvs_ignore)) continue; - my_strdup(_ALLOC_ID_, &type,(xctx->inst[i].ptr+ xctx->sym)->type); + type = (xctx->inst[i].ptr+ xctx->sym)->type; my_strdup(_ALLOC_ID_, &place,get_tok_value((xctx->inst[i].ptr+ xctx->sym)->prop_ptr,"place",0)); if( type && !strcmp(type,"netlist_commands") ) { if(place && !strcmp(place, "end" )) { @@ -586,7 +586,6 @@ int global_spice_netlist(int global) /* netlister driver */ } if(!debug_var) xunlink(netl_filename); } - my_free(_ALLOC_ID_, &type); my_free(_ALLOC_ID_, &place); xctx->netlist_count = 0; tclvareval("show_infotext ", my_itoa(err), NULL); /* critical error: force ERC window showing */ diff --git a/src/xschem.h b/src/xschem.h index 625a7c96..e9551d32 100644 --- a/src/xschem.h +++ b/src/xschem.h @@ -637,6 +637,12 @@ typedef struct double zoom; } Zoom; +typedef struct /* used to sort schematic pins (if no asssociated symbol exists) */ +{ + int n; + int pinnumber; +} Sch_pin_record; + typedef struct { @@ -1329,7 +1335,6 @@ extern const char *sanitize(const char *name); extern const char *add_ext(const char *f, const char *ext); extern void make_symbol(void); /* sort based on pinnumber pin attribute if present */ -extern void sort_symbol_pins(xRect *pin_array, int npins, const char *name); extern void make_schematic_symbol_from_sel(void); extern const char *get_sym_template(char *s, char *extra); /* bit0: invoke change_linewidth(), bit1: centered zoom */ @@ -1488,6 +1493,7 @@ extern void delete_files(void); extern int sym_vs_sch_pins(int all); extern char *get_generator_command(const char *str); extern int match_symbol(const char name[]); +extern Sch_pin_record *sort_schematic_pins(int *npins); extern int save_schematic(const char *); /* 20171020 added return value */ extern void copy_symbol(xSymbol *dest_sym, xSymbol *src_sym); extern void push_undo(void);