xschem/src/tedax_netlist.c

242 lines
8.5 KiB
C
Raw Normal View History

2020-08-08 15:47:34 +02:00
/* File: tedax_netlist.c
*
2020-08-08 15:47:34 +02:00
* This file is part of XSCHEM,
* a schematic capture and Spice/Vhdl/Verilog netlisting tool for circuit
2020-08-08 15:47:34 +02:00
* simulation.
* Copyright (C) 1998-2020 Stefan Frederik Schippers
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xschem.h"
void global_tedax_netlist(int global) /* netlister driver */
{
FILE *fd;
const char *str_tmp;
2020-08-08 15:47:34 +02:00
int i, save_ok;
unsigned int *stored_flags;
char netl_filename[PATH_MAX]; /* overflow safe 20161122 */
char tcl_cmd_netlist[PATH_MAX + 100]; /* 20081211 overflow safe 20161122 */
char cellname[PATH_MAX]; /* 20081211 overflow safe 20161122 */
2020-12-02 15:10:47 +01:00
if(xctx->modified) {
save_ok = save_schematic(xctx->sch[xctx->currsch]);
2020-08-08 15:47:34 +02:00
if(save_ok == -1) return;
}
statusmsg("",2); /* clear infowindow */
record_global_node(2, NULL, NULL); /* delete list of global nodes */
2020-12-02 19:35:42 +01:00
bus_char[0] = bus_char[1] = '\0';
hiersep[0]='.'; hiersep[1]='\0';
str_tmp = tclgetvar("bus_replacement_char");
if(str_tmp && str_tmp[0] && str_tmp[1]) {
2020-12-02 19:35:42 +01:00
bus_char[0] = str_tmp[0];
bus_char[1] = str_tmp[1];
}
2020-08-08 15:47:34 +02:00
netlist_count=0;
2020-11-17 01:29:47 +01:00
my_snprintf(netl_filename, S(netl_filename), "%s/.%s_%d",
netlist_dir, skip_dir(xctx->sch[xctx->currsch]), getpid());
2020-08-08 15:47:34 +02:00
fd=fopen(netl_filename, "w");
2020-12-02 15:10:47 +01:00
if(xctx->netlist_name[0]) {
my_snprintf(cellname, S(cellname), "%s", get_cell(xctx->netlist_name, 0));
2020-08-08 15:47:34 +02:00
} else {
my_snprintf(cellname, S(cellname), "%s.tdx", skip_dir(xctx->sch[xctx->currsch]));
2020-08-08 15:47:34 +02:00
}
if(fd==NULL){
2020-08-08 15:47:34 +02:00
dbg(0, "global_tedax_netlist(): problems opening netlist file\n");
return;
}
/* netlist_options */
for(i=0;i<xctx->instances;i++) {
if(!(xctx->inst[i].ptr+ xctx->sym)->type) continue;
if( !strcmp((xctx->inst[i].ptr+ xctx->sym)->type,"netlist_options") ) {
netlist_options(i);
}
}
2020-08-08 15:47:34 +02:00
dbg(1, "global_tedax_netlist(): opening %s for writing\n",netl_filename);
fprintf(fd,"tEDAx v1\nbegin netlist v1 %s\n", skip_dir( xctx->sch[xctx->currsch]) );
2020-08-08 15:47:34 +02:00
tedax_netlist(fd, 0);
netlist_count++;
2020-08-08 15:47:34 +02:00
/*fprintf(fd,"**** begin user architecture code\n"); */
/*if(xctx->schprop && xctx->schprop[0]) fprintf(fd, "%s\n", xctx->schprop); */
2020-08-08 15:47:34 +02:00
/*fprintf(fd,"**** end user architecture code\n"); */
/* /20100217 */
fprintf(fd, "end netlist\n");
/* preserve current level instance flags before descending hierarchy for netlisting, restore later */
stored_flags = my_calloc(149, xctx->instances, sizeof(unsigned int));
for(i=0;i<xctx->instances;i++) stored_flags[i] = xctx->inst[i].flags & 4;
2020-08-08 15:47:34 +02:00
if(global) /* was if(global) ... 20180901 no hierarchical tEDAx netlist for now */
2020-08-08 15:47:34 +02:00
{
unselect_all();
remove_symbols(); /* 20161205 ensure all unused symbols purged before descending hierarchy */
load_schematic(1, xctx->sch[xctx->currsch], 0);
2020-08-08 15:47:34 +02:00
my_strdup(482, &xctx->sch_path[xctx->currsch+1], xctx->sch_path[xctx->currsch]);
my_strcat(485, &xctx->sch_path[xctx->currsch+1], "->netlisting");
xctx->currsch++;
dbg(2, "global_tedax_netlist(): last defined symbol=%d\n",xctx->symbols);
for(i=0;i<xctx->symbols;i++)
2020-08-08 15:47:34 +02:00
{
if( strcmp(get_tok_value(xctx->sym[i].prop_ptr,"tedax_ignore",0),"true")==0 ) continue;
if(!xctx->sym[i].type) continue;
if(strcmp(xctx->sym[i].type,"subcircuit")==0 && check_lib(xctx->sym[i].name))
2020-08-08 15:47:34 +02:00
{
tedax_block_netlist(fd, i);
2020-08-08 15:47:34 +02:00
}
}
/*clear_drawing(); */
my_strncpy(xctx->sch[xctx->currsch] , "", S(xctx->sch[xctx->currsch]));
xctx->currsch--;
2020-08-08 15:47:34 +02:00
unselect_all();
/* remove_symbols(); */
load_schematic(1, xctx->sch[xctx->currsch], 0);
2020-08-08 15:47:34 +02:00
prepare_netlist_structs(1); /* so 'lab=...' attributes for unnamed nets are set */
/* symbol vs schematic pin check, we do it here since now we have ALL symbols loaded */
sym_vs_sch_pins();
/* restore hilight flags from errors found analyzing top level before descending hierarchy */
for(i=0;i<xctx->instances; i++) xctx->inst[i].flags |= stored_flags[i];
2020-08-08 15:47:34 +02:00
draw_hilight_net(1);
}
my_free(965, &stored_flags);
/* print globals nodes found in netlist 28032003 */
record_global_node(0,fd,NULL);
fprintf(fd, "__HIERSEP__ %s\n", hiersep);
2020-08-08 15:47:34 +02:00
dbg(1, "global_tedax_netlist(): starting awk on netlist!\n");
fclose(fd);
if(netlist_show) {
my_snprintf(tcl_cmd_netlist, S(tcl_cmd_netlist), "netlist {%s} show {%s}", netl_filename, cellname);
tcleval(tcl_cmd_netlist);
}
else {
my_snprintf(tcl_cmd_netlist, S(tcl_cmd_netlist), "netlist {%s} noshow {%s}", netl_filename, cellname);
tcleval(tcl_cmd_netlist);
}
if(!debug_var) xunlink(netl_filename);
netlist_count = 0;
2020-08-08 15:47:34 +02:00
}
void tedax_block_netlist(FILE *fd, int i)
2020-08-08 15:47:34 +02:00
{
int tedax_stop=0;
2020-08-08 15:47:34 +02:00
char filename[PATH_MAX];
const char *str_tmp;
char *extra=NULL;
if(!strcmp( get_tok_value(xctx->sym[i].prop_ptr,"tedax_stop",0),"true") )
2020-08-08 15:47:34 +02:00
tedax_stop=1;
else
tedax_stop=0;
fprintf(fd, "\n# expanding symbol: %s # of pins=%d\n\n",
xctx->sym[i].name,xctx->sym[i].rects[PINLAYER] );
fprintf(fd, "begin netlist v1 %s\n",skip_dir(xctx->sym[i].name));
print_tedax_subckt(fd, i);
my_strdup(420, &extra, get_tok_value(xctx->sym[i].prop_ptr,"extra",0) );
/* this is now done in print_spice_subckt */
/*
* fprintf(fd, "%s ", extra ? extra : "" );
*/
2020-08-08 15:47:34 +02:00
/* 20081206 new get_sym_template does not return token=value pairs where token listed in extra */
fprintf(fd, "%s", get_sym_template(xctx->sym[i].templ, extra));
2020-08-08 15:47:34 +02:00
my_free(966, &extra);
fprintf(fd, "\n");
if((str_tmp = get_tok_value(xctx->sym[i].prop_ptr, "schematic",0 ))[0]) {
2020-08-08 15:47:34 +02:00
my_strncpy(filename, abs_sym_path(str_tmp, ""), S(filename));
load_schematic(1,filename, 0);
} else {
dbg(1, "tedax_block_netlist(): loading: %s -> %s\n",
xctx->sym[i].name, add_ext(abs_sym_path(xctx->sym[i].name, ""), ".sch"));
dbg(1, "tedax_block_netlist(): current_dirname=%s\n", xctx->current_dirname);
load_schematic(1, add_ext(abs_sym_path(xctx->sym[i].name, ""), ".sch"), 0);
2020-08-08 15:47:34 +02:00
}
tedax_netlist(fd, tedax_stop);
2020-08-08 15:47:34 +02:00
netlist_count++;
if(xctx->schprop && xctx->schprop[0]) {
fprintf(fd,"#**** begin user architecture code\n");
fprintf(fd, "%s\n", xctx->schprop);
fprintf(fd,"#**** end user architecture code\n");
2020-08-08 15:47:34 +02:00
}
fprintf(fd, "end netlist\n\n");
2020-08-08 15:47:34 +02:00
}
void tedax_netlist(FILE *fd, int tedax_stop )
{
int i;
char *type=NULL;
2020-12-02 15:10:47 +01:00
xctx->prep_net_structs = 0;
2020-08-08 15:47:34 +02:00
prepare_netlist_structs(1);
traverse_node_hash(); /* print all warnings about unconnected floatings etc */
if(!tedax_stop) {
for(i=0;i<xctx->instances;i++) /* print first ipin/opin defs ... */
2020-08-08 15:47:34 +02:00
{
if( strcmp(get_tok_value(xctx->inst[i].prop_ptr,"tedax_ignore",0),"true")==0 ) continue;
if(xctx->inst[i].ptr<0) continue;
if(!strcmp(get_tok_value( (xctx->inst[i].ptr+ xctx->sym)->prop_ptr, "tedax_ignore",0 ), "true") ) {
2020-08-08 15:47:34 +02:00
continue;
}
my_strdup(421, &type,(xctx->inst[i].ptr+ xctx->sym)->type);
if( type && IS_PIN(type) ) {
2020-08-08 15:47:34 +02:00
print_tedax_element(fd, i) ; /* this is the element line */
}
}
for(i=0;i<xctx->instances;i++) /* ... then print other lines */
2020-08-08 15:47:34 +02:00
{
if( strcmp(get_tok_value(xctx->inst[i].prop_ptr,"tedax_ignore",0),"true")==0 ) continue;
if(xctx->inst[i].ptr<0) continue;
if(!strcmp(get_tok_value( (xctx->inst[i].ptr+ xctx->sym)->prop_ptr, "tedax_ignore",0 ), "true") ) {
continue;
}
my_strdup(423, &type,(xctx->inst[i].ptr+ xctx->sym)->type);
if( type && !IS_LABEL_OR_PIN(type) ) {
2020-12-02 15:10:47 +01:00
/* already done in global_tedax_netlist */
if(!strcmp(type,"netlist_commands") && netlist_count==0) continue;
if(netlist_count &&
!strcmp(get_tok_value(xctx->inst[i].prop_ptr, "only_toplevel", 0), "true")) continue;
if(!strcmp(type,"netlist_commands")) {
fprintf(fd,"#**** begin user architecture code\n");
print_tedax_element(fd, i) ; /* this is the element line */
fprintf(fd,"#**** end user architecture code\n");
} else {
print_tedax_element(fd, i) ; /* this is the element line */
}
2020-08-08 15:47:34 +02:00
}
}
}
if(!netlist_count) redraw_hilights(); /* draw_hilight_net(1); */
my_free(967, &type);
}