view ueda/unet-bind/readunet.c @ 139:bf188727e606

donl-rename-parts reader: no tEDAx-style escapes
author Mychaela Falconia <falcon@freecalypso.org>
date Mon, 07 Sep 2020 04:25:11 +0000
parents ffab0a4424ad
children
line wrap: on
line source

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include "../libueda/xga.h"
#include "../libunet/unetrd.h"
#include "struct.h"

extern char *pinname_to_pinnumber();
extern struct net *find_net_by_name();
extern struct instance *find_instance();

extern char *input_filename;
extern int unbound_instances;

static struct unetrd_state rdstate;
static struct unetrd_out rdout;

static int
resolve_pinnum_numeric(oc, pinnumstr)
	struct outcomp *oc;
	register char *pinnumstr;
{
	register int num;

	if (!string_is_valid_decnum(pinnumstr)) {
invnum:		fprintf(stderr,
"%s line %d: component %s has numeric pins and \"%s\" is not a valid pin number\n",
			input_filename, rdstate.lineno, oc->name, pinnumstr);
		exit(1);
	}
	num = atoi(pinnumstr);
	if (num < 1)
		goto invnum;
	if (num > oc->npins) {
		fprintf(stderr,
"%s line %d: attempting connection to pin %d on component %s that only has %d pins\n",
			input_filename, rdstate.lineno, num, oc->name,
			oc->npins);
		exit(1);
	}
	return(num - 1);
}

static int
resolve_pinnum_grid(oc, pinnumstr)
	struct outcomp *oc;
	char *pinnumstr;
{
	register struct grid_pkg_desc *xga = oc->grid_pkg;
	struct xga_parsed_pinnum rowcol;
	register int idx;

	if (parse_xga_pinnumber(xga, pinnumstr, &rowcol) < 0) {
		fprintf(stderr,
	"%s line %d: \"%s\" is not a valid pin number for grid package %s\n",
			input_filename, rdstate.lineno, pinnumstr, oc->name);
		exit(1);
	}
	idx = rowcol.row_0based * xga->ncolumns + rowcol.col_0based;
	if (xga->holes_array[idx]) {
		fprintf(stderr,
	"%s line %d: pin position %s is a hole in the grid package for %s\n",
			input_filename, rdstate.lineno, pinnumstr, oc->name);
		exit(1);
	}
	return(idx);
}

static int
resolve_pinnum(oc, pinnumstr)
	register struct outcomp *oc;
	char *pinnumstr;
{
	if (oc->grid_pkg)
		return resolve_pinnum_grid(oc, pinnumstr);
	else
		return resolve_pinnum_numeric(oc, pinnumstr);
}

static struct pinconn *
create_pinconn()
{
	register struct pinconn *conn;
	register struct net *net;

	if (rdout.connect_to_net) {
		net = find_net_by_name(rdout.connect_to_net);
		conn = (struct pinconn *) malloc(sizeof(struct pinconn));
		if (!conn) {
			perror("malloc");
			exit(1);
		}
		conn->net = net;
		conn->nc_comment = 0;
	} else {
		conn = (struct pinconn *) malloc(sizeof(struct pinconn) +
						 strlen(rdout.nc_comment) + 1);
		if (!conn) {
			perror("malloc");
			exit(1);
		}
		conn->net = 0;
		conn->nc_comment = (char *)(conn + 1);
		strcpy(conn->nc_comment, rdout.nc_comment);
	}
	conn->input_lineno = rdstate.lineno;
	return conn;
}

static void
connect_pin(oc, pinnumstr)
	register struct outcomp *oc;
	char *pinnumstr;
{
	register int pinidx;

	pinidx = resolve_pinnum(oc, pinnumstr);
	if (oc->reverse_2pin)
		pinidx = !pinidx;
	if (oc->conn_array[pinidx]) {
		fprintf(stderr,
	"error: multiple connections to %s pin %s (input lines %d and %d)\n",
			oc->name, pinnumstr,
			oc->conn_array[pinidx]->input_lineno, rdstate.lineno);
		exit(1);
	}
	oc->conn_array[pinidx] = create_pinconn();
}

static void
process_pinmap(inst)
	struct instance *inst;
{
	register struct outcomp *oc = inst->outcomp;
	register char *pinnum;

	if (!oc->mclcomp) {
		fprintf(stderr,
			"%s line %d: PINMAP is meaningless for starpoints\n",
			input_filename, rdstate.lineno);
		exit(1);
	}
	pinnum = pinname_to_pinnumber(oc->mclcomp, rdout.objname, inst->slot);
	if (!pinnum) {
		fprintf(stderr, "PINMAP error on %s line %d\n",
			input_filename, rdstate.lineno);
		exit(1);
	}
	connect_pin(oc, pinnum);
}

static void
process_component()
{
	struct instance *inst;

	inst = find_instance(rdout.objname);
	if (!inst) {
		fprintf(stderr, "%s line %d: instance %s not bound in MCL\n",
			input_filename, rdstate.lineno, rdout.objname);
		unbound_instances++;
	} else {
		if (inst->claimed) {
			fprintf(stderr,
			"%s line %d: instance %s appears more than once\n",
				input_filename, rdstate.lineno, inst->name);
			exit(1);
		}
		inst->claimed = 1;
	}
	for (;;) {
		if (!read_unet_line(&rdstate, &rdout)) {
			fprintf(stderr, "%s error: EOF in component block\n",
				input_filename);
			exit(1);
		}
		if (rdout.typecode == UNETOBJ_CLOSINGBRACE)
			break;
		switch(rdout.typecode) {
		case UNETOBJ_PRIMITIVE:
		case UNETOBJ_ALTNAME:
		case UNETOBJ_ATTR:
			continue;
		case UNETOBJ_PIN:
			if (inst)
				connect_pin(inst->outcomp, rdout.objname);
			continue;
		case UNETOBJ_PINMAP:
			if (inst)
				process_pinmap(inst);
			continue;
		default:
			fprintf(stderr,
		"%s line %d: object type %s unexpected in component block\n",
				input_filename, rdstate.lineno, rdout.keyword);
			exit(1);
		}
	}
}

process_input_unet()
{
	open_unet_input_file(input_filename, &rdstate);
	while (read_unet_line(&rdstate, &rdout)) {
		switch(rdout.typecode) {
		case UNETOBJ_CLOSINGBRACE:
			fprintf(stderr,
		"%s line %d: unexpected '}' outside of component block\n",
				input_filename, rdstate.lineno);
			exit(1);
		case UNETOBJ_NET:
			enter_net_object(rdout.objname, 0);
			continue;
		case UNETOBJ_COMPONENT:
			process_component();
			continue;
		case UNETOBJ_STARPOINT:
			fprintf(stderr,
"error: STARPOINT objects not expected in unet-bind input (%s line %d)\n",
				input_filename, rdstate.lineno);
			exit(1);
		default:
			fprintf(stderr,
				"%s line %d: unexpected object type %s\n",
				input_filename, rdstate.lineno, rdout.keyword);
			exit(1);
		}
	}
}