Fix o_net_consolidate_segments() to consolidate with all joined lines
[geda-gaf/pcjc2.git] / gnetlist / src / s_net.c
bloba9f43d05053671eb9a34b162df854aedcdc5425d
1 /* gEDA - GPL Electronic Design Automation
2 * gnetlist - gEDA Netlist
3 * Copyright (C) 1998-2010 Ales Hvezda
4 * Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include <config.h>
22 #include <missing.h>
24 #include <stdio.h>
25 #include <ctype.h>
26 #ifdef HAVE_STRING_H
27 #include <string.h>
28 #endif
29 #ifdef HAVE_STDLIB_H
30 #include <stdlib.h>
31 #endif
32 #ifdef HAVE_ASSERT_H
33 #include <assert.h>
34 #endif
36 #include <libgeda/libgeda.h>
38 #include "../include/globals.h"
39 #include "../include/prototype.h"
40 #include "../include/gettext.h"
42 #ifdef HAVE_LIBDMALLOC
43 #include <dmalloc.h>
44 #endif
46 static int unnamed_net_counter = 1;
47 static int unnamed_bus_counter = 1;
48 static int unnamed_pin_counter = 1;
50 #define MAX_UNNAMED_NETS 99999999
51 #define MAX_UNNAMED_PINS 99999999
53 /* hack rename this to be s_return_tail */
54 /* update object_tail or any list of that matter */
55 NET *s_net_return_tail(NET * head)
57 NET *n_current = NULL;
58 NET *ret_struct = NULL;
60 n_current = head;
61 while (n_current != NULL) { /* goto end of list */
62 ret_struct = n_current;
63 n_current = n_current->next;
66 return (ret_struct);
69 /* hack rename this to be s_return_head */
70 /* update object_tail or any list of that matter */
71 NET *s_net_return_head(NET * tail)
73 NET *n_current = NULL;
74 NET *ret_struct = NULL;
76 n_current = tail;
77 while (n_current != NULL) { /* goto end of list */
78 ret_struct = n_current;
79 n_current = n_current->prev;
82 return (ret_struct);
86 NET *s_net_add(NET * ptr)
88 NET *new_node;
90 new_node = (NET *) g_malloc(sizeof(NET));
92 /* setup node information */
93 new_node->net_name = NULL;
94 new_node->pin_label = NULL;
95 new_node->net_name_has_priority = FALSE;
96 new_node->nid = 0;
97 new_node->connected_to = NULL;
99 /* Setup link list stuff */
100 new_node->next = NULL;
102 if (ptr == NULL) {
103 new_node->prev = NULL; /* setup previous link */
104 return (new_node);
105 } else {
106 new_node->prev = ptr; /* setup previous link */
107 ptr->next = new_node;
108 return (ptr->next);
112 void s_net_print(NET * ptr)
114 NET *n_current = NULL;
116 n_current = ptr;
118 if (n_current == NULL) {
119 return;
122 while (n_current != NULL) {
124 if (n_current->nid != -1) {
126 #if DEBUG
127 if (n_current->net_name) {
128 printf(" %s [%d]\n", n_current->net_name, n_current->nid);
130 #endif
132 if (n_current->connected_to) {
133 printf(" %s [%d]\n", n_current->connected_to, n_current->nid);
137 n_current = n_current->next;
142 /* object being a pin */
143 char *s_net_return_connected_string(TOPLEVEL * pr_current, OBJECT * object,
144 char *hierarchy_tag)
146 OBJECT *o_current;
147 char *pinnum = NULL;
148 char *uref = NULL;
149 SCM scm_uref;
150 char *temp_uref = NULL;
151 char *string;
152 char *misc;
154 o_current = object;
156 pinnum = o_attrib_search_object_attribs_by_name (o_current, "pinnumber", 0);
158 #if DEBUG
159 printf("found pinnum: %s\n", pinnum);
160 #endif
162 scm_uref = g_scm_c_get_uref(pr_current, o_current->parent);
164 if (scm_is_string( scm_uref )) {
165 temp_uref = scm_to_utf8_string (scm_uref);
168 /* apply the hierarchy name to the uref */
169 uref = s_hierarchy_create_uref(pr_current, temp_uref, hierarchy_tag);
171 if (uref && pinnum) {
172 string = g_strdup_printf("%s %s", uref, pinnum);
173 } else {
174 if (pinnum) {
175 string = g_strdup_printf("POWER %s", pinnum);
176 } else {
177 if (hierarchy_tag) {
178 misc =
179 s_hierarchy_create_uref(pr_current, "U?",
180 hierarchy_tag);
181 string = g_strdup_printf("%s ?", misc);
182 g_free(misc);
183 } else {
184 string = g_strdup("U? ?");
187 fprintf(stderr, _("Missing Attributes (refdes and pin number)\n"));
191 g_free(pinnum);
193 g_free(uref);
195 g_free(temp_uref);
197 return (string);
200 int s_net_find(NET * net_head, NET * node)
202 NET *n_current;
204 n_current = net_head;
205 while (n_current != NULL) {
206 if (n_current->nid == node->nid) {
207 return (TRUE);
210 n_current = n_current->next;
212 return (FALSE);
215 char *s_net_name_search(TOPLEVEL * pr_current, NET * net_head)
217 NET *n_current;
218 char *name = NULL;
219 EdaConfig *cfg;
220 gint net_naming_priority;
221 gchar *str;
223 enum NetNamingPriority {
224 NETNAME_ATTRIBUTE,
225 NETATTRIB_ATTRIBUTE,
228 cfg = eda_config_get_context_for_file (NULL);
229 str = eda_config_get_string (cfg, "gnetlist", "net-naming-priority", NULL);
230 if (g_strcmp0 (str, "netname-attribute") == 0) {
231 net_naming_priority = NETNAME_ATTRIBUTE;
232 } else {
233 net_naming_priority = NETATTRIB_ATTRIBUTE;
235 g_free (str);
237 n_current = net_head;
240 while (n_current != NULL) {
242 if (n_current->net_name) {
244 if (name == NULL) {
246 name = n_current->net_name;
248 } else if (strcmp(name, n_current->net_name) != 0) {
251 #if DEBUG
252 fprintf(stderr, "Found a net with two names!\n");
253 fprintf(stderr, "Net called: [%s] and [%s]\n",
254 name, n_current->net_name);
255 #endif
258 /* only rename if this net name has priority */
259 /* AND, you are using net= attributes as the */
260 /* netnames which have priority */
261 if (net_naming_priority == NETATTRIB_ATTRIBUTE) {
263 #if DEBUG
264 printf("\nNETATTRIB_ATTRIBUTE\n");
265 #endif
266 if (n_current->net_name_has_priority) {
268 #if DEBUG
269 fprintf(stderr, "Net is now called: [%s]\n",
270 n_current->net_name);
272 /* this show how to rename nets */
273 printf("\nRENAME all nets: %s -> %s\n", name,
274 n_current->net_name);
275 #endif
276 s_rename_add(name, n_current->net_name);
278 name = n_current->net_name;
280 } else {
282 #if DEBUG
283 printf
284 ("\nFound a net name called [%s], but it doesn't have priority\n",
285 n_current->net_name);
286 #endif
288 /* do the rename anyways, this might cause problems */
289 /* this will rename net which have the same label= */
290 if (!s_rename_search
291 (name, n_current->net_name, TRUE)) {
292 fprintf(stderr,
293 _("Found duplicate net name, renaming [%s] to [%s]\n"),
294 name, n_current->net_name);
295 s_rename_add(name, n_current->net_name);
296 name = n_current->net_name;
300 } else { /* NETNAME_ATTRIBUTE */
302 #if DEBUG
303 printf("\nNETNAME_ATTRIBUTE\n");
304 #endif
306 /* here we want to rename the net */
307 /* that has priority to the label */
308 /* name */
309 if (n_current->net_name_has_priority) {
311 #if DEBUG /* this shows how to rename nets */
312 printf("\nRENAME all nets: %s -> %s (priority)\n",
313 n_current->net_name, name);
314 #endif
316 s_rename_add(n_current->net_name, name);
318 } else {
320 #if DEBUG /* this shows how to rename nets */
321 printf
322 ("\nRENAME all nets: %s -> %s (not priority)\n",
323 name, n_current->net_name);
324 #endif
325 /* do the rename anyways, this might cause problems */
326 /* this will rename net which have the same label= */
327 if (!s_rename_search
328 (name, n_current->net_name, TRUE)) {
329 fprintf(stderr,
330 _("Found duplicate net name, renaming [%s] to [%s]\n"),
331 name, n_current->net_name);
333 s_rename_add(name, n_current->net_name);
334 name = n_current->net_name;
338 #if DEBUG
339 fprintf(stderr, "Net is now called: [%s]\n", name);
340 #endif
346 n_current = n_current->next;
349 if (name) {
350 return (name);
351 } else {
352 return (NULL);
356 char *s_net_name (TOPLEVEL * pr_current, NETLIST * netlist_head,
357 NET * net_head, char *hierarchy_tag, int type)
359 char *string = NULL;
360 NET *n_start;
361 NETLIST *nl_current;
362 CPINLIST *pl_current;
363 char *net_name = NULL;
364 int found = 0;
365 char *temp;
366 int *unnamed_counter;
367 char *unnamed_string = NULL;
368 EdaConfig *cfg;
370 net_name = s_net_name_search(pr_current, net_head);
372 if (net_name) {
373 return (net_name);
376 #if DEBUG
377 printf("didn't find named net\n");
378 #endif
380 /* didn't find a name */
381 /* go looking for another net which might have already been named */
382 /* ie you don't want to create a new unnamed net if the net has */
383 /* already been named */
384 nl_current = netlist_head;
385 while (nl_current != NULL) {
386 if (nl_current->cpins) {
387 pl_current = nl_current->cpins;
388 while (pl_current != NULL) {
389 if (pl_current->nets) {
390 n_start = pl_current->nets;
391 if (n_start->next && net_head->next) {
392 found = s_net_find(n_start->next, net_head->next);
394 if (found) {
395 net_name =
396 s_net_name_search(pr_current, n_start);
397 if (net_name) {
398 return (net_name);
405 pl_current = pl_current->next;
408 nl_current = nl_current->next;
412 #if DEBUG
413 printf("didn't find previously named\n");
414 #endif
416 /* AND we don't want to assign a dangling pin */
417 /* which is signified by having only a head node */
418 /* which is just a place holder */
419 /* and the head node shows up here */
421 if (net_head->nid == -1 && net_head->prev == NULL
422 && net_head->next == NULL) {
423 string = g_strdup_printf("unconnected_pin-%d",
424 unnamed_pin_counter++);
426 return (string);
430 cfg = eda_config_get_context_for_file (NULL);
432 switch (type) {
433 case PIN_TYPE_NET:
434 unnamed_counter = &unnamed_net_counter;
435 unnamed_string = eda_config_get_string (cfg, "gnetlist", "default-net-name", NULL);
436 break;
437 case PIN_TYPE_BUS:
438 unnamed_counter = &unnamed_bus_counter;
439 unnamed_string = eda_config_get_string (cfg, "gnetlist", "default-bus-name", NULL);
440 break;
441 default:
442 g_critical (_("Incorrect connectivity type %i in s_name_nets()\n"), type);
443 return NULL;
446 /* have we exceeded the number of unnamed nets? */
447 if (*unnamed_counter < MAX_UNNAMED_NETS) {
449 if (netlist_mode == SPICE) {
450 string = g_strdup_printf("%d", (*unnamed_counter)++);
451 } else {
452 temp = g_strdup_printf ("%s%d", unnamed_string, (*unnamed_counter)++);
453 if (hierarchy_tag) {
454 string = s_hierarchy_create_netname (pr_current, temp, hierarchy_tag);
455 g_free (temp);
456 } else {
457 string = temp;
461 } else {
462 fprintf(stderr, _("Increase number of unnamed nets (s_net.c)\n"));
463 exit(-1);
466 g_free (unnamed_string);
467 return string;