/*
 * This file is part of the Alliance CAD System
 * Copyright (C) Laboratoire LIP6 - Département ASIM
 * Universite Pierre et Marie Curie
 * 
 * Home page          : http://www-asim.lip6.fr/alliance/
 * E-mail             : mailto:alliance-users@asim.lip6.fr
 * 
 * This progam 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.
 * 
 * Alliance VLSI  CAD System  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 the GNU C Library; see the  file COPYING. If not, write to the Free
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

/****************************************************************************/
/*                                                                          */
/*                      Chaine de CAO & VLSI   Alliance                     */
/*                                                                          */
/*    Produit : ring router                                                 */
/*    Fichier : posercircuit.c                                              */
/*                                                                          */
/*    (c) copyright 1992 Laboratoire MASI equipe CAO & VLSI                 */
/*    Tous droits reserves                                                  */
/*    Support : e-mail cao-vlsi@masi.ibp.fr                                 */
/*                                                                          */
/*    Ecrit   par : Olivier Van Hautte                  le : 01/08/92       */
/*    Modifie par : Franck Wajsburt                     le :  9/11/94       */
/*                                                                          */
/****************************************************************************/

/*-----------------------------------------------------------------------------------*/
/* RING  3 juillet 92                   POSERCIRCUIT.C                               */
/* poser des blocs coeur et barre de plots + segments pour fabriquer fig MBK         */
/*-----------------------------------------------------------------------------------*/

#include "posercircuit.h"
#include "bigvia.h"
#include "lireplace.h"
#include "compress.h"
#include "barre.h"
#include "stat.h"
#include "sesame.h"
#include "mgn.h"

extern long	bigvias, ringvias;

/*-----------------------------------------------------------------------------------*/
/* placement des  blocs barre de plots + coeur , avec les rotations necessaires.     */
/* pour face: nord -> sans rotation                                                  */
/*            sud  -> SYM_Y                                                          */
/*            est  -> SY_RP                                                          */
/*           ouest -> ROT_P                                                          */
/* warning: les coord pour genlib doivent etre / par SCALE_X                         */
/*-----------------------------------------------------------------------------------*/

void poser_blocs(phfig_list **circuit_ph, char *nomcircuit,
	BARRE_PLOTS tab_plots[NB_FACES], COEUR lecoeur)
{
	long	val;
	int	face;

	definir_fig_ph(nomcircuit);

	/* ----------------------------- */
	/* placement des barres de plots */
	/* ----------------------------- */

	for (face = 0; face < NB_FACES; face++) {
		if (mode_debug) 
			printf("face %d largeur %ld hauteur %ld x %ld y %ld piste %ld width coeur %ld height coeur %ld\n",
			     	        face, tab_plots[face].width, tab_plots[face].height, tab_plots[face].coord.xabs, tab_plots[face].coord.yabs,
			     tab_plots[face].coord.piste, lecoeur.width, lecoeur.height);

		if (0 != tab_plots[face].width) {
			switch (face) {
			case NORD:
				val = (tab_plots[face].coord.piste * pitch + lecoeur.coord.yabs + lecoeur.height) / SCALE_X;
				placer_instph(tab_plots[face].nomfig, tab_plots[face].nominst, NOSYM, (tab_plots[face].coord.xabs
				    / SCALE_X), val);
				break;

			case SUD:
				val = (tab_plots[face].coord.piste * -pitch - tab_plots[face].height + lecoeur.coord.yabs) /
				    SCALE_X;
				placer_instph(tab_plots[face].nomfig, tab_plots[face].nominst, SYM_Y, (tab_plots[face].coord.xabs
				    / SCALE_X), val);
				break;

			case EST:
				val = (tab_plots[face].coord.piste * pitch + lecoeur.coord.xabs + lecoeur.width) / SCALE_X;
				placer_instph(tab_plots[face].nomfig, tab_plots[face].nominst, SY_RP, val, (tab_plots[face].coord.yabs
				    / SCALE_X));
				break;

			case OUEST:
				val = (tab_plots[face].coord.piste * -pitch - tab_plots[face].height + lecoeur.coord.xabs) /
				    SCALE_X;
				placer_instph(tab_plots[face].nomfig, tab_plots[face].nominst, ROT_P, val, (tab_plots[face].coord.yabs
				    / SCALE_X));
				break;
			}
		}
	}

	/* ---------------------------------- */
	/* placement du coeur (sans rotation) */
	/* ---------------------------------- */

	placer_instph((lecoeur.coeur_ph)->NAME, (lecoeur.coeur_lo)->INSNAME, NOSYM, (lecoeur.coord.xabs / SCALE_X),  (lecoeur.coord.yabs / SCALE_X));

	/* ---------------------------- */
	/* Initialisation de circuit_ph */
	/* ---------------------------- */

	(*circuit_ph) = getphfig(nomcircuit, 'A');

	/* sauver_fig_ph();  */
}

/*----------------------------------------------------------------------------------*/
/* Cette procedure pour chaque equipotentielle lance la pose des segments mbk       */
/* et des vias associes.                                                            */
/*----------------------------------------------------------------------------------*/

