FreeCalypso > hg > ueda-linux
diff ueda/libuschem/graphnets.c @ 0:cd92449fdb51
initial import of ueda and ifctf-part-lib from ifctfvax CVS
author | Space Falcon <falcon@ivan.Harhan.ORG> |
---|---|
date | Mon, 20 Jul 2015 00:24:37 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ueda/libuschem/graphnets.c Mon Jul 20 00:24:37 2015 +0000 @@ -0,0 +1,365 @@ +/* + * 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); +}