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

gEDA-user: [PATCH 1/2] gnetlist: Add access to all attributes from components with multiple symbol instances.



This commit introduces 'gnetlist:get-all-package-attributes' to
retrieve every first attribute value for package consisting of
multiple symbol instances.

'gnetlist:get-package-attribute' gets redefined to use the above
procedure. To preserve backward compatibility, it returns the first
value found in file order and warns when detecting different, possibly
conflicting values. This behavior is configurable.

Derived from patch #3071482, C code by Sebastian Gieltjes.
---

 gnetlist/include/prototype.h |    2 +-
 gnetlist/scheme/gnetlist.scm |   41 ++++++++++++++++++++++++++++++++++++++
 gnetlist/src/g_netlist.c     |   45 +++++++++++++++++++++++++-----------------
 gnetlist/src/g_register.c    |    2 +-
 4 files changed, 70 insertions(+), 20 deletions(-)

diff --git a/gnetlist/include/prototype.h b/gnetlist/include/prototype.h
index d37d397..3a976c2 100644
--- a/gnetlist/include/prototype.h
+++ b/gnetlist/include/prototype.h
@@ -11,7 +11,7 @@ SCM g_get_all_unique_nets(SCM scm_level);
 SCM g_get_all_connections(SCM scm_netname);
 SCM g_get_nets(SCM scm_uref, SCM scm_pin);
 SCM g_get_pins_nets(SCM scm_uref);
-SCM g_get_package_attribute(SCM scm_uref, SCM scm_wanted_attrib);
+SCM g_get_all_package_attributes(SCM scm_uref, SCM scm_wanted_attrib);
 SCM g_get_attribute_by_pinseq(SCM scm_uref, SCM scm_pinseq, SCM scm_wanted_attrib);
 SCM g_get_attribute_by_pinnumber(SCM scm_uref, SCM scm_pin, SCM scm_wanted_attrib);
 SCM g_get_toplevel_attribute(SCM scm_wanted_attrib);
diff --git a/gnetlist/scheme/gnetlist.scm b/gnetlist/scheme/gnetlist.scm
index d798259..a58ec79 100644
--- a/gnetlist/scheme/gnetlist.scm
+++ b/gnetlist/scheme/gnetlist.scm
@@ -17,6 +17,8 @@
 ;;; along with this program; if not, write to the Free Software
 ;;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
+(use-modules (srfi srfi-1))
+
 ;;----------------------------------------------------------------------
 ;; The below functions added by SDB in Sept 2003 to support command-line flag
 ;; processing.
@@ -94,6 +96,45 @@
   )
 )
 
