void s_check_missing_attribute(OBJECT *object, char *attribute, SYMCHECK *s_current) { char *string; int found_first=FALSE; int counter=0; char *message; if (!attribute) { return; } string = o_attrib_search_object_attribs_by_name (object, attribute, counter); if (!string) { message = g_strdup_printf ( "Missing %s= attribute\n", attribute); s_current->warning_messages = g_list_append(s_current->warning_messages, message); s_current->warning_count++; } while (string) { if (found_first) { message = g_strdup_printf ( "Found multiple %s=%s attributes on one pin\n", attribute, string); s_current->error_messages = g_list_append(s_current->error_messages, message); s_current->error_count++; } /* this is the first attribute found */ if (!found_first) { message = g_strdup_printf ( "Found %s=%s attribute\n", attribute, string); s_current->info_messages = g_list_append(s_current->info_messages, message); found_first=TRUE; } g_free(string); counter++; string = o_attrib_search_object_attribs_by_name (object, attribute, counter); } }
CPINLIST *s_traverse_component(TOPLEVEL * pr_current, OBJECT * component, char *hierarchy_tag) { CPINLIST *cpinlist_head = NULL; CPINLIST *cpins = NULL; NET *nets_head = NULL; NET *nets = NULL; GList *iter; cpinlist_head = cpins = s_cpinlist_add(NULL); cpins->plid = -1; for (iter = component->complex->prim_objs; iter != NULL; iter = g_list_next (iter)) { OBJECT *o_current = iter->data; /* Ignore objects which aren't net pins */ if (o_current->type != OBJ_PIN || o_current->pin_type != PIN_TYPE_NET) continue; /* add cpin node */ cpins = s_cpinlist_add(cpins); cpins->plid = o_current->sid; cpins->type = o_current->pin_type; cpins->pin_number = o_attrib_search_object_attribs_by_name (o_current, "pinnumber", 0); cpins->pin_label = o_attrib_search_object_attribs_by_name (o_current, "pinlabel", 0); /* head nets node */ /* is this really need */ nets_head = nets = s_net_add(NULL); nets->nid = -1; /* This avoids us adding an unnamed net for an unconnected pin */ if (o_current->conn_list != NULL) { s_traverse_net (pr_current, nets, TRUE, o_current, hierarchy_tag, cpins->type); s_traverse_clear_all_visited (s_page_objects (pr_current->page_current)); } cpins->nets = nets_head; /* s_net_print(nets); */ } return (cpinlist_head); }
/*! \brief Find a pin with a particular attribute. * \par Function Description * Search for a pin inside the given complex which has an attribute * matching those passed. * * \param [in] object complex OBJECT whos pins to search. * \param [in] name the attribute name to search for. * \param [in] wanted_value the attribute value to search for. * \return The pin OBJECT with the given attribute, NULL otherwise. */ OBJECT *o_complex_find_pin_by_attribute (OBJECT *object, char *name, char *wanted_value) { GList *iter; OBJECT *o_current; char *value; int found; g_return_val_if_fail (object != NULL, NULL); g_return_val_if_fail (object->type == OBJ_COMPLEX || object->type == OBJ_PLACEHOLDER, NULL); for (iter = object->complex->prim_objs; iter != NULL; iter = g_list_next (iter)) { o_current = iter->data; if (o_current->type != OBJ_PIN) continue; value = o_attrib_search_object_attribs_by_name (o_current, name, 0); found = (value != NULL && strcmp (value, wanted_value) == 0); g_free (value); if (found) return o_current; } return NULL; }
/* object being a pin */ char *s_net_return_connected_string(TOPLEVEL * pr_current, OBJECT * object, char *hierarchy_tag) { OBJECT *o_current; char *pinnum = NULL; char *uref = NULL; SCM scm_uref; char *temp_uref = NULL; char *string; char *misc; o_current = object; pinnum = o_attrib_search_object_attribs_by_name (o_current, "pinnumber", 0); #if DEBUG printf("found pinnum: %s\n", pinnum); #endif scm_uref = g_scm_c_get_uref(pr_current, o_current->parent); if (scm_is_string( scm_uref )) { temp_uref = scm_to_utf8_string (scm_uref); } /* apply the hierarchy name to the uref */ uref = s_hierarchy_create_uref(pr_current, temp_uref, hierarchy_tag); if (uref && pinnum) { string = g_strdup_printf("%s %s", uref, pinnum); } else { if (pinnum) { string = g_strdup_printf("POWER %s", pinnum); } else { if (hierarchy_tag) { misc = s_hierarchy_create_uref(pr_current, "U?", hierarchy_tag); string = g_strdup_printf("%s ?", misc); g_free(misc); } else { string = g_strdup("U? ?"); } fprintf(stderr, "Missing Attributes (refdes and pin number)\n"); } } g_free(pinnum); g_free(uref); g_free(temp_uref); return (string); }
int s_hierarchy_graphical_search (OBJECT* o_current, int count) { char *graphical_attrib; graphical_attrib = o_attrib_search_object_attribs_by_name (o_current, "graphical", count); if (graphical_attrib) { g_free (graphical_attrib); return TRUE; } return FALSE; }
/*! \todo Finish function documentation!!! * \brief Change slot of selected component * \par Function Description * */ void o_slot_start (GSCHEM_TOPLEVEL *w_current, OBJECT *object) { char *slot_value; /* single object for now */ if (object->type != OBJ_COMPLEX) return; slot_value = o_attrib_search_object_attribs_by_name (object, "slot", 0); if (slot_value == NULL) { /* we didn't find a slot=? attribute, make something up */ /* for now.. this is an error condition */ slot_value = g_strdup ("1"); } slot_edit_dialog (w_current, slot_value); g_free (slot_value); }
/*! \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 ret = SCM_EOL; NETLIST *nl_current; char *uref; char *wanted_attrib; SCM_ASSERT(scm_is_string (scm_uref), scm_uref, SCM_ARG1, "gnetlist:get-all-package-attributes"); SCM_ASSERT(scm_is_string (scm_wanted_attrib), scm_wanted_attrib, SCM_ARG2, "gnetlist:get-all-package-attributes"); uref = scm_to_utf8_string (scm_uref); wanted_attrib = scm_to_utf8_string (scm_wanted_attrib); /* here is where you make it multi page aware */ nl_current = netlist_head; /* 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) { char *value = o_attrib_search_object_attribs_by_name (nl_current->object_ptr, wanted_attrib, 0); ret = scm_cons (value ? scm_from_utf8_string (value) : SCM_BOOL_F, ret); g_free (value); } } nl_current = nl_current->next; } free (uref); free (wanted_attrib); return scm_reverse_x (ret, SCM_EOL); }
/*! \brief Search for slotdef attribute. * \par Function Description * Search for slotdef attribute. * * \param [in] object The OBJECT list to search. * \param [in] slotnumber The slot number to search for. * \return Character string with attribute value, NULL otherwise. * * \warning * Caller must g_free returned character string. */ static char *s_slot_search_slotdef (OBJECT *object, int slotnumber) { int counter = 0; char *slotdef; char *search_for; search_for = g_strdup_printf ("%d:", slotnumber); while (1) { slotdef = o_attrib_search_object_attribs_by_name (object, "slotdef", counter++); if (slotdef == NULL || strncmp (slotdef, search_for, strlen (search_for)) == 0) break; g_free (slotdef); } g_free (search_for); return slotdef; }
void s_check_pintype (const GList *obj_list, SYMCHECK *s_current) { const GList *iter; int counter=0; char *pintype; char *message; char *pintypes[] = {"in", "out", "io", "oc", "oe", "pas", "tp", "tri", "clk", "pwr", NULL}; for (iter = obj_list; iter != NULL; iter = g_list_next (iter)) { OBJECT *o_current = iter->data; if (o_current->type == OBJ_PIN) { for (counter = 0; (pintype = o_attrib_search_object_attribs_by_name (o_current, "pintype", counter)) != NULL; counter++) { message = g_strdup_printf("Found pintype=%s attribute\n", pintype); s_current->info_messages = g_list_append(s_current->info_messages, message); if ( ! s_check_list_has_item(pintypes, pintype)) { message = g_strdup_printf ("Invalid pintype=%s attribute\n", pintype); s_current->error_messages = g_list_append(s_current->error_messages, message); s_current->error_count++; } g_free(pintype); } } } }
/*! \brief check the symversion of a complex object * \par Function Description * This function compares the symversion of a symbol with it's * earlier saved symversion in a schematic. * Major symversion changes are added to the toplevel object * (toplevel->major_changed_refdes), minor changes are reported * to the messaging system. * * \param toplevel The TOPLEVEL object * \param object The complex OBJECT */ void o_complex_check_symversion(TOPLEVEL* toplevel, OBJECT* object) { char *inside = NULL; char *outside = NULL; char *refdes = NULL; double inside_value = -1.0; double outside_value = -1.0; char *err_check = NULL; int inside_present = FALSE; int outside_present = FALSE; double inside_major, inside_minor; double outside_major, outside_minor; g_return_if_fail (object != NULL); g_return_if_fail ((object->type == OBJ_COMPLEX || object->type == OBJ_PLACEHOLDER)); g_return_if_fail (object->complex != NULL); /* first look on the inside for the symversion= attribute */ inside = o_attrib_search_inherited_attribs_by_name (object, "symversion", 0); /* now look for the symversion= attached to object */ outside = o_attrib_search_attached_attribs_by_name (object, "symversion", 0); /* get the uref for future use */ refdes = o_attrib_search_object_attribs_by_name(object, "refdes", 0); if (!refdes) { refdes = g_strdup ("unknown"); } if (inside) { inside_value = strtod(inside, &err_check); if (inside_value == 0 && inside == err_check) { if (inside) { s_log_message(_("WARNING: Symbol version parse error on refdes %s:\n" "\tCould not parse symbol file symversion=%s\n"), refdes, inside); } else { s_log_message(_("WARNING: Symbol version parse error on refdes %s:\n" "\tCould not parse symbol file symversion=\n"), refdes); } goto done; } inside_present = TRUE; } else { inside_present = FALSE; /* attribute not inside */ } if (outside) { outside_value = strtod(outside, &err_check); if (outside_value == 0 && outside == err_check) { s_log_message(_("WARNING: Symbol version parse error on refdes %s:\n" "\tCould not parse attached symversion=%s\n"), refdes, outside); goto done; } outside_present = TRUE; } else { outside_present = FALSE; /* attribute not outside */ } #if DEBUG printf("%s:\n\tinside: %.1f outside: %.1f\n\n", object->name, inside_value, outside_value); #endif /* symversion= is not present anywhere */ if (!inside_present && !outside_present) { /* symbol is legacy and versioned okay */ goto done; } /* No symversion inside, but a version is outside, this is a weird case */ if (!inside_present && outside_present) { s_log_message(_("WARNING: Symbol version oddity on refdes %s:\n" "\tsymversion=%s attached to instantiated symbol, " "but no symversion= inside symbol file\n"), refdes, outside); goto done; } /* inside & not outside is a valid case, means symbol in library is newer */ /* also if inside_value is greater than outside_value, then symbol in */ /* library is newer */ if ((inside_present && !outside_present) || ((inside_present && outside_present) && (inside_value > outside_value))) { s_log_message(_("WARNING: Symbol version mismatch on refdes %s (%s):\n" "\tSymbol in library is newer than " "instantiated symbol\n"), refdes, object->complex_basename); /* break up the version values into major.minor numbers */ inside_major = floor(inside_value); inside_minor = inside_value - inside_major; if (outside_present) { outside_major = floor(outside_value); outside_minor = outside_value - outside_major; } else { /* symversion was not attached to the symbol, set all to zero */ outside_major = 0.0; outside_minor = 0.0; outside_value = 0.0; } #if DEBUG printf("i: %f %f %f\n", inside_value, inside_major, inside_minor); printf("o: %f %f %f\n", outside_value, outside_major, outside_minor); #endif if (inside_major > outside_major) { char* refdes_copy; s_log_message(_("\tMAJOR VERSION CHANGE (file %.3f, " "instantiated %.3f, %s)!\n"), inside_value, outside_value, refdes); /* add the refdes to the major_changed_refdes GList */ /* make sure refdes_copy is freed somewhere */ refdes_copy = g_strconcat (refdes, " (", object->complex_basename, ")", NULL); toplevel->major_changed_refdes = g_list_append(toplevel->major_changed_refdes, refdes_copy); /* don't bother checking minor changes if there are major ones*/ goto done; } if (inside_minor > outside_minor) { s_log_message(_("\tMinor version change (file %.3f, " "instantiated %.3f)\n"), inside_value, outside_value); } goto done; } /* outside value is greater than inside value, this is weird case */ if ((inside_present && outside_present) && (outside_value > inside_value)) { s_log_message(_("WARNING: Symbol version oddity on refdes %s:\n" "\tInstantiated symbol is newer than " "symbol in library\n"), refdes); goto done; } /* if inside_value and outside_value match, then symbol versions are okay */ done: g_free(inside); g_free(outside); g_free(refdes); }
void s_check_pinseq (const GList *obj_list, SYMCHECK *s_current) { char *string; int found_first=FALSE; int missing_pinseq_attrib_sum=0; int multiple_pinseq_attrib_sum=0; int counter=0; GList *found_numbers = NULL; GList *ptr1 = NULL; GList *ptr2 = NULL; const GList *iter; char *number; char *message; for (iter = obj_list; iter != NULL; iter = g_list_next (iter)) { OBJECT *o_current = iter->data; if (o_current->type == OBJ_PIN) { missing_pinseq_attrib_sum = 0; multiple_pinseq_attrib_sum = 0; found_first = FALSE; counter = 0; string = o_attrib_search_object_attribs_by_name (o_current, "pinseq", counter); if (!string) { message = g_strdup ("Missing pinseq= attribute\n"); s_current->error_messages = g_list_append(s_current->error_messages, message); missing_pinseq_attrib_sum++; s_current->error_count++; } while (string) { message = g_strdup_printf ("Found pinseq=%s attribute\n", string); s_current->info_messages = g_list_append(s_current->info_messages, message); number = g_strdup (string); if (strcmp(number, "0") == 0) { message = g_strdup ("Found pinseq=0 attribute\n"); s_current->error_messages = g_list_append(s_current->error_messages, message); s_current->error_count++; } if (found_first) { message = g_strdup_printf ( "Found multiple pinseq=%s attributes on one pin\n", string); s_current->error_messages = g_list_append(s_current->error_messages, message); multiple_pinseq_attrib_sum++; s_current->error_count++; } g_free(string); /* this is the first attribute found */ if (!found_first) { found_numbers = g_list_append(found_numbers, number); found_first=TRUE; } else { g_free(number); } counter++; string = o_attrib_search_object_attribs_by_name (o_current, "pinseq", counter); } s_current->missing_pinseq_attrib += missing_pinseq_attrib_sum; s_current->multiple_pinseq_attrib += multiple_pinseq_attrib_sum; } } ptr1 = found_numbers; while (ptr1) { char *string = (char *) ptr1->data; int found = 0; ptr2 = found_numbers; while(ptr2 && string) { char *current = (char *) ptr2->data; if (current && strcmp(string, current) == 0) { found++; } ptr2 = g_list_next(ptr2); } if (found > 1) { message = g_strdup_printf ( "Found duplicate pinseq=%s attribute in the symbol\n", string); s_current->error_messages = g_list_append(s_current->error_messages, message); s_current->error_count++; s_current->duplicate_pinseq_attrib++; } ptr1 = g_list_next(ptr1); } ptr1 = found_numbers; while (ptr1) { g_free(ptr1->data); ptr1 = g_list_next(ptr1); } g_list_free(found_numbers); }
/*! \brief Get pin attributes * * This function takes a pointer to the OBJECT pin, and returns a list * of attribs found attached to the pin. The returned list is a * STRING_LIST where the ->data holds a name=value string. * The algorithm is as follows: * -# Form refdes:pinnumber label for this pin. * -# Get row number of this refdes:pinnumber * -# Create a list of name=value pairs from entries in the pin_table * on this row. * -# Return list of name=value pairs found. * * \param refdes Ref des string * \param pin Pin object * \returns name=value pair as a STRING_LIST */ STRING_LIST *s_toplevel_get_pin_attribs_in_sheet(char *refdes, OBJECT *pin) { STRING_LIST *new_attrib_list; STRING_LIST *local_attrib_list; int i; int row = -1; int count = 0; char *pinnumber; char *row_label; char *name_value_pair; char *new_attrib_value; char *new_attrib_name; #if DEBUG printf("----- Entering s_toplevel_get_pin_attribs_in_sheet.\n"); #endif /* First find pos of this pin in the master pin list */ /* first convert refdes, pin to refdes:pinno text string. Then call table_get_index. */ pinnumber = o_attrib_search_object_attribs_by_name (pin, "pinnumber", 0); if ( (refdes != NULL) && (pinnumber != NULL) ) { row_label = g_strconcat(refdes, ":", pinnumber, NULL); } else { fprintf(stderr, "In s_toplevel_get_pin_attribs_in_sheet, either refdes or pinnumber of object missing!\n"); return NULL; } row = s_table_get_index(sheet_head->master_pin_list_head, row_label); /* Sanity check */ if (row == -1) { /* we didn't find the item in the list */ fprintf(stderr, "In s_toplevel_get_pin_attribs_in_sheet, we didn't find the refdes:pin in the master list!\n"); return NULL; } /* Now get all attribs associated with this refdes (in TABLE, indexed * by position), and insert them into new_attrib_list. */ new_attrib_list = s_string_list_new(); /* init new_attrib_list */ i = 0; local_attrib_list = sheet_head->master_pin_attrib_list_head; while (local_attrib_list != NULL) { /* iterate over all possible attribs */ new_attrib_name = g_strdup(local_attrib_list->data); /* take attrib name from column headings */ if ( ((sheet_head->pin_table)[row][i]).attrib_value ) { new_attrib_value = g_strdup( ((sheet_head->pin_table)[row][i]).attrib_value ); name_value_pair = g_strconcat(new_attrib_name, "=", new_attrib_value, NULL); g_free(new_attrib_value); } else { name_value_pair = g_strconcat(new_attrib_name, "=", NULL); /* empty attrib */ } s_string_list_add_item(new_attrib_list, &count, name_value_pair); /* add name=value to new list */ g_free(new_attrib_name); g_free(name_value_pair); /* Sanity check */ if (count != i+1) { /* for some reason, we have lost a name_value_pair somewhere . . . */ fprintf(stderr, "In s_toplevel_get_pin_attribs_in_sheet, count != i! Exiting . . . .\n"); exit(-1); } /* iterate */ i++; local_attrib_list = local_attrib_list->next; } /* while (local_attrib_list != NULL) */ return new_attrib_list; }
/*! \brief Copy SHEET_DATA content to TOP_LEVEL * * This function * loops through all objects on (PAGE page)->(OBJECT *start_obj). * It takes the updated SHEET_DATA->TABLE data and then updates the * objects with the new attribs & attrib values. * For each component, it updates the attached * attrib values using the updated values held in the SHEET_DATA->TABLE * structure. It does so in three steps: * -# First find and update component attribs. * -# Then find and update net attribs. * -# Finally find and update pin attribs. * \param toplevel TOPLEVEL structure * \param page schematic page to copy */ void s_toplevel_sheetdata_to_toplevel (TOPLEVEL *toplevel, PAGE *page) { GList *copy_list; GList *o_iter, *prim_iter; char *temp_uref; STRING_LIST *new_comp_attrib_pair_list; STRING_LIST *new_pin_attrib_list; /* ----- First deal with all components on the page. ----- */ #ifdef DEBUG printf("----- In s_toplevel_sheetdata_to_toplevel, handling components\n"); #endif /* Work from a copy list, as objects can be deleted * from the list during iteration over the list. */ /* NB: g_list_copy doesn't declare its input const, so we cast */ copy_list = g_list_copy ((GList *)s_page_objects (page)); /* Iterate backwards since attributes are attached after their * parent objects in the list. Attributes can get deleted during * the iteration. */ for (o_iter = g_list_last (copy_list); o_iter != NULL; o_iter = g_list_previous (o_iter)) { OBJECT *o_current = o_iter->data; /* ------- Object is a component. Handle component attributes. ------- */ if (o_current->type == OBJ_COMPLEX) { /* Note that OBJ_COMPLEX = component + attribs */ #if 0 if (o_attrib_search_object_attribs_by_name (o_current, "graphical", 0)) { break; /* Ignore graphical components */ } #endif temp_uref = s_attrib_get_refdes(o_current); if (temp_uref != NULL) { /* Must create a name=value pair list for each particular component * which we can pass to function updating o_current. This function * places all attribs * found in the row into new_comp_attrib_pair_list. */ new_comp_attrib_pair_list = s_table_create_attrib_pair(temp_uref, sheet_head->component_table, sheet_head->master_comp_list_head, sheet_head->comp_attrib_count); /* Now update attribs in toplevel using this list. */ s_toplevel_update_component_attribs_in_toplevel(toplevel, o_current, new_comp_attrib_pair_list); g_free(temp_uref); } else { #ifdef DEBUG printf("In s_toplevel_sheetdata_to_toplevel, found complex with no refdes. name = %s\n", o_current->name); #endif } } /* if (o_current->type == OBJ_COMPLEX) */ } g_list_free (copy_list); #if 0 /* ----- Next deal with all nets on the page. ----- */ /* This is TBD */ #endif /* ----- Finally deal with all pins on the page. ----- */ /* ----- Next deal with all nets on the page. ----- */ #ifdef DEBUG printf("----- In s_toplevel_sheetdata_to_toplevel, handling pins\n"); #endif /* Work from a copy list in case objects are * deleted from the list during its iteration. */ /* NB: g_list_copy doesn't declare its input const, so we cast */ copy_list = g_list_copy ((GList *)s_page_objects (page)); for (o_iter = g_list_last (copy_list); o_iter != NULL; o_iter = g_list_previous (o_iter)) { OBJECT *o_current = o_iter->data; /* ------- Object is a complex. Handle pins by looking ------ */ /* ------- for all pins attached to a component. ------ */ if (o_current->type == OBJ_COMPLEX) { /* Upon finding a component, here's what to do: * 0. Get refdes of component. * 1. Loop over prim_objects, looking for pins. * 2. When a pin is found, create refdes:pinnumber pair * used in searching TABLE. * 3. Search TABLE using refdes:pinnumber as key, and get list of * attribs corresponding to this refdes:pinnumber * 4. Stick the attribs into the TOPLEVEL data structure. */ temp_uref = s_attrib_get_refdes(o_current); if ( (temp_uref != NULL) && (o_current->complex->prim_objs) ) { /* make sure object complex has a refdes */ for (prim_iter = o_current->complex->prim_objs; prim_iter != NULL; prim_iter = g_list_next (prim_iter)) { OBJECT *comp_prim_obj = prim_iter->data; if (comp_prim_obj->type == OBJ_PIN) { new_pin_attrib_list = s_toplevel_get_pin_attribs_in_sheet (temp_uref, comp_prim_obj); s_toplevel_update_pin_attribs_in_toplevel (toplevel, temp_uref, comp_prim_obj, new_pin_attrib_list); } } } /* if(temp_uref */ g_free(temp_uref); } } g_list_free (copy_list); return; }
/*! \brief Gets or generates free numbers for the autonumbering process. * \par Function Description * This function gets or generates new numbers for the <B>OBJECT o_current</B>. * It uses the element numbers <B>used_numbers</B> and the list of the free slots * <B>free_slots</B> of the <B>AUTONUMBER_TEXT</B> struct. * \return * The new number is returned into the <B>number</B> parameter. * <B>slot</B> is set if autoslotting is active, else it is set to zero. */ void autonumber_get_new_numbers(AUTONUMBER_TEXT *autotext, OBJECT *o_current, gint *number, gint *slot) { GList *item; gint new_number, numslots, i; AUTONUMBER_SLOT *freeslot; OBJECT *o_parent = NULL; GList *freeslot_item; gchar *numslot_str; new_number = autotext->startnum; /* Check for slots first */ /* 1. are there any unused slots in the database? */ o_parent = o_current->attached_to; if (autotext->slotting && o_parent != NULL) { freeslot = g_new(AUTONUMBER_SLOT,1); freeslot->symbolname = o_parent->complex_basename; freeslot->number = 0; freeslot->slotnr = 0; freeslot_item = g_list_find_custom(autotext->free_slots, freeslot, (GCompareFunc) freeslot_compare); g_free(freeslot); /* Yes! -> remove from database, apply it */ if (freeslot_item != NULL) { freeslot = freeslot_item->data; *number = freeslot->number; *slot = freeslot->slotnr; g_free(freeslot); autotext->free_slots = g_list_delete_link(autotext->free_slots, freeslot_item); return; } } /* get a new number */ item = autotext->used_numbers; while (1) { while (item != NULL && GPOINTER_TO_INT(item->data) < new_number) item = g_list_next(item); if (item == NULL || GPOINTER_TO_INT(item->data) > new_number) break; else /* new_number == item->data */ new_number++; } *number = new_number; *slot = 0; /* insert the new number to the used list */ autotext->used_numbers = g_list_insert_sorted(autotext->used_numbers, GINT_TO_POINTER(new_number), (GCompareFunc) autonumber_sort_numbers); /* 3. is o_current a slotted object ? */ if ((autotext->slotting) && o_parent != NULL) { numslot_str = o_attrib_search_object_attribs_by_name (o_parent, "numslots", 0); if (numslot_str != NULL) { sscanf(numslot_str," %d",&numslots); g_free(numslot_str); if (numslots > 0) { /* Yes! -> new number and slot=1; add the other slots to the database */ *slot = 1; for (i=2; i <=numslots; i++) { freeslot = g_new(AUTONUMBER_SLOT,1); freeslot->symbolname = o_parent->complex_basename; freeslot->number = new_number; freeslot->slotnr = i; autotext->free_slots = g_list_insert_sorted(autotext->free_slots, freeslot, (GCompareFunc) freeslot_compare); } } } } }
/*! \brief Refresh & cache number of connected entities. * * \par Function Description * Traverse all network segments reachable from this net and count * total number of unique entities connected to all net segments. * * For the purpose of this function, an entity is: * - pin * - bus * - attached netname attribute * * Computed number of entities is afterwards stored in all traversed * net segments. * * The algorithm does not handle corner cases, ie two bus segments * belonging to the same bus will be counted twice. * * \param [in] toplevel The TOPLEVEL object * \param [in] o_current The NET OBJECT to check connectivity of */ void o_net_refresh_conn_cache(TOPLEVEL *toplevel, OBJECT *o_current) { gint num_conns = 0; GHashTable *visited; GHashTableIter iter; GList *stack = NULL; OBJECT *obj; gpointer key; g_return_if_fail (toplevel); g_return_if_fail (o_current); g_return_if_fail (o_current->type == OBJ_NET); /* Keep track of visited nets, pins and buses in the hash table. * This way we short-circuit the search and avoid loops. */ visited = g_hash_table_new (NULL, NULL); /* * Add the starting net to the hash so: * 1. it is not traversed twice * 2. it is updated at the end if no connections are found */ g_hash_table_insert (visited, o_current, o_current); /* Check if a netname= is attached to the starting net segment */ if (NULL != o_attrib_search_object_attribs_by_name (o_current, "netname", 0)) { num_conns += 1; } /* Keep track of connections to search at each net segment in a stack. * Each stack entry points to an entry in obj->conn_list. * Pop the stack when we have no more connections to check. * Push next entry on the stack if we encounter a net segment. */ /* Initialise the stack for the starting net segment. */ stack = g_list_prepend (stack, o_current->conn_list); while (stack != NULL) { /* At start of the loop, take a new connection from the stack. */ GList *conn_list = (GList*) stack->data; CONN *conn; if (conn_list == NULL) { /* No more connections to check at this level. Pop the stack. */ stack = g_list_delete_link (stack, stack); continue; } /* Extract the next connected object and advance the connection list. */ conn = (CONN*) conn_list->data; stack->data = (gpointer) g_list_next (conn_list); if (conn == NULL) /* should not happen */ continue; obj = conn->other_object; if (obj == NULL) /* should not happen */ continue; /* Act upon the object that is connected to the segment. */ switch (obj->type) { case OBJ_PIN: case OBJ_BUS: if (NULL == g_hash_table_lookup (visited, obj)) { g_hash_table_insert (visited, obj, obj); num_conns += 1; } break; case OBJ_NET: if (NULL == g_hash_table_lookup (visited, obj)) { g_hash_table_insert (visited, obj, obj); /* Check if a netname= is attached to this net segment */ if (NULL != o_attrib_search_object_attribs_by_name (obj, "netname", 0)) { num_conns += 1; } /* Push new list of connections to check onto the stack */ stack = g_list_prepend (stack, obj->conn_list); } break; default: break; } } /* Cache value of num_conns in all visited objects */ g_hash_table_iter_init (&iter, visited); while (g_hash_table_iter_next (&iter, &key, NULL)) { obj = (OBJECT*) key; if (obj->type == OBJ_NET) { obj->net_num_connected = num_conns; obj->valid_num_connected = TRUE; } } g_hash_table_destroy (visited); g_list_free (stack); }
void s_check_pinnumber (const GList *obj_list, SYMCHECK *s_current) { char *string; int missing_pinnumber_attrib_sum=0; int multiple_pinnumber_attrib_sum=0; int counter=0; int i; gchar **net_tokens; gchar **pin_tokens; GList *net_numbers = NULL; GList *pin_numbers = NULL; GList *cur = NULL; GList *cur2 = NULL; const GList *iter; char *message; char *net = NULL; /* collect all net pins */ for (counter = 0; (net = o_attrib_search_floating_attribs_by_name (obj_list, "net", counter)) != NULL; counter++) { message = g_strdup_printf ("Found net=%s attribute\n", net); s_current->info_messages = g_list_append(s_current->info_messages, message); net_tokens = g_strsplit(net,":", -1); /* length of net tokens have to be 2 */ if (net_tokens[1] == NULL) { message = g_strdup_printf ("Bad net= attribute [net=%s]\n", net); s_current->error_messages = g_list_append(s_current->error_messages, message); s_current->error_count++; g_strfreev(net_tokens); continue; } else if (net_tokens[2] != NULL) { /* more than 2 tokens */ message = g_strdup_printf ("Bad net= attribute [net=%s]\n", net); s_current->error_messages = g_list_append(s_current->error_messages, message); s_current->error_count++; g_strfreev(net_tokens); continue; } pin_tokens = g_strsplit(net_tokens[1],",",-1); for (i = 0; pin_tokens[i] != NULL; i++) { net_numbers = g_list_append(net_numbers, g_strdup(pin_tokens[i])); message = g_strdup_printf ("Found pin number %s in net attribute\n", pin_tokens[i]); s_current->info_messages = g_list_append(s_current->info_messages, message); s_current->numnetpins++; } g_free(net); g_strfreev(net_tokens); g_strfreev(pin_tokens); } /* check for duplicate net pin numbers */ net_numbers = g_list_sort(net_numbers, (GCompareFunc)strcmp); for (cur = net_numbers; cur != NULL && g_list_next(cur) != NULL; cur = g_list_next(cur)) { if (strcmp((gchar*)cur->data, (gchar*) cur->next->data) == 0) { message = g_strdup_printf ("Found duplicate pin in net= " "attributes [%s]\n", (gchar*) cur->data); s_current->error_messages = g_list_append(s_current->error_messages, message); s_current->error_count++; } if (strcmp((gchar*) cur->data, "0") == 0) { message = g_strdup ("Found pinnumber 0 in net= attribute\n"); s_current->error_messages = g_list_append(s_current->error_messages, message); s_current->error_count++; } } /* collect all pin numbers */ for (iter = obj_list; iter != NULL; iter = g_list_next (iter)) { OBJECT *o_current = iter->data; if (o_current->type == OBJ_PIN) { s_current->numpins++; missing_pinnumber_attrib_sum = 0; multiple_pinnumber_attrib_sum = 0; for (counter = 0; (string = o_attrib_search_object_attribs_by_name (o_current, "pinnumber", counter)) != NULL; counter++) { message = g_strdup_printf ("Found pinnumber=%s attribute\n", string); s_current->info_messages = g_list_append(s_current->info_messages, message); if (counter == 0) { /* collect the first appearance */ pin_numbers = g_list_append(pin_numbers, string); } if (counter >= 1) { message = g_strdup_printf ("Found multiple pinnumber=%s attributes" " on one pin\n", string); s_current->error_messages = g_list_append(s_current->error_messages, message); multiple_pinnumber_attrib_sum++; s_current->error_count++; g_free(string); } } if (counter == 0) { message = g_strdup ("Missing pinnumber= attribute\n"); s_current->error_messages = g_list_append(s_current->error_messages, message); missing_pinnumber_attrib_sum++; s_current->error_count++; } s_current->missing_pinnumber_attrib += missing_pinnumber_attrib_sum; s_current->multiple_pinnumber_attrib += multiple_pinnumber_attrib_sum; } } /* check for duplicate pinlabel numbers */ pin_numbers = g_list_sort(pin_numbers, (GCompareFunc)strcmp); for (cur = pin_numbers; cur != NULL && g_list_next(cur) != NULL; cur = g_list_next(cur)) { if (strcmp((gchar*)cur->data, (gchar*) cur->next->data) == 0) { message = g_strdup_printf ("Found duplicate pinnumber=%s attribute " "in the symbol\n", (gchar*) cur->data); s_current->error_messages = g_list_append(s_current->error_messages, message); s_current->error_count++; s_current->duplicate_pinnumber_attrib++; } if (strcmp((gchar*) cur->data, "0") == 0) { message = g_strdup ("Found pinnumber=0 attribute\n"); s_current->error_messages = g_list_append(s_current->error_messages, message); s_current->error_count++; } } /* Check for all pins that are in both lists and print a warning. Sometimes this is useful and sometimes it's an error. */ cur = net_numbers; cur2 = pin_numbers; while (cur != NULL && cur2 != NULL) { i = strcmp((gchar*)cur->data, (gchar*)cur2->data); if (i == 0) { message = g_strdup_printf ("Found the same number in a pinnumber " "attribute and in a net attribute [%s]\n", (gchar*) cur->data); s_current->warning_messages = g_list_append(s_current->warning_messages, message); s_current->warning_count++; cur = g_list_next(cur); } else if ( i > 0 ) { cur2 = g_list_next(cur2); } else { /* i < 0 */ cur = g_list_next(cur); } } /* FIXME: this is not correct if a pinnumber is defined as pinnumber and inside a net. We have to calculate the union set */ message = g_strdup_printf ("Found %d pins inside symbol\n", s_current->numpins + s_current->numnetpins); s_current->info_messages = g_list_append(s_current->info_messages, message); g_list_foreach(pin_numbers, (GFunc) g_free, NULL); g_list_free(pin_numbers); g_list_foreach(net_numbers, (GFunc) g_free, NULL); g_list_free(net_numbers); }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void o_slot_end(GSCHEM_TOPLEVEL *w_current, OBJECT *object, const char *string) { TOPLEVEL *toplevel = w_current->toplevel; OBJECT *new_obj; char *slot_value; char *numslots_value; OBJECT *o_slot; char *value = NULL; int numslots; int new_slot_number; int status; g_return_if_fail (object != NULL); status = o_attrib_string_get_name_value (string, NULL, &value); if (!status) { s_log_message (_("Slot attribute malformed\n")); return; } numslots_value = o_attrib_search_object_attribs_by_name (object, "numslots", 0); if (!numslots_value) { s_log_message (_("numslots attribute missing\n")); s_log_message (_("Slotting not allowed for this component\n")); g_free (value); return; } numslots = atoi (numslots_value); g_free (numslots_value); new_slot_number = atoi (value); #if DEBUG printf ("numslots = %d\n", numslots); #endif if (new_slot_number > numslots || new_slot_number <=0 ) { s_log_message (_("New slot number out of range\n")); g_free (value); return; } /* first see if slot attribute already exists outside * complex */ slot_value = s_slot_search_slot (object, &o_slot); g_free (slot_value); if (o_slot != NULL && !o_attrib_is_inherited (o_slot)) { o_text_set_string (toplevel, o_slot, string); } else { /* here you need to do the add the slot attribute since it doesn't exist */ new_obj = o_text_new (toplevel, OBJ_TEXT, ATTRIBUTE_COLOR, object->complex->x, object->complex->y, LOWER_LEFT, 0, /* zero is angle */ string, 10, INVISIBLE, SHOW_NAME_VALUE); s_page_append (toplevel, toplevel->page_current, new_obj); /* manually attach attribute */ o_attrib_attach (toplevel, new_obj, object, FALSE); } s_slot_update_object (toplevel, object); toplevel->page_current->CHANGED = 1; g_free (value); }
/* given a net name, an attribute, and a wanted attribute, return all the given attribute of all the graphical objects connected to that net name */ SCM g_graphical_objs_in_net_with_attrib_get_attrib (SCM scm_netname, SCM scm_has_attribute, SCM scm_wanted_attribute) { SCM list = SCM_EOL; NETLIST *nl_current; CPINLIST *pl_current; char *wanted_net_name; char *wanted_attrib; char *has_attrib; char *net_name; char *attrib_value=NULL; char *has_attrib_value = NULL; char *has_attrib_name = NULL; SCM_ASSERT(scm_is_string (scm_netname), scm_netname, SCM_ARG1, "gnetlist:graphical-objs-in-net-with-attrib-get-attrib"); SCM_ASSERT(scm_is_string (scm_wanted_attribute), scm_wanted_attribute, SCM_ARG3, "gnetlist:graphical-objs-in-net-with-attrib-get-attrib"); SCM_ASSERT(scm_is_string (scm_has_attribute), scm_has_attribute, SCM_ARG2, "gnetlist:graphical-objs-in-net-with-attrib-get-attrib"); scm_dynwind_begin (0); wanted_net_name = scm_to_utf8_string (scm_netname); if (wanted_net_name == NULL) { return list; } scm_dynwind_free (wanted_net_name); wanted_attrib = scm_to_utf8_string (scm_wanted_attribute); scm_dynwind_free (wanted_attrib); has_attrib = scm_to_utf8_string (scm_has_attribute); scm_dynwind_free (has_attrib); nl_current = graphical_netlist_head; /* walk through the list of components, and through the list * of individual pins on each, adding net names to the list * being careful to ignore duplicates, and unconnected pins */ while (nl_current != NULL) { pl_current = nl_current->cpins; while (pl_current != NULL) { if (pl_current->net_name) { net_name = pl_current->net_name; if (strcmp(net_name, wanted_net_name) == 0) { if (o_attrib_string_get_name_value (has_attrib, &has_attrib_name, &has_attrib_value) != 0) { attrib_value = o_attrib_search_object_attribs_by_name (nl_current->object_ptr, has_attrib_name, 0); if ( ((has_attrib_value == NULL) && (attrib_value == NULL)) || ((has_attrib_value != NULL) && (attrib_value != NULL) && (strcmp(attrib_value, has_attrib_value) == 0)) ) { g_free (attrib_value); attrib_value = o_attrib_search_object_attribs_by_name (nl_current->object_ptr, wanted_attrib, 0); if (attrib_value) { list = scm_cons (scm_from_utf8_string (attrib_value), list); } g_free (attrib_value); } g_free (has_attrib_name); g_free (has_attrib_value); } } } pl_current = pl_current->next; } nl_current = nl_current->next; } scm_dynwind_end (); return list; }
/* scm_pin is the value associated with the pinnumber= attribute and uref */ SCM g_get_attribute_by_pinnumber(SCM scm_uref, SCM scm_pin, SCM scm_wanted_attrib) { SCM scm_return_value; NETLIST *nl_current; OBJECT *pin_object; char *uref; char *pin; char *wanted_attrib; char *return_value = NULL; int done = FALSE; SCM_ASSERT(scm_is_string (scm_uref), scm_uref, SCM_ARG1, "gnetlist:get-attribute-by-pinnumber"); SCM_ASSERT(scm_is_string (scm_pin), scm_pin, SCM_ARG2, "gnetlist:get-attribute-by-pinnumber"); SCM_ASSERT(scm_is_string (scm_wanted_attrib), scm_wanted_attrib, SCM_ARG3, "gnetlist:get-attribute-by-pinnumber"); scm_dynwind_begin (0); uref = scm_to_utf8_string (scm_uref); scm_dynwind_free (uref); pin = scm_to_utf8_string (scm_pin); scm_dynwind_free (pin); wanted_attrib = scm_to_utf8_string (scm_wanted_attrib); scm_dynwind_free (wanted_attrib); /* here is where you make it multi page aware */ nl_current = netlist_head; /* search for the first instance */ /* through the entire list */ while (nl_current != NULL && !done) { if (nl_current->component_uref) { if (strcmp(nl_current->component_uref, uref) == 0) { pin_object = o_complex_find_pin_by_attribute (nl_current->object_ptr, "pinnumber", pin); if (pin_object) { /* only look for the first occurance of wanted_attrib */ return_value = o_attrib_search_object_attribs_by_name (pin_object, wanted_attrib, 0); #if DEBUG if (return_value) { printf("GOT IT: %s\n", return_value); } #endif } else if (strcmp("pintype", wanted_attrib) == 0) { if (nl_current->cpins) { CPINLIST *pinobject = s_cpinlist_search_pin(nl_current->cpins, pin); if (pinobject) { return_value="pwr"; #if DEBUG printf("Supplied pintype 'pwr' for artificial pin '%s' of '%s'\n", pin, uref); #endif } } } } } nl_current = nl_current->next; } scm_dynwind_end (); if (return_value) { scm_return_value = scm_from_utf8_string (return_value); } else { scm_return_value = scm_from_utf8_string ("unknown"); } return (scm_return_value); }
/* with that pinseq pin and component */ SCM g_get_attribute_by_pinseq(SCM scm_uref, SCM scm_pinseq, SCM scm_wanted_attrib) { SCM scm_return_value; NETLIST *nl_current; char *uref; char *pinseq; char *wanted_attrib; char *return_value = NULL; OBJECT *o_pin_object; SCM_ASSERT(scm_is_string (scm_uref), scm_uref, SCM_ARG1, "gnetlist:get-attribute-by-pinseq"); SCM_ASSERT(scm_is_string (scm_pinseq), scm_pinseq, SCM_ARG2, "gnetlist:get-attribute-by-pinseq"); SCM_ASSERT(scm_is_string (scm_wanted_attrib), scm_wanted_attrib, SCM_ARG3, "gnetlist:get-attribute-by-pinseq"); scm_dynwind_begin (0); uref = scm_to_utf8_string (scm_uref); scm_dynwind_free (uref); pinseq = scm_to_utf8_string (scm_pinseq); scm_dynwind_free (pinseq); wanted_attrib = scm_to_utf8_string (scm_wanted_attrib); scm_dynwind_free (wanted_attrib); #if DEBUG printf("gnetlist:g_netlist.c:g_get_attribute_by_pinseq -- \n"); printf(" wanted uref = %s\n", uref); printf(" wanted_pin_seq = %s\n", pinseq); printf(" wanted_attrib = %s\n", wanted_attrib); #endif /* here is where you make it multi page aware */ nl_current = netlist_head; /* search for the first instance */ /* through the entire list */ while (nl_current != NULL) { if (nl_current->component_uref) { if (strcmp(nl_current->component_uref, uref) == 0) { o_pin_object = o_complex_find_pin_by_attribute (nl_current->object_ptr, "pinseq", pinseq); if (o_pin_object) { return_value = o_attrib_search_object_attribs_by_name (o_pin_object, wanted_attrib, 0); if (return_value) { break; } } /* Don't break until we search the whole netlist to handle slotted */ /* parts. 4.28.2007 -- SDB. */ } } nl_current = nl_current->next; } scm_dynwind_end (); if (return_value) { scm_return_value = scm_from_utf8_string (return_value); } else { scm_return_value = scm_from_utf8_string ("unknown"); } #if DEBUG printf("gnetlist:g_netlist.c:g_get_attribute_by_pinseq -- "); printf("return_value: %s\n", return_value); #endif return (scm_return_value); }
/*! \brief Add pins to pin table. * * This function iterates over adds all items found on this page * looking for pins. WHen it finds a pin, it gathers all * pin attribs and sticks them into the pin table. * \param obj_list List of objects on page */ void s_table_add_toplevel_pin_items_to_pin_table (const GList *obj_list) { gchar *temp_uref; gchar *pinnumber; gchar *row_label; int row, col; gchar *attrib_text; gchar *attrib_name; gchar *attrib_value; const GList *o_iter; GList *a_iter; GList *o_lower_iter; OBJECT *pin_attrib; if (verbose_mode) { printf("- Starting internal pin TABLE creation\n"); } #ifdef DEBUG printf("=========== Just entered s_table_add_toplevel_pin_items_to_pin_table! ==============\n"); #endif /* ----- Iterate through all objects found on page ----- */ for (o_iter = obj_list; o_iter != NULL; o_iter = g_list_next (o_iter)) { OBJECT *o_current = o_iter->data; #ifdef DEBUG printf(" ---> In s_table_add_toplevel_pin_items_to_pin_table, examining o_current->name = %s\n", o_current->name); #endif /* ----- Now process objects found on page ----- */ if (o_current->type == OBJ_COMPLEX && o_current->attribs != NULL) { /* ---- Don't process part if it lacks a refdes ----- */ temp_uref = s_attrib_get_refdes(o_current); if (temp_uref) { /* ----- Now iterate through lower level objects looking for pins. ----- */ for (o_lower_iter = o_current->complex->prim_objs; o_lower_iter != NULL; o_lower_iter = g_list_next (o_lower_iter)) { OBJECT *o_lower_current = o_lower_iter->data; if (o_lower_current->type == OBJ_PIN) { /* ----- Found a pin. First get its pinnumber. then get attrib head and loop on attribs. ----- */ pinnumber = o_attrib_search_object_attribs_by_name (o_lower_current, "pinnumber", 0); row_label = g_strconcat(temp_uref, ":", pinnumber, NULL); #if DEBUG printf(" In s_table_add_toplevel_pin_items_to_pin_table, examining pin %s\n", row_label); #endif a_iter = o_lower_current->attribs; while (a_iter != NULL) { pin_attrib = a_iter->data; if (pin_attrib->type == OBJ_TEXT && pin_attrib->text != NULL) { /* found an attribute */ attrib_text = g_strdup(pin_attrib->text->string); attrib_name = u_basic_breakup_string(attrib_text, '=', 0); attrib_value = s_misc_remaining_string(attrib_text, '=', 1); if ( (strcmp(attrib_name, "pinnumber") != 0) && (attrib_value != 0) ) { /* Don't include "pinnumber" because it is already in other master list. * Also must ensure that value is non-null; certain symbols are not well formed. */ /* Get row and col where to put this attrib */ row = s_table_get_index(sheet_head->master_pin_list_head, row_label); col = s_table_get_index(sheet_head->master_pin_attrib_list_head, attrib_name); /* Sanity check */ if (row == -1 || col == -1) { /* we didn't find the item in the table */ fprintf (stderr, "In s_table_add_toplevel_pin_items_to_pin_table, we didn't find either row or col in the lists!\n"); } else { #if DEBUG printf(" In s_table_add_toplevel_pin_items_to_pin_table, about to add row %d, col %d, attrib_value = %s\n", row, col, attrib_value); printf(" . . . current address of attrib_value cell is [%p]\n", &((sheet_head->component_table)[row][col]).attrib_value); #endif /* Is there a compelling reason for me to put this into a separate fcn? */ ((sheet_head->pin_table)[row][col]).row = row; ((sheet_head->pin_table)[row][col]).col = col; ((sheet_head->pin_table)[row][col]).row_name = g_strdup(row_label); ((sheet_head->pin_table)[row][col]).col_name = g_strdup(attrib_name); ((sheet_head->pin_table)[row][col]).attrib_value = g_strdup(attrib_value); } } g_free(attrib_name); g_free(attrib_text); g_free(attrib_value); } a_iter = g_list_next (a_iter); } /* while (pin_attrib != NULL) */ g_free(pinnumber); g_free(row_label); } } } g_free(temp_uref); } } verbose_done(); }
NET *s_traverse_net (TOPLEVEL *pr_current, NET *nets, int starting, OBJECT *object, char *hierarchy_tag, int type) { NET *new_net; CONN *c_current; GList *cl_current; char *temp = NULL; const gchar *netattrib_pinnum = NULL; visit (object); if (connection_type (object) != type) return nets; new_net = nets = s_net_add(nets); new_net->nid = object->sid; /* pins are not allowed to have the netname attribute attached to them */ if (object->type != OBJ_PIN) { /* Ignore netname attributes on buses */ if (object->type == OBJ_NET) temp = o_attrib_search_object_attribs_by_name (object, "netname", 0); if (temp) { new_net->net_name = s_hierarchy_create_netname(pr_current, temp, hierarchy_tag); g_free(temp); } else if (object->type == OBJ_NET) { /* search for the old label= attribute on nets */ temp = o_attrib_search_object_attribs_by_name (object, "label", 0); if (temp) { printf(_("WARNING: Found label=%s. label= is deprecated, please use netname=\n"), temp); new_net->net_name = s_hierarchy_create_netname(pr_current, temp, hierarchy_tag); g_free(temp); } } } #if DEBUG printf("inside traverse: %s\n", object->name); #endif if (object->type == OBJ_PIN) { verbose_print (starting ? "p" : "P"); new_net->connected_to = s_net_return_connected_string (pr_current, object, hierarchy_tag); temp = o_attrib_search_object_attribs_by_name (object, "pinlabel", 0); if (temp) { new_net->pin_label = temp; } /* net= new */ netattrib_pinnum = s_netattrib_connected_string_get_pinnum (nets->connected_to); if (netattrib_pinnum != NULL && type == PIN_TYPE_NET) { #if DEBUG printf("going to find netname %s \n", nets->connected_to); #endif nets->net_name = s_netattrib_return_netname (pr_current, object, nets->connected_to, hierarchy_tag); nets->net_name_has_priority = TRUE; g_free(nets->connected_to); nets->connected_to = NULL; } #if DEBUG printf("traverse connected_to: %s\n", new_net->connected_to); #endif /* Terminate if we hit a pin which isn't the one we started with */ if (!starting) return nets; } /*printf("Found net %s\n", object->name); */ verbose_print("n"); /* this is not perfect yet and won't detect a loop... */ if (is_visited(object) > 100) { fprintf(stderr, _("Found a possible net/pin infinite connection\n")); exit(-1); } cl_current = object->conn_list; while (cl_current != NULL) { c_current = (CONN *) cl_current->data; if (c_current->other_object != NULL) { if (!is_visited(c_current->other_object) && c_current->other_object != object) { nets = s_traverse_net (pr_current, nets, FALSE, c_current->other_object, hierarchy_tag, type); } } cl_current = g_list_next(cl_current); } return (nets); }
/*! \brief Update all slot attributes in an object. * \par Function Description * Update pinnumber attributes in a graphic object. * The interesting case is where the object is an * instantiation of a slotted part. This means that * s_slot_update_object iterates through all pins * found on object and sets the pinnumber= attrib * on each. This doesn't matter for non-slotted * parts, but on slotted parts, this is what sets the * pinnumber= attribute on slots 2, 3, 4.... * * \param [in] toplevel The TOPLEVEL object. * \param [in,out] object The OBJECT to update. */ void s_slot_update_object (TOPLEVEL *toplevel, OBJECT *object) { OBJECT *o_pin_object; OBJECT *o_pinnum_attrib; GList *attributes; char *string; char *slotdef; char *pinseq; int slot; int slot_string; int pin_counter; /* Internal pin counter private to this fcn. */ char* current_pin; /* text from slotdef= to be made into pinnumber= */ char* cptr; /* char pointer pointing to pinnumbers in slotdef=#:#,#,# string */ /* For this particular graphic object (component instantiation) */ /* get the slot number as a string */ string = o_attrib_search_object_attribs_by_name (object, "slot", 0); if (string == NULL) { /* Did not find slot= attribute. * This happens if there is no attached slot attribute, and * there is no default slot= attribute inside the symbol. * Assume slot=1. */ slot = 1; slot_string = 0; } else { slot_string = 1; slot = atoi (string); g_free (string); } /* OK, now that we have the slot number, use it to get the */ /* corresponding slotdef=#:#,#,# string. */ slotdef = s_slot_search_slotdef (object, slot); if (slotdef == NULL) { if (slot_string) /* only an error if there's a slot string */ s_log_message (_("Did not find slotdef=#:#,#,#... attribute\n")); return; } if (!strstr (slotdef, ":")) { /* Didn't find proper slotdef=#:... put warning into log */ s_log_message (_("Improper slotdef syntax: missing \":\".\n")); g_free (slotdef); return; } /* skip over slotdef number */ /* slotdef is in the form #:#,#,# */ /* this code skips first #: */ cptr = slotdef; while (*cptr != '\0' && *cptr != ':') { cptr++; } cptr++; /* skip colon */ if (*cptr == '\0') { s_log_message (_("Did not find proper slotdef=#:#,#,#... attribute\n")); g_free (slotdef); return; } /* loop on all pins found in slotdef= attribute */ pin_counter = 1; /* internal pin_counter */ /* get current pinnumber= from slotdef= attrib */ current_pin = strtok (cptr, DELIMITERS); while (current_pin != NULL) { /* get pin on this component with pinseq == pin_counter */ pinseq = g_strdup_printf ("%d", pin_counter); o_pin_object = o_complex_find_pin_by_attribute (object, "pinseq", pinseq); g_free (pinseq); if (o_pin_object != NULL) { /* Now rename pinnumber= attrib on this part with value found */ /* in slotdef attribute */ attributes = o_attrib_return_attribs (o_pin_object); o_pinnum_attrib = o_attrib_find_attrib_by_name (attributes, "pinnumber", 0); g_list_free (attributes); if (o_pinnum_attrib != NULL) { o_text_set_string (toplevel, o_pinnum_attrib, g_strdup_printf ("pinnumber=%s", current_pin)); } pin_counter++; } else { s_log_message (_("component missing pinseq= attribute\n")); } current_pin = strtok (NULL, DELIMITERS); } g_free (slotdef); }
void s_traverse_sheet (TOPLEVEL * pr_current, const GList *obj_list, char *hierarchy_tag) { NETLIST *netlist; char *temp; SCM scm_uref; char *temp_uref; gboolean is_hierarchy = TRUE; const GList *iter; GError *err = NULL; EdaConfig *cfg; cfg = eda_config_get_context_for_file (NULL); is_hierarchy = eda_config_get_boolean (cfg, "gnetlist", "traverse-hierarchy", &err); if (err != NULL) { is_hierarchy = TRUE; g_clear_error (&err); } if (verbose_mode) { printf("- Starting internal netlist creation\n"); } for (iter = obj_list; iter != NULL; iter = g_list_next (iter)) { OBJECT *o_current = iter->data; netlist = s_netlist_return_tail(netlist_head); if (o_current->type == OBJ_PLACEHOLDER) { printf(_("WARNING: Found a placeholder/missing component, are you missing a symbol file? [%s]\n"), o_current->complex_basename); } if (o_current->type == OBJ_COMPLEX) { gboolean is_graphical = FALSE; #if DEBUG printf("starting NEW component\n\n"); #endif verbose_print(" C"); /* look for special tag */ temp = o_attrib_search_object_attribs_by_name (o_current, "graphical", 0); if (g_strcmp0 (temp, "1") == 0) { /* traverse graphical elements, but adding them to the graphical netlist */ netlist = s_netlist_return_tail(graphical_netlist_head); is_graphical = TRUE; } g_free (temp); netlist = s_netlist_add(netlist); netlist->nlid = o_current->sid; scm_uref = g_scm_c_get_uref(pr_current, o_current); if (scm_is_string( scm_uref )) { temp_uref = scm_to_utf8_string (scm_uref); netlist->component_uref = s_hierarchy_create_uref(pr_current, temp_uref, hierarchy_tag); g_free(temp_uref); } else { if (hierarchy_tag) { netlist->component_uref = g_strdup (hierarchy_tag); } else { 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 /* it's a power or some other special symbol */ 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 (is_hierarchy) { s_hierarchy_traverse(pr_current, o_current, netlist); } } } verbose_done(); }
/*! \brief Creates a list of already numbered objects and slots * \par Function Description * This function collects the used numbers of a single schematic page. * The used element numbers are stored in a GList container * inside the <B>AUTONUMBER_TEXT</B> struct. * The slotting container is a little bit different. It stores free slots of * multislotted symbols, that were used only partially. * The criterias are derivated from the autonumber dialog entries. */ void autonumber_get_used(GschemToplevel *w_current, AUTONUMBER_TEXT *autotext) { gint number, numslots, slotnr, i; OBJECT *o_current, *o_parent; AUTONUMBER_SLOT *slot; GList *slot_item; char *numslot_str, *slot_str; const GList *iter; for (iter = s_page_objects (w_current->toplevel->page_current); iter != NULL; iter = g_list_next (iter)) { o_current = iter->data; if (autonumber_match(autotext, o_current, &number) == AUTONUMBER_RESPECT) { /* check slot and maybe add it to the lists */ o_parent = o_current->attached_to; if (autotext->slotting && o_parent != NULL) { /* check for slotted symbol */ numslot_str = o_attrib_search_object_attribs_by_name (o_parent, "numslots", 0); if (numslot_str != NULL) { sscanf(numslot_str," %d",&numslots); g_free(numslot_str); if (numslots > 0) { slot_str = o_attrib_search_object_attribs_by_name (o_parent, "slot", 0); if (slot_str == NULL) { s_log_message(_("slotted object without slot attribute may cause " "problems when autonumbering slots\n")); } else { sscanf(slot_str, " %d", &slotnr); slot = g_new(AUTONUMBER_SLOT,1); slot->number = number; slot->slotnr = slotnr; slot->symbolname = o_parent->complex_basename; slot_item = g_list_find_custom(autotext->used_slots, slot, (GCompareFunc) freeslot_compare); if (slot_item != NULL) { /* duplicate slot in used_slots */ s_log_message(_("duplicate slot may cause problems: " "[symbolname=%s, number=%d, slot=%d]\n"), slot->symbolname, slot->number, slot->slotnr); g_free(slot); } else { autotext->used_slots = g_list_insert_sorted(autotext->used_slots, slot, (GCompareFunc) freeslot_compare); slot_item = g_list_find_custom(autotext->free_slots, slot, (GCompareFunc) freeslot_compare); if (slot_item == NULL) { /* insert all slots to the list, except of the current one */ for (i=1; i <= numslots; i++) { if (i != slotnr) { slot = g_memdup(slot, sizeof(AUTONUMBER_SLOT)); slot->slotnr = i; autotext->free_slots = g_list_insert_sorted(autotext->free_slots, slot, (GCompareFunc) freeslot_compare); } } } else { g_free(slot_item->data); autotext->free_slots = g_list_delete_link(autotext->free_slots, slot_item); } } } } } } /* put number into the used list */ autotext->used_numbers = g_list_insert_sorted(autotext->used_numbers, GINT_TO_POINTER(number), (GCompareFunc) autonumber_sort_numbers); } } }