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);
+}