+;; Default resolver: returns value associated with first symbol instance
+;; in file order and warns if instances have different values.
+(define (unique-attribute refdes name values)
+    (let ((value (car values)))
+      (or (every (lambda (x) (equal? x value)) values)
+          (format (current-error-port) "\
+Possible attribute conflict for refdes: ~A
+name: ~A
+values: ~A
+" refdes name values))
+      value))
+
+(define (gnetlist:get-package-attribute refdes name)
+  "Return the value associated with attribute NAME on package
+identified by REFDES.
+
+It actually computes a single value from the full list of values
+produced by 'gnetlist:get-all-package-attributes' as that list is
+passed through 'unique-attribute'.
+
+For backward compatibility, the default behavior is to return the
+value associated with the first symbol instance for REFDES. If all
+instances of REFDES do not have the same value for NAME, it prints a
+warning.
+
+This can be modified by redefining 'unique-attribute' that is a
+procedure that gets provided a non-empty list of attribute values, the
+REFDES and the NAME used for the search. It is expected to return a
+single value as a string or #f for an empty or non-existent attribute
+value.
+
+Note that given the current load sequence of gnetlist, this
+customization can only happen in the backend itself or in a file
+loaded after the backend ('-m' option of gnetlist)."
+  (let* ((values (gnetlist:get-all-package-attributes refdes name))
+         (value  (and (not (null? values))
+                      (unique-attribute refdes name values))))
+    (or value "unknown")))
+
 ;;
 ;; Given a uref, returns the device attribute value (unknown if not defined)
 ;;
diff --git a/gnetlist/src/g_netlist.c b/gnetlist/src/g_netlist.c
index 14441cc..ef8d5fe 100644
--- a/gnetlist/src/g_netlist.c
+++ b/gnetlist/src/g_netlist.c
@@ -472,19 +472,34 @@ SCM g_get_pins_nets(SCM scm_uref)
 }
 
 
-SCM g_get_package_attribute(SCM scm_uref, SCM scm_wanted_attrib)
+/*! \brief Get attribute value(s) from a package with given uref.
+ *  \par Function Description
+ *  This function returns the values of a specific attribute type
+ *  attached to the symbol instances with the given refdes.
+ *
+ *  Every first attribute value found is added to the return list. A
+ *  Scheme false value is added if the instance has no such attribute.
+ *
+ *  \note The order of the values in the return list is the order of
+ *  symbol instances within gnetlist (the first element is the value
+ *  associated with the first symbol instance).
+ *
+ *  \param [in] scm_uref           Package reference.
+ *  \param [in] scm_wanted_attrib  Attribute name.
+ *  \return A list of attribute values as strings and #f.
+ */
+SCM g_get_all_package_attributes(SCM scm_uref, SCM scm_wanted_attrib)
 {
-    SCM scm_return_value;
+    SCM ret = SCM_EOL;
     NETLIST *nl_current;
     char *uref;
     char *wanted_attrib;
-    char *return_value = NULL;
 
     SCM_ASSERT(scm_is_string (scm_uref),
-	       scm_uref, SCM_ARG1, "gnetlist:get-package-attribute");
+	       scm_uref, SCM_ARG1, "gnetlist:get-all-package-attributes");
 
     SCM_ASSERT(scm_is_string (scm_wanted_attrib),
-	       scm_wanted_attrib, SCM_ARG2, "gnetlist:get-package-attribute");
+	       scm_wanted_attrib, SCM_ARG2, "gnetlist:get-all-package-attributes");
 
     uref          = scm_to_locale_string (scm_uref);
     wanted_attrib = scm_to_locale_string (scm_wanted_attrib);
@@ -492,33 +507,27 @@ SCM g_get_package_attribute(SCM scm_uref, SCM scm_wanted_attrib)
     /* here is where you make it multi page aware */
     nl_current = netlist_head;
 
-    /* search for the first instance */
-    /* through the entire list */
+    /* search for uref instances and through the entire list */
     while (nl_current != NULL) {
 
 	if (nl_current->component_uref) {
 	    if (strcmp(nl_current->component_uref, uref) == 0) {
-
-		return_value =
+		char *value =
 		    o_attrib_search_object_attribs_by_name (nl_current->object_ptr,
 		                                            wanted_attrib, 0);
-		break;
+
+		ret = scm_cons (value ? scm_from_locale_string (value) : SCM_BOOL_F, ret);
+
+		g_free (value);
 	    }
 	}
 	nl_current = nl_current->next;
     }
 
-    if (return_value) {
-      scm_return_value = scm_makfrom0str (return_value);
-    } else {
-      scm_return_value = scm_makfrom0str ("unknown");
-    }
-    g_free (return_value);
-
     free (uref);
     free (wanted_attrib);
 
-    return (scm_return_value);
+    return scm_reverse_x (ret, SCM_EOL);
 }
 
 /* takes a uref and pinseq number and returns wanted_attribute associated */
diff --git a/gnetlist/src/g_register.c b/gnetlist/src/g_register.c
index b46215d..a1bf749 100644
--- a/gnetlist/src/g_register.c
+++ b/gnetlist/src/g_register.c
@@ -81,7 +81,7 @@ static struct gsubr_t gnetlist_funcs[] = {
   { "gnetlist:get-nets",            2, 0, 0, g_get_nets },
   { "gnetlist:get-pins-nets",       1, 0, 0, g_get_pins_nets },
 
-  { "gnetlist:get-package-attribute",  2, 0, 0, g_get_package_attribute },
+  { "gnetlist:get-all-package-attributes", 2, 0, 0, g_get_all_package_attributes },
   { "gnetlist:get-toplevel-attribute", 1, 0, 0, g_get_toplevel_attribute },
   /* { "gnetlist:set-netlist-mode", 1, 0, 0, g_set_netlist_mode }, no longer needed */
   { "gnetlist:get-renamed-nets",    1, 0, 0, g_get_renamed_nets },



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