gnetlist

s_traverse.c

Go to the documentation of this file.
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 #ifdef HAVE_STRING_H
00026 #include <string.h>
00027 #endif
00028 #include <math.h>
00029 
00030 #include <libgeda/libgeda.h>
00031 
00032 #include "../include/globals.h"
00033 #include "../include/prototype.h"
00034 
00035 #ifdef HAVE_LIBDMALLOC
00036 #include <dmalloc.h>
00037 #endif
00038 
00044 static GHashTable *visit_table = NULL;
00045 
00047 static gboolean
00048 returns_true (gpointer key, gpointer value, gpointer user_data)
00049 {
00050   return TRUE;
00051 }
00052 
00054 static inline gint
00055 is_visited(OBJECT *obj)
00056 {
00057   gpointer val;
00058   gpointer orig_key;
00059   gboolean exist = g_hash_table_lookup_extended (visit_table,
00060                                                  obj,
00061                                                  &orig_key,
00062                                                  &val);
00063   return exist ? GPOINTER_TO_INT(val) : 0;
00064 }
00065 
00067 static inline gint
00068 visit(OBJECT *obj)
00069 {
00070   gpointer val = GINT_TO_POINTER(is_visited (obj) + 1);
00071   g_hash_table_replace (visit_table, obj, val);
00072   return GPOINTER_TO_INT (val);
00073 }
00074 
00076 static inline void
00077 s_traverse_clear_all_visited (const GList *obj_list)
00078 {
00079   g_hash_table_foreach_remove (visit_table,
00080                                (GHRFunc) returns_true,
00081                                NULL);
00082 }
00083 
00084 void s_traverse_init(void)
00085 {
00086     netlist_head = s_netlist_add(NULL);
00087     netlist_head->nlid = -1;    /* head node */
00088 
00089     graphical_netlist_head = s_netlist_add(NULL);
00090     graphical_netlist_head->nlid = -1;  /* head node */
00091 
00092     if (verbose_mode) {
00093     printf
00094         ("\n\n------------------------------------------------------\n");
00095     printf("Verbose mode legend\n\n");
00096     printf("n : Found net\n");
00097     printf("C : Found component (staring to traverse component)\n");
00098     printf
00099         ("p : Found pin (starting to traverse pin / or examining pin)\n");
00100     printf("P : Found end pin connection (end of this net)\n");
00101     printf("R : Starting to rename a net\n");
00102     printf("v : Found source attribute, traversing down\n");
00103     printf("^ : Finished underlying source, going back up\n");
00104     printf("u : Found a refdes which needs to be demangle\n");
00105     printf
00106         ("U : Found a connected_to refdes which needs to be demangle\n");
00107     printf
00108         ("------------------------------------------------------\n\n");
00109 
00110     }
00111 
00112     /* Initialise the hashtable which contains the visit
00113        count. N.b. no free functions are required. */
00114     visit_table = g_hash_table_new (g_direct_hash,
00115                                     g_direct_equal);
00116 }
00117 
00118 void s_traverse_start(TOPLEVEL * pr_current)
00119 {
00120   GList *iter;
00121   PAGE *p_current;
00122 
00123   for ( iter = geda_list_get_glist( pr_current->pages );
00124         iter != NULL;
00125         iter = g_list_next( iter ) ) {
00126 
00127     p_current = (PAGE *)iter->data;
00128 
00129     /* only traverse pages which are toplevel, ie not underneath */
00130     if (p_current->page_control == 0) {
00131       pr_current->page_current = p_current;
00132       s_traverse_sheet (pr_current, s_page_objects (p_current), NULL);
00133     }
00134   }
00135 
00136   /* now that all the sheets have been read, go through and do the */
00137   /* post processing work */
00138   s_netlist_post_process(pr_current, netlist_head);
00139 
00140   /* Now match the graphical netlist with the net names already assigned */
00141   s_netlist_name_named_nets(pr_current, netlist_head,
00142                             graphical_netlist_head);
00143 
00144   if (verbose_mode) {
00145     printf("\nInternal netlist representation:\n\n");
00146     s_netlist_print(netlist_head);
00147   }
00148 }
00149 
00150 
00151 void
00152 s_traverse_sheet (TOPLEVEL * pr_current, const GList *obj_list, char *hierarchy_tag)
00153 {
00154   NETLIST *netlist;
00155   char *temp;
00156   SCM scm_uref;
00157   char *temp_uref;
00158   gboolean is_graphical=FALSE;
00159   const GList *iter;
00160 
00161   if (verbose_mode) {
00162     printf("- Starting internal netlist creation\n");
00163   }
00164 
00165   for (iter = obj_list; iter != NULL; iter = g_list_next (iter)) {
00166     OBJECT *o_current = iter->data;
00167 
00168     netlist = s_netlist_return_tail(netlist_head);
00169 
00170     if (o_current->type == OBJ_PLACEHOLDER) {
00171       printf("WARNING: Found a placeholder/missing component, are you missing a symbol file? [%s]\n", o_current->complex_basename);
00172     }
00173 
00174     if (o_current->type == OBJ_COMPLEX) {
00175 
00176 #if DEBUG
00177       printf("starting NEW component\n\n");
00178 #endif
00179 
00180       verbose_print(" C");
00181 
00182       /* look for special tag */
00183       temp = o_attrib_search_object_attribs_by_name (o_current, "graphical", 0);
00184       if (temp) {
00185         /* traverse graphical elements, but adding them to the
00186        graphical netlist */
00187         g_free(temp);
00188     
00189     netlist = s_netlist_return_tail(graphical_netlist_head);
00190     is_graphical = TRUE;
00191     
00192     
00193       }
00194       netlist = s_netlist_add(netlist);
00195       netlist->nlid = o_current->sid;
00196 
00197       scm_uref = g_scm_c_get_uref(pr_current, o_current);
00198 
00199       if (scm_is_string( scm_uref )) {
00200         temp_uref = scm_to_utf8_string (scm_uref);
00201         netlist->component_uref =
00202           s_hierarchy_create_uref(pr_current, temp_uref, hierarchy_tag);
00203         g_free(temp_uref);
00204       } else {
00205         if (hierarchy_tag) {
00206           netlist->component_uref = g_strdup (hierarchy_tag);
00207         } else {
00208           netlist->component_uref = NULL;
00209         }
00210       }
00211       
00212       if (hierarchy_tag) {
00213     netlist->hierarchy_tag = g_strdup (hierarchy_tag);
00214       }
00215 
00216       netlist->object_ptr = o_current;
00217       
00218       if (!netlist->component_uref) {
00219     
00220     /* search of net attribute */
00221     /* maybe symbol is not a component */
00222     /* but a power / gnd symbol */
00223     temp = o_attrib_search_object_attribs_by_name (o_current, "net", 0);
00224     
00225     /* nope net attribute not found */
00226     if ( (!temp) && (!is_graphical) ) {
00227       
00228       fprintf(stderr,
00229           "Could not find refdes on component and could not find any special attributes!\n");
00230       
00231       netlist->component_uref = g_strdup("U?");
00232     } else {
00233       
00234 #if DEBUG
00235       printf("yeah... found a power symbol\n");
00236 #endif
00237       /* it's a power or some other special symbol */
00238       netlist->component_uref = NULL;
00239       g_free(temp);
00240     }
00241     
00242       }
00243 
00244       netlist->cpins =
00245     s_traverse_component(pr_current, o_current,
00246                  hierarchy_tag);
00247       
00248       /* here is where you deal with the */
00249       /* net attribute */
00250       s_netattrib_handle(pr_current, o_current, netlist,
00251              hierarchy_tag);
00252       
00253       /* now you need to traverse any underlying schematics */
00254       if (pr_current->hierarchy_traversal == TRUE) {
00255     s_hierarchy_traverse(pr_current, o_current, netlist);
00256       }
00257     }
00258   }
00259 
00260   verbose_done();
00261 }
00262 
00263 CPINLIST *s_traverse_component(TOPLEVEL * pr_current, OBJECT * component,
00264                    char *hierarchy_tag)
00265 {
00266   CPINLIST *cpinlist_head = NULL;
00267   CPINLIST *cpins = NULL;
00268   NET *nets_head = NULL;
00269   NET *nets = NULL;
00270   GList *iter;
00271 
00272   cpinlist_head = cpins = s_cpinlist_add(NULL);
00273   cpins->plid = -1;
00274 
00275   for (iter = component->complex->prim_objs;
00276        iter != NULL;
00277        iter = g_list_next (iter)) {
00278     OBJECT *o_current = iter->data;
00279 
00280     /* Ignore objects which aren't net pins */
00281     if (o_current->type != OBJ_PIN ||
00282         o_current->pin_type != PIN_TYPE_NET)
00283       continue;
00284 
00285     /* add cpin node */
00286     cpins = s_cpinlist_add(cpins);
00287     cpins->plid = o_current->sid;
00288     cpins->type = o_current->pin_type;
00289 
00290     cpins->pin_number =
00291       o_attrib_search_object_attribs_by_name (o_current, "pinnumber", 0);
00292 
00293     cpins->pin_label =
00294       o_attrib_search_object_attribs_by_name (o_current, "pinlabel", 0);
00295 
00296     /* head nets node */
00297     /* is this really need */
00298     nets_head = nets = s_net_add(NULL);
00299     nets->nid = -1;
00300 
00301     /* This avoids us adding an unnamed net for an unconnected pin */
00302     if (o_current->conn_list != NULL) {
00303       (void) s_traverse_net (pr_current, nets, TRUE,
00304                              o_current, hierarchy_tag, cpins->type);
00305       s_traverse_clear_all_visited (s_page_objects (pr_current->page_current));
00306     }
00307 
00308     cpins->nets = nets_head;
00309     /* s_net_print(nets); */
00310   }
00311 
00312 
00313   return (cpinlist_head);
00314 }
00315 
00316 
00317 static int connection_type (OBJECT *object)
00318 {
00319   switch (object->type) {
00320     case OBJ_PIN:  return object->pin_type;
00321     case OBJ_NET:  return PIN_TYPE_NET;
00322     case OBJ_BUS:  return PIN_TYPE_BUS;
00323     default:
00324       g_critical ("Non-connectable object being queried for connection type\n");
00325       return PIN_TYPE_NET;
00326   }
00327 }
00328 
00329 
00330 NET *s_traverse_net (TOPLEVEL *pr_current, NET *nets, int starting,
00331                      OBJECT *object, char *hierarchy_tag, int type)
00332 {
00333   NET *new_net;
00334   CONN *c_current;
00335   GList *cl_current;
00336   char *temp = NULL;
00337 
00338   visit (object);
00339 
00340   if (connection_type (object) != type)
00341     return nets;
00342 
00343   new_net = nets = s_net_add(nets);
00344   new_net->nid = object->sid;
00345 
00346   /* pins are not allowed to have the netname attribute attached to them */
00347   if (object->type != OBJ_PIN) {
00348     /* Ignore netname attributes on buses */
00349     if (object->type == OBJ_NET)
00350       temp = o_attrib_search_object_attribs_by_name (object, "netname", 0);
00351 
00352     if (temp) {
00353       new_net->net_name =
00354         s_hierarchy_create_netname(pr_current, temp,
00355                                    hierarchy_tag);
00356       g_free(temp);
00357     } else if (object->type == OBJ_NET) {
00358       /* search for the old label= attribute on nets */
00359       temp = o_attrib_search_object_attribs_by_name (object, "label", 0);
00360       if (temp) {
00361         printf("WARNING: Found label=%s. label= is deprecated, please use netname=\n", temp);
00362         new_net->net_name =
00363           s_hierarchy_create_netname(pr_current, temp,
00364                                      hierarchy_tag);
00365         g_free(temp);
00366       }
00367     }
00368   }
00369 #if DEBUG
00370   printf("inside traverse: %s\n", object->name);
00371 #endif
00372 
00373   if (object->type == OBJ_PIN) {
00374 
00375     verbose_print (starting ? "p" : "P");
00376 
00377     new_net->connected_to =
00378       s_net_return_connected_string (pr_current, object, hierarchy_tag);
00379 
00380     temp = o_attrib_search_object_attribs_by_name (object, "pinlabel", 0);
00381 
00382     if (temp) {
00383       new_net->pin_label = temp;
00384     }
00385 
00386     /* net= new */
00387     if (strstr(nets->connected_to, "POWER") &&
00388         type == PIN_TYPE_NET) {
00389 
00390 #if DEBUG
00391       printf("going to find netname %s \n", nets->connected_to);
00392 #endif
00393       nets->net_name =
00394         s_netattrib_return_netname (pr_current, object,
00395                                     nets->connected_to,
00396                                     hierarchy_tag);
00397       nets->net_name_has_priority = TRUE;
00398       g_free(nets->connected_to);
00399       nets->connected_to = NULL;
00400     }
00401 #if DEBUG
00402     printf("traverse connected_to: %s\n", new_net->connected_to);
00403 #endif
00404 
00405     /* Terminate if we hit a pin which isn't the one we started with */
00406     if (!starting)
00407       return nets;
00408   }
00409 
00410   /*printf("Found net %s\n", object->name); */
00411   verbose_print("n");
00412 
00413   /* this is not perfect yet and won't detect a loop... */
00414   if (is_visited(object) > 100) {
00415     fprintf(stderr, "Found a possible net/pin infinite connection\n");
00416     exit(-1);
00417   }
00418 
00419   cl_current = object->conn_list;
00420   while (cl_current != NULL) {
00421 
00422     c_current = (CONN *) cl_current->data;
00423 
00424     if (c_current->other_object != NULL) {
00425 
00426       if (!is_visited(c_current->other_object) &&
00427           c_current->other_object != object) {
00428         nets = s_traverse_net (pr_current, nets, FALSE,
00429                                c_current->other_object, hierarchy_tag, type);
00430       }
00431 
00432     }
00433     cl_current = g_list_next(cl_current);
00434   }
00435 
00436   return (nets);
00437 }
 All Data Structures Files Functions Variables Defines