/****************************************************************************/
/*                                                                          */
/*                      Chaine de CAO & VLSI   Alliance                     */
/*                                                                          */
/*    Produit : NetOptim                                                    */
/*    Fichier : graph.c                                                     */
/*                                                                          */
/*    (c) copyright 1991 Laboratoire MASI equipe CAO & VLSI                 */
/*    Tous droits reserves                                                  */
/*    Support : e-mail cao-vlsi@masi.ibp.fr                                 */
/*                                                                          */
/*    Auteur(s) : Vincent POUILLEY                      le : 12/11/1991     */
/*                                                                          */
/*    Modifie par : V. POUILLEY                         le : 11/05/1992     */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*                                                                          */
/****************************************************************************/

/* Section include */
#include <stdio.h>
#include <stdlib.h>
#include "mut302.h"
#include "mlo301.h"
#include "log120.h"
#include "no_struct.h"
#include "../include/vh_btype.h"
#include "../include/types.h"
#include "../net/no_type.h"
#include "../load/util.h"
#include "../load/neto.h"
#include "../load/optim.h"

/* section constantes */
#define NO_AVANT 1
#define NO_ARRIERE 0

/* section donnees globales */
t_noeud ** no_tabnoeuds;
int no_nbnoeud;
t_tabsorties * no_tabsorties;
int no_nbsortie;
t_tabentrees * no_tabentrees;
int no_nbentree;

/*--------------------------- init_recursion ------------------------*/
void init_recursion(sens)
char sens;
{
	int i, j;
	chain_list * paux;

	if (sens == NO_AVANT)
		for (i = 0; i < no_nbnoeud; i +=2)
		{
			for (paux = no_tabnoeuds[i]->pred, j = 0; paux; paux = paux->NEXT)
				j ++;
			no_tabnoeuds[i]->recursion = no_tabnoeuds[i+1]->recursion = j;
		}
	else
		for (i = 0; i < no_nbnoeud; i += 2)
		{
			for (paux = no_tabnoeuds[i]->next, j = 0; paux; paux = paux->NEXT)
				j ++;
			no_tabnoeuds[i]->recursion = no_tabnoeuds[i+1]->recursion = j;
		}
} /* init_recursion */

/*--------------------------- nettoie_recursion ---------------------*/
void nettoie_recursion()
{
	int i;

	for (i = 0; i < no_nbnoeud; i++)
		no_tabnoeuds[i]->recursion = 0;
} /* nettoie-recurcion */

/*--------------------------- sortie_trouvee ------------------------*/
void sortie_trouvee(arete, entree)
t_arete * arete;
t_tabentrees * entree;
{
	int i;
	ptype_list * ptype;

	for (i = 0; i < no_nbsortie; i++)
		if ((arete == no_tabsorties[i].noeud1) || (arete == no_tabsorties[i].noeud0))
		{
			for (ptype = no_tabsorties[i].entrees; ptype; ptype = ptype->NEXT)
				if ((t_tabentrees *)ptype->DATA == entree)
				{
					ptype->TYPE += 1;
					break;
				}
			if (ptype == NULL)
			{
				no_tabsorties[i].entrees = addptype(no_tabsorties[i].entrees, 1, entree);
				entree->sorties = addchain(entree->sorties, no_tabsorties + i);
			}
			break;
		}
} /* sortie_trouvee */

/*--------------------------- trouve_sortie -------------------------*/
void trouve_sortie(noeud, entree)
t_noeud * noeud;
t_tabentrees * entree;
{
	chain_list * pchain;

	if (noeud->recursion == 1)
		return ;
	noeud->recursion = 1;
	for (pchain = noeud->next; pchain; pchain = pchain->NEXT)
		if (((t_arete *)(pchain->DATA))->dest == NULL)
			sortie_trouvee((t_arete *)(pchain->DATA), entree);
		else
			trouve_sortie(((t_arete *)(pchain->DATA))->dest, entree);
} /* trouve_sortie */

/*--------------------------- creer_graphe --------------------------*/
void creer_graphe(ptfig)
lofig_list * ptfig;
{
	int i, j, genere, erreur, ok, trouve;
	losig_list * ptsig;
	locon_list * ptcon;
	ptype_list * ptype;
	chain_list * pchain;
	t_noeud * ptn0, * ptn1;
	t_arete * arhh, * arhl, * arlh, * arll;
	char * namesig, * n_vdd, * n_vss;

	if (NO_TRACE)
		puts("Creation du graphe ...");
	for (i = 0, ptsig = ptfig->LOSIG; ptsig; ptsig = ptsig->NEXT)
		i++;
	no_nbnoeud = i << 1;
	no_tabentrees = (t_tabentrees *)malloc(sizeof(t_tabentrees) * i);
	no_tabsorties = (t_tabsorties *)malloc(sizeof(t_tabsorties) * i);
	no_tabnoeuds = (t_noeud **)malloc(sizeof(t_noeud *) * no_nbnoeud);
	if ((no_tabentrees == NULL) || (no_tabsorties == NULL) || (no_tabnoeuds == NULL))
	{
		puts("\ncreer_graphe : erreur d'allocation memoire");
		exit(-1);
	}
	n_vdd = namealloc("vdd");
	n_vss = namealloc("vss");
	for (i = 0, ptsig = ptfig->LOSIG; ptsig; ptsig = ptsig->NEXT)
	{
		/* n'alloue pas de noeud pour vdd et vss */
		namesig = getsigname(ptsig);
		if ((namesig == n_vdd) || (namesig == n_vss))
		{
			no_nbnoeud --;
			no_nbnoeud --;
			continue;
		}
		ptn0 = (t_noeud *)malloc(sizeof(t_noeud));
		ptn1 = (t_noeud *)malloc(sizeof(t_noeud));
		if ((ptn0 == NULL) || (ptn1 == NULL))
		{
			puts("\ncreer_graphe : erreur d'allocation memoire");
			exit(-1);
		}
		no_tabnoeuds[i++] = ptn0;
		no_tabnoeuds[i++] = ptn1;
		ptn0->losig = ptn1->losig = ptsig;
		ptn0->niveau = 0;
		ptn1->niveau = 1;
		ptn0->recursion = ptn1->recursion = 0;
		ptn0->totcapa = ptn1->totcapa = 0.;
		ptn0->temps = ptn1->temps = 0;
		ptn0->slack = ptn1->slack = 0;
		ptn0->loins = ptn1->loins = NULL;
		ptn0->locon = ptn1->locon = NULL;
		ptn0->next = ptn1->next = NULL;
		ptn0->pred = ptn1->pred = NULL;
	}
	for (i = 0; i < no_nbnoeud; i += 2)
	{
		genere = 0;
		for (pchain = getptype(no_tabnoeuds[i]->losig->USER, (long)LOFIGCHAIN)->DATA; pchain; pchain = pchain->NEXT)
		{
			if (((locon_list *)(pchain->DATA))->TYPE == INTERNAL)
			{
				if (((locon_list *)(pchain->DATA))->DIRECTION == OUT)
				{
					if (genere == 1)
					{
						printf("\nCreergraphe : Les portes %s et %s generent le meme signal\n",
							no_tabnoeuds[i]->loins->INSNAME, ((loins_list *)(((locon_list *)(pchain->DATA))->ROOT))->INSNAME);
/*						exit(-1);*/
					}
					no_tabnoeuds[i]->loins = no_tabnoeuds[i+1]->loins =
						((locon_list *)(pchain->DATA))->ROOT;
					no_tabnoeuds[i]->locon = no_tabnoeuds[i+1]->locon =
						(locon_list *)(pchain->DATA);
					for (ptcon = no_tabnoeuds[i]->loins->LOCON; ptcon; ptcon = ptcon->NEXT)
						if (ptcon->DIRECTION == IN)
							for (j = 0; j < no_nbnoeud; j += 2)
								if (no_tabnoeuds[j]->losig == ptcon->SIG)
								{
									switch (cellLoadPolarity(no_tabnoeuds[i]->loins->FIGNAME))
									{
										case NEG :
											arhl = (t_arete *)malloc(sizeof(t_arete));
											arlh = (t_arete *)malloc(sizeof(t_arete));
											if ((arlh == NULL) || (arhl == NULL))
											{
												puts("\ncreer_graphe : erreur d'allocation memoire");
												exit(-1);
											}
											arhl->source = no_tabnoeuds[j+1];
											no_tabnoeuds[j+1]->next = addchain(no_tabnoeuds[j+1]->next, arhl);
											arhl->dest = no_tabnoeuds[i];
											no_tabnoeuds[i]->pred = addchain(no_tabnoeuds[i]->pred, arhl);
											arlh->source = no_tabnoeuds[j];
											no_tabnoeuds[j]->next = addchain(no_tabnoeuds[j]->next, arlh);
											arlh->dest = no_tabnoeuds[i+1];
											no_tabnoeuds[i+1]->pred = addchain(no_tabnoeuds[i+1]->pred, arlh);
											arhl->capa = arlh->capa = cellLoadCin(no_tabnoeuds[i]->loins->FIGNAME, ptcon->NAME);
											arhl->R = cellLoadR(no_tabnoeuds[i]->loins->FIGNAME, ptcon->NAME, ROFF);
											arlh->R = cellLoadR(no_tabnoeuds[i]->loins->FIGNAME, ptcon->NAME, RON);
											arhl->tpxx = cellLoadTp(no_tabnoeuds[i]->loins->FIGNAME, ptcon->NAME, HL);
											arlh->tpxx = cellLoadTp(no_tabnoeuds[i]->loins->FIGNAME, ptcon->NAME, LH);
											arhl->locon = arlh->locon = ptcon;
											break;
										case POS :
											arhh = (t_arete *)malloc(sizeof(t_arete));
											arll = (t_arete *)malloc(sizeof(t_arete));
											if ((arll == NULL) || (arhh == NULL))
											{
												puts("\ncreer_graphe : erreur d'allocation memoire");
												exit(-1);
											}
											arhh->source = no_tabnoeuds[j+1];
											no_tabnoeuds[j+1]->next = addchain(no_tabnoeuds[j+1]->next, arhh);
											arhh->dest = no_tabnoeuds[i+1];
											no_tabnoeuds[i+1]->pred = addchain(no_tabnoeuds[i+1]->pred, arhh);
											arll->source = no_tabnoeuds[j];
											no_tabnoeuds[j]->next = addchain(no_tabnoeuds[j]->next, arll);
											arll->dest = no_tabnoeuds[i];
											no_tabnoeuds[i]->pred = addchain(no_tabnoeuds[i]->pred, arll);
											arhh->capa = arll->capa = cellLoadCin(no_tabnoeuds[i]->loins->FIGNAME, ptcon->NAME);
											arhh->R = cellLoadR(no_tabnoeuds[i]->loins->FIGNAME, ptcon->NAME, RON);
											arll->R = cellLoadR(no_tabnoeuds[i]->loins->FIGNAME, ptcon->NAME, ROFF);
											arhh->tpxx = cellLoadTp(no_tabnoeuds[i]->loins->FIGNAME, ptcon->NAME, HH);
											arll->tpxx = cellLoadTp(no_tabnoeuds[i]->loins->FIGNAME, ptcon->NAME, LL);
											arhh->locon = arll->locon = ptcon;
											break;
										case AUT :
											arhl = (t_arete *)malloc(sizeof(t_arete));
											arlh = (t_arete *)malloc(sizeof(t_arete));
											arhh = (t_arete *)malloc(sizeof(t_arete));
											arll = (t_arete *)malloc(sizeof(t_arete));
											if ((arlh == NULL) || (arhl == NULL) ||
												(arll == NULL) || (arhh == NULL))
											{
												puts("\ncreer_graphe : erreur d'allocation memoire");
												exit(-1);
											}
											arhl->source = no_tabnoeuds[j+1];
											no_tabnoeuds[j+1]->next = addchain(no_tabnoeuds[j+1]->next, arhl);
											arhl->dest = no_tabnoeuds[i];
											no_tabnoeuds[i]->pred = addchain(no_tabnoeuds[i]->pred, arhl);
											arlh->source = no_tabnoeuds[j];
											no_tabnoeuds[j]->next = addchain(no_tabnoeuds[j]->next, arlh);
											arlh->dest = no_tabnoeuds[i+1];
											no_tabnoeuds[i+1]->pred = addchain(no_tabnoeuds[i+1]->pred, arlh);
											arhh->source = no_tabnoeuds[j+1];
											no_tabnoeuds[j+1]->next = addchain(no_tabnoeuds[j+1]->next, arhh);
											arhh->dest = no_tabnoeuds[i+1];
											no_tabnoeuds[i+1]->pred = addchain(no_tabnoeuds[i+1]->pred, arhh);
											arll->source = no_tabnoeuds[j];
											no_tabnoeuds[j]->next = addchain(no_tabnoeuds[j]->next, arll);
											arll->dest = no_tabnoeuds[i];
											no_tabnoeuds[i]->pred = addchain(no_tabnoeuds[i]->pred, arll);
											arhl->capa = arlh->capa = arhh->capa = arll->capa = cellLoadCin(no_tabnoeuds[i]->loins->FIGNAME, ptcon->NAME);
											arhl->R = cellLoadR(no_tabnoeuds[i]->loins->FIGNAME, ptcon->NAME, ROFF);
											arlh->R = cellLoadR(no_tabnoeuds[i]->loins->FIGNAME, ptcon->NAME, RON);
											arhh->R = cellLoadR(no_tabnoeuds[i]->loins->FIGNAME, ptcon->NAME, RON);
											arll->R = cellLoadR(no_tabnoeuds[i]->loins->FIGNAME, ptcon->NAME, ROFF);
											arhl->tpxx = cellLoadTp(no_tabnoeuds[i]->loins->FIGNAME, ptcon->NAME, HL);
											arlh->tpxx = cellLoadTp(no_tabnoeuds[i]->loins->FIGNAME, ptcon->NAME, LH);
											arhh->tpxx = cellLoadTp(no_tabnoeuds[i]->loins->FIGNAME, ptcon->NAME, HH);
											arll->tpxx = cellLoadTp(no_tabnoeuds[i]->loins->FIGNAME, ptcon->NAME, LL);
											arhl->locon = arlh->locon = arhh->locon = arll->locon = ptcon;
											break;
									} /* switch */
									break;
								} /* for if */
					switch (cellLoadType(no_tabnoeuds[i]->loins->FIGNAME))
					{
						case REG :
							no_tabnoeuds[i]->recursion = no_tabnoeuds[i+1]->recursion = 1;
							/* il n'y a surtout pas de break */
						case COMBI :
							genere = 1;
							break;
					}
				}
				else
					if (((locon_list *)(pchain->DATA))->DIRECTION != IN)
					{
						printf("le connecteur %s de la figure %s est en %c\n",
							((locon_list *)(pchain->DATA))->NAME, ((loins_list *)(((locon_list *)(pchain->DATA))->ROOT))->INSNAME, ((locon_list *)(pchain->DATA))->DIRECTION);
					}
			} /* if internal */
		} /* for sur tous les connecteur */
	} /* for sur tous les noeuds */
	/* phase de verification et d'allocation des e/s */
	erreur = 0;
	for (i = 0; i < no_nbnoeud; i++)
	{
		if (no_tabnoeuds[i]->next == NULL)
		{
			ok = 0;
			for (pchain = getptype(no_tabnoeuds[i]->losig->USER, (long)LOFIGCHAIN)->DATA; pchain; pchain = pchain->NEXT)
				if (((locon_list *)(pchain->DATA))->TYPE == EXTERNAL)
					if (((locon_list *)(pchain->DATA))->DIRECTION == IN)
					{
						printf("Warning : le connecteur IN %s est relie sur une sortie\n",
							((locon_list *)(pchain->DATA))->NAME);
						erreur += 1;
					}
					else
					{
						for (j = trouve = 0; j < no_nbsortie; j++)
							if ((locon_list *)(pchain->DATA) == no_tabsorties[j].locon)
							{
								trouve = 1;
								break;
							}
						if (!trouve)
						{
							j = no_nbsortie++;
							no_tabsorties[j].locon = (locon_list *)(pchain->DATA);
						}
						arll = (t_arete *)malloc(sizeof(t_arete));
						if (arll == NULL)
						{
							puts("\ncreer_graphe : erreur d'allocation memoire");
							exit(-1);
						}
						arll->source = no_tabnoeuds[i];
						arll->dest = NULL;
						no_tabnoeuds[i]->next = addchain(no_tabnoeuds[i]->next, arll);
						arll->locon = (locon_list *)(pchain->DATA);
						if (no_tabnoeuds[i]->niveau == 0)
							no_tabsorties[j].noeud0 = arll;
						else
							no_tabsorties[j].noeud1 = arll;
						arll->capa = 0.;
						arll->R = arll->tpxx = 0;
						for (ptype = NO_CAPAPO; ptype; ptype = ptype->NEXT)
							if ((char *)ptype->DATA == ((locon_list *)(pchain->DATA))->NAME)
							{
								arll->capa = ptype->TYPE;
								break;
							}
						ok = 1;
					}
			if (!ok)
			{
				printf("Warning : la sortie %d (%s) est en l'air\n",
					no_tabnoeuds[i]->losig->INDEX, getsigname(no_tabnoeuds[i]->losig));
				erreur += 1;
			}
		}
		if (no_tabnoeuds[i]->pred == NULL)
		{
			ok = 0;
			for (pchain = getptype(no_tabnoeuds[i]->losig->USER, (long)LOFIGCHAIN)->DATA; pchain; pchain = pchain->NEXT)
				if (((locon_list *)(pchain->DATA))->TYPE == EXTERNAL)
					if (((locon_list *)(pchain->DATA))->DIRECTION == OUT)
					{
						printf("Warning : le connecteur OUT %s est relie sur une entree\n",
							((locon_list *)(pchain->DATA))->NAME);
						erreur += 1;
					}
					else
					{
						for (j = trouve = 0; j < no_nbentree; j++)
							if ((locon_list *)(pchain->DATA) == no_tabentrees[j].locon)
							{
								trouve = 1;
								break;
							}
						if (!trouve)
						{
							j = no_nbentree++;
							no_tabentrees[j].locon = (locon_list *)(pchain->DATA);
						}
						arll = (t_arete *)malloc(sizeof(t_arete));
						if (arll == NULL)
						{
							puts("\ncreer_graphe : erreur d'allocation memoire");
							exit(-1);
						}
						arll->dest = no_tabnoeuds[i];
						arll->source = NULL;
						no_tabnoeuds[i]->pred = addchain(no_tabnoeuds[i]->pred, arll);
						arll->locon = (locon_list *)(pchain->DATA);
						if (no_tabnoeuds[i]->niveau == 0)
							no_tabentrees[j].noeud0 = addchain(no_tabentrees[j].noeud0, arll);
						else
							no_tabentrees[j].noeud1 = addchain(no_tabentrees[j].noeud1, arll);
						arll->capa = 0.;
						arll->R = arll->tpxx = 0;
						for (ptype = NO_RESISTPI; ptype; ptype = ptype->NEXT)
							if ((char *)ptype->DATA == ((locon_list *)(pchain->DATA))->NAME)
							{
								arll->R = ptype->TYPE;
								break;
							}
						for (ptype = NO_DELAYPI; ptype; ptype = ptype->NEXT)
							if ((char *)ptype->DATA == ((locon_list *)(pchain->DATA))->NAME)
							{
								arll->tpxx = ptype->TYPE;
								break;
							}
						ok = 1;
					}
			if (!ok)
			{
				printf("Warning : l'entree %d (%s) est en l'air\n",
					no_tabnoeuds[i]->losig->INDEX, getsigname(no_tabnoeuds[i]->losig));
				erreur += 1;
			}
		}
		if (no_tabnoeuds[i]->recursion == 1)
		{
			no_tabnoeuds[i]->recursion = 0;
			for (j = trouve = 0; j < no_nbentree; j++)
				if (no_tabnoeuds[i]->locon == no_tabentrees[j].locon)
				{
					trouve = 1;
					break;
				}
			if (!trouve)
			{
				j = no_nbentree++;
				no_tabentrees[j].locon = no_tabnoeuds[i]->locon;
			}
			arll = (t_arete *)malloc(sizeof(t_arete));
			if (arll == NULL)
			{
				puts("\ncreer_graphe : erreur d'allocation memoire");
				exit(-1);
			}
			arll->source = NULL;
			arll->dest = no_tabnoeuds[i];
			arll->R = arll->tpxx = 0;
			arll->capa = 0.;
			for (pchain = no_tabnoeuds[i]->pred; pchain; pchain = pchain->NEXT)
			{
				if (((t_arete *)(pchain->DATA))->R > arll->R)
					arll->R = ((t_arete *)(pchain->DATA))->R;
				if (((t_arete *)(pchain->DATA))->tpxx > arll->tpxx)
					arll->tpxx = ((t_arete *)(pchain->DATA))->tpxx;
			}
			arll->locon = no_tabnoeuds[i]->locon;
			if (no_tabnoeuds[i]->niveau == 0)
				no_tabentrees[j].noeud0 = addchain(no_tabentrees[j].noeud0, arll);
			else
				no_tabentrees[j].noeud1 = addchain(no_tabentrees[j].noeud1, arll);
			for (pchain = no_tabnoeuds[i]->pred; pchain; pchain = pchain->NEXT)
			{
				for (j = trouve = 0; j < no_nbsortie; j++)
					if (((t_arete *)(pchain->DATA))->source->locon == no_tabsorties[j].locon)
					{
						trouve = 1;
						break;
					}
				if (!trouve)
				{
					j = no_nbsortie++;
					no_tabsorties[j].locon = ((t_arete *)(pchain->DATA))->source->locon;
				}
				((t_arete *)(pchain->DATA))->dest = NULL;
				if (no_tabnoeuds[i]->niveau == 0)
					no_tabsorties[j].noeud0 = (t_arete *)(pchain->DATA);
				else
					no_tabsorties[j].noeud1 = (t_arete *)(pchain->DATA);
			} /* for */
			freechain(no_tabnoeuds[i]->pred);
			no_tabnoeuds[i]->pred = NULL;
			no_tabnoeuds[i]->pred = addchain(no_tabnoeuds[i]->pred, arll);
		} /* il recursion */
		for (pchain = no_tabnoeuds[i]->next; pchain; pchain = pchain->NEXT)
			no_tabnoeuds[i]->totcapa += ((t_arete *)(pchain->DATA))->capa;
		if (no_tabnoeuds[i]->losig->CAPA != 0.)
			no_tabnoeuds[i]->totcapa += no_tabnoeuds[i]->losig->CAPA;
		else
			no_tabnoeuds[i]->totcapa *= 2;
	}
	if (erreur)
	{
		printf("\nCreer_graphe : Attention %d warning(s)\n", erreur);
	}
	/* Trouve chemin */
	for (i = 0; i < no_nbentree; i++)
	{
		for (pchain = no_tabentrees[i].noeud1; pchain; pchain = pchain->NEXT)
			if (((t_arete *)(pchain->DATA))->dest != NULL)
			{
				trouve_sortie(((t_arete *)(pchain->DATA))->dest, no_tabentrees + i);
				nettoie_recursion();
			}
			else
			{
				printf("\nCreer_graphe : erreur dans le chainage des aretes\n");
				exit(-1);
			}
		for (pchain = no_tabentrees[i].noeud0; pchain; pchain = pchain->NEXT)
			if (((t_arete *)(pchain->DATA))->dest != NULL)
			{
				trouve_sortie(((t_arete *)(pchain->DATA))->dest, no_tabentrees + i);
				nettoie_recursion();
			}
			else
			{
				printf("\nCreer_graphe : erreur dans le chainage des aretes\n");
				exit(-1);
			}
	}
	if (NO_TRACE)
		puts("Creation du graphe terminee\n");
} /* creer_graphe */

/*--------------------------- calcul_temps_noeud --------------------*/
void calcul_temps_noeud(noeud)
t_noeud * noeud;
{
	int temps;
	chain_list * pchain;

	if (noeud->recursion == -3)
		return ;
	if ((noeud->recursion == 1) || (noeud->recursion == 0))
	{
		noeud->recursion = -3;
		noeud->temps = 0;
		for (pchain = noeud->pred; pchain; pchain = pchain->NEXT)
		{
			temps = ((t_arete *)(pchain->DATA))->tpxx + ((t_arete *)(pchain->DATA))->R * noeud->totcapa;
			if (temps > noeud->temps)
				noeud->temps = temps;
		}
		for (pchain = noeud->next; pchain; pchain = pchain->NEXT)
			if (((t_arete *)(pchain->DATA))->dest != NULL)
				calcul_temps_noeud(((t_arete *)(pchain->DATA))->dest);
	}
	else
		(noeud->recursion)--;
} /* calcul_temps_noeud */

/*--------------------------- calcul_temps --------------------------*/
void calcul_temps()
{
	int i, erreur;
	chain_list * pchain;

	if (NO_TRACE)
		puts("Calcul des temps de propagation ...");
	init_recursion(NO_AVANT);
	for (i = 0; i < no_nbentree; i++)
	{
		for (pchain = no_tabentrees[i].noeud1; pchain; pchain = pchain->NEXT)
			if (((t_arete *)(pchain->DATA))->dest != NULL)
				calcul_temps_noeud(((t_arete *)(pchain->DATA))->dest);
			else
			{
				printf("\nCalcul temps : erreur dans le chainage des aretes\n");
				exit(-1);
			}
		for (pchain = no_tabentrees[i].noeud0; pchain; pchain = pchain->NEXT)
			if (((t_arete *)(pchain->DATA))->dest != NULL)
				calcul_temps_noeud(((t_arete *)(pchain->DATA))->dest);
			else
			{
				printf("\nCalcul temps : erreur dans le chainage des aretes\n");
				exit(-1);
			}
	}
	erreur = 0;
	for (i = 0; i < no_nbnoeud; i++)
	{
		if (no_tabnoeuds[i]->recursion != -3)
		{
			printf("\nCalcul_Temps : Un rebouclage sur la porte %s empeche le calcul du temps\n",
				no_tabnoeuds[i]->loins->FIGNAME);
			erreur += 1;
		}
		no_tabnoeuds[i]->recursion = 0;
	}
	if (erreur)
	{
		printf("\nCalcul_Temps : Fin de NetOptim apres %d erreur(s)\n", erreur);
		exit(-1);
	}
	for (i = 0; i < no_nbsortie; i++)
		no_tabsorties[i].temps_res = MAX(no_tabsorties[i].noeud1->source->temps,no_tabsorties[i].noeud0->source->temps);
	if (NO_TRACE)
		puts("Fin du calcul des temps de propagation");
} /* calcul_temps */