void poser_segments(LST_EQUIPO lst_equipo, COEUR lecoeur,
	lofig_list *circuit_lo, phfig_list *circuit_ph)
{
	long	ringviasanc = 0, bigviasanc = 0;

	while (NULL != lst_equipo) {
		if (mode_debug) 
			printf("Pose des segments MBK des equipotentielles %ld \n", lst_equipo->index);
		poser_segments_eq(lst_equipo, lecoeur, circuit_lo);

		ringviasanc = ringvias; 
		bigviasanc = bigvias;
		poser_vias_eq(lst_equipo, lecoeur, circuit_ph);
		if (mode_stat)
			maj_stat_vias(lst_equipo, ringviasanc, bigviasanc, ringvias, bigvias);
		lst_equipo = lst_equipo->suiv;
	}

	if (mode_debug) 
		printf("***** VIAS TOTAL %ld VIAS COURONNE %ld ****\n\n", bigvias, ringvias);

	/* sauver_fig_ph();  */
}

/*---------------------------------------------------------------------------------*/
/* pose de tous les vrais segments de l'equipo courante                            */
/*---------------------------------------------------------------------------------*/

void poser_segments_eq(LST_EQUIPO equipo, COEUR lecoeur, lofig_list *circuit_lo)
{
	long	x1 = 0, y1 = 0, x2 = 0, y2 = 0;
	LST_SEGMENT precseg;
	chain_list * lst_seg = equipo->lst_seg;
	char	*nameseg;

	nameseg = getsigname(getlosig(circuit_lo, equipo->index));

	/* --------------------------------- */
	/* Parcours des segments de l`equipo */
	/* --------------------------------- */

	while (NULL != lst_seg) {
		/* ----------------------------------------------------------- */
		/* calcul des coordonnees du seg sachant que (x1,y1) < (x2,y2) */
		/* ----------------------------------------------------------- */

		precseg = (LST_SEGMENT) lst_seg->DATA;

		/*if (mode_debug) printf("pointeur ptprecseg %ld face %ld\n",(long) precseg,(long)precseg->face); */

		if (VRAI_SEG == precseg->vraifaux) {
			switch (precseg->face) {
			case NORD:
				x1 = precseg->c1->xabs / SCALE_X; 
				x2 = precseg->c2->xabs / SCALE_X;
				y1 = (precseg->piste1 * pitch + lecoeur.coord.yabs + lecoeur.height) / SCALE_X;
				y2 = (precseg->piste2 * pitch + lecoeur.coord.yabs + lecoeur.height) / SCALE_X;
				break;

			case SUD:
				x1 = precseg->c1->xabs / SCALE_X; 
				x2 = precseg->c2->xabs / SCALE_X;
				y1 = (precseg->piste1 * -pitch + lecoeur.coord.yabs ) / SCALE_X;
				y2 = (precseg->piste2 * -pitch + lecoeur.coord.yabs ) / SCALE_X;
				break;

			case EST:
				y1 = precseg->c1->yabs / SCALE_X; 
				y2 = precseg->c2->yabs / SCALE_X;
				x1 = (precseg->piste1 * pitch + lecoeur.coord.xabs + lecoeur.width) / SCALE_X;
				x2 = (precseg->piste2 * pitch + lecoeur.coord.xabs + lecoeur.width) / SCALE_X;
				break;

			case OUEST:
				y1 = precseg->c1->yabs / SCALE_X; 
				y2 = precseg->c2->yabs / SCALE_X;
				x1 = (precseg->piste1 * -pitch + lecoeur.coord.xabs ) / SCALE_X;
				x2 = (precseg->piste2 * -pitch + lecoeur.coord.xabs ) / SCALE_X;
				break;
			}

			placer_segph(precseg->layer, (precseg->largeur / SCALE_X), nameseg, x1, y1, x2, y2);

			/* ----------------------------------------- */
			/* mode stat on remplit la stucture adequate */
			/* ----------------------------------------- */

			if (mode_stat) 
				remplit_stat(precseg, equipo);

		} /* fin du if vrai seg */

		lst_seg = lst_seg->NEXT;
	}

}

/*----------------------------------------------------------------------------------------------------*/
/* Cette procedure pose les vias pour les segments d'une equipo                                       */
/* Elle recherche les intersections de segments de layer different pour poser le vias de 2 manieres:  */
/* -- recherche par direction perpendiculaire au seg courant dans la meme face                        */
/* -- recherche de coordonnees identiques (coins de couronnes qui n'ont pas de proprietaire)          */
/* Modif: si on traite les eq alim, on parcours les segments avec l'attribut sans_via                 */
/*        car si le con coeur a un deport layer, il ne faut pas oublier de poser un via.              */
/* (ce trt special vient du fait que l'attribut via ne determine pas lequel des 2 points              */
/* du segment subit cet attribut)                                                                     */
/*----------------------------------------------------------------------------------------------------*/

void poser_vias_eq(LST_EQUIPO equipo, COEUR lecoeur, phfig_list *circuit_ph)
{
	long	x1 = 0, y1 = 0, x2 = 0, y2 = 0, minvia = 0;
	long	x1seg2 = 0, y1seg2 = 0, x2seg2 = 0, y2seg2 = 0;
	LST_SEGMENT seg, seg2;
	chain_list * liste, *lst_seg = equipo->lst_seg;
	int	viapose;
	LST_PSEUDO_CON con = (LST_PSEUDO_CON) (equipo->lst_con)->DATA;

	if ((con->nom_con == eq_vdd) || (con->nom_con == eq_vss))

		/* --------------------------------------------------------------------------------------- */
		/* parcours des segments sans via pour traiter les cas de changement de layer des concoeur */
		/* --------------------------------------------------------------------------------------- */

		poser_vias_visavisalim(equipo, lecoeur, circuit_ph);

	while (NULL != lst_seg) {
		seg = (LST_SEGMENT) lst_seg->DATA;

		/* -------------------------- */
		/* parcours des faux segments */
		/* -------------------------- */

		while ((NULL != lst_seg->NEXT) && (FAUX_SEG == seg->vraifaux)) {
			lst_seg = lst_seg->NEXT;
			seg = (LST_SEGMENT) lst_seg->DATA;
		}

		if (mode_debug) 
			printf("seg pt %ld layer %ld ptc1 %ld ptc2 %ld piste1 %ld piste2 %ld\n", (long) seg, (long)seg->layer,
			    (long)seg->c1, (long)seg->c2, seg->piste1, seg->piste2);

		if (FAUX_SEG == seg->vraifaux) 
			break;

		/* ----------------------------------------------------------- */
		/* calcul des coordonnees du seg sachant que (x1,y1) < (x2,y2) */
		/* ----------------------------------------------------------- */

		switch (seg->face) {
		case NORD:
			x1 = seg->c1->xabs; 
			x2 = seg->c2->xabs;
			y1 = (seg->piste1 * pitch + lecoeur.coord.yabs + lecoeur.height) ;
			y2 = (seg->piste2 * pitch + lecoeur.coord.yabs + lecoeur.height);
			break;

		case SUD:
			x1 = seg->c1->xabs; 
			x2 = seg->c2->xabs;
			y1 = (seg->piste1 * -pitch + lecoeur.coord.yabs );
			y2 = (seg->piste2 * -pitch + lecoeur.coord.yabs ) ;
			break;

		case EST:
			y1 = seg->c1->yabs; 
			y2 = seg->c2->yabs;
			x1 = (seg->piste1 * pitch + lecoeur.coord.xabs + lecoeur.width);
			x2 = (seg->piste2 * pitch + lecoeur.coord.xabs + lecoeur.width);
			break;

		case OUEST:
			y1 = seg->c1->yabs; 
			y2 = seg->c2->yabs;
			x1 = (seg->piste1 * -pitch + lecoeur.coord.xabs );
			x2 = (seg->piste2 * -pitch + lecoeur.coord.xabs );
			break;
		}

		if (mode_debug) 
			printf("seg pt %ld layer %ld x1 %ld y1 %ld x2 %ld y2 %ld\n", (long) seg, (long)seg->layer, x1, y1, x2,
			     y2);
		liste = lst_seg;

		/* ----------------------------------------------------------- */
		/* parcours des autres segments par rapport au segment courant */
		/* ----------------------------------------------------------- */

		while ((NULL != liste) && (AVEC_VIA == seg->via)) {
			seg2 =  (LST_SEGMENT) liste->DATA;
			viapose = 0;

			if ((VRAI_SEG == seg2->vraifaux) && (AVEC_VIA == seg2->via)) {

				/* --------------------------------------------------------------------------- */
				/* calcul des coordonnees du seg sachant que (x1seg2,y1seg2) < (x2seg2,y2seg2) */
				/* --------------------------------------------------------------------------- */

				switch (seg2->face) {
				case NORD:
					x1seg2 = seg2->c1->xabs; 
					x2seg2 = seg2->c2->xabs;
					y1seg2 = (seg2->piste1 * pitch + lecoeur.coord.yabs + lecoeur.height);
					y2seg2 = (seg2->piste2 * pitch + lecoeur.coord.yabs + lecoeur.height);
					break;

				case SUD:
					x1seg2 = seg2->c1->xabs; 
					x2seg2 = seg2->c2->xabs;
					y1seg2 = (seg2->piste1 * -pitch + lecoeur.coord.yabs );
					y2seg2 = (seg2->piste2 * -pitch + lecoeur.coord.yabs );
					break;

				case EST:
					y1seg2 = seg2->c1->yabs; 
					y2seg2 = seg2->c2->yabs;
					x1seg2 = (seg2->piste1 * pitch + lecoeur.coord.xabs + lecoeur.width);
					x2seg2 = (seg2->piste2 * pitch + lecoeur.coord.xabs + lecoeur.width);
					break;

				case OUEST:
					y1seg2 = seg2->c1->yabs; 
					y2seg2 = seg2->c2->yabs;
					x1seg2 = (seg2->piste1 * -pitch + lecoeur.coord.xabs );
					x2seg2 = (seg2->piste2 * -pitch + lecoeur.coord.xabs );
					break;
				}

				if (mode_debug) 
					printf("*seg2 pt %ld layer %ld x1 %ld y1 %ld x2 %ld y2 %ld\n", (long) seg2, (long)seg2->layer,
					     x1seg2, y1seg2, x2seg2, y2seg2);

				/* ------------------------------*/
				/* si les 2 seg sont de layer <> */
				/* ------------------------------*/

				if ((seg2 != seg) && (seg2->layer != seg->layer)) {

					/* ---------------------------------------------------------------------------------- */
					/* Si le segment seg a une extremite qui est un coin de couronne (proprio == NULL)    */
					/* on regarde si on trouve pas son segment voisin seg2, et alors catapultage d`un via */
					/* Ancienne version  au niveau genlib x* y* a diviser par SCALE_X                     */
   					/* pose d'un via unique, pour debogage rapide                                         */
					/* ---------------------------------------------------------------------------------- */

					/* On regarde si seg2 touche seg */
					if ((x1 == x2) && ((x1seg2 == x1) || (x2seg2 == x1))) {
						if ((y1seg2 >= y1) && (y1seg2 <= y2)) {
							viapose = 1;
							bigvia_ring(seg->layer,seg2->layer,circuit_ph, x1, y1seg2, seg->largeur, seg2->largeur);
						} else if ((y2seg2 >= y1) && (y2seg2 <= y2)) {
							viapose = 1;
							bigvia_ring(seg->layer,seg2->layer,circuit_ph, x1, y2seg2, seg->largeur, seg2->largeur);
						}
					} else if ((y1 == y2) && ((y1seg2 == y1) || (y2seg2 == y1))) {
						if ((x1seg2 >= x1) && (x1seg2 <= x2)) {
							viapose = 1;
							bigvia_ring(seg->layer,seg2->layer,circuit_ph, x1seg2, y1, seg2->largeur, seg->largeur);
						} else if ((x2seg2 >= x1) && (x2seg2 <= x2)) {
							viapose = 1;
							bigvia_ring(seg->layer,seg2->layer,circuit_ph, x2seg2, y1, seg2->largeur, seg->largeur);
						}
					}
	
					if (!viapose) {
						if ((x1seg2 == x2seg2) && ((x1seg2 == x1) || (x1seg2 == x2))) {
							if ((y1 >= y1seg2) && (y1 <= y2seg2)) {
								viapose = 1;
								bigvia_ring(seg->layer,seg2->layer,circuit_ph, x1seg2, y1, seg2->largeur, seg->largeur);
							} else if ((y2 >= y1seg2) && (y2 <= y2seg2)) {
								viapose = 1;
								bigvia_ring(seg->layer,seg2->layer,circuit_ph, x1seg2, y2, seg2->largeur, seg->largeur);
							}
						} else if ((y1seg2 == y2seg2) && ((y1seg2 == y1) || (y1seg2 == y2))) {
							if ((x1 >= x1seg2) && (x1 <= x2seg2)) {
								viapose = 1;
								bigvia_ring(seg->layer,seg2->layer,circuit_ph, x1, y1seg2, seg->largeur, seg2->largeur);
							} else if ((x2 >= x1seg2) && (x2 <= x2seg2)) {
								viapose = 1;
								bigvia_ring(seg->layer,seg2->layer,circuit_ph, x2, y1seg2, seg->largeur, seg2->largeur);
							}
						}
					} /* fin du if !viapose */
	
					if (!viapose) {
						if (seg->largeur < seg2->largeur) 
							minvia = seg->largeur;
						else 
							minvia = seg2->largeur;
	
						if ((x1 == x1seg2) && (y1 == y1seg2)) {
							bigvia_ring(seg->layer,seg2->layer,circuit_ph, x1, y1, minvia, minvia);
						}
	
						if ((x1 == x2seg2) && (y1 == y2seg2)) {
							bigvia_ring(seg->layer,seg2->layer,circuit_ph, x1, y1, minvia, minvia);
						}
	
						if ((x2 == x1seg2) && (y2 == y1seg2)) {
							bigvia_ring(seg->layer,seg2->layer,circuit_ph, x2, y2, minvia, minvia);
						}
	
						if ((x2 == x2seg2) && (y2 == y2seg2)) {
							bigvia_ring(seg->layer,seg2->layer,circuit_ph, x2, y2, minvia, minvia);
						}
	
					}
	
				}

			} /* fin du if vrai seg */

			liste = liste->NEXT;
		}

		/* MARQUAGE DU SEGMENT TRAITE */
		seg->via = SANS_VIA;

		lst_seg = lst_seg->NEXT;
	} /* fin du while */
}

/*---------------------------------------------------------------------------------*/

void remonte_con_circuit(chain_list *nom_plot[NB_FACES],
	chain_list *liste_plotsph, BARRE_PLOTS tab_plots[NB_FACES],
	COEUR lecoeur, lofig_list *circuit_lo, phfig_list *circuit_ph,
	char	*nom_circuit_ph, chain_list  *lst_conestouest)
{

	int	face;

	/* ---------------------------------------------------------------------------- */
	/* rq: obligation de definir l'abutmentbox avant la mise a plat, car bug genlib */
	/* pour definir l'ab apres la mise a plat des barres de plots                   */
	/* definition de l'abument box du circuit                                       */
	/* ---------------------------------------------------------------------------- */

	definir_ab_fig();

	/* ------------------------------- */
	/* mise a plat des barres de plots */
	/* ------------------------------- */

	for (face = 0; face < NB_FACES; face++)
		if (0 != tab_plots[face].width) 
			miseaplat_instph(tab_plots[face].nominst, NO);

	tirer_coins(circuit_ph, tab_plots, lst_conestouest);

	/* -------------------------------------------------- */
	/* Si on veut mettre des wire a la place des plots... */
	/* miseaplat_plotsvide(nom_circuit_ph);               */
	/* -------------------------------------------------- */


	/* -------------------------------- */
	/* construction des equipo externes */
	/* -------------------------------- */

	traite_equipo_ext(nom_plot, liste_plotsph, tab_plots, lecoeur, circuit_lo, circuit_ph);

	sauver_fig_ph();
}

/*------------------------------------------------------------------------------------*/
/* cette procedure fabrique les eq externe con circuit avec con plots,                */
/* mais verifie ces eq de telle sorte les connecteurs de plots de ces eq              */
/* appartiennent aux faces nord des modeles physique du plot, sinon ringerreur dans   */
/* le fichier C compile par genlib                                                    */
/*------------------------------------------------------------------------------------*/

