diff --git a/gnetlist/include/prototype.h b/gnetlist/include/prototype.h
index d90e59e..e719531 100644
--- a/gnetlist/include/prototype.h
+++ b/gnetlist/include/prototype.h
@@ -50,7 +50,7 @@ CPINLIST *s_cpinlist_add(CPINLIST *ptr);
 void s_cpinlist_print(CPINLIST *ptr);
 CPINLIST *s_cpinlist_search_pin(CPINLIST *ptr, char *pin_number);
 /* s_hierarchy.c */
-void s_hierarchy_traverse(TOPLEVEL *pr_current, OBJECT *o_current, NETLIST *netlist);
+void s_hierarchy_traverse(TOPLEVEL *pr_current, OBJECT *o_current, NETLIST *netlist, GList *parameters);
 void s_hierarchy_post_process(TOPLEVEL *pr_current, NETLIST *head);
 int s_hierarchy_setup_rename(TOPLEVEL *pr_current, NETLIST *head, char *uref, char *label, char *new_name);
 void s_hierarchy_remove_urefconn(NETLIST *head, char *uref_disable);
@@ -61,6 +61,8 @@ char *s_hierarchy_create_netattrib(TOPLEVEL *pr_current, char *basename, char *h
 void s_hierarchy_remove_uref_mangling(TOPLEVEL *pr_current, NETLIST *head);
 char *s_hierarchy_return_baseuref(TOPLEVEL *pr_current, char *uref);
 int s_hierarchy_graphical_search(OBJECT* o_current, int count);
+void s_hierarchy_apply_parameters(const GList* objs, GList *parameters);
+gchar *s_hierarchy_apply_parameters_to_text(const gchar *s, GList *parameters);
 /* s_misc.c */
 void verbose_print(char *string);
 void verbose_done(void);
@@ -108,7 +110,7 @@ SCM g_get_renamed_nets(SCM scm_level);
 /* s_traverse.c */
 void s_traverse_init(void);
 void s_traverse_start(TOPLEVEL *pr_current);
-void s_traverse_sheet(TOPLEVEL *pr_current, const GList *obj_list, char *hierarchy_tag);
+void s_traverse_sheet(TOPLEVEL *pr_current, const GList *obj_list, char *hierarchy_tag, GList *parameters);
 CPINLIST *s_traverse_component(TOPLEVEL *pr_current, OBJECT *component, char *hierarchy_tag);
 NET *s_traverse_net(TOPLEVEL *pr_current, NET *nets, int starting, OBJECT *object, char *hierarchy_tag, int type);
 /* vams_misc.c */
diff --git a/gnetlist/src/s_hierarchy.c b/gnetlist/src/s_hierarchy.c
index b481ba2..fe09abd 100644
--- a/gnetlist/src/s_hierarchy.c
+++ b/gnetlist/src/s_hierarchy.c
@@ -37,7 +37,7 @@
 
 void
 s_hierarchy_traverse(TOPLEVEL * pr_current, OBJECT * o_current,
-		     NETLIST * netlist)
+		     NETLIST * netlist, GList* parameters)
 {
     char *attrib;
     int page_control=-1;
@@ -50,6 +50,25 @@ s_hierarchy_traverse(TOPLEVEL * pr_current, OBJECT * o_current,
     char *current_filename;
     int graphical=FALSE;
 
+    // Maintain a list of parameters.  
+    // The inherited ones are prepended first, the attached later.
+    // When looking for a parameter, use the first match in the list.
+    GList* pars = parameters;
+    attrib = o_attrib_search_inherited_attribs_by_name(o_current, "parameter", count);
+    while (attrib) {
+	parameters = g_list_prepend(parameters, attrib);
+	count++;
+	attrib = o_attrib_search_inherited_attribs_by_name(o_current, "parameter", count);
+    }
+    count = 0;
+    attrib = o_attrib_search_attached_attribs_by_name(o_current, "parameter", count);
+    while (attrib) {
+	parameters = g_list_prepend(parameters, attrib);
+	count++;
+	attrib = o_attrib_search_attached_attribs_by_name(o_current, "parameter", count);
+    }
+	    
+    count = 0;
     attrib = o_attrib_search_attached_attribs_by_name (o_current, "source", 0);
 
     /* if above is null, then look inside symbol */
@@ -100,6 +119,10 @@ s_hierarchy_traverse(TOPLEVEL * pr_current, OBJECT * o_current,
                                                   HIERARCHY_FORCE_LOAD,
                                                   &err);
 
+	    // apply parameters to child_page
+
+	    s_hierarchy_apply_parameters(s_page_objects(child_page), parameters);
+
 	    if (child_page == NULL) {
               g_warning (_("Failed to load subcircuit '%s': %s\n"),
                          current_filename, err->message);
@@ -122,7 +145,7 @@ s_hierarchy_traverse(TOPLEVEL * pr_current, OBJECT * o_current,
 		/*netlist->hierarchy_tag = u_basic_strdup (netlist->component_uref);*/
 		s_traverse_sheet (pr_current,
 		                  s_page_objects (pr_current->page_current),
-		                  netlist->component_uref);
+		                  netlist->component_uref, parameters);
 
 		verbose_print("^");
 	    }
@@ -176,6 +199,15 @@ s_hierarchy_traverse(TOPLEVEL * pr_current, OBJECT * o_current,
           } 
        }
     }
