FreeCalypso > hg > ueda-linux
view ueda/libuschem/graphnets.c @ 154:2328205328a9 default tip
m4-fp: WR-FPC 1mm pitch FFC/FPC connectors
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Tue, 25 Oct 2022 07:36:09 +0000 |
parents | cd92449fdb51 |
children |
line wrap: on
line source
/* * preen_graphnets() functionality */ #include <sys/types.h> #include <stdio.h> #include <strings.h> #include "schemstruct.h" #include "graphsym.h" extern char *malloc(); extern struct graphsym_pininst *find_comp_pininst(); extern struct graphsym_pininst *find_pin_by_coord(); static struct schem *schem_being_preened; static int dowarn, docorrect, severe_err; static int tjoin_hit_check(obj, tjoin) struct schemobj *obj; register struct netpoint *tjoin; { register struct netpoint *netpt, *nextpt; for (netpt = obj->netobj_points; netpt && (nextpt = netpt->netpt_next); netpt = nextpt) { if (!netpt->netpt_coord_valid || !nextpt->netpt_coord_valid) { fprintf(stderr, "%s: line %d: Pin w/o coordinates impedes search for Tjoin antecedent\n", schem_being_preened->orig_filename, obj->obj_lineno); severe_err = -1; return(-1); } /* check for horizontal segments */ if (netpt->netpt_y == tjoin->netpt_y && nextpt->netpt_y == tjoin->netpt_y) { if (tjoin->netpt_x > netpt->netpt_x && tjoin->netpt_x < nextpt->netpt_x) return(1); if (tjoin->netpt_x < netpt->netpt_x && tjoin->netpt_x > nextpt->netpt_x) return(1); } /* check for vertical segments */ if (netpt->netpt_x == tjoin->netpt_x && nextpt->netpt_x == tjoin->netpt_x) { if (tjoin->netpt_y > netpt->netpt_y && tjoin->netpt_y < nextpt->netpt_y) return(1); if (tjoin->netpt_y < netpt->netpt_y && tjoin->netpt_y > nextpt->netpt_y) return(1); } } return(0); } static struct schemobj * find_grouphead_tail(ghead) register struct schemobj *ghead; { register struct schemobj *obj, *next; for (obj = ghead; ; obj = next) { next = obj->obj_next; if (next->obj_type != OBJTYPE_GRAPHNET) return(obj); if (next->netobj_grouphead != ghead) return(obj); } } static preen_tjoin(obj, netpt, first, got_tjoin) struct schemobj *obj; register struct netpoint *netpt; int first, *got_tjoin; { register struct schem *schem; register struct schemobj *prevobj; struct schemobj *ghead; register int c; schem = schem_being_preened; if (first) *got_tjoin = 1; else if (!netpt->netpt_next) { if (*got_tjoin) { fprintf(stderr, "%s: line %d: Tjoin on both ends of a GraphNet is illegal\n", schem->orig_filename, obj->obj_lineno); severe_err = -1; return; } *got_tjoin = 1; } else { fprintf(stderr, "%s: line %d: Tjoin in the middle of a GraphNet is meaningless\n", schem->orig_filename, obj->obj_lineno); severe_err = -1; return; } for (prevobj = obj->obj_prev, c = 0; prevobj != (struct schemobj *)schem; prevobj = prevobj->obj_prev) if (prevobj->obj_type == OBJTYPE_GRAPHNET) { c = tjoin_hit_check(prevobj, netpt); if (c < 0) return; if (c) break; } if (!c) { fprintf(stderr, "%s: line %d: Tjoin antecedent not found\n", schem->orig_filename, obj->obj_lineno); severe_err = -1; return; } netpt->netpt_tjoin_to = prevobj; obj->netobj_grouphead = ghead = prevobj->netobj_grouphead; /* netname logic */ if (obj->netobj_netname) { /* accumulate on the group head */ if (!ghead->netobj_netname) ghead->netobj_netname = obj->netobj_netname; else if (strcmp(ghead->netobj_netname, obj->netobj_netname)) { fprintf(stderr, "%s: line %d: Tjoin connects two netnames: %s and %s\n", schem->orig_filename, obj->obj_lineno, ghead->netobj_netname, obj->netobj_netname); severe_err = -1; return; } } /* shuffling around to bring groups together */ prevobj = obj->obj_prev; if (prevobj->obj_type != OBJTYPE_GRAPHNET || prevobj->netobj_grouphead != ghead) { prevobj = find_grouphead_tail(ghead); schemobj_unlink(obj); schemobj_insert_after(prevobj, obj); } } static preen_pin(obj, netpt) struct schemobj *obj; register struct netpoint *netpt; { register int i = 0, c; struct graphsym_pininst *pinc, *pinn; struct schemobj *comp; char *soughtpin; int bynum; if (netpt->netpt_coord_valid) { i |= 2; pinc = find_pin_by_coord(schem_being_preened, netpt->netpt_x, netpt->netpt_y); } if (netpt->netpt_pin_nameref) { i |= 1; c = parse_pin_nameref(schem_being_preened, obj->obj_lineno, netpt->netpt_pin_nameref, &comp, &soughtpin, &bynum); if (c < 0) severe_err = -1; } switch (i) { case 1: if (dowarn) fprintf(stderr, "%s: line %d: Pin w/o coordinates, run uschem-rewrite -g to fix\n", schem_being_preened->orig_filename, obj->obj_lineno); if (c < 0) return; if (!comp->compobj_isgraph) { nograph: fprintf(stderr, "%s: line %d: %s: GraphNet refers to a non-graphical component\n", schem_being_preened->orig_filename, obj->obj_lineno, netpt->netpt_pin_nameref); severe_err = -1; return; } pinn = find_comp_pininst(comp, soughtpin, bynum); if (!pinn) { pinnotfound: fprintf(stderr, "%s: line %d: %s: pin not found\n", schem_being_preened->orig_filename, obj->obj_lineno, netpt->netpt_pin_nameref); severe_err = -1; return; } /* fix it */ netpt->netpt_x = pinn->x; netpt->netpt_y = pinn->y; netpt->netpt_coord_valid = 1; return; case 2: if (dowarn) fprintf(stderr, "%s: line %d: Pin given by coordinates only, run uschem-rewrite -g to fix\n", schem_being_preened->orig_filename, obj->obj_lineno); if (!pinc) { fprintf(stderr, "%s: line %d: no pin found at (%d,%d)\n", schem_being_preened->orig_filename, obj->obj_lineno, netpt->netpt_x, netpt->netpt_y); severe_err = -1; return; } comp = pinc->compinst; if (comp->obj_type != OBJTYPE_COMPINST) { fprintf(stderr, "%s: line %d: Pin refers to a non-component\n", schem_being_preened->orig_filename, obj->obj_lineno); severe_err = -1; return; } if (!docorrect) return; if (pinc->pindef->gspd_pinname) { soughtpin = pinc->pindef->gspd_pinname; bynum = 0; } else if (pinc->pindef->gspd_pinnumber) { soughtpin = pinc->pindef->gspd_pinnumber; bynum = 1; } else { fprintf(stderr, "%s: %s pin at (%d,%d) has no pinname or pinnumber attribute\n", schem_being_preened->orig_filename, comp->compobj_instname, netpt->netpt_x, netpt->netpt_y); severe_err = -1; return; } netpt->netpt_pin_nameref = malloc(strlen(comp->compobj_instname) + strlen(soughtpin) + 2); if (!netpt->netpt_pin_nameref) { perror("malloc"); exit(1); } sprintf(netpt->netpt_pin_nameref, "%s%c%s", comp->compobj_instname, bynum ? '-' : '.', soughtpin); return; case 3: if (!dowarn || c < 0) return; if (!comp->compobj_isgraph) goto nograph; pinn = find_comp_pininst(comp, soughtpin, bynum); if (!pinn) goto pinnotfound; if (pinc != pinn) fprintf(stderr, "%s: line %d: Pin(%d,%d)=%s: pin name and coordinates don't match\n", schem_being_preened->orig_filename, obj->obj_lineno, netpt->netpt_x, netpt->netpt_y, netpt->netpt_pin_nameref); return; } } static preen_pseudopin(obj, netpt) struct schemobj *obj; register struct netpoint *netpt; { register struct graphsym_pininst *pin; register struct schemobj *ghead; pin = find_pin_by_coord(schem_being_preened, netpt->netpt_x, netpt->netpt_y); if (!pin) { fprintf(stderr, "%s: line %d: no pin found at (%d,%d)\n", schem_being_preened->orig_filename, obj->obj_lineno, netpt->netpt_x, netpt->netpt_y); severe_err = -1; return; } if (pin->compinst->obj_type != OBJTYPE_GRAPHSYM) { fprintf(stderr, "%s: line %d: Pseudo refers to a real component pin (use Pin instead)\n", schem_being_preened->orig_filename, obj->obj_lineno); severe_err = -1; return; } if (!pin->pindef->gspd_forcenet) return; obj->netobj_forcenets++; ghead = obj->netobj_grouphead; if (!ghead) ghead = obj; if (!ghead->netobj_netname) { if (dowarn) fprintf(stderr, "%s: line %d: GraphNet needs to be forced to net %s (run uschem-rewrite -g to fix)\n", schem_being_preened->orig_filename, obj->obj_lineno, pin->pindef->gspd_forcenet); if (docorrect) ghead->netobj_netname = pin->pindef->gspd_forcenet; } else if (strcmp(ghead->netobj_netname, pin->pindef->gspd_forcenet)) { fprintf(stderr, "%s: line %d: Graphnet %s is forced to net %s by a special symbol connection\n", schem_being_preened->orig_filename, obj->obj_lineno, ghead->netobj_netname, pin->pindef->gspd_forcenet); severe_err = -1; } } static do_graphnet(obj, do_tjoin, do_pins) struct schemobj *obj; { register struct netpoint *netpt; register int first; int got_tjoin = 0; if (do_tjoin) obj->netobj_grouphead = obj; /* for now at least */ for (netpt = obj->netobj_points, first = 1; netpt; netpt = netpt->netpt_next, first = 0) { if (dowarn && first && !netpt->netpt_next) fprintf(stderr, "%s: line %d: singular GraphNet\n", schem_being_preened->orig_filename, obj->obj_lineno); switch (netpt->netpt_type) { case NETPT_TYPE_TJOIN: if (do_tjoin) preen_tjoin(obj, netpt, first, &got_tjoin); continue; case NETPT_TYPE_PIN: if (do_pins) preen_pin(obj, netpt); continue; case NETPT_TYPE_PSEUDO: if (do_pins) preen_pseudopin(obj, netpt); continue; } } } preen_graphnets(schem, do_tjoin, do_pins, warn, correct) struct schem *schem; { register struct schemobj *obj, *next; schem_being_preened = schem; dowarn = warn; docorrect = correct; severe_err = 0; for (obj = schem->obj_next; obj != (struct schemobj *)schem; obj = next) { next = obj->obj_next; if (obj->obj_type == OBJTYPE_GRAPHNET) do_graphnet(obj, do_tjoin, do_pins); } return(severe_err); }