void traite_equipo_ext(chain_list *nom_plot[NB_FACES], chain_list *liste_plotsph,
	BARRE_PLOTS tab_plots[NB_FACES], COEUR lecoeur,
	lofig_list *circuit_lo, phfig_list *circuit_ph)
{

	locon_list * con_circuit = circuit_lo->LOCON ;
	locon_list * con_plot;
	losig_list * sig_circuit;
	loins_list * plot;
	int	trouve, face;
	chain_list * liste_plots, *lsterr = NULL;

	if (mode_debug) 
		printf("Traitement des equipo externes\n");

	/* --------------------------- */
	/* boucle des locon du circuit */
	/* --------------------------- */

	while (con_circuit != NULL) {
		sig_circuit = con_circuit->SIG;  /* un signal unique par connecteur */
		if (mode_debug) 
			printf("pointeur Sigcircuit %ld\n", (long) sig_circuit);
		if (mode_debug) 
			printf("*******NOM concircuit %s signal %ld*********\n", con_circuit->NAME, sig_circuit->INDEX);

		trouve = 0;

		/* ---------------------------- */
		/* Parcours des instances plots */
		/* ---------------------------- */

		for (face = 0; (face < NB_FACES); face++) {/*  for (face=0;((face< NB_FACES) && (!trouve));face++)  */

			liste_plots = nom_plot[face];

			while (liste_plots != NULL) {

				plot = (loins_list * ) liste_plots->DATA;

				/* -------------------------------------------------------------------------- */
				/* S'il s'agit d'un plot on regarde les signaux des connecteurs du plot pour  */
				/* trouver meme signal que con_circuit                                        */
				/* -------------------------------------------------------------------------- */

				if (mode_debug) 
					printf("PLOT  %s de la face %d\n", plot->INSNAME, face);

				if ((con_plot = existe_sig_plot(sig_circuit, plot, liste_plotsph)) != NULL) {
					if (existe_leconnecteur_faceplot(plot->FIGNAME, con_plot->NAME, NORD, liste_plotsph)) {
						trouve = 1;
						remonte_con(con_circuit, con_plot, liste_plotsph, circuit_ph);

						/* ----------------------------------------------------------------------------------------------- */
						/* Pour les vdd* et vss* possibilite de plusieurs connecteurs physiques de meme nom sur le circuit */
						/* donc pas de break;                                                                              */
						/* ----------------------------------------------------------------------------------------------- */
					} else if (existe_leconnecteur_faceplot(plot->FIGNAME, con_plot->NAME, SUD, liste_plotsph)){
						lsterr = addchain(lsterr, (void * )con_plot->NAME);
						lsterr = addchain(lsterr, (void * )plot->INSNAME);
						lsterr = addchain(lsterr, (void * )con_circuit->NAME);
						trouve = 1;
						break;
					}
				}

				liste_plots = liste_plots->NEXT;
			} /* fin parcours instances plots d'une face */

		} /* fin  de parcours de toutes les faces */

		if (!trouve) 
			ringerreur(ERR_CONEXT_ENLAIR, con_circuit->NAME, NULL);

		con_circuit = con_circuit->NEXT;

	} /* fin de parcours des con du circuit  */

	if (NULL != lsterr) 
		ringerreur(ERR_EQEXTERNE, (void * )lsterr, NULL);

}

/*-----------------------------------------------------------------------------------*/

void remonte_con(locon_list *con_circuit, locon_list *con_plot,
	chain_list *liste_plotsph, phfig_list *circuit_ph)
{
	phcon_list * conph;

	conph = cherche_conph_circuit(con_plot, liste_plotsph, circuit_ph);

	if (NULL != conph)
		remonter_uncon_instph(conph->INDEX, conph->NAME, ((loins_list * )con_plot->ROOT)->INSNAME, con_circuit->NAME);

}

/*-----------------------------------------------------------------------------*/
/* Cette procedure termine la couronne de plots en tirant les fils necessaires */
/* pour fabriquer les coins de fils. utilisation de lst_conestouest.           */
/* on tire en coin que si 2 barres de plots sont mitoyennes                    */
/*-----------------------------------------------------------------------------*/

void tirer_coins(phfig_list  *circuit_ph, BARRE_PLOTS tab_plots[NB_FACES],
	chain_list  *lst_conestouest)
{
	phfig_list * barre[NB_FACES], *fig, *fig2;
	phins_list * firstinst, *lastinst, *firstinst2, *lastinst2;
	phcon_list * con, *con1, *con2;
	chain_list * lst;
	int	face;
	long	xcon1, xcon2, ycon1, ycon2;

	for (face = 0; face < NB_FACES; face++)
		if (0 != tab_plots[face].width)
			barre[face] = getphfig(tab_plots[face].nomfig, 'A');

	if (0 != tab_plots[SUD].width) {
		if (0 != tab_plots[OUEST].width) {

			/* ------------------------------------------------------------- */
			/* recuperation des 1eres et der instances de plots des 2 barres */
			/* ------------------------------------------------------------- */

			if (mode_debug) 
				printf("coin sud-ouest\n");
			firstlastinst_barre(barre[SUD], &firstinst, &lastinst);
			firstlastinst_barre(barre[OUEST], &firstinst2, &lastinst2);

			fig = getphfig(firstinst->FIGNAME, 'A');
			fig2 = getphfig(firstinst2->FIGNAME, 'A');

			firstinst = getphins(circuit_ph, firstinst->INSNAME);
			firstinst2 = getphins(circuit_ph, firstinst2->INSNAME);
			lst = lst_conestouest;

			/* ------------------------------------------------------------ */
			/* Calcul des coordonnees des coins et pose des fils avec wire2 */
			/* ------------------------------------------------------------ */

			while (NULL != lst) {
				con = (phcon_list * ) lst->DATA;
				con1 = getphcon(fig, con->NAME, con->INDEX);
				con2 = getphcon(fig2, con->NAME, con->INDEX);

				xyflat(&xcon1, &ycon1, con1->XCON, con1->YCON, firstinst->XINS, firstinst->YINS, fig->XAB1,
				     			fig->YAB1, fig->XAB2, fig->YAB2, firstinst->TRANSF);

				xyflat(&xcon2, &ycon2, con2->XCON, con2->YCON, firstinst2->XINS, firstinst2->YINS, fig2->XAB1,
				     			fig2->YAB1, fig2->XAB2, fig2->YAB2, firstinst2->TRANSF);

				poser_wire2(con->LAYER, con->WIDTH / SCALE_X, firstinst->INSNAME, con->NAME, con->INDEX, firstinst2->INSNAME,
				     con->NAME, con->INDEX, xcon2 / SCALE_X, ycon1 / SCALE_X);

				/* ---------------------------------------- */
				/* coin alu2 ajoute wx = wy obligatoirement */
				/* ---------------------------------------- */

				ajout_coin(xcon2 / SCALE_X, ycon1 / SCALE_X, con->WIDTH / SCALE_X, con->WIDTH / SCALE_X, con->LAYER);

				lst = lst->NEXT->NEXT;
			}

		}

		if (0 != tab_plots[EST].width) {

			/* ------------------------------------------------------------- */
			/* recuperation des 1eres et der instances de plots des 2 barres */
			/* ------------------------------------------------------------- */

			if (mode_debug) 
				printf("coin sud-est\n");

			firstlastinst_barre(barre[SUD], &firstinst, &lastinst);
			firstlastinst_barre(barre[EST], &firstinst2, &lastinst2);

			fig = getphfig(lastinst->FIGNAME, 'A');
			fig2 = getphfig(firstinst2->FIGNAME, 'A');

			lastinst = getphins(circuit_ph, lastinst->INSNAME);
			firstinst2 = getphins(circuit_ph, firstinst2->INSNAME);
			lst = lst_conestouest;

			/* ------------------------------------------------------------- */
			/* Calcul des coordonnees des coins et pose des fils avec wire2  */
			/* ------------------------------------------------------------- */

			while (NULL != lst) {
				con1 = (phcon_list * ) lst->NEXT->DATA;
				con2 = (phcon_list * ) lst->DATA;
				con1 = getphcon(fig, con1->NAME, con1->INDEX);
				con2 = getphcon(fig2, con2->NAME, con2->INDEX);

				xyflat(&xcon1, &ycon1, con1->XCON, con1->YCON, lastinst->XINS, lastinst->YINS, fig->XAB1,
				     			fig->YAB1, fig->XAB2, fig->YAB2, lastinst->TRANSF);

				xyflat(&xcon2, &ycon2, con2->XCON, con2->YCON, firstinst2->XINS, firstinst2->YINS, fig2->XAB1,
				     			fig2->YAB1, fig2->XAB2, fig2->YAB2, firstinst2->TRANSF);

				poser_wire2(con1->LAYER, con1->WIDTH / SCALE_X, lastinst->INSNAME, con1->NAME, con1->INDEX, 
				     firstinst2->INSNAME, con2->NAME, con2->INDEX, xcon2 / SCALE_X, ycon1 / SCALE_X);

				/* ---------------------------------------- */
				/* coin alu2 ajoute wx = wy obligatoirement */
				/* ---------------------------------------- */

				ajout_coin(xcon2 / SCALE_X, ycon1 / SCALE_X, con1->WIDTH / SCALE_X, con1->WIDTH / SCALE_X, con1->LAYER);

				lst = lst->NEXT->NEXT;
			}
		}
	}

	if (0 != tab_plots[NORD].width) {
		if (0 != tab_plots[OUEST].width) {

			/* ------------------------------------------------------------- */
			/* recuperation des 1eres et der instances de plots des 2 barres */
			/* ------------------------------------------------------------- */

			if (mode_debug) 
				printf("coin nord-ouest\n");

			firstlastinst_barre(barre[NORD], &firstinst, &lastinst);
			firstlastinst_barre(barre[OUEST], &firstinst2, &lastinst2);

			fig = getphfig(firstinst->FIGNAME, 'A');
			fig2 = getphfig(lastinst2->FIGNAME, 'A');

			firstinst = getphins(circuit_ph, firstinst->INSNAME);
			lastinst2 = getphins(circuit_ph, lastinst2->INSNAME);
			lst = lst_conestouest;

			/* ------------------------------------------------------------- */
			/* Calcul des coordonnees des coins et pose des fils avec wire2  */
			/* ------------------------------------------------------------- */

			while (NULL != lst) {
				con1 = (phcon_list * ) lst->DATA;
				con2 = (phcon_list * ) lst->NEXT->DATA;
				con1 = getphcon(fig, con1->NAME, con1->INDEX);
				con2 = getphcon(fig2, con2->NAME, con2->INDEX);

				xyflat(&xcon1, &ycon1, con1->XCON, con1->YCON, firstinst->XINS, firstinst->YINS, fig->XAB1,
				     			fig->YAB1, fig->XAB2, fig->YAB2, firstinst->TRANSF);

				xyflat(&xcon2, &ycon2, con2->XCON, con2->YCON, lastinst2->XINS, lastinst2->YINS, fig2->XAB1,
				     			fig2->YAB1, fig2->XAB2, fig2->YAB2, lastinst2->TRANSF);

				poser_wire2(con1->LAYER, con1->WIDTH / SCALE_X, firstinst->INSNAME, con1->NAME, con1->INDEX, lastinst2->INSNAME,
				     con2->NAME, con2->INDEX, xcon2 / SCALE_X, ycon1 / SCALE_X);

				/* ---------------------------------------- */
				/* coin alu2 ajoute wx = wy obligatoirement */
				/* ---------------------------------------- */

				ajout_coin(xcon2 / SCALE_X, ycon1 / SCALE_X, con1->WIDTH / SCALE_X, con1->WIDTH / SCALE_X, con1->LAYER);

				lst = lst->NEXT->NEXT;
			}
		}

		if (0 != tab_plots[EST].width) {

			/* ------------------------------------------------------------- */
			/* recuperation des 1eres et der instances de plots des 2 barres */
			/* ------------------------------------------------------------- */

			if (mode_debug) 
				printf("coin nord-est\n");

			firstlastinst_barre(barre[NORD], &firstinst, &lastinst);
			firstlastinst_barre(barre[EST], &firstinst2, &lastinst2);

			fig = getphfig(lastinst->FIGNAME, 'A');
			fig2 = getphfig(lastinst2->FIGNAME, 'A');

			lastinst = getphins(circuit_ph, lastinst->INSNAME);
			lastinst2 = getphins(circuit_ph, lastinst2->INSNAME);
			lst = lst_conestouest;

			/* ------------------------------------------------------------- */
			/* Calcul des coordonnees des coins et pose des fils avec wire2  */
			/* ------------------------------------------------------------- */

			while (NULL != lst) {
				con = (phcon_list * ) lst->NEXT->DATA;
				con1 = getphcon(fig, con->NAME, con->INDEX);
				con2 = getphcon(fig2, con->NAME, con->INDEX);

				xyflat(&xcon1, &ycon1, con1->XCON, con1->YCON, lastinst->XINS, lastinst->YINS, fig->XAB1,
				     			fig->YAB1, fig->XAB2, fig->YAB2, lastinst->TRANSF);

				xyflat(&xcon2, &ycon2, con2->XCON, con2->YCON, lastinst2->XINS, lastinst2->YINS, fig2->XAB1,
				     			fig2->YAB1, fig2->XAB2, fig2->YAB2, lastinst2->TRANSF);

				poser_wire2(con->LAYER, con->WIDTH / SCALE_X, lastinst->INSNAME, con->NAME, con->INDEX, lastinst2->INSNAME,
				     con->NAME, con->INDEX, xcon2 / SCALE_X, ycon1 / SCALE_X);

				/* ---------------------------------------- */
				/* coin alu2 ajoute wx = wy obligatoirement */
				/* ---------------------------------------- */

				ajout_coin(xcon2 / SCALE_X, ycon1 / SCALE_X, con->WIDTH / SCALE_X, con->WIDTH / SCALE_X, con->LAYER);

				lst = lst->NEXT->NEXT;
			}
		}
	}

}

