view ueda/libuschem/pins.c @ 13:1f3283f8e482

unet-bind: instance hash implemented
author Space Falcon <falcon@ivan.Harhan.ORG>
date Sun, 02 Aug 2015 00:00:15 +0000
parents cd92449fdb51
children
line wrap: on
line source

/*
 * Working with graphical symbol pin instances
 */

#include <sys/types.h>
#include <stdio.h>
#include <strings.h>
#include "schemstruct.h"
#include "graphsym.h"

extern char *malloc();

#define	HASH_SIZE	1103

static int
hash_coord(x, y)
{
	return((x + y) % HASH_SIZE);
}

static
add_pin_to_hash(schem, pin)
	struct schem *schem;
	register struct graphsym_pininst *pin;
{
	register struct graphsym_pininst *hp, **hpp;

	for (hpp = schem->pininst_hash + hash_coord(pin->x, pin->y); hp = *hpp;
	     hpp = &hp->nextinhash)
		if (pin->x == hp->x && pin->y == hp->y) {
		    fprintf(stderr,
		    "%s: more than one pin at (%d,%d), see lines %d and %d\n",
			schem->orig_filename, pin->x, pin->y,
			hp->compinst->obj_lineno, pin->compinst->obj_lineno);
		    return(-1);
		}
	*hpp = pin;
	return(0);
}

static
instantiate_obj_pins(schem, obj, dohash)
	struct schem *schem;
	register struct schemobj *obj;
{
	register struct graphsym_pindef *pd;
	register struct graphsym_pininst *pi;
	int npins;
	int x, y;
	int errflag = 0, clashflag = 0;

	npins = obj->compobj_graphsym->gs_npins;
	pi = (struct graphsym_pininst *)
			malloc(sizeof(struct graphsym_pininst) * npins);
	if (!pi) {
		perror("malloc");
		exit(1);
	}
	obj->compobj_pins = pi;
	for (pd = obj->compobj_graphsym->gs_pins; pd; pd = pd->gspd_next, pi++){
		pi->compinst = obj;
		pi->pindef = pd;
		x = pd->gspd_x;
		y = pd->gspd_y;
		if (obj->compobj_mirror)
			x = -x;
		switch (obj->compobj_rotate) {
		case 0:
			pi->x = x;
			pi->y = y;
			break;
		case 90:
			pi->x = -y;
			pi->y = x;
			break;
		case 180:
			pi->x = -x;
			pi->y = -y;
			break;
		case 270:
			pi->x = y;
			pi->y = -x;
			break;
		default:
			if (!errflag) {
				fprintf(stderr,
	"%s: line %d: symbol rotated by %d deg, can't do pin instances\n",
					schem->orig_filename, obj->obj_lineno,
					obj->compobj_rotate);
				errflag = 1;
			}
			/* a dummy so we don't have to abort */
			pi->x = pi->y = 0;
		}
		pi->x += obj->compobj_x;
		pi->y += obj->compobj_y;
		pi->nextinhash = NULL;
		if (dohash && !errflag)
			if (add_pin_to_hash(schem, pi))
				clashflag = 1;
	}
	return(errflag || clashflag);
}

/* prerequisite: load_graphsyms() */
instantiate_graphsym_pins(schem, dohash)
	struct schem *schem;
{
	register struct schemobj *obj;
	int errstat = 0;
	struct graphsym_pininst **hashtab;

	if (dohash) {
		hashtab = (struct graphsym_pininst **)
			malloc(sizeof(struct graphsym_pininst *) * HASH_SIZE);
		if (!hashtab) {
			perror("malloc");
			exit(1);
		}
		bzero(hashtab, sizeof(struct graphsym_pininst *) * HASH_SIZE);
		schem->pininst_hash = hashtab;
	}

	for (obj = schem->obj_next; obj != (struct schemobj *)schem;
	     obj = obj->obj_next)
		switch (obj->obj_type) {
		case OBJTYPE_COMPINST:
			if (!obj->compobj_isgraph)
				continue;
			/* FALL THRU */
		case OBJTYPE_GRAPHSYM:
			if (instantiate_obj_pins(schem, obj, dohash))
				errstat = -1;
			break;
		}
	return(errstat);
}

report_pininst_hash_quality(schem)
	struct schem *schem;
{
	struct graphsym_pininst **hashtab;
	int maxchain, total;
	register int hb, curchain;
	register struct graphsym_pininst *pin;

	hashtab = schem->pininst_hash;
	for (hb = 0, total = maxchain = 0; hb < HASH_SIZE; hb++) {
		for (pin = hashtab[hb], curchain = 0; pin;
		     pin = pin->nextinhash) {
			curchain++;
			total++;
		}
		if (curchain > maxchain)
			maxchain = curchain;
	}
	printf("%s: %d pin instances total, longest hash chain is %d\n",
		schem->orig_filename, total, maxchain);
}

struct graphsym_pininst *
find_comp_pininst(comp, soughtpin, bynum)
	struct schemobj *comp;
	char *soughtpin;
	int bynum;
{
	int npins;
	register int i;
	register struct graphsym_pininst *pi;
	register char *pinid;

	npins = comp->compobj_graphsym->gs_npins;
	for (pi = comp->compobj_pins, i = 0; i < npins; pi++, i++) {
		if (bynum)
			pinid = pi->pindef->gspd_pinnumber;
		else
			pinid = pi->pindef->gspd_pinname;
		if (pinid && !strcmp(pinid, soughtpin))
			return(pi);
	}
	return(NULL);
}

struct graphsym_pininst *
find_pin_by_coord(schem, x, y)
	struct schem *schem;
	register int x, y;
{
	register struct graphsym_pininst *pin;

	for (pin = schem->pininst_hash[hash_coord(x, y)]; pin;
	     pin = pin->nextinhash)
		if (pin->x == x && pin->y == y)
			return(pin);
	return(NULL);
}