1 /* gEDA - GPL Electronic Design Automation
2 * gnetlist - gEDA Netlist
3 * Copyright (C) 1998-2007 Ales Hvezda
4 * Copyright (C) 1998-2007 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., 59 Temple Place, Suite 330, Boston, MA 02111 USA
29 #include <libgeda/libgeda.h>
31 #include "../include/globals.h"
32 #include "../include/prototype.h"
34 #ifdef HAVE_LIBDMALLOC
38 void s_traverse_init(void)
40 netlist_head
= s_netlist_add(NULL
);
41 netlist_head
->nlid
= -1; /* head node */
43 graphical_netlist_head
= s_netlist_add(NULL
);
44 graphical_netlist_head
->nlid
= -1; /* head node */
48 ("\n\n------------------------------------------------------\n");
49 printf("Verbose mode legend\n\n");
50 printf("n : Found net\n");
51 printf("C : Found component (staring to traverse component)\n");
53 ("p : Found pin (starting to traverse pin / or examining pin)\n");
54 printf("P : Found end pin connection (end of this net)\n");
55 printf("R : Starting to rename a net\n");
56 printf("v : Found source attribute, traversing down\n");
57 printf("^ : Finished underlying source, going back up\n");
58 printf("u : Found a refdes which needs to be demangle\n");
60 ("U : Found a connected_to refdes which needs to be demangle\n");
62 ("------------------------------------------------------\n\n");
67 void s_traverse_start(TOPLEVEL
* pr_current
)
72 for ( iter
= geda_list_get_glist( pr_current
->pages
);
74 iter
= g_list_next( iter
) ) {
76 p_current
= (PAGE
*)iter
->data
;
78 /* only traverse pages which are toplevel, ie not underneath */
79 if (p_current
->object_head
&& p_current
->page_control
== 0) {
80 /* XXX Does this require s_toplevel_goto_page to get the right cwd? */
81 pr_current
->page_current
= p_current
;
82 s_traverse_sheet(pr_current
, p_current
->object_head
, NULL
);
86 /* now that all the sheets have been read, go through and do the */
87 /* post processing work */
88 s_netlist_post_process(pr_current
, netlist_head
);
90 /* Now match the graphical netlist with the net names already assigned */
91 s_netlist_name_named_nets(pr_current
, netlist_head
,
92 graphical_netlist_head
);
95 printf("\nInternal netlist representation:\n\n");
96 s_netlist_print(netlist_head
);
102 s_traverse_sheet(TOPLEVEL
* pr_current
, OBJECT
*o_current
,
103 char const *hierarchy_tag
)
109 gboolean is_graphical
=FALSE
;
112 printf("- Starting internal netlist creation\n");
115 while (o_current
!= NULL
) {
116 netlist
= s_netlist_return_tail(netlist_head
);
118 if (o_current
->type
== OBJ_PLACEHOLDER
) {
119 printf("WARNING: Found a placeholder/missing component, are you missing a symbol file? [%s]\n", o_current
->complex_basename
);
122 if (o_current
->type
== OBJ_COMPLEX
) {
124 printf("starting NEW component\n\n");
129 /* look for special tag */
130 temp
= o_attrib_search_component(o_current
, "graphical");
132 /* traverse graphical elements, but adding them to the
136 netlist
= s_netlist_return_tail(graphical_netlist_head
);
139 netlist
= s_netlist_add(netlist
);
140 netlist
->nlid
= o_current
->sid
;
142 scm_uref
= g_scm_c_get_uref(pr_current
, o_current
);
144 if (scm_is_string( scm_uref
)) {
145 temp_uref
= scm_to_locale_string( scm_uref
);
146 netlist
->component_uref
=
147 s_hierarchy_create_uref(pr_current
, temp_uref
, hierarchy_tag
);
151 netlist
->component_uref
= g_strdup (hierarchy_tag
);
153 netlist
->component_uref
= NULL
;
158 netlist
->hierarchy_tag
= g_strdup (hierarchy_tag
);
161 netlist
->object_ptr
= o_current
;
163 if (!netlist
->component_uref
) {
164 /* search of net attribute */
165 /* maybe symbol is not a component */
166 /* but a power / gnd symbol */
168 o_attrib_search_name(o_current
->complex->prim_objs
,
171 /* nope net attribute not found */
172 if ( (!temp
) && (!is_graphical
) ) {
174 "Could not find refdes on component and could not find any special attributes!\n");
176 netlist
->component_uref
= g_strdup("U?");
180 printf("yeah... found a power symbol\n");
182 /* it's a power or some other special symbol */
183 netlist
->component_uref
= NULL
;
189 s_traverse_component(pr_current
, o_current
,
192 /* here is where you deal with the */
194 s_netattrib_handle(pr_current
, o_current
, netlist
,
197 /* now you need to traverse any underlying schematics */
198 if (pr_current
->hierarchy_traversal
== TRUE
) {
199 s_hierarchy_traverse(pr_current
, o_current
, netlist
);
203 o_current
= o_current
->next
;
209 CPINLIST
*s_traverse_component(TOPLEVEL
* pr_current
, OBJECT
* component
,
210 char const *hierarchy_tag
)
212 CPINLIST
*cpinlist_head
= NULL
;
213 CPINLIST
*cpins
= NULL
;
214 OBJECT
*o_current
= NULL
;
215 NET
*nets_head
= NULL
;
221 o_current
= component
->complex->prim_objs
;
223 cpinlist_head
= cpins
= s_cpinlist_add(NULL
);
226 while (o_current
!= NULL
) {
227 if (o_current
->type
== OBJ_PIN
) {
231 o_current
->visited
= 1;
234 cpins
= s_cpinlist_add(cpins
);
235 cpins
->plid
= o_current
->sid
;
237 /* search the object only */
238 cpins
->pin_number
= o_attrib_search_name_single(o_current
, "pinnumber",
242 o_attrib_search_name_single_count(o_current
, "pinlabel",
246 cpins
->pin_label
= temp
;
250 /* is this really need */
251 nets_head
= nets
= s_net_add(NULL
);
255 cl_current
= o_current
->conn_list
;
256 while (cl_current
!= NULL
) {
258 c_current
= (CONN
*) cl_current
->data
;
261 if (c_current
->other_object
!= NULL
) {
264 printf("c_current other_object, not NULL\n");
267 if (!c_current
->other_object
->visited
&&
268 c_current
->other_object
!= o_current
) {
270 nets
= s_net_add(nets
);
271 nets
->nid
= o_current
->sid
;
274 s_net_return_connected_string(pr_current
,
279 if (strstr(nets
->connected_to
, "POWER")) {
281 printf("going to find netname %s\n",
285 s_netattrib_return_netname(pr_current
,
290 nets
->net_name_has_priority
= TRUE
;
291 g_free(nets
->connected_to
);
292 nets
->connected_to
= NULL
;
295 printf("%s\n", nets
->connected_to
);
298 s_traverse_net(pr_current
, o_current
, nets
,
299 c_current
->other_object
,
302 s_traverse_clear_all_visited(pr_current
->
303 page_current
->object_head
);
307 cl_current
= g_list_next(cl_current
);
310 cpins
->nets
= nets_head
;
311 /* s_net_print(nets); */
314 /* should pass in page_current in top level func */
316 s_traverse_clear_all_visited(pr_current
->page_current
->
319 o_current
= o_current
->next
;
323 return (cpinlist_head
);
327 void s_traverse_clear_all_visited(OBJECT
* object_head
)
331 o_current
= object_head
;
333 while (o_current
!= NULL
) {
336 if (o_current
->visited
) {
337 printf("%s\n", o_current
->name
);
341 o_current
->visited
= 0;
343 if (o_current
->type
== OBJ_COMPLEX
344 && o_current
->complex->prim_objs
) {
345 s_traverse_clear_all_visited(o_current
->complex->prim_objs
);
348 o_current
= o_current
->next
;
353 NET
*s_traverse_net(TOPLEVEL
* pr_current
, OBJECT
* previous_object
,
354 NET
* nets
, OBJECT
* object
, char const *hierarchy_tag
)
364 new_net
= nets
= s_net_add(nets
);
365 new_net
->nid
= object
->sid
;
367 /* pins are not allowed to have the netname attribute attached to them */
368 if (o_current
->type
!= OBJ_PIN
) {
369 temp
= o_attrib_search_name_single(o_current
, "netname", NULL
);
373 s_hierarchy_create_netname(pr_current
, temp
,
378 /* search for the old label= attribute */
379 temp
= o_attrib_search_name_single(o_current
, "label", NULL
);
381 printf("WARNING: Found label=%s. label= is deprecated, please use netname=\n", temp
);
383 s_hierarchy_create_netname(pr_current
, temp
,
390 printf("inside traverse: %s\n", object
->name
);
393 if (object
->type
== OBJ_PIN
) {
397 new_net
->connected_to
=
398 s_net_return_connected_string(pr_current
, o_current
,
401 temp
= o_attrib_search_name_single_count(o_current
, "pinlabel", 0);
404 new_net
->pin_label
= temp
;
408 if (strstr(nets
->connected_to
, "POWER")) {
411 printf("going to find netname %s \n", nets
->connected_to
);
414 s_netattrib_return_netname(pr_current
, o_current
,
417 nets
->net_name_has_priority
= TRUE
;
418 g_free(nets
->connected_to
);
419 nets
->connected_to
= NULL
;
422 printf("traverse connected_to: %s\n", new_net
->connected_to
);
428 /*printf("Found net %s\n", object->name); */
433 /* this is not perfect yet and won't detect a loop... */
434 if (object
->visited
> 100) {
435 fprintf(stderr
, "Found a possible net/pin infinite connection\n");
439 cl_current
= object
->conn_list
;
440 while (cl_current
!= NULL
) {
442 c_current
= (CONN
*) cl_current
->data
;
444 if (c_current
->other_object
!= NULL
) {
447 printf("c_current %s visited: %d\n",
448 c_current
->other_object
->name
,
449 c_current
->other_object
->visited
);
452 if (!c_current
->other_object
->visited
&&
453 c_current
->other_object
!= o_current
&&
454 c_current
->other_object
->type
!= OBJ_BUS
) {
457 s_traverse_net(pr_current
, object
, nets
,
458 c_current
->other_object
, hierarchy_tag
);
462 cl_current
= g_list_next(cl_current
);