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
This commit is contained in:
parent
5969b0f472
commit
9f368d32e5
130
src/save.c
130
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;i<xctx->instances; ++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;i<xctx->instances; ++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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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;i<xctx->instances; ++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;i<xctx->instances; ++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;i<xctx->instances; ++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;i<xctx->instances; ++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;i<npins; ++i) {
|
||||
int n = pinnumber_list[i].n;
|
||||
str_tmp = expandlabel ( (xctx->inst[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;i<xctx->instances; ++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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue