/* flop.c :
   this file belongs to the Alliance cad system sources.
   Written by Frederic Petrot. */

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/time.h>

#include MUT_H
#include MLO_H
#include MLU_H
#include MPH_H
#include MPU_H
#include SCR_H
#include "util.h"

char buffer[BUFSIZ];

static void
	usage(s)
char *s;
{
	fprintf(stderr,
		"Usage : %s planet [-v] [-nswe] [-o filename] [supply width] [[supply width]]\n",
		s);
	exit(1);
}

static char *checkname(name)
char *name;
{
static char str[256];
char *s, *t;

	strcpy(str, name); /* do not alter user strings */
	s = t = str;
	while (*t) {
		if (isspace(*t)) {
			(void)fflush(stdout);
			(void)fprintf(stderr, "bbr error : space detected in argument '%s'\n",
								name);
			EXIT(1);
		}
		if (*t == '[')
			*t = ' ';
		else if (*t == ']')
			if (*(++t) == '\0') /* ok, it's finished */
				goto end;
			else if (*t == '[') /* multiple array */
				continue;
		*s++ = *t++;
	}
end:
	*s = '\0';
	return str;
}


#define INIT \
			if (verbose) \
				(void)time(&from);
#define DELAY(when) \
			if (verbose) \
				(void)fprintf(stdout, " : %ld seconds\n", time(NULL) - when);

main(argc, argv)
int argc;
char **argv;
{
lofig_list *lf;
phfig_list *pf;
channel_list *ch;
ptype_list *pt = NULL;
int i = 2, j, k, verbose = 0;
time_t start, from;
char *out, separ;
char f = '\0';

	if (argc == 1)
		usage(argv[0]);
	mbkenv();
	separ = SEPAR, SEPAR = '_', out = concatname(argv[1], "f"), SEPAR = separ;
	while (i < argc) {
		if (*argv[i] == '-') {
			if (*++argv[i] == 'v')
				verbose = 1;
			else if (*argv[i] == 'o') {
				if (++i >= argc) {
					fprintf(stderr, "%s: no name specified with -o\n", argv[0]);
					exit(1);
				}
				out = namealloc(argv[i]);
			} else if (*argv[i] == 'n')
				f = NORTH;
			else if (*argv[i] == 's')
				f = SOUTH;
			else if (*argv[i] == 'e')
				f = EAST;
			else if (*argv[i] == 'w')
				f = WEST;
			else {
				fprintf(stderr, "%s: illegal argument '%c'\n", argv[0], *argv[i]);
				exit(1);
			}
			i++;
			continue;
		}
		if (i + 1 >= argc || (j = atoi(argv[i + 1])) == 0) {
			fprintf(stderr, "%s: supply '%s' with zero width\n", argv[0], argv[i]);
			exit(1);
		}
		pt = addptype(pt, (j / 2) * 2 + 1, namealloc(checkname(argv[i])));
		i += 2;
	}

	alliancebanner("BBR", "1.0", "Gridless channel router for two blocs",
						"92, 93", ALC);

	if (verbose)
		(void)time(&start);
	if (verbose) {
		fprintf(stdout, "loading logical view                          ");
		fflush(stdout);
	}
	
	INIT;
	lf = getlofig(argv[1], 'A');
	DELAY(from);
	if (verbose) {
		fprintf(stdout, "loading physical view                         ");
		fflush(stdout);
	}
	INIT;
	pf = getphfig(argv[1], 'A');
	DELAY(from);
	if (verbose) {
		fprintf(stdout, "checking and merging logical and physical view");
		fflush(stdout);
	}
	INIT;
	ch = checkandbuild(pf, lf, pt, f);
	if (!ch->NETS) {
		fprintf(stderr, "flop : empty channel, check placement!\n");
		exit(1);
	}
	DELAY(from);
	if (verbose) {
		fprintf(stdout, "routing the channel                           ");
		fflush(stdout);
	}
	INIT;
	routechannel(pf, ch);
	DELAY(from);
	if (verbose) {
		fprintf(stdout, "eliminating zero length wires                 ");
		fflush(stdout);
	}
	INIT;
	destroysegments(getphfig(ch->NAME, 'A'), null);
	DELAY(from);
	if (verbose) {
		fprintf(stdout, "merging colinear wires                        ");
		fflush(stdout);
	}
	INIT;
	verticalmerge(getphfig(ch->NAME, 'A'));
	if (pt)
		connectsupplies(getphfig(ch->NAME, 'A'), pt);
	/* changelayer(getphfig(ch->NAME, 'A')); avoid that!, for powers! */
	DELAY(from);
	if (verbose) {
		fprintf(stdout, "computing statistics                          ");
		fflush(stdout);
	}
	INIT;
	if (verbose)
		statistics(getphfig(ch->NAME, 'A'), &i, &j, &k);
	DELAY(from);
	if (verbose) {
		fprintf(stdout, "   metal2 routing length : %ld\n", i);
		fprintf(stdout, "   metal1 routing length : %ld\n", j);
		fprintf(stdout, "   number of vias poked  : %ld\n", k);
	}
	if (verbose) {
		fprintf(stdout, "building the final block                      ");
		fflush(stdout);
	}
	INIT;
	makeblock(pf, ch, pt);
	DELAY(from);
	pf->NAME = out;
	if (verbose) {
		fprintf(stdout, "saving the final block                        ");
		fflush(stdout);
	}
	INIT;
	savephfig(pf);
	DELAY(from);
	if (verbose) {
		fprintf(stdout, "total time spend                              ");
		fflush(stdout);
	}
	DELAY(start);
	return 0;
}
