/*
 * Electric(tm) VLSI Design System
 *
 * File: simpal.c
 * Simulation aid: deck generator for ABEL PAL system, from Data I/O
 * Written by: Steven M. Rubin, Static Free Software
 *
 * Copyright (c) 2000 Static Free Software.
 *
 * Electric(tm) is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * Electric(tm) is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Electric(tm); see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, Mass 02111-1307, USA.
 *
 * Static Free Software
 * 4119 Alpine Road
 * Portola Valley, California 94028
 * info@staticfreesoft.com
 */

#include "config.h"
#if SIMAID

#include "global.h"
#include "sim.h"
#include "efunction.h"
#include "network.h"

/* prototypes for local routines */
char *sim_palnetname(PNET*);

/*********************** ABEL PAL FILE GENERATION ***********************/

/*
 * routine to write a ".pal" file from the facet "np"
 */
void sim_writepalnetlist(NODEPROTO *np)
{
	char name[100], *fun, *truename;
	INTSML power, ground, components, nets;
	REGISTER INTSML j, a, y;
	REGISTER PCOMP *p;
	REGISTER PNET *net;
	REGISTER PCOMP *pcompused;
	PNET *pnetused;
	REGISTER FILE *palfile;
	extern AIDENTRY *net_aid;

	/* make sure network tool is on */
	if ((net_aid->aidstate&AIDON) == 0)
	{
		ttyputerr("Network tool must be running...turning it on");
		aidturnon(net_aid, 0);
		ttyputerr("...now reissue the simulation command");
		return;
	}

	/* first write the "pal" file */
	(void)strcpy(name, np->cell->cellname);
	(void)strcat(name, ".pal");
	palfile = xcreate(name, FILETYPEPAL, "PAL File", &truename);
	if (palfile == NULL)
	{
		if (truename != 0) ttyputerr("Cannot write %s", truename);
		return;
	}

	/* write header information */
	xprintf(palfile, "module %s\n", np->cell->cellname);
	xprintf(palfile, "title 'generated by Electric'\n");

	/* build flattened representation of circuit */
	pcompused = net_makepseudo(np, &components, &nets, &power, &ground, &pnetused,
		1, 0, 0);
	if (pcompused == NOPCOMP) return;

	/* mark the used ports */
	for(net = pnetused; net != NOPNET; net = net->nextpnet) net->flags = 0;
	for(p = pcompused; p != NOPCOMP; p = p->nextpcomp)
	{
		switch (p->function)
		{
			case NPGATEAND:
			case NPGATEOR:
			case NPGATEXOR:
			case NPBUFFER:
				for(y=0; y<p->wirecount; y++)
					if (namesame(p->portlist[y]->protoname, "y") == 0) break;
				if (y >= p->wirecount) break;
				p->netnumbers[y]->flags++;
				for(a=0; a<p->wirecount; a++)
					if (namesame(p->portlist[a]->protoname, "a") == 0) p->netnumbers[a]->flags++;
				break;
		}
	}

	/* number all ports */
	j = 1;
	for(net = pnetused; net != NOPNET; net = net->nextpnet)
		if (net->realport != NOPORTPROTO && net->flags != 0) net->flags = j++;
	for(net = pnetused; net != NOPNET; net = net->nextpnet)
		if (net->realport == NOPORTPROTO && net->flags != 0) net->flags = j++;

	/* print exported ports */
	for(net = pnetused; net != NOPNET; net = net->nextpnet)
		if (net->realport != NOPORTPROTO && net->flags != 0)
			xprintf(palfile, "    %s pin %d;\n", sim_palnetname(net), net->flags);

	/* print internal points */
	for(net = pnetused; net != NOPNET; net = net->nextpnet)
		if (net->realport == NOPORTPROTO && net->flags != 0)
			xprintf(palfile, "    %s = 0,1;\n", sim_palnetname(net));

	xprintf(palfile, "\nequations\n");
	for(p = pcompused; p != NOPCOMP; p = p->nextpcomp)
	{
		switch (p->function)
		{
			case NPGATEAND:
			case NPGATEOR:
			case NPGATEXOR:
			case NPBUFFER:
				if (p->function == NPGATEAND) fun = "&"; else
					if (p->function == NPGATEOR) fun = "#"; else
						if (p->function == NPGATEXOR) fun = "$"; else
							fun = "";
				for(y=0; y<p->wirecount; y++)
					if (namesame(p->portlist[y]->protoname, "y") == 0) break;
				if (y >= p->wirecount)
				{
					ttyputmsg("Cannot find output port on %s", describenodeinst(p->actual));
					break;
				}
				xprintf(palfile, "   ");
				if ((p->state[y]&NEGATEDPORT) != 0) xprintf(palfile, "!");
				xprintf(palfile, "%s =", sim_palnetname(p->netnumbers[y]));
				j = 0;
				for(a=0; a<p->wirecount; a++)
					if (namesame(p->portlist[a]->protoname, "a") == 0)
				{
					if (j != 0) xprintf(palfile, " %s", fun);
					xprintf(palfile, " ");
					if ((p->state[a]&NEGATEDPORT) != 0) xprintf(palfile, "!");
					xprintf(palfile, "%s", sim_palnetname(p->netnumbers[a]));
					j++;
				}
				xprintf(palfile, ";\n");
				break;

			default:
				ttyputmsg("Don't know how to handle %s objects", describenodeinst(p->actual));
				break;
		}
	}

	/* clean up */
	xprintf(palfile, "\nend %s\n", describenodeproto(np));
	xclose(palfile);
	ttyputmsg("%s written", truename);

	/* free all PNETs and PCOMPs */
	net_freeallpnet(pnetused);
	net_freeallpcomp(pcompused);
}

char *sim_palnetname(PNET *net)
{
	static char line[20];

	if (net->realport != NOPORTPROTO) return(net->realport->protoname);
	(void)sprintf(line, "I%d", net->flags);
	return(line);
}

#endif  /* SIMAID - at top */
