[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

gEDA-user: Make-sure-internal-order-of-symbols-is-not-relevant-.patch



This is the patch that makes gnetlist output of footprints for multi 
part components insensitive to internal order. Like so many projects, this is 
not the final solution to all problems of computer science. See my discussion 
with John Doty on this list. It may be useful to apply this algorithm to more 
attributes than just footprints. However, this patch fixes the immediate 
problem that made me to start hacking in the first place.

Please check the diffs for obvious problems.
Most of the new code is in s_netlist.c and a hook in s_traverse.c.  
There is a new struct COMPONENT in libgeda/include/libgeda/struct.h
which was necessary for the conversion of the internal representation from 
NETLIST to GList and back.

I'd be pleased to see this patch hit the main branch of gnetlist.

---<(kaimartin)>---
-- 
Kai-Martin Knaak
Email: kmk@xxxxxxxxxxxxxxx
Öffentlicher PGP-Schlüssel:
http://pgp.mit.edu:11371/pks/lookup?op=get&search=0x6C0B9F53

From 0437bff2e02d74d5148def8bae8d9f59b8a2c5be Mon Sep 17 00:00:00 2001
From: Kai-Martin Knaak <kmk@xxxxxxxxxxxx>
Date: Wed, 29 Jul 2009 04:05:30 +0200
Subject: [PATCH] # Make sure, internal order of symbols is not relevant for footprint
 # attributes of multi part symbols (
 #
 # 1) converts internal NETLIST of symbols to GList
 # 2) sorts GList according to refdes and footprint
 # 3) warns if there are different footprints for the same refdes present
 # 4) copies the first footprint found to the other symbols with same refdes
 # 5) converts internal GList of symbols back to NETLIST
 #
 #	modified:   src/s_netlist.c
 #	modified:   src/s_traverse.c
 #	modified:   ../libgeda/include/libgeda/prototype.h
 #	modified:   ../libgeda/include/libgeda/struct.h
 #	modified:   ../libgeda/src/o_attrib.c
 #
 #---<(kaimartin)>---
 #

---
 gnetlist/src/s_netlist.c            |  288 +++++++++++++++++++++++++++++++++--
 gnetlist/src/s_traverse.c           |   33 +++--
 libgeda/include/libgeda/prototype.h |    1 +
 libgeda/include/libgeda/struct.h    |   18 ++-
 libgeda/src/o_attrib.c              |    2 +-
 5 files changed, 304 insertions(+), 38 deletions(-)

diff --git a/gnetlist/src/s_netlist.c b/gnetlist/src/s_netlist.c
index a45b3e0..900c693 100644
--- a/gnetlist/src/s_netlist.c
+++ b/gnetlist/src/s_netlist.c
@@ -13,8 +13,8 @@
  * 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 
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111 USA
  */
 
@@ -38,6 +38,8 @@
 #include <dmalloc.h>
 #endif
 
+#define DEBUG 0
+
 /* used by the extract functions below */
 #define DELIMITERS ",; "
 
@@ -65,7 +67,7 @@ NETLIST *s_netlist_return_head(NETLIST * tail)
     NETLIST *ret_struct = NULL;
 
     nl_current = tail;
-    while (nl_current != NULL) {	/* goto end of list */
+    while (nl_current != NULL) {	/* goto start of list */
 	ret_struct = nl_current;
 	nl_current = nl_current->prev;
     }
@@ -74,7 +76,7 @@ NETLIST *s_netlist_return_head(NETLIST * tail)
 }
 
 
-/* returns new node */
+/* returns new NETLIST node */
 NETLIST *s_netlist_add(NETLIST * ptr)
 {
     NETLIST *new_node;
@@ -102,13 +104,169 @@ NETLIST *s_netlist_add(NETLIST * ptr)
     }
 }
 
