view netdiff/convert/tedax2donl.c @ 136:65f87111090c

netdiff: tedax2donl written
author Mychaela Falconia <falcon@freecalypso.org>
date Mon, 07 Sep 2020 03:02:42 +0000
parents
children 6f528e2a9e23
line wrap: on
line source

/*
 * This program converts a tEDAx netlist into our
 * Diff-Oriented Netlist (DONL) format.
 */

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>

#define	MAX_FIELDS	32

static char *infname;
static FILE *inf;
static char linebuf[512];
static int lineno;
static char *fields[MAX_FIELDS];
static unsigned nfields;

static
get_line()
{
	if (!fgets(linebuf, sizeof linebuf, inf))
		return(0);
	lineno++;
	if (!index(linebuf, '\n')) {
		fprintf(stderr, "%s line %d: missing newline\n",
			infname, lineno);
		exit(1);
	}
	return(1);
}

static void
parse_into_fields()
{
	char *cp;

	nfields = 0;
	for (cp = linebuf; ; ) {
		while (isspace(*cp))
			cp++;
		if (*cp == '\0' || *cp == '#')
			break;
		if (nfields >= MAX_FIELDS) {
			fprintf(stderr, "%s line %d: too many fields\n",
				infname, lineno);
			exit(1);
		}
		fields[nfields++] = cp;
		while (*cp) {
			if (isspace(*cp)) {
				*cp++ = '\0';
				break;
			}
			if (*cp++ != '\\')
				continue;
			switch (*cp++) {
			case '\\':
			case 'n':
			case 'r':
			case 't':
			case ' ':
			case '\t':
				continue;
			default:
				fprintf(stderr, "%s line %d: invalid escape\n",
					infname, lineno);
				exit(1);
			}
		}
	}
}

static void
get_tedax_header()
{
	do {
		if (!get_line()) {
			fprintf(stderr, "%s: EOF before tEDAx header\n",
				infname);
			exit(1);
		}
		parse_into_fields();
	} while (!nfields);
	if (strcmp(fields[0], "tEDAx")) {
		fprintf(stderr, "%s line %d: expected tEDAx header\n",
			infname, lineno);
		exit(1);
	}
	if (nfields != 2 || strcmp(fields[1], "v1")) {
		fprintf(stderr, "%s line %d: expected tEDAx v1\n",
			infname, lineno);
		exit(1);
	}
}

static void
skip_wrong_block()
{
	for (;;) {
		if (!get_line()) {
			fprintf(stderr,
				"%s: EOF in the middle of a skip block\n",
				infname, lineno);
			exit(1);
		}
		if (!nfields)
			continue;
		if (!strcmp(fields[0], "begin")) {
			fprintf(stderr, "%s line %d: nested block beginning\n",
				infname, lineno);
			exit(1);
		}
		if (!strcmp(fields[0], "end"))
			return;
	}
}

static void
find_begin_netlist()
{
	for (;;) {
		do {
			if (!get_line()) {
				fprintf(stderr,
				"%s: EOF before beginning of netlist block\n",
					infname);
				exit(1);
			}
			parse_into_fields();
		} while (!nfields);
		if (strcmp(fields[0], "begin")) {
			fprintf(stderr, "%s line %d: expected begin line\n",
				infname, lineno);
			exit(1);
		}
		if (nfields != 4) {
			fprintf(stderr,
			"%s line %d: begin line has wrong number of fields\n",
				infname, lineno);
			exit(1);
		}
		if (!strcmp(fields[1], "netlist"))
			break;
		skip_wrong_block();
	}
	if (strcmp(fields[2], "v1")) {
		fprintf(stderr,
			"%s line %d: netlist block has wrong version\n",
			infname, lineno);
		exit(1);
	}
}

static void
process_netlist_block()
{
	for (;;) {
		if (!get_line()) {
			fprintf(stderr,
				"%s: EOF in the middle of the netlist block\n",
				infname, lineno);
			exit(1);
		}
		if (!nfields)
			continue;
		if (!strcmp(fields[0], "begin")) {
			fprintf(stderr, "%s line %d: nested block beginning\n",
				infname, lineno);
			exit(1);
		}
		if (!strcmp(fields[0], "end"))
			return;
		if (strcmp(fields[0], "conn"))
			continue;
		if (nfields != 4) {
			fprintf(stderr,
			"%s line %d: conn line has wrong number of fields\n",
				infname, lineno);
			exit(1);
		}
		printf("%s\t%s.%s\n", fields[1], fields[2], fields[3]);
	}
}

main(argc, argv)
	char **argv;
{
	if (argc != 2) {
		fprintf(stderr, "usage: %s tedax-netlist-file\n", argv[0]);
		exit(1);
	}
	infname = argv[1];
	inf = fopen(infname, "r");
	if (!inf) {
		perror(infname);
		exit(1);
	}
	get_tedax_header();
	find_begin_netlist();
	process_netlist_block();
	exit(0);
}