/*--------------------------- calcul_slack_noeud --------------------*/
void calcul_slack_noeud(noeud)
t_noeud * noeud;
{
	int tmp;
	chain_list * pchain;

	if (noeud->recursion == -3)
		return ;
	if ((noeud->recursion == 1) || (noeud->recursion == 0))
	{
		noeud->recursion = -3;
		noeud->slack = 0;
		for (pchain = noeud->next; pchain; pchain = pchain->NEXT)
		{
			if (((t_arete *)(pchain->DATA))->dest != NULL)
				tmp = noeud->temps - ((t_arete *)(pchain->DATA))->dest->temps + ((t_arete *)(pchain->DATA))->dest->slack +
					((t_arete *)(pchain->DATA))->tpxx + ((t_arete *)(pchain->DATA))->R * ((t_arete *)(pchain->DATA))->dest->totcapa;
			else
				tmp = 0;
			if (tmp > noeud->slack)
				noeud->slack = tmp;
		}
		for (pchain = noeud->pred; pchain; pchain = pchain->NEXT)
			if (((t_arete *)(pchain->DATA))->source != NULL)
				calcul_slack_noeud(((t_arete *)(pchain->DATA))->source);
	}
	else
		(noeud->recursion)--;
} /* calcul_slack_noeud */

/*--------------------------- calcul_slacks -------------------------*/
void calcul_slacks()
{
	int i;
	chain_list * pchain;
	ptype_list * ptype;

	if (NO_TRACE)
		puts("Calcul des slacks ...");
	init_recursion(NO_ARRIERE);
	for (i = 0; i < no_nbsortie; i++)
		no_tabsorties[i].temps_voulu = NO_DELAY;
	/* affecter les delay particulier */
	for (ptype = NO_DELAYPO; ptype; ptype = ptype->NEXT)
	{
		for (i = 0; i < no_nbsortie; i++)
			if (no_tabsorties[i].locon->NAME == ((char *)(ptype->DATA)))
			{
/* PB : doit-on prendre le delai particulier tel quel ou verifier
   qu'il n'est pas superieur au delai global */
				no_tabsorties[i].temps_voulu = ptype->TYPE;
				break;
			}
	}
	for (i = 0; i < no_nbsortie; i++)
	{
		no_tabsorties[i].noeud0->source->slack = no_tabsorties[i].noeud0->source->temps - no_tabsorties[i].temps_voulu;
		for (pchain = no_tabsorties[i].noeud0->source->pred; pchain; pchain = pchain->NEXT)
			if (((t_arete *)(pchain->DATA))->source != NULL)
				calcul_slack_noeud(((t_arete *)(pchain->DATA))->source);
		no_tabsorties[i].noeud1->source->slack = no_tabsorties[i].noeud1->source->temps - no_tabsorties[i].temps_voulu;
		for (pchain = no_tabsorties[i].noeud1->source->pred; pchain; pchain = pchain->NEXT)
			if (((t_arete *)(pchain->DATA))->source != NULL)
				calcul_slack_noeud(((t_arete *)(pchain->DATA))->source);
	}
	nettoie_recursion();
	if (NO_TRACE)
		puts("Fin du calcul des slacks");
} /* calcul_slacks */