+/*! \brief free the memory assigened to a NETLIST */
+/* Only free the list itself, not the data referenced by pointers */
+void s_netlist_NETLIST_free(NETLIST *nl_ptr)
+{
+    NETLIST *nl_current = NULL;
+    NETLIST *nl_next = NULL;
+
+    nl_current = nl_ptr;
+    while (nl_current != NULL){
+        nl_next = nl_current->next ;
+        g_free( nl_current );
+        nl_current = nl_next;
+    }
+    return;
+}
+
+/*! free COMPONENT struct       */
+/* used by s_netlist_GList_free */
+void s_netlist_COMPONENT_free(COMPONENT *comp, gpointer notused)
+{
+    g_free(comp);
+    return;
+}
+
+/*! \brief free the memory of a GList netlist */
+/* Only free the list itself, not the data referenced by pointers */
+void s_netlist_GList_free(GList *gl_ptr)
+{
+    g_list_foreach(gl_ptr, (GFunc) s_netlist_COMPONENT_free, NULL);
+    g_list_free(gl_ptr);
+    return;
+}
+
+/* convert NETLIST to GList */
+GList *s_netlist_convert_NETLIST_to_GList(NETLIST * nl_ptr)
+{
+    NETLIST *nl_current = NULL;
+    GList *gl_current = NULL;
+    COMPONENT *comp = NULL;
+    COMPONENT *current_component = NULL;
+
+    if (nl_ptr == NULL) {
+        printf("Warning: tried to convert empty NETLIST to GList.\n");
+	return(NULL);
+    }
+
+    nl_current = nl_ptr;
+
+    while (nl_current != NULL) {
+       /* copy the contents of nl_current to struct comp */
+       comp = g_malloc( sizeof(COMPONENT) );
+       comp->nlid = nl_current->nlid;
+       comp->component_uref = nl_current->component_uref;
+       comp->object_ptr = nl_current->object_ptr;
+       comp->cpins = nl_current->cpins;
+       comp->hierarchy_tag = nl_current->hierarchy_tag;
+       comp->composite_component = nl_current->composite_component;
+
+       /* add an item to the start of the list */
+       /* (more efficient than appending to the end of the list) */
+       gl_current = g_list_prepend(gl_current, comp);
+
+#if DEBUG
+       current_component = gl_current->data;
+       printf("component converted: %s, nlid: %i\n",
+                current_component->component_uref,
+                current_component->nlid );
+#endif
+       /* advance to the next item in the NETLIST */
+       nl_current = nl_current->next;
+    }
+
+    /* reverse the list for correct order */
+    gl_current = g_list_reverse(gl_current);
+    return(gl_current);
+}
+
+
+/* convert GList to NETLIST */
+NETLIST *s_netlist_convert_GList_to_NETLIST(GList * gl_ptr)
+{
+    NETLIST *nl_current = NULL;
+    GList *gl_current = NULL;
+    COMPONENT *comp = NULL;
+
+    gl_current = g_list_first(gl_ptr);
+    if (gl_current == NULL) {
+        printf("Warning: tried to convert empty GList to NETLIST.\n");
+	return(NULL);
+    }
+
+    while (gl_current != NULL) {
+       /* add an item to the NETLIST */
+       nl_current = s_netlist_add(nl_current);
+
+       /* copy the contents of gl_current->data to struct nl_current */
+       comp = gl_current->data;
+       nl_current->nlid = comp->nlid;
+       nl_current->component_uref = comp->component_uref;
+       nl_current->object_ptr = comp->object_ptr;
+       nl_current->cpins = comp->cpins;
+       nl_current->hierarchy_tag = comp->hierarchy_tag;
+       nl_current->composite_component = comp->composite_component;
+
+#if DEBUG
+       printf("component reconverted:%s, nlid:%i\n",
+              nl_current->component_uref, nl_current->nlid );
+#endif
+       /* advance to the next item in the GList */
+       gl_current = gl_current->next;
+    }
+
+    /* move to start of NETLIST */
+    nl_current = s_netlist_return_head(nl_current);
+    return(nl_current);
+}
+
+/*! \brief Compare refdes and footprint of components             */
+/* Compare function needed to g_sort the GList of components.     */
+/* Returns -1 if the refdes of comp1 is smaller than comp2.       */
+/* If both refdes are identical, compare footprints.              */
+/* Footprint order is inverted, so empty footprints go to the end.*/
+gint s_netlist_compare_component_refdes( gconstpointer ptr_comp1,
+                                          gconstpointer ptr_comp2 )
+{
+    gint result = 0;
+    char *f_comp1;
+    char *f_comp2;
+    COMPONENT *comp1 = NULL;
+    COMPONENT *comp2 = NULL;
+
+    comp1 = (COMPONENT*) ptr_comp1;
+    comp2 = (COMPONENT*) ptr_comp2;
+    result = g_strcmp0 ( comp1->component_uref, comp2->component_uref );
+
+    /* Compare footprints if the refdes of both components is the same */
+    if (result == 0) {
+        f_comp1 = o_attrib_search_attached_attribs_by_name
+                                    (comp1->object_ptr, "footprint", 0);
+        f_comp2 = o_attrib_search_attached_attribs_by_name
+                                    (comp2->object_ptr, "footprint", 0);
+        result = g_strcmp0( f_comp2, f_comp1 ) ;
+#if DEBUG
+        printf("first footprint: %s, second: %s, result: %i\n", f_comp1, f_comp2, result);
+#endif
+        g_free(f_comp1);
+        g_free(f_comp2);
+    }
+
+
+    return(result);
+}
+
+
 void s_netlist_print(NETLIST * ptr)
 {
     NETLIST *nl_current = NULL;
+    char *foot_current;
 
     nl_current = ptr;
 
     if (nl_current == NULL) {
+        printf("Warning: tried to print empty list of components.\n");
 	return;
     }
 
@@ -126,6 +284,12 @@ void s_netlist_print(NETLIST * ptr)
 		printf("Hierarchy tag: %s\n", nl_current->hierarchy_tag);
 	    }
 