/*-------------------------------------------------------------------------------*/
/* Ajout de coin en alu2 car la fonction wire2 ne le fait pas                    */
/*-------------------------------------------------------------------------------*/

void ajout_coin(long x, long y, long wx, long wy, char layer)
{
	long	x1, x2, y1, y2, w;

	if ((wx > 2 * EXTENSION_ALU2) && (wy > 2 * EXTENSION_ALU2)) {
		if (0 == (wx % 2)) { /* fil vertical */
			y1 = y - wx / 2 + EXTENSION_ALU2;
			y2 = y + wx / 2 - EXTENSION_ALU2;
			w  = wy;
			x1 = x2 = x;
		}  else {
			x1 = x - wy / 2 + EXTENSION_ALU2;
			x2 = x + wy / 2 - EXTENSION_ALU2;
			w  = wx;
			y1 = y2 = y;
		}
		placer_segph(layer, w, genNAME("coin_%ld_%ld_%ld_%ld",x1, y1, x2, y2), x1, y1, x2, y2);
	}
}

/*-----------------------------------------------------------------------*/
/* cette procedure parcours les segments avec l'attribut SANS_VIA et     */
/* regarde s'il ne manque pas de via vers le con du coeur, cas ou le     */
/* con coeur a un deport layer                                           */
/*-----------------------------------------------------------------------*/