+
+    // Delete the parameters defined in this object.
+    // This assumes that the original list remained unchanged
+    // at the tail.
+    while (parameters && parameters != pars) {
+        g_free(parameters->data);
+	parameters = g_list_delete_link(parameters, parameters);
+    }
+
 }
 
 
@@ -646,3 +678,94 @@ int s_hierarchy_graphical_search (OBJECT* o_current, int count)
   return FALSE;
 }
 
+void s_hierarchy_apply_parameters(const GList* objs, GList *parameters)
+{
+	OBJECT *a_current;
+	const GList *iter;
+	gchar *new_text;
+	for (iter = objs; iter != NULL; iter = g_list_next (iter)) {
+		a_current = iter->data;
+		if (a_current->type == OBJ_TEXT) {
+			new_text = s_hierarchy_apply_parameters_to_text(a_current->text->string, parameters);
+			if (new_text) {
+				g_free(a_current->text->string);
+				a_current->text->string = new_text;
+			}
+		}
+		// Do we need to descend into the objects?
+	}
+}
+
+// Return s with parameters substituted
+// Parameters have the form $UPPERCASE
+
+gchar *s_hierarchy_apply_parameters_to_text(const gchar *s, GList *parameters)
+{
+	// This assumes that all texts are valid utf-8.
+
+	gchar *new = NULL;
+	gchar *dollar;
+
+	dollar = g_utf8_strchr(s, -1, g_utf8_get_char ("$"));
+	while (dollar) {
+		int plen = 0;
+		gchar *pstart = g_utf8_find_next_char (dollar, NULL);
+		gchar *pend = pstart;
+		gunichar pchar = g_utf8_get_char(pend);
+		// skip a double $$
+		if (pchar == g_utf8_get_char("$"))
+			pend = g_utf8_find_next_char (pend, NULL);
+		else if (pchar == g_utf8_get_char("{")) {
+			// a parameter name in ${BRACES}
+			pstart = g_utf8_find_next_char (pend, NULL);
+			pend = pstart;
+			while (*pend && g_utf8_get_char(pend) != g_utf8_get_char("}")) {
+				plen++;
+				pend = g_utf8_find_next_char (pend, NULL);
+			}
+			plen = pend - pstart;
+			if (*pend)
+				pend = g_utf8_find_next_char (pend, NULL);
+		}
+		else
+			// count the number of UTF-8 uppercase letters and numbers
+			while (g_unichar_isupper (pchar)
+			       || g_unichar_isdigit(pchar)) {
+				plen++;
+				pend = g_utf8_find_next_char (pend, NULL);
+				pchar = g_utf8_get_char(pend);
+				plen = pend - pstart;
+			}
+		if (plen) {
+			// find the first parameter definition that matches the 
+			// parameter.  A colon separates the parameter name from the value
+			// in the definition
+			const GList *iter;
+			for (iter = parameters; iter != NULL; iter = g_list_next (iter)) 
+				if (!strncmp(pstart, iter->data, plen))
+					if (g_utf8_get_char(iter->data+plen)==g_utf8_get_char (":"))
+						break;
+			if (iter) {
+				// copy the prefix and substitution into new, and
+				// resume with the remaining s
+				gchar *nnew = new;
+				gchar *nval = g_utf8_find_next_char(iter->data+plen, NULL);
+				gchar *opre = g_strndup(s, dollar-s);
+				if (new)
+					new = g_strconcat(new, opre, nval, NULL);
+				else
+					new = g_strconcat(opre, nval, NULL);
+				g_free(opre);
+				g_free(nnew);
+				s = pend;
+			}
+		}
+		dollar = g_utf8_strchr(pend, -1, g_utf8_get_char ("$"));
+	}
+	if (new && *s) {
+		gchar *nnew = new;
+		new = g_strconcat(new, s);
+		g_free(nnew);
+	}
+	return new;
+}
diff --git a/gnetlist/src/s_traverse.c b/gnetlist/src/s_traverse.c
index eb4cefb..70c5a45 100644
--- a/gnetlist/src/s_traverse.c
+++ b/gnetlist/src/s_traverse.c
@@ -126,7 +126,7 @@ void s_traverse_start(TOPLEVEL * pr_current)
     /* only traverse pages which are toplevel, ie not underneath */
     if (p_current->page_control == 0) {
       pr_current->page_current = p_current;
-      s_traverse_sheet (pr_current, s_page_objects (p_current), NULL);
+      s_traverse_sheet (pr_current, s_page_objects (p_current), NULL, NULL);
     }
   }
 
@@ -146,7 +146,7 @@ void s_traverse_start(TOPLEVEL * pr_current)
 
 
 void
-s_traverse_sheet (TOPLEVEL * pr_current, const GList *obj_list, char *hierarchy_tag)
+s_traverse_sheet (TOPLEVEL * pr_current, const GList *obj_list, char *hierarchy_tag, GList *parameters)
 {
   NETLIST *netlist;
   char *temp;
@@ -259,7 +259,7 @@ s_traverse_sheet (TOPLEVEL * pr_current, const GList *obj_list, char *hierarchy_
       
       /* now you need to traverse any underlying schematics */
       if (is_hierarchy) {
-	s_hierarchy_traverse(pr_current, o_current, netlist);
+	s_hierarchy_traverse(pr_current, o_current, netlist, parameters);
       }
     }
   }