/*--------------------------- detruit_graphe ------------------------*/
void detruit_graphe()
{
	int i;
	chain_list * pchain;

	if (NO_TRACE)
		puts("Destruction du graphe");
	for (i = 0; i < no_nbnoeud; i++)
	{
		for (pchain = no_tabnoeuds[i]->pred; pchain; pchain = pchain->NEXT)
			free((t_arete *)(pchain->DATA));
		freechain(no_tabnoeuds[i]->pred);
		freechain(no_tabnoeuds[i]->next);
		free(no_tabnoeuds[i]);
	}
	free(no_tabnoeuds);
	no_nbnoeud = 0;
	for (i = 0; i < no_nbentree; i++)
	{
		freechain(no_tabentrees[i].noeud0);
		freechain(no_tabentrees[i].noeud1);
		freechain(no_tabentrees[i].sorties);
	}
	free(no_tabentrees);
	no_nbentree = 0;
	for (i = 0; i < no_nbsortie; i++)
	{
		free(no_tabsorties[i].noeud0);
		free(no_tabsorties[i].noeud1);
		freeptype(no_tabsorties[i].entrees);
	}
	free(no_tabsorties);
	no_nbsortie = 0;
} /* detruit_graphe */

/*--------------------------- debug_graphe --------------------------*/
void debug_graphe()
{
	int i, j;
	chain_list * pchain;
	ptype_list * ptype;

	printf("\n\n Affichage du graphe :\n\n Nombre de noeuds : %d\n", no_nbnoeud);
	for (i = 0; i < no_nbnoeud; i++)
	{
		printf("\nnoeud %d :\n", i);
		printf("   niveau : %d\n", no_tabnoeuds[i]->niveau);
		printf("   recursion : %d\n", no_tabnoeuds[i]->recursion);
		printf("   totcapa : %f\n", no_tabnoeuds[i]->totcapa);
		printf("   temps : %d\n", no_tabnoeuds[i]->temps);
		printf("   slack : %d\n", no_tabnoeuds[i]->slack);
		if (no_tabnoeuds[i]->losig == NULL)
			printf("   losig : NULL\n");
		else
			printf("   losig : %d nom : (%s) capa : %f\n", no_tabnoeuds[i]->losig->INDEX, getsigname(no_tabnoeuds[i]->losig), no_tabnoeuds[i]->losig->CAPA);
		if (no_tabnoeuds[i]->loins == NULL)
			printf("   loins : NULL\n");
		else
			printf("   loins : (%s) modele : (%s)\n", no_tabnoeuds[i]->loins->INSNAME, no_tabnoeuds[i]->loins->FIGNAME);
		if (no_tabnoeuds[i]->locon == NULL)
			printf("   locon : NULL\n");
		else
			printf("   locon : (%s) direction : %c type : %c signal : (%s)\n", no_tabnoeuds[i]->locon->NAME, no_tabnoeuds[i]->locon->DIRECTION, no_tabnoeuds[i]->locon->TYPE, getsigname(no_tabnoeuds[i]->locon->SIG));
		printf("   arete sortante :\n");
		for (pchain = no_tabnoeuds[i]->next; pchain; pchain = pchain->NEXT)
		{
			printf("      capa : %f\n", ((t_arete *)(pchain->DATA))->capa);
			printf("      R : %d\n", ((t_arete *)(pchain->DATA))->R);
			printf("      tpxx : %d\n", ((t_arete *)(pchain->DATA))->tpxx);
			if (((t_arete *)(pchain->DATA))->locon == NULL)
				printf("      locon : NULL\n");
			else
				printf("      locon : (%s) direction : %c type : %c signal : (%s)\n", ((t_arete *)(pchain->DATA))->locon->NAME, ((t_arete *)(pchain->DATA))->locon->DIRECTION, ((t_arete *)(pchain->DATA))->locon->TYPE, getsigname(((t_arete *)(pchain->DATA))->locon->SIG));
			if (((t_arete *)(pchain->DATA))->dest == NULL)
				printf("      dest : NULL\n\n");
			else
			{
				for (j = 0; j < no_nbnoeud; j++)
					if (((t_arete *)(pchain->DATA))->dest == no_tabnoeuds[j])
						break;
				printf("      dest : noeud %d\n\n", j);
			}
		}
		printf("   arete entrante :\n");
		for (pchain = no_tabnoeuds[i]->pred; pchain; pchain = pchain->NEXT)
		{
			printf("      capa : %f\n", ((t_arete *)(pchain->DATA))->capa);
			printf("      R : %d\n", ((t_arete *)(pchain->DATA))->R);
			printf("      tpxx : %d\n", ((t_arete *)(pchain->DATA))->tpxx);
			if (((t_arete *)(pchain->DATA))->locon == NULL)
				printf("      locon : NULL\n");
			else
				printf("      locon : (%s) direction : %c type : %c signal : (%s)\n", ((t_arete *)(pchain->DATA))->locon->NAME, ((t_arete *)(pchain->DATA))->locon->DIRECTION, ((t_arete *)(pchain->DATA))->locon->TYPE, getsigname(((t_arete *)(pchain->DATA))->locon->SIG));
			if (((t_arete *)(pchain->DATA))->source == NULL)
				printf("      source : NULL\n\n");
			else
			{
				for (j = 0; j < no_nbnoeud; j++)
					if (((t_arete *)(pchain->DATA))->source == no_tabnoeuds[j])
						break;
				printf("      source : noeud %d\n\n", j);
			}
		}
	}
	printf("\naffichage de la table des entrees :\n\nNombre d'entrees : %d\n", no_nbentree);
	for (i = 0; i < no_nbentree; i++)
	{
		printf("\nEntree : %d\n", i);
		if (no_tabentrees[i].locon == NULL)
			printf("   locon : NULL\n");
		else
			printf("   locon : (%s) direction : %c type : %c signal : (%s)\n", no_tabentrees[i].locon->NAME, no_tabentrees[i].locon->DIRECTION, no_tabentrees[i].locon->TYPE, getsigname(no_tabentrees[i].locon->SIG));
		printf("   noeud0 :\n");
		for (pchain = no_tabentrees[i].noeud0; pchain; pchain = pchain->NEXT)
		{
			printf("      capa : %f\n", ((t_arete *)(pchain->DATA))->capa);
			printf("      R : %d\n", ((t_arete *)(pchain->DATA))->R);
			printf("      tpxx : %d\n", ((t_arete *)(pchain->DATA))->tpxx);
			printf("      locon : (%s) direction : %c type : %c signal : (%s)\n", ((t_arete *)(pchain->DATA))->locon->NAME, ((t_arete *)(pchain->DATA))->locon->DIRECTION, ((t_arete *)(pchain->DATA))->locon->TYPE, getsigname(((t_arete *)(pchain->DATA))->locon->SIG));
			if (((t_arete *)(pchain->DATA))->dest == NULL)
				printf("      dest : NULL\n\n");
			else
			{
				for (j = 0; j < no_nbnoeud; j++)
					if (((t_arete *)(pchain->DATA))->dest == no_tabnoeuds[j])
						break;
				printf("      dest : noeud %d\n\n", j);
			}
		}
		printf("   noeud1 :\n");
		for (pchain = no_tabentrees[i].noeud1; pchain; pchain = pchain->NEXT)
		{
			printf("      capa : %f\n", ((t_arete *)(pchain->DATA))->capa);
			printf("      R : %d\n", ((t_arete *)(pchain->DATA))->R);
			printf("      tpxx : %d\n", ((t_arete *)(pchain->DATA))->tpxx);
			printf("      locon : (%s) direction : %c type : %c signal : (%s)\n", ((t_arete *)(pchain->DATA))->locon->NAME, ((t_arete *)(pchain->DATA))->locon->DIRECTION, ((t_arete *)(pchain->DATA))->locon->TYPE, getsigname(((t_arete *)(pchain->DATA))->locon->SIG));
			if (((t_arete *)(pchain->DATA))->dest == NULL)
				printf("      dest : NULL\n\n");
			else
			{
				for (j = 0; j < no_nbnoeud; j++)
					if (((t_arete *)(pchain->DATA))->dest == no_tabnoeuds[j])
						break;
				printf("      dest : noeud %d\n\n", j);
			}
		}
		printf("   sorties :\n");
		for (pchain = no_tabentrees[i].sorties; pchain; pchain = pchain->NEXT)
		{
			for (j = 0; j < no_nbsortie; j++)
				if (((t_tabsorties *)(pchain->DATA)) == no_tabsorties + j)
					break;
			printf("      sortie %d\n", j);
		}
	}
	printf("\naffichage de la table des sorties :\n\nNombre de sorties : %d\n", no_nbsortie);
	for (i = 0; i < no_nbsortie; i++)
	{
		printf("\nSortie : %d\n", i);
		if (no_tabsorties[i].locon == NULL)
			printf("   locon : NULL\n");
		else
			printf("   locon : (%s) direction : %c type : %c signal : (%s)\n", no_tabsorties[i].locon->NAME, no_tabsorties[i].locon->DIRECTION, no_tabsorties[i].locon->TYPE, getsigname(no_tabsorties[i].locon->SIG));
		printf("   temps_res : %d\n", no_tabsorties[i].temps_res);
		printf("   temps_voulu : %d\n", no_tabsorties[i].temps_voulu);
		if (no_tabsorties[i].noeud0 == NULL)
			printf("   noeud0 : NULL\n");
		else
		{
			printf("   noeud0 :\n");
			printf("      capa : %f\n", no_tabsorties[i].noeud0->capa);
			printf("      R : %d\n", no_tabsorties[i].noeud0->R);
			printf("      tpxx : %d\n", no_tabsorties[i].noeud0->tpxx);
			printf("      locon : (%s) direction : %c type : %c signal : (%s)\n", no_tabsorties[i].noeud0->locon->NAME, no_tabsorties[i].noeud0->locon->DIRECTION, no_tabsorties[i].noeud0->locon->TYPE, getsigname(no_tabsorties[i].noeud0->locon->SIG));
			if (no_tabsorties[i].noeud0->source == NULL)
				printf("      source : NULL\n");
			else
			{
				for (j = 0; j < no_nbnoeud; j++)
					if (no_tabsorties[i].noeud0->source == no_tabnoeuds[j])
						break;
				printf("      source : noeud %d\n", j);
			}
		}
		if (no_tabsorties[i].noeud1 == NULL)
			printf("   noeud1 : NULL\n");
		else
		{
			printf("   noeud1 :\n");
			printf("      capa : %f\n", no_tabsorties[i].noeud1->capa);
			printf("      R : %d\n", no_tabsorties[i].noeud1->R);
			printf("      tpxx : %d\n", no_tabsorties[i].noeud1->tpxx);
			printf("      locon : (%s) direction : %c type : %c signal : (%s)\n", no_tabsorties[i].noeud1->locon->NAME, no_tabsorties[i].noeud1->locon->DIRECTION, no_tabsorties[i].noeud1->locon->TYPE, getsigname(no_tabsorties[i].noeud1->locon->SIG));
			if (no_tabsorties[i].noeud1->source == NULL)
				printf("      source : NULL\n");
			else
			{
				for (j = 0; j < no_nbnoeud; j++)
					if (no_tabsorties[i].noeud1->source == no_tabnoeuds[j])
						break;
				printf("      source : noeud %d\n", j);
			}
		}
		printf("   entrees :\n");
		for (ptype = no_tabsorties[i].entrees; ptype; ptype = ptype->NEXT)
		{
			for (j = 0; j < no_nbentree; j++)
				if (((t_tabentrees *)(ptype->DATA)) == no_tabentrees + j)
					break;
			printf("      entree %d, nombre de chemin : %ld\n", j, ptype->TYPE);
		}
	}
} /* debug_graphe */

