gnetlist
|
00001 /* gEDA - GPL Electronic Design Automation 00002 * gnetlist - gEDA Netlist 00003 * Copyright (C) 1998-2010 Ales Hvezda 00004 * Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details) 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00019 */ 00020 00021 #include <config.h> 00022 #include <missing.h> 00023 00024 #include <stdio.h> 00025 #include <ctype.h> 00026 #ifdef HAVE_STRING_H 00027 #include <string.h> 00028 #endif 00029 #ifdef HAVE_STDLIB_H 00030 #include <stdlib.h> 00031 #endif 00032 #ifdef HAVE_ASSERT_H 00033 #include <assert.h> 00034 #endif 00035 00036 #include <libgeda/libgeda.h> 00037 00038 #include "../include/globals.h" 00039 #include "../include/prototype.h" 00040 00041 #ifdef HAVE_LIBDMALLOC 00042 #include <dmalloc.h> 00043 #endif 00044 00045 static int unnamed_net_counter = 1; 00046 static int unnamed_bus_counter = 1; 00047 static int unnamed_pin_counter = 1; 00048 00049 #define MAX_UNNAMED_NETS 99999999 00050 #define MAX_UNNAMED_PINS 99999999 00051 00052 /* hack rename this to be s_return_tail */ 00053 /* update object_tail or any list of that matter */ 00054 NET *s_net_return_tail(NET * head) 00055 { 00056 NET *n_current = NULL; 00057 NET *ret_struct = NULL; 00058 00059 n_current = head; 00060 while (n_current != NULL) { /* goto end of list */ 00061 ret_struct = n_current; 00062 n_current = n_current->next; 00063 } 00064 00065 return (ret_struct); 00066 } 00067 00068 /* hack rename this to be s_return_head */ 00069 /* update object_tail or any list of that matter */ 00070 NET *s_net_return_head(NET * tail) 00071 { 00072 NET *n_current = NULL; 00073 NET *ret_struct = NULL; 00074 00075 n_current = tail; 00076 while (n_current != NULL) { /* goto end of list */ 00077 ret_struct = n_current; 00078 n_current = n_current->prev; 00079 } 00080 00081 return (ret_struct); 00082 } 00083 00084 00085 NET *s_net_add(NET * ptr) 00086 { 00087 NET *new_node; 00088 00089 new_node = (NET *) g_malloc(sizeof(NET)); 00090 00091 /* setup node information */ 00092 new_node->net_name = NULL; 00093 new_node->pin_label = NULL; 00094 new_node->net_name_has_priority = FALSE; 00095 new_node->nid = 0; 00096 new_node->connected_to = NULL; 00097 00098 /* Setup link list stuff */ 00099 new_node->next = NULL; 00100 00101 if (ptr == NULL) { 00102 new_node->prev = NULL; /* setup previous link */ 00103 return (new_node); 00104 } else { 00105 new_node->prev = ptr; /* setup previous link */ 00106 ptr->next = new_node; 00107 return (ptr->next); 00108 } 00109 } 00110 00111 void s_net_print(NET * ptr) 00112 { 00113 NET *n_current = NULL; 00114 00115 n_current = ptr; 00116 00117 if (n_current == NULL) { 00118 return; 00119 } 00120 00121 while (n_current != NULL) { 00122 00123 if (n_current->nid != -1) { 00124 00125 #if DEBUG 00126 if (n_current->net_name) { 00127 printf(" %s [%d]\n", n_current->net_name, n_current->nid); 00128 } 00129 #endif 00130 00131 if (n_current->connected_to) { 00132 printf(" %s [%d]\n", n_current->connected_to, n_current->nid); 00133 } 00134 } 00135 00136 n_current = n_current->next; 00137 } 00138 } 00139 00140 00141 /* object being a pin */ 00142 char *s_net_return_connected_string(TOPLEVEL * pr_current, OBJECT * object, 00143 char *hierarchy_tag) 00144 { 00145 OBJECT *o_current; 00146 char *pinnum = NULL; 00147 char *uref = NULL; 00148 SCM scm_uref; 00149 char *temp_uref = NULL; 00150 char *string; 00151 char *misc; 00152 00153 o_current = object; 00154 00155 pinnum = o_attrib_search_object_attribs_by_name (o_current, "pinnumber", 0); 00156 00157 #if DEBUG 00158 printf("found pinnum: %s\n", pinnum); 00159 #endif 00160 00161 scm_uref = g_scm_c_get_uref(pr_current, o_current->parent); 00162 00163 if (scm_is_string( scm_uref )) { 00164 temp_uref = scm_to_utf8_string (scm_uref); 00165 } 00166 00167 /* apply the hierarchy name to the uref */ 00168 uref = s_hierarchy_create_uref(pr_current, temp_uref, hierarchy_tag); 00169 00170 if (uref && pinnum) { 00171 string = g_strdup_printf("%s %s", uref, pinnum); 00172 } else { 00173 if (pinnum) { 00174 string = g_strdup_printf("POWER %s", pinnum); 00175 } else { 00176 if (hierarchy_tag) { 00177 misc = 00178 s_hierarchy_create_uref(pr_current, "U?", 00179 hierarchy_tag); 00180 string = g_strdup_printf("%s ?", misc); 00181 g_free(misc); 00182 } else { 00183 string = g_strdup("U? ?"); 00184 } 00185 00186 fprintf(stderr, "Missing Attributes (refdes and pin number)\n"); 00187 } 00188 } 00189 00190 g_free(pinnum); 00191 00192 g_free(uref); 00193 00194 g_free(temp_uref); 00195 00196 return (string); 00197 } 00198 00199 int s_net_find(NET * net_head, NET * node) 00200 { 00201 NET *n_current; 00202 00203 n_current = net_head; 00204 while (n_current != NULL) { 00205 if (n_current->nid == node->nid) { 00206 return (TRUE); 00207 } 00208 00209 n_current = n_current->next; 00210 } 00211 return (FALSE); 00212 } 00213 00214 char *s_net_name_search(TOPLEVEL * pr_current, NET * net_head) 00215 { 00216 NET *n_current; 00217 char *name = NULL; 00218 00219 n_current = net_head; 00220 00221 00222 while (n_current != NULL) { 00223 00224 if (n_current->net_name) { 00225 00226 if (name == NULL) { 00227 00228 name = n_current->net_name; 00229 00230 } else if (strcmp(name, n_current->net_name) != 0) { 00231 00232 00233 #if DEBUG 00234 fprintf(stderr, "Found a net with two names!\n"); 00235 fprintf(stderr, "Net called: [%s] and [%s]\n", 00236 name, n_current->net_name); 00237 #endif 00238 00239 00240 /* only rename if this net name has priority */ 00241 /* AND, you are using net= attributes as the */ 00242 /* netnames which have priority */ 00243 if (pr_current->net_naming_priority == NETATTRIB_ATTRIBUTE) { 00244 00245 #if DEBUG 00246 printf("\nNETATTRIB_ATTRIBUTE\n"); 00247 #endif 00248 if (n_current->net_name_has_priority) { 00249 00250 #if DEBUG 00251 fprintf(stderr, "Net is now called: [%s]\n", 00252 n_current->net_name); 00253 00254 /* this show how to rename nets */ 00255 printf("\nRENAME all nets: %s -> %s\n", name, 00256 n_current->net_name); 00257 #endif 00258 s_rename_add(name, n_current->net_name); 00259 00260 name = n_current->net_name; 00261 00262 } else { 00263 00264 #if DEBUG 00265 printf 00266 ("\nFound a net name called [%s], but it doesn't have priority\n", 00267 n_current->net_name); 00268 #endif 00269 00270 /* do the rename anyways, this might cause problems */ 00271 /* this will rename net which have the same label= */ 00272 if (!s_rename_search 00273 (name, n_current->net_name, TRUE)) { 00274 fprintf(stderr, 00275 "Found duplicate net name, renaming [%s] to [%s]\n", 00276 name, n_current->net_name); 00277 s_rename_add(name, n_current->net_name); 00278 name = n_current->net_name; 00279 } 00280 } 00281 00282 } else { /* NETNAME_ATTRIBUTE */ 00283 00284 #if DEBUG 00285 printf("\nNETNAME_ATTRIBUTE\n"); 00286 #endif 00287 00288 /* here we want to rename the net */ 00289 /* that has priority to the label */ 00290 /* name */ 00291 if (n_current->net_name_has_priority) { 00292 00293 #if DEBUG /* this shows how to rename nets */ 00294 printf("\nRENAME all nets: %s -> %s (priority)\n", 00295 n_current->net_name, name); 00296 #endif 00297 00298 s_rename_add(n_current->net_name, name); 00299 00300 } else { 00301 00302 #if DEBUG /* this shows how to rename nets */ 00303 printf 00304 ("\nRENAME all nets: %s -> %s (not priority)\n", 00305 name, n_current->net_name); 00306 #endif 00307 /* do the rename anyways, this might cause problems */ 00308 /* this will rename net which have the same label= */ 00309 if (!s_rename_search 00310 (name, n_current->net_name, TRUE)) { 00311 fprintf(stderr, 00312 "Found duplicate net name, renaming [%s] to [%s]\n", 00313 name, n_current->net_name); 00314 00315 s_rename_add(name, n_current->net_name); 00316 name = n_current->net_name; 00317 } 00318 } 00319 00320 #if DEBUG 00321 fprintf(stderr, "Net is now called: [%s]\n", name); 00322 #endif 00323 00324 } 00325 } 00326 } 00327 00328 n_current = n_current->next; 00329 } 00330 00331 if (name) { 00332 return (name); 00333 } else { 00334 return (NULL); 00335 } 00336 } 00337 00338 char *s_net_name (TOPLEVEL * pr_current, NETLIST * netlist_head, 00339 NET * net_head, char *hierarchy_tag, int type) 00340 { 00341 char *string = NULL; 00342 NET *n_start; 00343 NETLIST *nl_current; 00344 CPINLIST *pl_current; 00345 char *net_name = NULL; 00346 int found = 0; 00347 char *temp; 00348 int *unnamed_counter; 00349 char *unnamed_string; 00350 00351 net_name = s_net_name_search(pr_current, net_head); 00352 00353 if (net_name) { 00354 return (net_name); 00355 } 00356 00357 #if DEBUG 00358 printf("didn't find named net\n"); 00359 #endif 00360 00361 /* didn't find a name */ 00362 /* go looking for another net which might have already been named */ 00363 /* ie you don't want to create a new unnamed net if the net has */ 00364 /* already been named */ 00365 nl_current = netlist_head; 00366 while (nl_current != NULL) { 00367 if (nl_current->cpins) { 00368 pl_current = nl_current->cpins; 00369 while (pl_current != NULL) { 00370 if (pl_current->nets) { 00371 n_start = pl_current->nets; 00372 if (n_start->next && net_head->next) { 00373 found = s_net_find(n_start->next, net_head->next); 00374 00375 if (found) { 00376 net_name = 00377 s_net_name_search(pr_current, n_start); 00378 if (net_name) { 00379 return (net_name); 00380 } 00381 00382 } 00383 } 00384 } 00385 00386 pl_current = pl_current->next; 00387 } 00388 } 00389 nl_current = nl_current->next; 00390 } 00391 00392 00393 #if DEBUG 00394 printf("didn't find previously named\n"); 00395 #endif 00396 00397 /* AND we don't want to assign a dangling pin */ 00398 /* which is signified by having only a head node */ 00399 /* which is just a place holder */ 00400 /* and the head node shows up here */ 00401 00402 if (net_head->nid == -1 && net_head->prev == NULL 00403 && net_head->next == NULL) { 00404 string = g_strdup_printf("unconnected_pin-%d", 00405 unnamed_pin_counter++); 00406 00407 return (string); 00408 00409 } 00410 00411 switch (type) { 00412 case PIN_TYPE_NET: 00413 unnamed_counter = &unnamed_net_counter; 00414 unnamed_string = pr_current->unnamed_netname; 00415 break; 00416 case PIN_TYPE_BUS: 00417 unnamed_counter = &unnamed_bus_counter; 00418 unnamed_string = pr_current->unnamed_busname; 00419 break; 00420 default: 00421 g_critical ("Incorrect connectivity type %i in s_name_nets()\n", type); 00422 return NULL; 00423 } 00424 00425 /* have we exceeded the number of unnamed nets? */ 00426 if (*unnamed_counter < MAX_UNNAMED_NETS) { 00427 00428 if (netlist_mode == SPICE) { 00429 string = g_strdup_printf("%d", (*unnamed_counter)++); 00430 } else { 00431 temp = g_strdup_printf ("%s%d", unnamed_string, (*unnamed_counter)++); 00432 if (hierarchy_tag) { 00433 string = s_hierarchy_create_netname (pr_current, temp, hierarchy_tag); 00434 g_free (temp); 00435 } else { 00436 string = temp; 00437 } 00438 } 00439 00440 } else { 00441 fprintf(stderr, "Increase number of unnamed nets (s_net.c)\n"); 00442 exit(-1); 00443 } 00444 00445 return string; 00446 00447 }