+            foot_current = o_attrib_search_attached_attribs_by_name (
+                                          nl_current->object_ptr, "footprint", 0);
+            if (foot_current) {
+                printf("footprint: %s\n", foot_current);
+            }
+
 	    if (nl_current->cpins) {
 		s_cpinlist_print(nl_current->cpins);
 	    }
@@ -147,7 +311,7 @@ void s_netlist_post_process(TOPLEVEL * pr_current, NETLIST * head)
     nl_current = head;
 
     if (verbose_mode) {
-	printf("\n- Staring post processing\n");
+	printf("\n- Starting post processing, part 1\n");
 	printf("- Naming nets:\n");
 	vi = 0;
     }
@@ -180,7 +344,7 @@ void s_netlist_post_process(TOPLEVEL * pr_current, NETLIST * head)
 				       nl_current->hierarchy_tag,
 				       pl_current->type);
 
-			/* put this name also in the first 
+			/* put this name also in the first
 			   node of the nets linked list */
 			if (pl_current->net_name && pl_current->nets) {
 			    if (pl_current->nets->next) {
@@ -221,6 +385,98 @@ void s_netlist_post_process(TOPLEVEL * pr_current, NETLIST * head)
     verbose_done();
 }
 
+
+/*! \brief Associated every refdes with exactly one footprint */
+void s_netlist_normalize_footprints(TOPLEVEL *pr_current, GList *gl_ptr)
+{
+    GList *gl_current = NULL;
+    COMPONENT *c_current = NULL;
+    OBJECT *foot_attr = NULL;
+    TEXT *foot_text = NULL;
+    char *ref_prev = NULL;
+    char *ref_curr = NULL;
+    char *foot_curr = NULL;
+    char *foot_prev = NULL;
+
+    gl_current = gl_ptr ;
+    while ( gl_current != NULL ) {
+        foot_prev = foot_curr;
+        ref_prev = ref_curr;
+        c_current = gl_current->data;
+        ref_curr = c_current->component_uref;
+        if (c_current->object_ptr != NULL)
+        {
+            foot_curr = o_attrib_search_attached_attribs_by_name (
+                                c_current->object_ptr, "footprint", 0);
+	    /* if same refdes and previous footprint exist */
+            if ( ( g_strcmp0(ref_curr, ref_prev) == 0) && (foot_prev != NULL) ) {
+                if ( (g_strcmp0(foot_prev, foot_curr) != 0) && (foot_curr != NULL)){
+                    printf("warning: two different footprints (%s, %s) "
+                                "attached to refdes (%s). "
+                                "Setting footprint to %s\n",
+                                foot_prev, foot_curr, ref_curr, foot_prev);
+                }
+                foot_attr = o_attrib_find_attrib_by_name(
+                               c_current->object_ptr->attribs, "footprint", 0);
+                /* add footprint, if there is no footprint attribute, yet */
+                if (foot_attr == NULL) {
+                    foot_text = g_malloc0(sizeof(TEXT));
+                    foot_attr = g_malloc0(sizeof(OBJECT));
+                    foot_text->string = "footprint=foo";
+                    foot_attr->text = foot_text;
+                    foot_attr->type = OBJ_TEXT;
+                    o_attrib_attach (pr_current, foot_attr , c_current->object_ptr, 0);
+#if DEBUG
+                    printf("added a footprint attribute to %s\n", ref_curr);
+#endif
+                }
+                foot_attr->text->string = g_strconcat("footprint=", foot_prev, NULL);
+                foot_curr = foot_prev;
+#if DEBUG
+                printf("footprint attribute of %s is now %s\n",
+                                    ref_curr, foot_attr->text->string);
+#endif
+
+                /* TODO: check for identical pins */
+                /* TODO: check for required symbols */
+            }
+        }
+        /* go to next item in GList */
+        gl_current = gl_current->next;
+    }
+}
+
+
+/*! \brief normalize the list of components:                 */
+/*   --> sort according to refdes                            */
+/*   -->   */
+NETLIST *s_netlist_normalize_components(TOPLEVEL *pr_current, NETLIST *nl_ptr)
+{
+    GList *gl_ptr = NULL;
+
+    if (nl_ptr == NULL) {
+        printf("Warning: tried to normalize empty list of components.");
+	return(NULL);
+    }
+
+    /* convert NETLIST to GLIST */
+    gl_ptr = s_netlist_convert_NETLIST_to_GList(nl_ptr);
+    s_netlist_NETLIST_free(nl_ptr);
+
+    /* sort netlist according to refdes and footprint */
+    gl_ptr = g_list_sort(gl_ptr, s_netlist_compare_component_refdes);
+
+    /* deal with multi part components with the same refdes */
+    s_netlist_normalize_footprints(pr_current, gl_ptr);
+
+    /* convert GLIST to NETLIST */
+    nl_ptr = s_netlist_convert_GList_to_NETLIST(gl_ptr);
+    s_netlist_GList_free(gl_ptr);
+
+    return(nl_ptr);
+}
+
+
 void s_netlist_name_named_nets (TOPLEVEL *pr_current,
 				NETLIST *named_netlist,
 				NETLIST *unnamed_netlist) {
@@ -229,12 +485,12 @@ void s_netlist_name_named_nets (TOPLEVEL *pr_current,
   CPINLIST *pl_current;
   NET *n_current;
   char *net_name;
-  
+
   if (verbose_mode) {
-    printf("\n- Staring post processing\n");
+    printf("\n- Starting post processing, part 2\n");
     printf("- Naming nets of graphical objects:\n");
   }
-  
+
   /* this pass gives all nets a name, whether specified or creates a */
   /* name */
   nl_current = unnamed_netlist;
@@ -242,11 +498,11 @@ void s_netlist_name_named_nets (TOPLEVEL *pr_current,
     if (nl_current->cpins) {
       pl_current = nl_current->cpins;
       while (pl_current != NULL) {
-	
+
 	if (pl_current->plid != -1) {
 	  verbose_print("p");
 	}
-	
+
 	if (pl_current->plid != -1 && pl_current->nets) {
 	  verbose_print("n");
 	  net_name = NULL;
@@ -256,7 +512,7 @@ void s_netlist_name_named_nets (TOPLEVEL *pr_current,
 	    n_current->net_name = s_netlist_netname_of_netid(pr_current,
 							     named_netlist,
 							     n_current->nid);
-	    
+
 	    if (n_current->net_name != NULL) {
 	      net_name = n_current->net_name;
 	    }
@@ -273,7 +529,7 @@ void s_netlist_name_named_nets (TOPLEVEL *pr_current,
   }
 
   verbose_done();
-    
+
 }
 
 char *s_netlist_netname_of_netid (TOPLEVEL *pr_current,
@@ -283,9 +539,9 @@ char *s_netlist_netname_of_netid (TOPLEVEL *pr_current,
   NETLIST *nl_current;
   CPINLIST *pl_current;
   NET *n_current;
-  
+
   nl_current = netlist_head;
-  
+
   /* walk through the list of components, and through the list
    * of individual pins on each, looking for the net identifier
    */
@@ -304,6 +560,6 @@ char *s_netlist_netname_of_netid (TOPLEVEL *pr_current,
       pl_current = pl_current->next;
     }
     nl_current = nl_current->next;
-    } 
+    }
   return NULL;
 }
diff --git a/gnetlist/src/s_traverse.c b/gnetlist/src/s_traverse.c
index a23fa34..d91e05d 100644
--- a/gnetlist/src/s_traverse.c
+++ b/gnetlist/src/s_traverse.c
@@ -35,6 +35,8 @@
 #include <dmalloc.h>
 #endif
 
+#define DEBUG 0
+
 /*! Tracks which OBJECTs have been visited so far, and how many times.
  *
  * The keys of the table are the OBJECT pointers, and the visit count
@@ -93,7 +95,7 @@ void s_traverse_init(void)
 	    ("\n\n------------------------------------------------------\n");
 	printf("Verbose mode legend\n\n");
 	printf("n : Found net\n");
-	printf("C : Found component (staring to traverse component)\n");
+	printf("C : Found component (starting to traverse component)\n");
 	printf
 	    ("p : Found pin (starting to traverse pin / or examining pin)\n");
 	printf("P : Found end pin connection (end of this net)\n");
@@ -136,6 +138,9 @@ void s_traverse_start(TOPLEVEL * pr_current)
   /* post processing work */
   s_netlist_post_process(pr_current, netlist_head);
 
+  /* normalize the list of components */
+  netlist_head = s_netlist_normalize_components(pr_current, netlist_head);
+
   /* Now match the graphical netlist with the net names already assigned */
   s_netlist_name_named_nets(pr_current, netlist_head,
                             graphical_netlist_head);
@@ -184,11 +189,11 @@ s_traverse_sheet (TOPLEVEL * pr_current, const GList *obj_list, char *hierarchy_
         /* traverse graphical elements, but adding them to the
 	   graphical netlist */
         g_free(temp);
-	
+
 	netlist = s_netlist_return_tail(graphical_netlist_head);
 	is_graphical = TRUE;
-	
-    
+
+
       }
       netlist = s_netlist_add(netlist);
       netlist->nlid = o_current->sid;
@@ -207,29 +212,29 @@ s_traverse_sheet (TOPLEVEL * pr_current, const GList *obj_list, char *hierarchy_
           netlist->component_uref = NULL;
         }
       }
-      
+
       if (hierarchy_tag) {
 	netlist->hierarchy_tag = g_strdup (hierarchy_tag);
       }
 
       netlist->object_ptr = o_current;
-      
+
       if (!netlist->component_uref) {
-	
+
 	/* search of net attribute */
 	/* maybe symbol is not a component */
 	/* but a power / gnd symbol */
 	temp = o_attrib_search_object_attribs_by_name (o_current, "net", 0);
-	
+
 	/* nope net attribute not found */
 	if ( (!temp) && (!is_graphical) ) {
-	  
+
 	  fprintf(stderr,
 		  "Could not find refdes on component and could not find any special attributes!\n");
-	  
+
 	  netlist->component_uref = g_strdup("U?");
 	} else {
-	  
+
 #if DEBUG
 	  printf("yeah... found a power symbol\n");
 #endif
@@ -237,18 +242,18 @@ s_traverse_sheet (TOPLEVEL * pr_current, const GList *obj_list, char *hierarchy_
 	  netlist->component_uref = NULL;
 	  g_free(temp);
 	}
-	
+
       }
 
       netlist->cpins =
 	s_traverse_component(pr_current, o_current,
 			     hierarchy_tag);
-      
+
       /* here is where you deal with the */
       /* net attribute */
       s_netattrib_handle(pr_current, o_current, netlist,
 			 hierarchy_tag);
-      
+
       /* now you need to traverse any underlying schematics */
       if (pr_current->hierarchy_traversal == TRUE) {
 	s_hierarchy_traverse(pr_current, o_current, netlist);
diff --git a/libgeda/include/libgeda/prototype.h b/libgeda/include/libgeda/prototype.h
index 77d608f..fd1b77d 100644
--- a/libgeda/include/libgeda/prototype.h
+++ b/libgeda/include/libgeda/prototype.h
@@ -103,6 +103,7 @@ void o_attrib_remove(TOPLEVEL *toplevel, GList **list, OBJECT *remove);
 gboolean o_attrib_string_get_name_value (const gchar *string, gchar **name_ptr, gchar **value_ptr);
 gboolean o_attrib_get_name_value (OBJECT *attrib, gchar **name_ptr, gchar **value_ptr);
 GList *o_attrib_find_floating_attribs (const GList *list);
+OBJECT *o_attrib_find_attrib_by_name (const GList *list, char *name, int count);
 char *o_attrib_search_floating_attribs_by_name (const GList *list, char *name, int counter);
 char *o_attrib_search_attached_attribs_by_name (OBJECT *object, char *name, int counter);
 char *o_attrib_search_inherited_attribs_by_name (OBJECT *object, char *name, int counter);
diff --git a/libgeda/include/libgeda/struct.h b/libgeda/include/libgeda/struct.h
index 2606798..8514d05 100644
--- a/libgeda/include/libgeda/struct.h
+++ b/libgeda/include/libgeda/struct.h
@@ -588,22 +588,26 @@ struct st_toplevel {
 
 /* for every component in the object database */
 struct st_netlist {
-
   int nlid;
-
   char *component_uref;
-
   OBJECT *object_ptr;
-
-  CPINLIST *cpins;		
-
+  CPINLIST *cpins;
   char *hierarchy_tag;
   int composite_component;
-
   NETLIST *prev;
   NETLIST *next;
 };
 
+/* A struct type to hold the data of a component */
+/* This is necessary for the GList version of the netlist */
+typedef struct {
+  int nlid;
+  char *component_uref;
+  OBJECT *object_ptr;
+  CPINLIST *cpins;
+  char *hierarchy_tag;
+  int composite_component;
+} COMPONENT;
 
 /* for every pin on a component */
 struct st_cpinlist {
diff --git a/libgeda/src/o_attrib.c b/libgeda/src/o_attrib.c
index 117ff91..9c329d6 100644
--- a/libgeda/src/o_attrib.c
+++ b/libgeda/src/o_attrib.c
@@ -461,7 +461,7 @@ GList *o_attrib_find_floating_attribs (const GList *list)
  *  \param [in] counter  Which occurance to return.
  *  \return The n'th attribute object in the given list with the given name.
  */
-static OBJECT *o_attrib_find_attrib_by_name (const GList *list, char *name, int count)
+OBJECT *o_attrib_find_attrib_by_name (const GList *list, char *name, int count)
 {
   OBJECT *a_current;
   const GList *iter;
-- 
1.6.3.3


Attachment: pgpIynbNm4aCE.pgp
Description: PGP signature


_______________________________________________
geda-user mailing list
geda-user@xxxxxxxxxxxxxx
http://www.seul.org/cgi-bin/mailman/listinfo/geda-user