void poser_vias_visavisalim(LST_EQUIPO equipo, COEUR lecoeur,
	phfig_list *circuit_ph)
{
	long	x1 = 0, y1 = 0, x2 = 0, y2 = 0, minvia = 0;
	long	x1seg2 = 0, y1seg2 = 0, x2seg2 = 0, y2seg2 = 0;
	LST_SEGMENT seg, seg2;
	chain_list * liste, *lst_seg = equipo->lst_seg;

	if (mode_debug) 
		printf("poser_vias_viavisalim index %ld\n", equipo->index);

	while (NULL != lst_seg) {
		seg = (LST_SEGMENT) lst_seg->DATA;

		/* -------------------------- */
		/* parcours des faux segments */
		/* -------------------------- */

		while ((NULL != lst_seg->NEXT) && (FAUX_SEG == seg->vraifaux)) {
			lst_seg = lst_seg->NEXT;
			seg = (LST_SEGMENT) lst_seg->DATA;
		}

		if (mode_debug) 
			printf("seg pt %ld layer %ld ptc1 %ld ptc2 %ld piste1 %ld piste2 %ld\n", (long) seg, (long)seg->layer,
			    (long)seg->c1, (long)seg->c2, seg->piste1, seg->piste2);

		if (FAUX_SEG == seg->vraifaux) 
			break;

		/* ----------------------------------------------------------- */
		/* calcul des coordonnees du seg sachant que (x1,y1) < (x2,y2) */
		/* ON GARDE DS X1,Y1 LA COORDONNEE LA + PROCHE DU COEUR        */
		/* ----------------------------------------------------------- */

		switch (seg->face) {
		case NORD:
			x1 = seg->c1->xabs; 
			x2 = seg->c2->xabs;
			y1 = (seg->piste1 * pitch + lecoeur.coord.yabs + lecoeur.height) ;
			y2 = (seg->piste2 * pitch + lecoeur.coord.yabs + lecoeur.height);
			if (y2 < y1) { 
				y1 = y2; 
				x1 = x2;
			}
			break;

		case SUD:
			x1 = seg->c1->xabs; 
			x2 = seg->c2->xabs;
			y1 = (seg->piste1 * -pitch + lecoeur.coord.yabs );
			y2 = (seg->piste2 * -pitch + lecoeur.coord.yabs ) ;
			if (y2 > y1) { 
				y1 = y2; 
				x1 = x2;
			}
			break;

		case EST:
			y1 = seg->c1->yabs; 
			y2 = seg->c2->yabs;
			x1 = (seg->piste1 * pitch + lecoeur.coord.xabs + lecoeur.width);
			x2 = (seg->piste2 * pitch + lecoeur.coord.xabs + lecoeur.width);
			if (x2 < x1) { 
				y1 = y2; 
				x1 = x2;
			}
			break;

		case OUEST:
			y1 = seg->c1->yabs; 
			y2 = seg->c2->yabs;
			x1 = (seg->piste1 * -pitch + lecoeur.coord.xabs );
			x2 = (seg->piste2 * -pitch + lecoeur.coord.xabs );
			if (x2 > x1) { 
				y1 = y2; 
				x1 = x2;
			}
			break;
		}

		if (mode_debug) 
			printf("seg pt %ld layer %ld x1 %ld y1 %ld x2 %ld y2 %ld\n", (long) seg, (long)seg->layer, x1, y1, x2,
			     y2);
		liste = lst_seg;

		/* ----------------------------------------------------------- */
		/* parcours des autres segments par rapport au segment courant */
		/* ----------------------------------------------------------- */

		while ((NULL != liste) && (SANS_VIA == seg->via)) {
			seg2 =  (LST_SEGMENT) liste->DATA;

			if ((VRAI_SEG == seg2->vraifaux) && (AVEC_VIA == seg2->via)) {

				/* --------------------------------------------------------------------------- */
				/* calcul des coordonnees du seg sachant que (x1seg2,y1seg2) < (x2seg2,y2seg2) */
				/* --------------------------------------------------------------------------- */

				switch (seg2->face) {
				case NORD:
					x1seg2 = seg2->c1->xabs; 
					x2seg2 = seg2->c2->xabs;
					y1seg2 = (seg2->piste1 * pitch + lecoeur.coord.yabs + lecoeur.height);
					y2seg2 = (seg2->piste2 * pitch + lecoeur.coord.yabs + lecoeur.height);
					break;

				case SUD:
					x1seg2 = seg2->c1->xabs; 
					x2seg2 = seg2->c2->xabs;
					y1seg2 = (seg2->piste1 * -pitch + lecoeur.coord.yabs );
					y2seg2 = (seg2->piste2 * -pitch + lecoeur.coord.yabs );
					break;

				case EST:
					y1seg2 = seg2->c1->yabs; 
					y2seg2 = seg2->c2->yabs;
					x1seg2 = (seg2->piste1 * pitch + lecoeur.coord.xabs + lecoeur.width);
					x2seg2 = (seg2->piste2 * pitch + lecoeur.coord.xabs + lecoeur.width);
					break;

				case OUEST:
					y1seg2 = seg2->c1->yabs; 
					y2seg2 = seg2->c2->yabs;
					x1seg2 = (seg2->piste1 * -pitch + lecoeur.coord.xabs );
					x2seg2 = (seg2->piste2 * -pitch + lecoeur.coord.xabs );
					break;
				}

				if (mode_debug) 
					printf("*seg2 pt %ld layer %ld x1 %ld y1 %ld x2 %ld y2 %ld\n", (long) seg2, (long)seg2->layer,
					     x1seg2, y1seg2, x2seg2, y2seg2);

				/* ----------------------------- */
				/* si les 2 seg sont de layer <> */
				/* ----------------------------- */

				if ((seg2 != seg) && (seg2->layer != seg->layer)) {

					/* ---------------------------------------------------------------------------------- */
					/* Si le segment seg a une extremite qui est un coin de couronne (proprio == NULL)    */
					/* on regarde si on trouve pas son segment voisin seg2, et alors catapultage d`un via */
					/* ---------------------------------------------------------------------------------- */

					if (seg->largeur < seg2->largeur) 
						minvia = seg->largeur;
					else 
						minvia = seg2->largeur;
	
					if ((x1 == x1seg2) && (y1 == y1seg2)) {
						bigvia_ring(seg->layer, seg2->layer, circuit_ph, x1, y1, minvia, minvia);
					}
	
					if ((x1 == x2seg2) && (y1 == y2seg2)) {
						bigvia_ring(seg->layer, seg2->layer, circuit_ph, x1, y1, minvia, minvia);
					}
				} /* fin du if seg2 */
	
			} /* fin du if vrai seg */
	
			liste = liste->NEXT;
		}
	
		lst_seg = lst_seg->NEXT;
	} /* fin du while */

}
