/* $Id$
 *
 * C-Code kernel / runtime library..
 *
 * Copyright (C) 2010 FAUmachine Team <info@faumachine.org>.
 * This program is free software. You can redistribute it and/or modify it
 * under the terms of the GNU General Public License, either version 2 of
 * the License, or (at your option) any later version. See COPYING.
 */

#include <unistd.h>
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#include <getopt.h>
#undef _GNU_SOURCE
#else /* _GNU_SOURCE already defined */
#include <getopt.h>
#endif /* _GNU_SOURCE not defined? */

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <pthread.h>
#include "mangle_names.h"
#include "basetypes.h"
#include "runtime.h"

/* init routine as defined by the c-file */
extern int 
vhdl_call_by_name(struct vhdl_kernel *kernel, const char *name);


#if 0 /* FIXME */
static int
simulation_cycle(void)
{
	for (;;) {
		/* advance simulation time to next event */
		/* update signals from driving values */
		/* wake up all processes with events */
		/* resume all processes with events */
		/* check for delta cycle, if so back to start */
		/* here's a good place to call the tracer */
	}
}
#endif

static int
start_simulation(const char *top_entity)
{
	char buf[2048];
	int ret;

	ret = mangle_name(top_entity, buf, sizeof(buf));
	assert(0 <= ret);
	assert((size_t)ret < sizeof(buf));
#if 0 /* FIXME */
	ret = vhdl_call_by_name(buf);
	/* TODO */
#endif
	return ret;
}

static void
usage(const char *prog)
{
	fprintf(stderr, "%s [options]\n", prog);
	fprintf(stderr, "  Generated VHDL Simulator.\n");
	fprintf(stderr, "Options:\n");
	fprintf(stderr, "  -s ENTITY, --simulate=ENTITY   Start simulation "
			"with ENTITY as top entity.\n");
	fprintf(stderr, "  -o VCDFILE, --output=VCDFILE   Output trace to ");
	fprintf(stderr, "VCDFILE.\n");
	fprintf(stderr, "  -t, --trace=ENTITY             Trace all signals "
			"in ENTITY\n");
	fprintf(stderr, "  -h, --help                     Show this help.");
	fprintf(stderr, "\n");
}


int
main(int argc, char **argv)
{
	int c;
	int ret;
	const char *top_entity = NULL;
	const char *trace_file = NULL;

	const struct option l_opts[] = {
		{"simulate", 1, NULL, 's'},
		{"output", 1, NULL, 'o'},
		{"trace", 1, NULL, 't'},
		{"help", 0, NULL, 'h'},
		{0, 0, 0, 0}
	};

	for (;;) {
		c = getopt_long(argc, argv, "s:o:t:h", l_opts, NULL);
		if (c == -1) {
			break;
		}

		switch (c) {
		case 's':
			top_entity = optarg;
			break;

		case 'o':
			trace_file = optarg;
			break;

		case 't':
			assert(0);
			/* FIXME */
			break;

		case 'h':
			usage(argv[0]);
			return EXIT_SUCCESS;

		default:
			usage(argv[0]);
			return EXIT_FAILURE;
		}
	}

	if (argc - optind != 0) {
		usage(argv[0]);
		return EXIT_FAILURE;
	}

	/* FIXME tracer... */
	ret = start_simulation(top_entity);
	return ret;
}
