From 7f7488bbb2f767474613159af452f7d15c6caeb4 Mon Sep 17 00:00:00 2001 From: Christophe Alexandre Date: Wed, 13 Mar 2002 19:23:37 +0000 Subject: [PATCH] ring is back ... --- alliance/src/ring/Makefile.am | 3 + alliance/src/ring/configure.in | 52 + alliance/src/ring/doc/Makefile.am | 4 + alliance/src/ring/doc/ring.1 | 348 ++++ alliance/src/ring/src/Makefile.am | 41 + alliance/src/ring/src/barre.c | 271 ++++ alliance/src/ring/src/barre.h | 27 + alliance/src/ring/src/bigvia.c | 169 ++ alliance/src/ring/src/bigvia.h | 10 + alliance/src/ring/src/compress.c | 367 +++++ alliance/src/ring/src/compress.h | 18 + alliance/src/ring/src/deport.c | 1229 ++++++++++++++ alliance/src/ring/src/deport.h | 21 + alliance/src/ring/src/distance.c | 323 ++++ alliance/src/ring/src/distance.h | 15 + alliance/src/ring/src/lireplace.c | 401 +++++ alliance/src/ring/src/lireplace.h | 14 + alliance/src/ring/src/lirevues.c | 317 ++++ alliance/src/ring/src/lirevues.h | 11 + alliance/src/ring/src/param.c | 216 +++ alliance/src/ring/src/param.h | 7 + alliance/src/ring/src/placement.c | 2255 ++++++++++++++++++++++++++ alliance/src/ring/src/placement.h | 51 + alliance/src/ring/src/posercircuit.c | 1013 ++++++++++++ alliance/src/ring/src/posercircuit.h | 34 + alliance/src/ring/src/ring2.c | 298 ++++ alliance/src/ring/src/ringram.y | 48 + alliance/src/ring/src/rinscan.l | 34 + alliance/src/ring/src/routage.c | 805 +++++++++ alliance/src/ring/src/routage.h | 28 + alliance/src/ring/src/routalim.c | 688 ++++++++ alliance/src/ring/src/routalim.h | 22 + alliance/src/ring/src/sesame.c | 608 +++++++ alliance/src/ring/src/sesame.h | 13 + alliance/src/ring/src/stat.c | 135 ++ alliance/src/ring/src/stat.h | 10 + alliance/src/ring/src/struct.c | 1646 +++++++++++++++++++ alliance/src/ring/src/struct.h | 387 +++++ alliance/src/ring/src/struct2.c | 1195 ++++++++++++++ 39 files changed, 13134 insertions(+) create mode 100644 alliance/src/ring/Makefile.am create mode 100644 alliance/src/ring/configure.in create mode 100644 alliance/src/ring/doc/Makefile.am create mode 100644 alliance/src/ring/doc/ring.1 create mode 100644 alliance/src/ring/src/Makefile.am create mode 100644 alliance/src/ring/src/barre.c create mode 100644 alliance/src/ring/src/barre.h create mode 100644 alliance/src/ring/src/bigvia.c create mode 100644 alliance/src/ring/src/bigvia.h create mode 100644 alliance/src/ring/src/compress.c create mode 100644 alliance/src/ring/src/compress.h create mode 100644 alliance/src/ring/src/deport.c create mode 100644 alliance/src/ring/src/deport.h create mode 100644 alliance/src/ring/src/distance.c create mode 100644 alliance/src/ring/src/distance.h create mode 100644 alliance/src/ring/src/lireplace.c create mode 100644 alliance/src/ring/src/lireplace.h create mode 100644 alliance/src/ring/src/lirevues.c create mode 100644 alliance/src/ring/src/lirevues.h create mode 100644 alliance/src/ring/src/param.c create mode 100644 alliance/src/ring/src/param.h create mode 100644 alliance/src/ring/src/placement.c create mode 100644 alliance/src/ring/src/placement.h create mode 100644 alliance/src/ring/src/posercircuit.c create mode 100644 alliance/src/ring/src/posercircuit.h create mode 100644 alliance/src/ring/src/ring2.c create mode 100644 alliance/src/ring/src/ringram.y create mode 100644 alliance/src/ring/src/rinscan.l create mode 100644 alliance/src/ring/src/routage.c create mode 100644 alliance/src/ring/src/routage.h create mode 100644 alliance/src/ring/src/routalim.c create mode 100644 alliance/src/ring/src/routalim.h create mode 100644 alliance/src/ring/src/sesame.c create mode 100644 alliance/src/ring/src/sesame.h create mode 100644 alliance/src/ring/src/stat.c create mode 100644 alliance/src/ring/src/stat.h create mode 100644 alliance/src/ring/src/struct.c create mode 100644 alliance/src/ring/src/struct.h create mode 100644 alliance/src/ring/src/struct2.c diff --git a/alliance/src/ring/Makefile.am b/alliance/src/ring/Makefile.am new file mode 100644 index 00000000..ce9d1044 --- /dev/null +++ b/alliance/src/ring/Makefile.am @@ -0,0 +1,3 @@ +## Process this file with automake to produce Makefile.in + +SUBDIRS = doc src diff --git a/alliance/src/ring/configure.in b/alliance/src/ring/configure.in new file mode 100644 index 00000000..b69350fe --- /dev/null +++ b/alliance/src/ring/configure.in @@ -0,0 +1,52 @@ +dnl Process this file with autoconf to produce a configure script. +AC_INIT(src/ring2.c) + +RING_MAJOR_VERSION=3 +RING_MINOR_VERSION=0 +RING_VERSION=$RING_MAJOR_VERSION.$RING_MINOR_VERSION + +AC_SUBST(RING_MAJOR_VERSION) +AC_SUBST(RING_MINOR_VERSION) +AC_SUBST(RING_VERSION) + +# libtool versioning +LT_RELEASE=$RING_MAJOR_VERSION.$RING_MINOR_VERSION +AC_SUBST(LT_RELEASE) + +# For automake. +VERSION=$RING_VERSION +PACKAGE=ring + +dnl Initialize automake stuff +AM_INIT_AUTOMAKE($PACKAGE, $VERSION) + +dnl Specify a configuration file +dnl AM_CONFIG_HEADER(config.h) + +dnl Initialize libtool +AM_PROG_LIBTOOL + +dnl Checks for programs. +AC_PROG_CC +AM_PROG_LEX +AC_PROG_YACC +AC_PROG_MAKE_SET + +changequote(,)dnl +INCLUDES=-I${ALLIANCE_TOP}/include +LDFLAGS=-L${ALLIANCE_TOP}/lib +changequote([,])dnl + +AC_SUBST(INCLUDES) +AC_SUBST(LDFLAGS) + +dnl Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST + +dnl Checks for library functions. + +AC_OUTPUT([ +Makefile +doc/Makefile +src/Makefile +]) diff --git a/alliance/src/ring/doc/Makefile.am b/alliance/src/ring/doc/Makefile.am new file mode 100644 index 00000000..06732658 --- /dev/null +++ b/alliance/src/ring/doc/Makefile.am @@ -0,0 +1,4 @@ +## Process this file with automake to produce Makefile.in + +man_MANS = ring.1 +EXTRA_DIST = $(man_MANS) diff --git a/alliance/src/ring/doc/ring.1 b/alliance/src/ring/doc/ring.1 new file mode 100644 index 00000000..aafc66c2 --- /dev/null +++ b/alliance/src/ring/doc/ring.1 @@ -0,0 +1,348 @@ +.\" $Id: ring.1,v 1.1 2002/03/13 19:23:26 xtof Exp $ +.\" @(#)Labo.l 0.0 90/22/08 UPMC; +.TH RING 1 "October 1, 1997" "ASIM/LIP6" "ALLIANCE USER COMMANDS" +.SH NAME +RING \- PAD RING router +.SH SYNOPSIS +RING \fIsource\fP \fIresult\fP \fB[ stat ]\fP +.so man1/alc_origin.1 +.SH DESCRIPTION +.IR source +defines two input files: +.RS +\-\- the file describing the input netlist (MBK_IN_LO(1) format). +.br +.RS +example: source.al +.br +.LP +.RE +\-\- the parameter file: source.rin +.br +This file consists in 5 sections: 4 for the pad placement on circuit +sides, one to define the power sypply width (in lambda units). +.LP +.br +.TP 10 +example: +.RS +.IR east +() # none pad at east side. +.br +.IR north +( +.br +p_pck p_i0 p_i1 +.br +p_i3) +.br +.IR south +(p_vssb p_vddb p_i2) +.br +.IR width +(vss 50 vdd 80) +.br +.RE +.LP +Separators (spaces, tabulations and new line) are allowed between instance names. +.LP +.br +\-\- east(), north(), south(), west() define the relative pad order. +They use the pad instance names. +.LP +.br +For the north() and south() sections, the instance name declaration +are from the +.IR left +(first pad) to the +.IR right +(last pad). +.LP +.br +For the east() and west() sections, the instance name declaration +are from the +.IR bottom +(first pad) to the +.IR top +(last pad). +.LP +.br +Any section may be missing. It means so the revalive side has no pad, +however at least one side must has one pad. +.LP +.br +\-\- the width() section is optional and describes the +power (vdd), and ground (vss) track width. +.LP +.br +.RE +.IR \fIresult\fP +defines the output filename. +.LP +.br +.RS +This file contains the layout of the routed circuit (MBK_OUT_PH(1) format). +.br +.RS +example: result.ap +.LP +.RE +.br +RING uses a pad library whose path directory is defined with the +MBK_CATA_LIB(1) environment variable. +It also uses a catalog filename which is defined with the MBK_CATAL_NAME(1) +environment variable. +.br +The catalog must contain all the pad model names used in the +circuit. The core model-name must not be present in the catalog. +.br +.LP +Part of catalog file: +.RS +.br +a2_y C +.br +high_y C +.br +pck_sp C +.br +piot_sp C +.br +pvssick_sp C +.br +\.\.\.\. +.br +pvdde_sp C +.br +pvddi_sp C +.br +.LP +.RE +.br +.RE +.IR [stat] +(optional parameter) defines another output file: +.br +.LP +.RS +.br +\-\- the statistic file: result.stat +.br +.LP +It contains data about length (lambdas) and area (lambdas * lambdas) in ALU1 and ALU2, for each +equipotential. It describes how many vias were placed. +.br +.LP +.RS +example: *** STATISTIC FILE < result.stat > *** +.br +.LP +.RE +Equipotential list : +.br +.LP +.nf +.if t \{\ +.ft CR \} +index| name |lgth A1|lgth A2|area A1|area A2| nb vias +.br +_________________________________________________________ +.br + 60 | vss | 9034 | 4408 | 614288| 454024| 1128 +.br +_________________________________________________________ +.br + 59 | vdd | 7494 | 3968 | 574248| 408704| 1128 +.br +_________________________________________________________ +.br + 54 | b2_coeur | 2253 | 1899 | 2253| 3798| 4 +_________________________________________________________ +.br +Total length alu1 : 18781 (lambdas) +.br +Total length alu2 : 10275 (lambdas) +.br +Total area alu1 : 1190789 (lambdas * lambdas) +.br +Total area alu2 : 866526 (lambdas * lambdas) +.br +Total of vias : 2260 +.br +.ft R +.fi +.LP +.RE +.br +.LP +.SH ENVIRONMENT VARIABLES +.LP +.br +\fBMBK_IN_LO(1)\fP defines the input file format for the netlist. +.br +\fBMBK_IN_PH(1)\fP defines the input file format for the layout. +.br +\fBMBK_OUT_PH(1)\fP defines the output file format for the layout. +.br +\fBMBK_CATAL_NAME(1)\fP defines the catalog filename. +.br +\fBMBK_CATA_LIB(1)\fP defines the library pad cells directory. +.br +\fBMBK_WORK_LIB(1)\fP defines the work directory. +.br +.LP +.SH USAGE +.LP +.br +RING performs the physical routing between core of +circuit and pad ring. +RING is not a floor plan router and allows only one core. +.LP +.br +A core is designed, for example, with the standard +cells router SCR, which places the input and output connectors on +the abutment box. The physical core connectors must be +separated by more than one pitch in any metal (in ALU1 or ALU2). +.LP +.br +Netlist and layout views relative to the same figure must have +the same name. For example, the netlist core name and the routed core name. +.LP +.br +RING performs an automatic placement of the pad ring +and core. It is not necessary to place pads, but only +to describe their relative position on each side, in the parameter file +(source.rin). +.LP +.br +Distance between the first track and any instance (pad or core) is the pitch +so 5 lambdas. +.FF +.br +.SH EXAMPLE +.LP +.br +Let chip.al be the circuit netlist and core.ap the routed core. +80 lambdas for supply track width and the pad placement are described as follows. +.LP +.RE +.br +.br +.TP 10 +.IR chip.rin: +.LP +.RS +# This is a comment: 1 comment per line +.br +north(p_a1 p_a2 p_a3 p_a4) +.br +south( +.br +p_i1 #another comment: the rest of the line +.br +p_i2 +.br +p_i3 +.br +p_i4) +.br +east(p_b4 p_b3 p_b2 p_b1) +.br +west(p_f1 p_f2 p_f3 p_f4) +.br +width( +.br +vdd 80 +.br +vss 80 +.br +) +.br +.TP 10 +We want a ring of pads as follow: +.LP +.br +.RS +.nf +.if t \{\ +.ft CR \} ++-------------------------------------------------+ +.br +| |p_a1|p_a2|p_a3|p_a4| | +.br +|----+---------------------------------------+----| +.br +|p_f4| |p_b1| +.br +|----| +-------+ |----| +.br +|p_f3| | | |p_b2| +.br +|----| | CORE | |----| +.br +|p_f2| | | |p_b3| +.br +|----| +-------+ |----| +.br +|p_f1| |p_b4| +.br +|----+---------------------------------------+----| +.br +| |p_i1|p_i2|p_i3|p_i4| | +.br ++-------------------------------------------------+ +.ft R +.fi +.LP +.RE +.br +.br +In order to obtain the routed circuit (chipr.ap): +.LP +.br +> +.IR ring +.IR chip +.IR chipr +.LP +.br +.SH "SEE ALSO" +genlib(1) +lvx(1) +ocp(1) +ocr(1) +druc(1) + + +.SH DIAGNOSTICS +Physical core must have at least one physical connector by side, +otherwise it can't place pads correctly, and maybe dump a core file. +.LP +.br +Whenever lots of core connectors (bus) are placed close ones from each others, +RING may have problems to connect pad connectors placed just in front of them. +In such a case, it is recommended to not have pad connectors at that place and +thus to place an instance pad without connector (as pvdde_sp) +or to cut the bus into several parts to let space between connectors. +.LP +.br +When core connectors are to close from corners, RING sometimes connects those +one to supply rings, to solve this bug, move core connectors or change pad +placement. In any case, use \fBdruc(1)\fP or \fBlvx(1)\fP to detect problem. +.br +.LP +Supply vdd and vss pads (resp. pvddi_sp and pvssi_sp) +must be placed as close as possible of the core side middle +(i.e. not in the corners). +Otherwise, RING cannot link supply pad connector to ring supplies and +exits with a error message. +.br +.LP +Supply tracks from pads and core are connected at the supply ring. +There is sometimes few problems when core and pad tracks are opposite. +Move pads usually corrects problem. +.br +.LP + +.so man1/alc_bug_report.1 + diff --git a/alliance/src/ring/src/Makefile.am b/alliance/src/ring/src/Makefile.am new file mode 100644 index 00000000..bc964d28 --- /dev/null +++ b/alliance/src/ring/src/Makefile.am @@ -0,0 +1,41 @@ +## Process this file with automake to produce Makefile.in + +YACC = @YACC@ -d + +bin_PROGRAMS = ring + +ring_LDADD = @LIBS@ \ + -lMpu -lMlu \ + -lMcl -lMcp \ + -lMal -lMap \ + -lMsl \ + -lMel -lMgl \ + -lMhl \ + -lMvl \ + -lMgn \ + -lMmg \ + -lMlo \ + -lMph -lMut \ + -lRcn + +ring_SOURCES = bigvia.c bigvia.h \ + compress.c compress.h \ + deport.c deport.h \ + distance.c distance.h \ + ringram.y rinscan.l \ + lireplace.c \ + lireplace.h lirevues.c \ + lirevues.h \ + param.c \ + param.h placement.c \ + placement.h posercircuit.c \ + posercircuit.h ring2.c \ + routage.c routage.h \ + routalim.c routalim.h \ + sesame.c sesame.h \ + stat.c stat.h \ + struct2.c struct.c \ + struct.h \ + barre.c barre.h + +CLEANFILES = ringram.c ringram.h rinscan.c diff --git a/alliance/src/ring/src/barre.c b/alliance/src/ring/src/barre.c new file mode 100644 index 00000000..184b1afd --- /dev/null +++ b/alliance/src/ring/src/barre.c @@ -0,0 +1,271 @@ +/* + * 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 support : mailto:alliance-support@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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/****************************************************************************/ +/* */ +/* Chaine de CAO & VLSI Alliance */ +/* */ +/* Produit : ring router */ +/* Fichier : barre.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 26 mai 92 */ +/* Fichier BARRE.C */ +/* Fichier utilise pour construire les barres de plots avec genlib */ +/* Interdiction d'utiliser les super structures de mbk ou autres car genlib */ +/* generateur de macro. Type de donnees autorises long et char* exclusivement */ +/*-----------------------------------------------------------------------------------*/ + +#include +#include + +#include "barre.h" + +extern char mode_debug; + +/*-----------------------------------------------------------------------------------*/ +/* cette fonction ajoute un transforme un nom de signal vectorise mbk */ +/* avec des espaces en nom de signal GENLIB avec des crochets [ ] */ +/*-----------------------------------------------------------------------------------*/ + +static char *busname(name) +char *name; +{ +static char buffer[255]; +char *s, *t; +char one = 1; + + if (!name) + return NULL; + s = name; + t = buffer; + while (*s) { + if (*s == ' ') + { + if (one) { + *t++ = '['; + s++; + one = 0; + } else { + *t++ = ']'; + *t++ = '['; + s++; + } + } + if (*s == '_' && !one) { /* was SEPAR and not / */ + *t++ = ']'; + one = 1; + } + *t++ = *s++; + } + if (!one) + *t++ = ']'; + *t = '\0'; + return buffer; +} + +/*-----------------------------------------------------------------------------------*/ + +void definir_fig_ph(char *nomfig) +{ + if (mode_debug) + printf("defphfig %s\n", nomfig); + GENLIB_DEF_PHFIG(nomfig); + +} + +/*-----------------------------------------------------------------------------------*/ +/* Attention utiliser definir_reference_inst() avant d'utiliser cette fonction */ +/*-----------------------------------------------------------------------------------*/ + +void abouteright_plot_fig(char *nomfig, char *nominst) +{ + + if (mode_debug) + printf("abouteright_plot_fig %s inst %s\n", nomfig, nominst); + + GENLIB_PLACE_RIGHT(nomfig, nominst, NOSYM); + +} + +/*-----------------------------------------------------------------------------------*/ +/* Attention utiliser definir_reference_inst() avant d'utiliser cette fonction */ +/*-----------------------------------------------------------------------------------*/ + +void abouteleft_plot_fig(char *nomfig, char *nominst) +{ + + if (mode_debug) + printf("abouteleft_plot_fig %s inst %s\n", nomfig, nominst); + + GENLIB_PLACE_LEFT(nomfig, nominst, NOSYM); + +} + +/*-----------------------------------------------------------------------------------*/ + +void definir_reference_inst(char *name) +{ + + if (mode_debug) + printf("definir reference instance %s\n", name); + + GENLIB_DEF_PHINS(name); +} + +/*-----------------------------------------------------------------------------------*/ + +void definir_ab_fig() +{ + if (mode_debug) + printf("def ab 0000\n"); + + GENLIB_DEF_AB(0L, 0L, 0L, 0L); +} + +void definir_ab_fig2() +{ + if (mode_debug) + printf("def ab2\n"); + + GENLIB_DEF_AB(-100L, -100L, 100L, 100L); +} + +/*-----------------------------------------------------------------------------------*/ + +void sauver_fig_ph() +{ + if (mode_debug) + printf("sauve phfig\n"); + + GENLIB_SAVE_PHFIG(); +} + +/*-----------------------------------------------------------------------------------*/ + +void remonter_consud_instph(char *nominst) +{ + if (mode_debug) + printf("Remonte con sud de l'inst %s\n", nominst); + + GENLIB_COPY_UP_ALL_CON(SOUTH, nominst, YES); +} + +/*-----------------------------------------------------------------------------------*/ + +void remonter_connord_instph(char *nominst) +{ + if (mode_debug) + printf("Remonte con nord de l'inst %s\n", nominst); + + GENLIB_COPY_UP_ALL_CON(NORTH, nominst, YES); +} + +/*-----------------------------------------------------------------------------------*/ + +void placer_instph(char *nomfig, char *nominst, char symetrie, + long x, long y) +{ + + if (mode_debug) + printf("placer instance nomfig %s inst %s symetrie %c x %ld y %ld\n", nomfig, nominst, symetrie, x, y); + + GENLIB_PLACE(nomfig, nominst, symetrie, x, y); +} + +/*-----------------------------------------------------------------------------------*/ + +void placer_segph(char layer, long width, char *nameseg, + long x1, long y1, long x2, long y2) +{ + + if (mode_debug) + { + if (nameseg) + printf("placer segment layer %d width %ld name %s x1 %ld y1 %ld x2 %ld y2 %ld\n", (int)layer, width, nameseg, + x1, y1, x2, y2); + else + printf("placer segment layer %d width %ld x1 %ld y1 %ld x2 %ld y2 %ld\n", (int)layer, width, + x1, y1, x2, y2); + } + + GENLIB_PHSEG(layer, width, busname(nameseg), x1, y1, x2, y2); +} + +/*----------------------------------------------------------------------------------*/ +void miseaplat_instph(char *insname, char cheminom) +{ + + if (mode_debug) + printf("mise a plat de l'instance %s et cheminon %d\n", insname, (int)cheminom); + + GENLIB_FLATTEN_PHFIG(insname, cheminom); +} + +/*----------------------------------------------------------------------------------*/ + +void remonter_uncon_instph(long index, char *locname, char *insname, char *newname) +{ + + if (mode_debug) + printf("remontee du con %s index %ld de l'instance %s et newname %s\n", locname, index, insname, newname); + + locname = namealloc( busname(locname)); + newname = namealloc( busname(newname)); + GENLIB_COPY_UP_CON(index, locname, insname, newname); +} + +/*----------------------------------------------------------------------------*/ + +void poser_wire1(char layer, long width, char* ins1, char *con1, + long index1, char* ins2, char* con2,long index2) +{ + + if (mode_debug) + printf("wire1 layer %d width %ld ins1 %s con1 %s index1 %ld ins2 %s con2 %s index2 %ld\n", (int) layer, width, + ins1, con1, index1, ins2, con2, index2); + + GENLIB_WIRE1(layer, width, ins1, con1, index1, ins2, con2, index2); +} + +/*--------------------------------------------------------------------------------------*/ + +void poser_wire2(char layer, long width, char* ins1, char* con1, + long index1, char* ins2, char* con2, long index2, long x, long y) +{ + + if (mode_debug) + printf("wire2 layer %d width %ld ins1 %s con1 %s index1 %ld ins2 %s con2 %s index2 %ld x %ld y %ld\n", (int) layer, + width, ins1, con1, index1, ins2, con2, index2, x, y); + + GENLIB_WIRE2(layer, width, ins1, con1, index1, ins2, con2, index2, x, y); +} diff --git a/alliance/src/ring/src/barre.h b/alliance/src/ring/src/barre.h new file mode 100644 index 00000000..c246ada0 --- /dev/null +++ b/alliance/src/ring/src/barre.h @@ -0,0 +1,27 @@ +#ifndef __BARRE_H +#define __BARRE_H + +#include "struct.h" + +extern void definir_fig_ph(char *nomfig); +extern void abouteright_plot_fig(char *nomfig, char *nominst); +extern void abouteleft_plot_fig(char *nomfig, char *nominst); +extern void definir_reference_inst(char *name); +extern void definir_ab_fig(); +extern void definir_ab_fig2(); +extern void sauver_fig_ph(); +extern void remonter_consud_instph(char *nominst); +extern void remonter_connord_instph(char *nominst); +extern void placer_instph(char *nomfig, char *nominst, char symetrie, + long x, long y); +extern void placer_segph(char layer, long width, char *nameseg, + long x1, long y1, long x2, long y2); +extern void miseaplat_instph(char *insname, char cheminom); +extern void remonter_uncon_instph(long index, char *locname, char *insname, char *newname); +extern void poser_wire1(char layer, long width, char* ins1, char *con1, + long index1, char* ins2, char* con2,long index2); + +extern void poser_wire2(char layer, long width, char* ins1, char* con1, + long index1, char* ins2, char* con2, long index2, long x, long y); + +#endif /* __BARRE_H */ diff --git a/alliance/src/ring/src/bigvia.c b/alliance/src/ring/src/bigvia.c new file mode 100644 index 00000000..85b7c61f --- /dev/null +++ b/alliance/src/ring/src/bigvia.c @@ -0,0 +1,169 @@ +/* + * 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 support : mailto:alliance-support@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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/****************************************************************************/ +/* */ +/* Chaine de CAO & VLSI Alliance */ +/* */ +/* Produit : ring router */ +/* Fichier : bigvia.c */ +/* */ +/* (c) copyright 1992 Laboratoire MASI equipe CAO & VLSI */ +/* Tous droits reserves */ +/* Support : e-mail cao-vlsi@masi.ibp.fr */ +/* */ +/* Ecrit par : Fred le : 01/08/92 */ +/* Modifie par : Franck Wajsburt le : 9/11/94 */ +/* */ +/****************************************************************************/ + +#include "bigvia.h" + +/*-----------------------------------------------------------------------------*/ +/* #define BV_VIA_VIA 4 must be even, whatever! */ +/* #define BV_VIASIZE 3 design rule for equipotential vias */ +/* */ +/* this creates a mega-via, the best way we can do it, I hope */ +/* the envelop of the bigvia is calculated, and then its center is placed */ +/* as close as possible of the x, y coordinates given as arguments. */ +/*-----------------------------------------------------------------------------*/ +void +bigvia_ring(char l1, char l2, phfig_list* f, long x, long y, long dx, long dy) +{ + int i, j; + long stepx, stepy, xv, yv, dxv, dyv; + + if (((l1==ALU1)&&(l2==ALU2)) + || ((l2==ALU1)&&(l1==ALU2))) { + addphvia(f, CONT_VIA, x, y, dx, dy, (char *)NULL); + } else + if (((l1==ALU2)&&(l2==ALU3)) + || ((l2==ALU2)&&(l1==ALU3))) { + addphvia(f, CONT_VIA2, x, y, dx, dy, (char *)NULL); + } else { + fflush(stdout); + fprintf(stderr, "*** mbk error ***\n bigvia impossible :"); + EXIT(1); + } +return; + + if (dx < 0 || dy < 0) { + fflush(stdout); + fprintf(stderr, "*** mbk error ***\n bigvia impossible :"); + fprintf(stderr, " negative values dx = %ld, dy = %ld\n", dx, dy); + fprintf(stderr, "in figure '%s' at (%ld, %ld)\n", f->NAME, x, y); + EXIT(1); + } + + /* -------------------------------------------------------------------- */ + /* euclidian division : */ + /* dividing and then multipliing doesen't give the initial value. */ + /* calculate the center of the bunch of vias and adjust it to the given */ + /* x, y coordinates. */ + /* -------------------------------------------------------------------- */ + + stepx = (dx - BV_VIASIZE * SCALE_X) / (BV_VIA_VIA * SCALE_X); + stepy = (dy - BV_VIASIZE * SCALE_X) / (BV_VIA_VIA * SCALE_X); + dxv = stepx * BV_VIA_VIA * SCALE_X; + dyv = stepy * BV_VIA_VIA * SCALE_X; + xv = x - dxv / 2; + yv = y - dyv / 2; + + /* ------------- */ + /* draw the vias */ + /* ------------- */ + + for (i = 0; i <= stepx; i++) + for (j = 0; j <= stepy; j++) { + bigvias++; + + if (mode_debug) { + + /* ------------------------------------------------------------ */ + /* new rules for disk space : just a ring of via for big pates. */ + /* ------------------------------------------------------------ */ + + if (i == 0 || i == stepx || j == 0 || j == stepy) { + if (((l1==ALU1)&&(l2==ALU2)) + || ((l2==ALU1)&&(l1==ALU2))) { + addphvia(f, CONT_VIA, + xv + i * BV_VIA_VIA * SCALE_X, yv + j * BV_VIA_VIA * SCALE_X,0,0, NULL); + } else + if (((l1==ALU2)&&(l2==ALU3)) + || ((l2==ALU2)&&(l1==ALU3))) { + addphvia(f, CONT_VIA2, + xv + i * BV_VIA_VIA * SCALE_X, yv + j * BV_VIA_VIA * SCALE_X,0,0, NULL); + } + ringvias++; + } + } /* fin du if mode_debug */ else { /* pave complet de vias ! */ + if (i == 0 || i == stepx || j == 0 || j == stepy) + ringvias++; + + if (((l1==ALU1)&&(l2==ALU2)) + || ((l2==ALU1)&&(l1==ALU2))) { + addphvia(f, CONT_VIA, + xv + i * BV_VIA_VIA * SCALE_X, yv + j * BV_VIA_VIA * SCALE_X,0,0, NULL); + } else + if (((l1==ALU2)&&(l2==ALU3)) + || ((l2==ALU2)&&(l1==ALU3))) { + addphvia(f, CONT_VIA2, + xv + i * BV_VIA_VIA * SCALE_X, yv + j * BV_VIA_VIA * SCALE_X,0,0, NULL); + } + } + } + + /* ----------------------------------------------------------------------------------------- */ + /* put segments around the vias : this warranties that no notches may appear on the borders. */ + /* ----------------------------------------------------------------------------------------- */ + + if (stepx) + addphseg(f, l1, BV_VIASIZE * SCALE_X, xv, yv, xv + stepx * BV_VIA_VIA * SCALE_X, yv, NULL); + if (stepx || stepy) + addphseg(f, l1, BV_VIASIZE * SCALE_X, xv + stepx * BV_VIA_VIA * SCALE_X, yv, xv + stepx * BV_VIA_VIA * + SCALE_X, yv + stepy * BV_VIA_VIA * SCALE_X, NULL); + if (stepx || stepy) + addphseg(f, l1, BV_VIASIZE * SCALE_X, xv + stepx * BV_VIA_VIA * SCALE_X, yv + stepy * BV_VIA_VIA * SCALE_X, + xv, yv + stepy * BV_VIA_VIA * SCALE_X, NULL); + if (stepy) + addphseg(f, l1, BV_VIASIZE * SCALE_X, xv, yv, xv, yv + stepy * BV_VIA_VIA * SCALE_X, NULL); + if (stepx) + addphseg(f, l2, BV_VIASIZE * SCALE_X, xv, yv, xv + stepx * BV_VIA_VIA * SCALE_X, yv, NULL); + if (stepx || stepy) + addphseg(f, l2, BV_VIASIZE * SCALE_X, xv + stepx * BV_VIA_VIA * SCALE_X, yv, xv + stepx * BV_VIA_VIA * + SCALE_X, yv + stepy * BV_VIA_VIA * SCALE_X, NULL); + if (stepx || stepy) + addphseg(f, l2, BV_VIASIZE * SCALE_X, xv + stepx * BV_VIA_VIA * SCALE_X, yv + stepy * BV_VIA_VIA * SCALE_X, + xv, yv + stepy * BV_VIA_VIA * SCALE_X, NULL); + if (stepy) + addphseg(f, l2, BV_VIASIZE * SCALE_X, xv, yv, xv, yv + stepy * BV_VIA_VIA * SCALE_X, NULL); + + /* ----------------------------------------------------------------------------------------------------------------------------- */ + /* fill the leftover space : we use computed via coordinates, and substract one in order not to take care of even or odd values. */ + /* ----------------------------------------------------------------------------------------------------------------------------- */ + + if (dxv && dyv) + addphseg(f, l2, dyv - 1 * SCALE_X, xv, yv + dyv / 2, xv + dxv, yv + dyv / 2, NULL); + if (dxv && dyv) + addphseg(f, l1, dyv - 1 * SCALE_X, xv, yv + dyv / 2, xv + dxv, yv + dyv / 2, NULL); +} diff --git a/alliance/src/ring/src/bigvia.h b/alliance/src/ring/src/bigvia.h new file mode 100644 index 00000000..fb7dd36e --- /dev/null +++ b/alliance/src/ring/src/bigvia.h @@ -0,0 +1,10 @@ +#ifndef __BIGVIA_H +#define __BIGVIA_H + +#include +#include +#include "struct.h" + +extern void bigvia_ring(char l1, char l2, phfig_list* f, long x, long y, long dx, long dy); + +#endif /* __BIGVIA_H */ diff --git a/alliance/src/ring/src/compress.c b/alliance/src/ring/src/compress.c new file mode 100644 index 00000000..db54e675 --- /dev/null +++ b/alliance/src/ring/src/compress.c @@ -0,0 +1,367 @@ +/* + * 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 support : mailto:alliance-support@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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/****************************************************************************/ +/* */ +/* Chaine de CAO & VLSI Alliance */ +/* */ +/* Produit : ring router */ +/* Fichier : compress.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 24 juillet 92 COMPRESS.C */ +/* compression des canaux libres + mise a jour des coordonnees de tous les segments */ +/*-----------------------------------------------------------------------------------*/ + +#include "compress.h" + +#include + +/*----------------------------------------------------------------------------------*/ +/* cette procedure retourne la 1ere et la derniere instance du mode physique */ +/* selon la face */ +/*----------------------------------------------------------------------------------*/ + +void firstlastinst_barre(phfig_list *barre, phins_list **firstinst, phins_list **lastinst) +{ + + phins_list * lst = barre->PHINS; + long min, max; + + max = min = lst->XINS; + *firstinst = *lastinst = lst; + lst = lst->NEXT; + + while (NULL != lst) { + if (lst->XINS < min) { + min = lst->XINS; + *firstinst = lst; + } + if (lst->XINS > max) { + max = lst->XINS; + *lastinst = lst; + } + lst = lst->NEXT; + } + if (mode_debug) + printf("firstinst %s x %ld lastinst %s x %ld\n", (*firstinst)->INSNAME, (*firstinst)->XINS, (*lastinst)->INSNAME, + (*lastinst)->XINS); + +} + +/*------------------------------------------------------------------------------------*/ +/* Cette procedure calcul le nombre de pistes libres pour chaque canal de chaque face */ +/* et range dans: */ +/* - nblibres: le nombre total de piste libres entre la derniere piste occupee par */ +/* le routage et les pistes d'alim. */ +/* - firstlibre: le numero de la 1ere piste libre dans la face concernee */ +/*------------------------------------------------------------------------------------*/ + +void calcul_nbpiste_libre(BARRE_PLOTS tab_plots[NB_FACES], COEUR lecoeur, + LST_SEGMENT segx_occ[NB_FACES], LST_SEGMENT segy_occ[NB_FACES], + long nblibres[NB_FACES], long firstlibre[NB_FACES]) +{ + PT_COORDONNEES debut, fin; + long piste, pistelibre, maxpiste = 0; + char niveaupiste = 0; + LST_SEGMENT * segpiste = NULL; + int face; + + alloue_coord(0L, 0, &debut); + alloue_coord(0L, 0, &fin); + + debut->xabs = lecoeur.coord.xabs - 10; + debut->yabs = lecoeur.coord.yabs - 10; + fin->xabs = lecoeur.coord.xabs + lecoeur.width + 10; + fin->yabs = lecoeur.coord.yabs + lecoeur.height + 10; + + for (face = 0; face < NB_FACES; face++) + if ((0 != tab_plots[face].width) && (tab_plots[face].coord.piste > maxpiste)) + maxpiste = tab_plots[face].coord.piste; + + for (face = 0; face < NB_FACES; face++) { + firstlibre[face] = maxpiste; + nblibres[face] = 0; + } + + for (face = 0; face < NB_FACES; face++) { + switch (face) { + case NORD: + case SUD: + segpiste = segx_occ; + niveaupiste = xmetal; + break; + case EST: + case OUEST: + segpiste = segy_occ; + niveaupiste = ymetal; + break; + } + + for (piste = 2; piste < maxpiste; piste++) + if (segment_libre(debut, fin, piste, piste, face, SEG_PISTE, segpiste, niveaupiste)) { + firstlibre[face] = piste; + + for (pistelibre = piste; pistelibre < maxpiste; pistelibre++) + if (!segment_libre(debut, fin, pistelibre, pistelibre, face, SEG_PISTE, segpiste, + niveaupiste)) { + nblibres[face] = pistelibre - piste; + break; + } + + if (mode_debug) + printf("face %d firstpistelibre %ld nbpistelibres %ld\n", (int)face, firstlibre[face], + nblibres[face]); + + break; + } + } + +} + +/*--------------------------------------------------------------------------------*/ +/* Compression du canal de chaque face en prenant la contrainte la plus forte: */ +/* - le nombre minimum de pistes libres entre le nb total de pistes libres et */ +/* la difference de pistes entre 2 barres de plots mitoyennes. */ +/* - les coordonnees sont mises a jour, et un champ compress marque la compression*/ +/* deja effectuee. */ +/*--------------------------------------------------------------------------------*/ + +void compression_canaux(BARRE_PLOTS tab_plots[NB_FACES], COEUR lecoeur, + LST_SEGMENT segx_occ[NB_FACES], LST_SEGMENT segy_occ[NB_FACES], + long nblibres[NB_FACES], long firstlibre[NB_FACES]) +{ + long nblibresenv[NB_FACES]; + long nblibresfin[NB_FACES]; + long diff1, diff2; + LST_SEGMENT lstsegx, lstsegy; + + int face; + + for (face = 0; face < NB_FACES; face++) { + diff1 = diff2 = nblibresenv[face] = nblibres[face]; + + if (0 != tab_plots[face].width) + switch (face) { + case NORD: + if (mode_debug) + printf("nord"); + if (0 != tab_plots[EST].width) + diff1 = ((lecoeur.coord.yabs + lecoeur.height + tab_plots[NORD].coord.piste * pitch) + -(tab_plots[EST].coord.yabs + tab_plots[EST].width)) / pitch; + if (0 != tab_plots[OUEST].width) + diff2 = ((lecoeur.coord.yabs + lecoeur.height + tab_plots[NORD].coord.piste * pitch) + -(tab_plots[OUEST].coord.yabs + tab_plots[OUEST].width)) / pitch; + + if (diff1 < diff2) + nblibresenv[NORD] = diff1; + else + nblibresenv[NORD] = diff2; + + break; + + case SUD: + if (mode_debug) + printf("sud"); + if (0 != tab_plots[EST].width) + diff1 = ( -(lecoeur.coord.yabs - tab_plots[SUD].coord.piste * pitch) + (tab_plots[EST].coord.yabs)) + / pitch; + if (0 != tab_plots[OUEST].width) + diff2 = ( -(lecoeur.coord.yabs - tab_plots[SUD].coord.piste * pitch) + (tab_plots[OUEST].coord.yabs)) + / pitch; + + if (diff1 < diff2) + nblibresenv[SUD] = diff1; + else + nblibresenv[SUD] = diff2; + + break; + + case EST: + if (mode_debug) + printf("est"); + if (0 != tab_plots[NORD].width) + diff1 = ((lecoeur.coord.xabs + lecoeur.width + tab_plots[EST].coord.piste * pitch) - + (tab_plots[NORD].coord.xabs + tab_plots[NORD].width)) / pitch; + if (0 != tab_plots[SUD].width) + diff2 = ((lecoeur.coord.xabs + lecoeur.width + tab_plots[EST].coord.piste * pitch) - + (tab_plots[SUD].coord.xabs + tab_plots[SUD].width)) / pitch; + + if (diff1 < diff2) + nblibresenv[EST] = diff1; + else + nblibresenv[EST] = diff2; + break; + + case OUEST: + if (mode_debug) + printf("ouest"); + if (0 != tab_plots[NORD].width) + diff1 = (-(lecoeur.coord.xabs - tab_plots[OUEST].coord.piste * pitch ) + (tab_plots[NORD].coord.xabs)) + / pitch; + if (0 != tab_plots[SUD].width) + diff2 = (-(lecoeur.coord.xabs - tab_plots[OUEST].coord.piste * pitch ) + (tab_plots[SUD].coord.xabs)) + / pitch; + + if (diff1 < diff2) + nblibresenv[OUEST] = diff1; + else + nblibresenv[OUEST] = diff2; + break; + } + + /* ------------------------------------------------------ */ + /* on prend la contrainte la plus forte donc le min des 2 */ + /* ------------------------------------------------------ */ + + if (nblibres[face] < nblibresenv[face]) + nblibresfin[face] = nblibres[face]; + else + nblibresfin[face] = nblibresenv[face]; + + if (mode_debug) + printf("nblibresenv face %d nb %ld nblibresfin %ld\n", (int)face, nblibresenv[face], nblibresfin[face]); + } + + /* --------------------------------------------------------- */ + /* compression des canaux avec la liste des segments occupes */ + /* --------------------------------------------------------- */ + + for (face = 0; face < NB_FACES; face++) { + lstsegx = segx_occ[face]; + lstsegy = segy_occ[face]; + + /* --------------------------------- */ + /* rapprochement des barres de plots */ + /* --------------------------------- */ + + tab_plots[face].coord.piste -= nblibresfin[face]; + + /* ------------------------------- */ + /* parcours des listes de segments */ + /* ------------------------------- */ + + if (mode_debug) + printf("compression face %d des segx\n", (int)face); + + while (NULL != lstsegx) { + switch (face) { + case NORD: + case SUD: + if ((lstsegx->piste1 > firstlibre[face]) && (lstsegx->piste2 > firstlibre[face])) { + if ((lstsegx->c1->xabs < lecoeur.coord.xabs) && (SANS_COMPRESS == lstsegx->c1->compress) && + (NULL == lstsegx->c1->proprio)) { + lstsegx->c1->xabs += nblibresfin[OUEST] * pitch; + lstsegx->c1->compress = AVEC_COMPRESS; + } + + if ((lstsegx->c2->xabs > (lecoeur.coord.xabs + lecoeur.width)) && (SANS_COMPRESS == + lstsegx->c2->compress) && (NULL == lstsegx->c2->proprio)) { + lstsegx->c2->xabs -= nblibresfin[EST] * pitch; + lstsegx->c2->compress = AVEC_COMPRESS; + } + } + break; + + case EST: + case OUEST: + if ((lstsegx->piste1 > firstlibre[face]) && (lstsegx->piste2 > firstlibre[face])) { + if ((lstsegx->c1->yabs < lecoeur.coord.yabs) && (SANS_COMPRESS == lstsegx->c1->compress) && + (NULL == lstsegx->c1->proprio)) { + lstsegx->c1->yabs += nblibresfin[SUD] * pitch; + lstsegx->c1->compress = AVEC_COMPRESS; + } + + if ((lstsegx->c2->yabs > (lecoeur.coord.yabs + lecoeur.height)) && (SANS_COMPRESS == + lstsegx->c2->compress) && (NULL == lstsegx->c2->proprio)) { + lstsegx->c2->yabs -= nblibresfin[NORD] * pitch; + lstsegx->c2->compress = AVEC_COMPRESS; + } + } + break; + } + if (lstsegx->piste1 > firstlibre[face]) + lstsegx->piste1 -= nblibresfin[face]; + if (lstsegx->piste2 > firstlibre[face]) + lstsegx->piste2 -= nblibresfin[face]; + + lstsegx = lstsegx->suiv; + } + + if (mode_debug) + printf("compression face %d des segy\n", (int)face); + + while (NULL != lstsegy) { + switch (face) { + case NORD: + case SUD: + if ((lstsegy->piste1 > firstlibre[face]) && (lstsegy->piste2 > firstlibre[face])) { + if ((lstsegy->c1->xabs < lecoeur.coord.xabs) && (SANS_COMPRESS == lstsegy->c1->compress) && + (NULL == lstsegy->c1->proprio)) { + lstsegy->c1->xabs += nblibresfin[OUEST] * pitch; + lstsegy->c1->compress = AVEC_COMPRESS; + } + + if ((lstsegy->c2->xabs > (lecoeur.coord.xabs + lecoeur.width)) && (SANS_COMPRESS == + lstsegy->c2->compress) && (NULL == lstsegy->c2->proprio)) { + lstsegy->c2->xabs -= nblibresfin[EST] * pitch; + lstsegy->c2->compress = AVEC_COMPRESS; + } + } + break; + + case EST: + case OUEST: + if ((lstsegy->piste1 > firstlibre[face]) && (lstsegy->piste2 > firstlibre[face])) { + if ((lstsegy->c1->yabs < lecoeur.coord.yabs) && (SANS_COMPRESS == lstsegy->c1->compress) && + (NULL == lstsegy->c1->proprio)) { + lstsegy->c1->yabs += nblibresfin[SUD] * pitch; + lstsegy->c1->compress = AVEC_COMPRESS; + } + + if ((lstsegy->c2->yabs > (lecoeur.coord.yabs + lecoeur.height)) && (SANS_COMPRESS == + lstsegy->c2->compress) && (NULL == lstsegy->c2->proprio)) { + lstsegy->c2->yabs -= nblibresfin[NORD] * pitch; + lstsegy->c2->compress = AVEC_COMPRESS; + } + } + break; + } + if (lstsegy->piste1 > firstlibre[face]) + lstsegy->piste1 -= nblibresfin[face]; + if (lstsegy->piste2 > firstlibre[face]) + lstsegy->piste2 -= nblibresfin[face]; + + lstsegy = lstsegy->suiv; + } + } /* fin du for */ +} diff --git a/alliance/src/ring/src/compress.h b/alliance/src/ring/src/compress.h new file mode 100644 index 00000000..d8fd957f --- /dev/null +++ b/alliance/src/ring/src/compress.h @@ -0,0 +1,18 @@ +#ifndef __COMPRESS_H +#define __COMPRESS_H + +#include +#include +#include "struct.h" + +extern void firstlastinst_barre(phfig_list *barre, phins_list **firstinst, phins_list **lastinst); + +extern void calcul_nbpiste_libre(BARRE_PLOTS tab_plots[NB_FACES], COEUR lecoeur, + LST_SEGMENT segx_occ[NB_FACES], LST_SEGMENT segy_occ[NB_FACES], + long nblibres[NB_FACES], long firstlibre[NB_FACES]); + +extern void compression_canaux(BARRE_PLOTS tab_plots[NB_FACES], COEUR lecoeur, + LST_SEGMENT segx_occ[NB_FACES], LST_SEGMENT segy_occ[NB_FACES], + long nblibres[NB_FACES], long firstlibre[NB_FACES]); + +#endif /* __COMPRESS_H */ diff --git a/alliance/src/ring/src/deport.c b/alliance/src/ring/src/deport.c new file mode 100644 index 00000000..d78a2031 --- /dev/null +++ b/alliance/src/ring/src/deport.c @@ -0,0 +1,1229 @@ +/* + * 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 support : mailto:alliance-support@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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/****************************************************************************/ +/* */ +/* Chaine de CAO & VLSI Alliance */ +/* */ +/* Produit : ring router */ +/* Fichier : deport.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 17 juillet 92 DEPORT.C */ +/* traitement des deports (y compris alim) */ +/* et pose des segments pour les deports (hors alim) */ +/*-----------------------------------------------------------------------------------*/ + +#include "deport.h" +#include "placement.h" +#include "sesame.h" + +/*-----------------------------------------------------------------------------------*/ +/* Attribution des couronnes d'alimentation de maniere a avoir le moins de fils a */ +/* tirer pour la couronne inferieure . Exception: si alim ds mauvais layer, on */ +/* essayre de s'arranger pour mettre ce type d'alim en couronne superieure (on tirera*/ +/* directement le fil dans le mauvais layer */ +/*-----------------------------------------------------------------------------------*/ + +void attribuer_couronne_alim(LST_EQUIPO lst_equipo, char **coursup, char **courinf) +{ + + LST_EQUIPO equipo_vdd, equipo_vss; + LST_PSEUDO_CON con; + ptype_list * ptvdd = NULL , *ptvss = NULL, *ptcour; + int hyp1, hyp2, vddequi = 0, vddtotal = 0, vssequi = 0, vsstotal = 0; + char *alim; + + recherche_equipo_alim(&equipo_vdd, &equipo_vss, lst_equipo); + + ptvdd = equipo_vdd->lst_visavis; + ptvss = equipo_vss->lst_visavis; + + /* -------------------------- */ + /* trt des visavis equipo vdd */ + /* -------------------------- */ + + ptcour = ptvdd; + while (ptcour != NULL) { + con = (LST_PSEUDO_CON) ptcour->DATA; + + if (mode_debug) + printf("visavis vdd %s\n", con->nom_con); + + if (con->nom_con == eq_vdd) { + vddequi++; + vddtotal++; + } else if (con->nom_con == eq_vss) + vddtotal++; + + ptcour = ptcour->NEXT; + } + + /* -------------------------- */ + /* trt des visavis equipo vss */ + /* -------------------------- */ + + ptcour = ptvss; + while (ptcour != NULL) { + con = (LST_PSEUDO_CON) ptcour->DATA; + + if (mode_debug) + printf("visavis vss %s\n", con->nom_con); + + if (con->nom_con == eq_vss) { + vssequi++; + vsstotal++; + } else if (con->nom_con == eq_vdd) + vsstotal++; + + ptcour = ptcour->NEXT; + } + + hyp1 = vsstotal + vddequi; + hyp2 = vddtotal + vssequi; + + if ((alim = existe_unique_deport_alim(equipo_vdd, equipo_vss)) == NULL) + if (hyp1 < hyp2) { + *courinf = eq_vss; + *coursup = eq_vdd; + } + else { + *courinf = eq_vdd; + *coursup = eq_vss; + } + else + { + if (mode_debug) + printf("Unique deport trouve %s\n", alim); + if (alim == eq_vss) { + *courinf = eq_vdd; + *coursup = eq_vss; + } else { + *courinf = eq_vss; + *coursup = eq_vdd; + } + } + + if (mode_debug) + printf("COURSUP %s courinf %s vddtotal %d vsstotal %d vddequi %d vssequi %d\n", *coursup, *courinf, vddtotal, + vsstotal, vddequi, vssequi); +} + +/*------------------------------------------------------------------------------*/ +/* Retourne le nom de l'equipo alim ssi unique deport pour les alim */ +/*------------------------------------------------------------------------------*/ + +char* existe_unique_deport_alim(LST_EQUIPO equipo_vdd, LST_EQUIPO equipo_vss) +{ + LST_PSEUDO_CON con; + chain_list * ptvdd = NULL , *ptvss = NULL, *ptcour; + + int trouvevdd = 0, trouvevss = 0; + + ptvdd = equipo_vdd->lst_con; + ptvss = equipo_vss->lst_con; + + ptcour = ptvdd; + + while (ptcour != NULL) { + con = (LST_PSEUDO_CON) ptcour->DATA; + if ((con->coeur_plot == PLOT_CON) && (con->deport != NULL)) + trouvevdd = 1; + ptcour = ptcour->NEXT; + } + + ptcour = ptvss; + + while (ptcour != NULL) { + con = (LST_PSEUDO_CON) ptcour->DATA; + if ((con->coeur_plot == PLOT_CON) && (con->deport != NULL)) + trouvevss = 1; + ptcour = ptcour->NEXT; + } + + if ((trouvevdd && trouvevss) == 0) + if (trouvevdd) + return(eq_vdd); + else if (trouvevss) + return(eq_vss); + else + return(NULL); + + else + return(NULL); + +} + +/*-----------------------------------------------------------------------------------------*/ +/* trt des deports d'alim: pour le coeur changement layer ds ts les cas, prend une */ +/* piste, ou plus si largeur du connecteur non standart. */ +/* pour les plots, si coursup = alim mauvais layer, on ne deporte */ +/* pas, sinon on deporte quand meme. */ +/* */ +/* trt des vis a vis d'alim: si elles se croisent et non equi, on deporte alim coeur */ +/* (cherche_deport_alim) */ +/* on occupe les colonnes avoisinantes pour la taille du fil */ +/* si elles se croisent et equi, et croisement < largfil /2 */ +/* on deporte aussi. */ +/*SI DEPORT PLOT ALIM (MAUVAIS LAYER) => ALLOCATION EXCEPTIONNELLE DE FAUX SEGMENTS */ +/*-----------------------------------------------------------------------------------------*/ + +void deport_alim(LST_EQUIPO lst_equipo, BARRE_PLOTS tab_plots[NB_FACES], + char *coursup, char *courinf, LST_SEGMENT segx_occ[NB_FACES], + LST_SEGMENT segy_occ[NB_FACES]) +{ + PT_COORDONNEES lst_coor, ptcoor; + LST_EQUIPO equipo_vdd, equipo_vss; + LST_PSEUDO_CON con; + chain_list * ptvdd = NULL , *ptvss = NULL, *ptcour; + ptype_list * ptvddvav = NULL , *ptvssvav = NULL, *ptcourvav; + long largeurmin = 0; + int i, nbcolatrouver, face; + long largmetalpiste, largmetalcol, piste; + char niveaucol, niveaupiste; + LST_SEGMENT * segcol; + LST_SEGMENT * segpiste; + + recherche_equipo_alim(&equipo_vdd, &equipo_vss, lst_equipo); + + ptvdd = equipo_vdd->lst_con; + ptvss = equipo_vss->lst_con; + + ptvddvav = equipo_vdd->lst_visavis; + ptvssvav = equipo_vss->lst_visavis; + + for (face = 0; face < NB_FACES; face++) { + segx_occ[face] = NULL; /* INITIALISATION DES SEGMENTS */ + segy_occ[face] = NULL; + } + + /* ---------------------------- */ + /* traitement des deports layer */ + /* ---------------------------- */ + + ptcour = ptvdd; + + while (ptcour != NULL) { + con = (LST_PSEUDO_CON) ptcour->DATA; + if ((con->coeur_plot == PLOT_CON) && (con->deport != NULL)) { + if (con->nom_con != coursup) + + /* -------------------------------------- */ + /* foutu, on est oblige de deporter arghh */ + /* -------------------------------------- */ + + switch (con->face) { + case NORD: + case SUD : + niveaucol = ymetal; + niveaupiste = xmetal; + segcol = segy_occ; + segpiste = segx_occ; + largmetalpiste = xmetal_width; + largmetalcol = ymetal_width; + + if (mode_debug) + printf("deport alimplot layer %s\n", con->nom_con); + (con->deport)->xabs = (con->coord)->xabs; + (con->deport)->piste = (tab_plots[con->face].coord).piste - (con->largeur + pitch) + / pitch; + + /* ------------------------------------------------- */ + /* allocation de faux segments si deport alim plot ! */ + /* ------------------------------------------------- */ + + if (con->largeur > largmetalcol) { + for (piste = tab_plots[con->face].coord.piste - 1; piste >= (con->deport->piste - + (con->largeur / 2 + pitch) / pitch); piste--) + alloue_etchaine_segment(con->coord, con->coord, piste, piste, con->face, + SEG_PISTE, segpiste, largmetalpiste, niveaupiste, FAUX_SEG, AVEC_VIA, + equipo_vdd); + } + + break; + + case EST : + case OUEST: + niveaucol = xmetal; + niveaupiste = ymetal; + segcol = segx_occ; + segpiste = segy_occ; + largmetalpiste = ymetal_width; + largmetalcol = xmetal_width; + + if (mode_debug) + printf("deport alimplot layer %s\n", con->nom_con); + (con->deport)->yabs = (con->coord)->yabs; + (con->deport)->piste = (tab_plots[con->face].coord).piste - (con->largeur + pitch) + / pitch; + + /* ------------------------------------------------- */ + /* allocation de faux segments si deport alim plot ! */ + /* ------------------------------------------------- */ + + if (con->largeur > largmetalcol) { + for (piste = tab_plots[con->face].coord.piste - 1; piste >= (con->deport->piste - + (con->largeur / 2 + pitch) / pitch); piste--) + alloue_etchaine_segment(con->coord, con->coord, piste, piste, con->face, + SEG_PISTE, segpiste, largmetalpiste, niveaupiste, FAUX_SEG, AVEC_VIA, + equipo_vdd); + } + + break; + } + } /* fin du if */ else if (con->deport != NULL) /* deport coeur */ + switch (con->face) { + case NORD: + case SUD : + largeurmin = ymetal_width; + if (mode_debug) + printf("deport coeuralim layer %s\n", con->nom_con); + (con->deport)->xabs = (con->coord)->xabs; + if (con->largeur > largeurmin) + (con->deport)->piste = (con->largeur + pitch) / pitch; + else + (con->deport)->piste = 1; /* premiere piste pour deport layer */ + + break; + + case EST : + case OUEST: + largeurmin = xmetal_width; + if (mode_debug) + printf("deport coeuralim layer %s\n", con->nom_con); + (con->deport)->yabs = (con->coord)->yabs; + if (con->largeur > largeurmin) + (con->deport)->piste = (con->largeur + pitch) / pitch; + else + (con->deport)->piste = 1; /* premiere piste pour deport layer */ + + break; + } + + ptcour = ptcour->NEXT; + } + + ptcour = ptvss; + + while (ptcour != NULL) { + con = (LST_PSEUDO_CON) ptcour->DATA; + if ((con->coeur_plot == PLOT_CON) && (con->deport != NULL)) { + if (con->nom_con != coursup) + + /* -------------------------------------- */ + /* foutu, on est oblige de deporter arghh */ + /* -------------------------------------- */ + + switch (con->face) { + case NORD: + case SUD : + niveaucol = ymetal; + niveaupiste = xmetal; + segcol = segy_occ; + segpiste = segx_occ; + largmetalpiste = xmetal_width; + largmetalcol = ymetal_width; + + if (mode_debug) + printf("deport alimplot layer %s\n", con->nom_con); + (con->deport)->xabs = (con->coord)->xabs; + (con->deport)->piste = (tab_plots[con->face].coord).piste - (con->largeur + pitch) / pitch; + + /* ------------------------------------------------- */ + /* allocation de faux segments si deport alim plot ! */ + /* ------------------------------------------------- */ + + if (con->largeur > largmetalcol) { + for (piste = tab_plots[con->face].coord.piste - 1; piste >= (con->deport->piste - + (con->largeur / 2 + pitch) / pitch); piste--) + alloue_etchaine_segment(con->coord, con->coord, piste, piste, con->face, + SEG_PISTE, segpiste, largmetalpiste, niveaupiste, FAUX_SEG, AVEC_VIA, + equipo_vss); + } + + break; + + case EST : + case OUEST: + niveaucol = xmetal; + niveaupiste = ymetal; + segcol = segx_occ; + segpiste = segy_occ; + largmetalpiste = ymetal_width; + largmetalcol = xmetal_width; + + if (mode_debug) + printf("deport alimplot layer %s\n", con->nom_con); + (con->deport)->yabs = (con->coord)->yabs; + (con->deport)->piste = (tab_plots[con->face].coord).piste - (con->largeur + pitch) + / pitch; + + /* ------------------------------------------------- */ + /* allocation de faux segments si deport alim plot ! */ + /* ------------------------------------------------- */ + + if (con->largeur > largmetalcol) { + for (piste = tab_plots[con->face].coord.piste - 1; piste >= (con->deport->piste - + (con->largeur / 2 + pitch) / pitch); piste--) + alloue_etchaine_segment(con->coord, con->coord, piste, piste, con->face, + SEG_PISTE, segpiste, largmetalpiste, niveaupiste, FAUX_SEG, AVEC_VIA, + equipo_vss); + } + + break; + } + } /* fin du if */ else if (con->deport != NULL) /* deport coeur */ + switch (con->face) { + case NORD: + case SUD : + if (mode_debug) + printf("deport coeuralim layer %s\n", con->nom_con); + (con->deport)->xabs = (con->coord)->xabs; + if (con->largeur > largeurmin) + (con->deport)->piste = (con->largeur + pitch) / pitch; + else + (con->deport)->piste = 1; /* premiere piste pour deport layer */ + + break; + + case EST : + case OUEST: + if (mode_debug) + printf("deport coeuralim layer %s\n", con->nom_con); + (con->deport)->yabs = (con->coord)->yabs; + if (con->largeur > largeurmin) + (con->deport)->piste = (con->largeur + pitch) / pitch; + else + (con->deport)->piste = 1; /* premiere piste pour deport layer */ + + break; + } + + ptcour = ptcour->NEXT; + } + + /*-----------------------------------------------------------------------------------*/ + /* traitement des vis a vis coeur alim, si alim <> et se croisent on deporte */ + /* si alim = et croisement < largfil /2 */ + /*-----------------------------------------------------------------------------------*/ + + if (mode_debug) + printf("traitement des vis a vis alim\n"); + + ptcourvav = ptvddvav; + + while (ptcourvav != NULL) { + con = (LST_PSEUDO_CON) ptcourvav->DATA; + if ((con->coeur_plot == COEUR_CON) && (con->nom_con == eq_vss) && (courinf == eq_vdd)) { + + /* -------------------------------------- */ + /* foutu, on est oblige de deporter arghh */ + /* -------------------------------------- */ + + if (mode_debug) + printf("\n**** alim visavis coeur vss %s\t", con->con_lo->NAME); + ptcoor = cherche_deport_grille(con, ptvdd); + + /* ------------------------------------------------------- */ + /* Occupation des colonnes necessaires au deport de l'alim */ + /* ------------------------------------------------------- */ + + nbcolatrouver = (con->largeur + pitch) / (2 * pitch); + lst_coor = ptcoor->suiv; + for (i = 0; i < nbcolatrouver; i++) + if ((NULL != lst_coor) && (NULL == lst_coor->proprio)) { + if (mode_debug) + printf("colonne occupee par deport x %ld y %ld\n", lst_coor->xabs, lst_coor->yabs); + lst_coor->proprio = (void * )con; + lst_coor = lst_coor->suiv; + } + + lst_coor = ptcoor->prec; + for (i = 0; i < nbcolatrouver; i++) + if ((NULL != lst_coor) && (NULL == lst_coor->proprio)) { + if (mode_debug) + printf("colonne occupee par deport x %ld y %ld\n", lst_coor->xabs, lst_coor->yabs); + lst_coor->proprio = (void * )con; + lst_coor = lst_coor->prec; + } + + con->deport = ptcoor; + ptcoor->proprio = (void * ) con; + if (mode_debug) + printf("deport alim coeur trouve %ld %ld\n", ptcoor->xabs, ptcoor->yabs); + + } + + if ((con->coeur_plot == COEUR_CON) && (con->nom_con == eq_vdd) && (!croisementok_alimequi(con, ptvdd, SANS_TESTLAYER))) { + + /* -------------------------------------- */ + /* foutu, on est oblige de deporter arghh */ + /* -------------------------------------- */ + + if (mode_debug) + printf("\n**** alim equi visavis coeur vdd %s\t", con->con_lo->NAME); + ptcoor = cherche_deport_grille(con, ptvdd); + + /* ------------------------------------------------------- */ + /* Occupation des colonnes necessaires au deport de l'alim */ + /* ------------------------------------------------------- */ + + nbcolatrouver = (con->largeur + pitch) / (2 * pitch); + lst_coor = ptcoor->suiv; + for (i = 0; i < nbcolatrouver; i++) + if ((NULL != lst_coor) && (NULL == lst_coor->proprio)) { + if (mode_debug) + printf("colonne occupee par deport x %ld y %ld\n", lst_coor->xabs, lst_coor->yabs); + lst_coor->proprio = (void * )con; + lst_coor = lst_coor->suiv; + } + + lst_coor = ptcoor->prec; + for (i = 0; i < nbcolatrouver; i++) + if ((NULL != lst_coor) && (NULL == lst_coor->proprio)) { + if (mode_debug) + printf("colonne occupee par deport x %ld y %ld\n", lst_coor->xabs, lst_coor->yabs); + lst_coor->proprio = (void * )con; + lst_coor = lst_coor->prec; + } + + con->deport = ptcoor; + ptcoor->proprio = (void * ) con; + if (mode_debug) + printf("deport alim coeur trouve %ld %ld\n", ptcoor->xabs, ptcoor->yabs); + + } + + ptcourvav = ptcourvav->NEXT; + } + + ptcourvav = ptvssvav; + + while (ptcourvav != NULL) { + con = (LST_PSEUDO_CON) ptcourvav->DATA; + if ((con->coeur_plot == COEUR_CON) && (con->nom_con == eq_vdd) && (courinf == eq_vss)) { + + /* -------------------------------------- */ + /* foutu, on est oblige de deporter arghh */ + /* -------------------------------------- */ + + if (mode_debug) + printf("\n**** alim visavis coeur vdd %s\t", con->con_lo->NAME); + ptcoor = cherche_deport_grille(con, ptvss); + + /* ------------------------------------------------------- */ + /* Occupation des colonnes necessaires au deport de l'alim */ + /* ------------------------------------------------------- */ + + nbcolatrouver = (con->largeur + pitch) / (2 * pitch); + lst_coor = ptcoor->suiv; + for (i = 0; i < nbcolatrouver; i++) + if ((NULL != lst_coor) && (NULL == lst_coor->proprio)) { + if (mode_debug) + printf("colonne occupee par deport x %ld y %ld\n", lst_coor->xabs, lst_coor->yabs); + lst_coor->proprio = (void * )con; + lst_coor = lst_coor->suiv; + } + + lst_coor = ptcoor->prec; + for (i = 0; i < nbcolatrouver; i++) + if ((NULL != lst_coor) && (NULL == lst_coor->proprio)) { + if (mode_debug) + printf("colonne occupee par deport x %ld y %ld\n", lst_coor->xabs, lst_coor->yabs); + lst_coor->proprio = (void * )con; + lst_coor = lst_coor->prec; + } + + con->deport = ptcoor; + ptcoor->proprio = (void * ) con; + if (mode_debug) + printf("deport alim coeur trouve %ld %ld\n", ptcoor->xabs, ptcoor->yabs); + + } + + if ((con->coeur_plot == COEUR_CON) && (con->nom_con == eq_vss) && (!croisementok_alimequi(con, ptvss, SANS_TESTLAYER))) { + + /* -------------------------------------- */ + /* foutu, on est oblige de deporter arghh */ + /* -------------------------------------- */ + + if (mode_debug) + printf("\n**** alim equi visavis coeur vss %s\t", con->con_lo->NAME); + ptcoor = cherche_deport_grille(con, ptvss); + + /* ------------------------------------------------------- */ + /* Occupation des colonnes necessaires au deport de l'alim */ + /* ------------------------------------------------------- */ + + nbcolatrouver = (con->largeur + pitch) / (2 * pitch); + lst_coor = ptcoor->suiv; + for (i = 0; i < nbcolatrouver; i++) + if ((NULL != lst_coor) && (NULL == lst_coor->proprio)) { + if (mode_debug) + printf("colonne occupee par deport x %ld y %ld\n", lst_coor->xabs, lst_coor->yabs); + lst_coor->proprio = (void * )con; + lst_coor = lst_coor->suiv; + } + + lst_coor = ptcoor->prec; + for (i = 0; i < nbcolatrouver; i++) + if ((NULL != lst_coor) && (NULL == lst_coor->proprio)) { + if (mode_debug) + printf("colonne occupee par deport x %ld y %ld\n", lst_coor->xabs, lst_coor->yabs); + lst_coor->proprio = (void * )con; + lst_coor = lst_coor->prec; + } + + con->deport = ptcoor; + ptcoor->proprio = (void * ) con; + if (mode_debug) + printf("deport alim coeur trouve %ld %ld\n", ptcoor->xabs, ptcoor->yabs); + + } + + ptcourvav = ptcourvav->NEXT; + } + +} + +/*------------------------------------------------------------------------------------*/ +/* Traitement de tous les deports coeur et plot sauf alim (deja fait) */ +/* on commence par traiter les deports qui sont en face du coeur, */ +/* puis les deports gauches */ +/* puis les deports droits */ +/*------------------------------------------------------------------------------------*/ + +void deport_connecteurs(BARRE_PLOTS tab_plots[NB_FACES], + LST_PSEUDO_CON tab_coeur[NB_FACES], + COEUR lecoeur, GRILLE tab_grilles[NB_FACES]) +{ + + int face, trouve; + long pistelayercentre, pistelayergauche, pistelayerdroite, piste, pistederniere; + long largeurmin; + + LST_PSEUDO_CON liste_coeur, liste_plots, ptcentre, ptdernier; + PT_COORDONNEES ptcoor, ptqueue; + + for (face = 0; face < NB_FACES; face++) { + + if (mode_debug) + printf("FACE %d\n", face); + + /* --------------------------------------------------- */ + /* Tous les connecteurs coeur/plot trt layer sauf alim */ + /* Quand on est dans la croix du coeur trt specialu */ + /* --------------------------------------------------- */ + + liste_plots = tab_plots[face].lst_con; + liste_coeur = tab_coeur[face]; + pistelayergauche = 0; + pistelayerdroite = 0; + pistelayercentre = 0; + ptcentre = NULL; + ptdernier = NULL; + pistederniere = (tab_plots[face].coord).piste; + + switch (face) { + case NORD: + case SUD : + + /* ------------------------------------------------------------------------------------------------------------------- */ + /* ptcentre debut conplots dans la face du coeur, ptdernier dernier conplot normalement en dehors de la croix du coeur */ + /* ------------------------------------------------------------------------------------------------------------------- */ + + largeurmin = ymetal_width; + + while (liste_plots != NULL) { + if ((liste_plots->coord)->xabs >= (lecoeur.coord).xabs) { + if ((liste_plots->prec == NULL) || (((liste_plots->prec)->coord)->xabs < (lecoeur.coord).xabs)) + ptcentre = liste_plots; + } + if (liste_plots->suiv == NULL) + ptdernier = liste_plots; + + liste_plots = liste_plots->suiv; + } + + /*------------------- TRT DES DEPORTS DES CONPLOTS DU CENTRE ---------------------- */ + + while ((ptcentre != NULL) && ((ptcentre->coord)->xabs <= ((lecoeur.coord).xabs + lecoeur.width))) { + if ((ptcentre->nom_con != eq_vdd) && (ptcentre->nom_con != eq_vss)) + + if (ptcentre->deport != NULL) { + ptcentre->situe_deport = DEPORTC; + + if (mode_debug) + printf("deport centre con %s %s piste%ld\n", ptcentre->nom_con, + ((loins_list *)(ptcentre->con_lo)->ROOT)->INSNAME, (ptcentre->deport)->piste); + pistelayercentre = 1; + if ((ptcentre->deport)->piste != 1) /* pas uniquement layer */ { + + /*----------------------------------------------------------------------------*/ + /* Le deport n'est pas chaine dans la grille , donc on appelle la procedure */ + /* qui modifie ses pointeurs suiv et prec */ + /*----------------------------------------------------------------------------*/ + + chaine_deportcon_grille(ptcentre->coord, tab_grilles[face].lst_pas, + face); + + /* ----------------------------------------- */ + /* on marque qu'il existe des deports layers */ + /* ----------------------------------------- */ + + if (ptcentre->layer != ymetal) + pistelayercentre = 1; + + if (((ptcentre->coord)->prec != NULL) && (((ptcentre->coord)->prec)->proprio == + NULL)) /*gauche */ { + ptcentre->deport = (ptcentre->coord)->prec; + (ptcentre->deport)->proprio = (void * )ptcentre; + (ptcentre->deport)->piste = pistederniere - 1; /* 1ere piste */ + } else if (((ptcentre->coord)->suiv != NULL) && (((ptcentre->coord)->suiv)->proprio == + NULL)) /* droite */ { + ptcentre->deport = (ptcentre->coord)->suiv; + (ptcentre->deport)->proprio = (void * ) ptcentre; + (ptcentre->deport)->piste = pistederniere - 1; /* 1ere piste */ + } else + ringerreur(ERR_ECHECDEPORT, (void * )ptcentre, NULL); + } else /* trt layer unique */ { + (ptcentre->deport)->xabs = (ptcentre->coord)->xabs; + (ptcentre->deport)->piste = pistederniere - 1; /* 1ere piste */ + } + + } /* fin trt deport */ + ptcentre = ptcentre->suiv; + + } /* fin trt centre */ + + /*-------------- TRT DES DEPORTS GAUCHE EN DEHORS DE FACE COEUR --------------------- */ + + liste_plots = tab_plots[face].lst_con; + piste = pistederniere - 2; /* on laisse une piste pour les deports */ + + while ((liste_plots != NULL) && ((liste_plots->coord)->xabs < (lecoeur.coord).xabs)) { + if (liste_plots->deport->piste == 1) + pistelayergauche = 1; + + /* -------------------- */ + /* ds ts les cas deport */ + /* -------------------- */ + + liste_plots->situe_deport = DEPORTG; + + if (mode_debug) + printf("deport gauche con %s %s\n", liste_plots->nom_con, ((loins_list * )(liste_plots->con_lo)->ROOT)->INSNAME); + trouve = 0; + + ptcoor = tab_grilles[face].lst_pas; + while (ptcoor != NULL) { + trouve = (ptcoor->proprio == NULL); + if (trouve) + break; + ptcoor = ptcoor->suiv; + } + + if (trouve) { + ptcoor->piste = piste; + ptcoor->proprio = (void * ) liste_plots; + piste--; + liste_plots->deport = ptcoor; + } else + ringerreur(ERR_ECHECDEPORT, liste_plots, NULL); + + liste_plots = liste_plots->suiv; + } + + /*------------- TRT DES DEPORTS DROIT EN DEHORS FACE COEUR --------------------------*/ + + ptqueue = tab_grilles[face].lst_pas; + while ((ptqueue != NULL) && (ptqueue->suiv != NULL)) + ptqueue = ptqueue->suiv; + + piste = pistederniere - 2; /* on laisse une piste pour les deports */ + + while ((ptdernier != NULL) && ((ptdernier->coord)->xabs > ((lecoeur.coord).xabs + lecoeur.width))) { + if ((ptdernier->deport)->piste == 1) + pistelayerdroite = 1; + + /* -------------------- */ + /* ds ts les cas deport */ + /* -------------------- */ + + ptdernier->situe_deport = DEPORTD; + + if (mode_debug) + printf("deport droite con %s %s\n", ptdernier->nom_con, ((loins_list * )(ptdernier->con_lo)->ROOT)->INSNAME); + + trouve = 0; + + ptcoor = ptqueue; + while (ptcoor != NULL) { + if (mode_debug) + printf("coord x%ld y%ld \n", ptcoor->xabs, ptcoor->yabs); + + trouve = (ptcoor->proprio == NULL); + if (trouve) + break; + ptcoor = ptcoor->prec; + } + + if (trouve) { + ptcoor->piste = piste; + ptcoor->proprio = (void * ) ptdernier; + piste--; + ptdernier->deport = ptcoor; + } else + ringerreur(ERR_ECHECDEPORT, ptdernier, NULL); + + ptdernier = ptdernier->prec; + } + + /*---------------------- TRT DES CONCOEUR, DEPORT LAYER UNIQUEMENT --------------------*/ + + while (liste_coeur != NULL) { + if ((liste_coeur->deport != NULL) && (liste_coeur->nom_con != eq_vdd) && (liste_coeur->nom_con != + eq_vss)) /* changement layer */ { + liste_coeur->situe_deport = DEPORTC; + liste_coeur->deport->xabs = (liste_coeur->coord)->xabs; + if (liste_coeur->largeur > largeurmin) + (liste_coeur->deport)->piste = (liste_coeur->largeur + pitch) / pitch; + else + (liste_coeur->deport)->piste = 1; /* premiere piste pour deport layer */ + if (mode_debug) + printf("Deport layer concoeur %s piste %ld largeur %ld\n", liste_coeur->nom_con, + liste_coeur->deport->piste, liste_coeur->largeur); + } + liste_coeur = liste_coeur->suiv; + } + + break; + + case EST : + case OUEST: + + /* ------------------------------------------------------------------------------------------------------------------- */ + /* ptcentre debut conplots dans la face du coeur, ptdernier dernier conplot normalement en dehors de la croix du coeur */ + /* ------------------------------------------------------------------------------------------------------------------- */ + + largeurmin = xmetal_width; + + while (liste_plots != NULL) { + if ((liste_plots->coord)->yabs >= (lecoeur.coord).yabs) { + if ((liste_plots->prec == NULL) || (((liste_plots->prec)->coord)->yabs < (lecoeur.coord).yabs)) + ptcentre = liste_plots; + } + if (liste_plots->suiv == NULL) + ptdernier = liste_plots; + + liste_plots = liste_plots->suiv; + } + + /*------------------ TRT DES DEPORTS DES CONPLOTS DU CENTRE --------------------------*/ + + while ((ptcentre != NULL) && ((ptcentre->coord)->yabs <= ((lecoeur.coord).yabs + lecoeur.height))) { + if ((ptcentre->nom_con != eq_vdd) && (ptcentre->nom_con != eq_vss)) + + if (ptcentre->deport != NULL) { + ptcentre->situe_deport = DEPORTC; + pistelayercentre = 1; + if ((ptcentre->deport)->piste != 1) /* pas uniquement layer */ { + if (mode_debug) + printf("deport centre con %s %s piste%ld\n", ptcentre->nom_con, + ((loins_list * )(ptcentre->con_lo)->ROOT)->INSNAME, (ptcentre->deport)->piste); + + /* ------------------------------------------------------------------------ */ + /* Le deport n'est pas chaine dans la grille , donc on appelle la procedure */ + /* qui modifie ses pointeurs suiv et prec */ + /* ------------------------------------------------------------------------ */ + + chaine_deportcon_grille(ptcentre->coord, tab_grilles[face].lst_pas, + face); + + /* ----------------------------------------- */ + /* on marque qu'il existe des deports layers */ + /* ----------------------------------------- */ + + if (ptcentre->layer != xmetal) + pistelayercentre = 1; + + if (((ptcentre->coord)->prec != NULL) && (((ptcentre->coord)->prec)->proprio == + NULL)) /*gauche */ { + ptcentre->deport = (ptcentre->coord)->prec; + (ptcentre->deport)->proprio = (void * )ptcentre; + (ptcentre->deport)->piste = pistederniere - 1; /* 1ere piste */ + } else if (((ptcentre->coord)->suiv != NULL) && (((ptcentre->coord)->suiv)->proprio == + NULL)) /* droite */ { + ptcentre->deport = (ptcentre->coord)->suiv; + (ptcentre->deport)->proprio = (void * ) ptcentre; + (ptcentre->deport)->piste = pistederniere - 1; /* 1ere piste */ + } else + ringerreur(ERR_ECHECDEPORT, ptcentre, NULL); + } else /* trt layer unique */ { + (ptcentre->deport)->yabs = (ptcentre->coord)->yabs; + (ptcentre->deport)->piste = pistederniere - 1; /* 1ere piste */ + } + + } /* fin trt deport */ + ptcentre = ptcentre->suiv; + + } /* fin trt centre */ + + /*--------------- TRT DES DEPORTS GAUCHE EN DEHORS DE FACE COEUR -------------------- */ + + liste_plots = tab_plots[face].lst_con; + piste = pistederniere - 2; /* on laisse une piste pour les deports */ + + while ((liste_plots != NULL) && ((liste_plots->coord)->yabs < (lecoeur.coord).yabs)) { + if (liste_plots->deport->piste == 1) + pistelayergauche = 1; + /* ds ts les cas deport */ + + liste_plots->situe_deport = DEPORTG; + + if (mode_debug) + printf("deport gauche con %s %s\n", liste_plots->nom_con, ((loins_list * )(liste_plots->con_lo)->ROOT)->INSNAME); + + trouve = 0; + + ptcoor = tab_grilles[face].lst_pas; + while (ptcoor != NULL) { + trouve = (ptcoor->proprio == NULL); + if (trouve) + break; + ptcoor = ptcoor->suiv; + } + + if (trouve) { + ptcoor->piste = piste; + ptcoor->proprio = (void * ) liste_plots; + piste--; + liste_plots->deport = ptcoor; + } else + ringerreur(ERR_ECHECDEPORT, liste_plots, NULL); + liste_plots = liste_plots->suiv; + } + + /*------------------ TRT DES DEPORTS DROIT EN DEHORS FACE COEUR----------------------- */ + + ptqueue = tab_grilles[face].lst_pas; + while ((ptqueue != NULL) && (ptqueue->suiv != NULL)) + ptqueue = ptqueue->suiv; + + piste = pistederniere - 2; /* on laisse une piste pour les deports */ + + while ((ptdernier != NULL) && ((ptdernier->coord)->yabs > ((lecoeur.coord).yabs + lecoeur.height))) { + if (ptdernier->deport->piste == 1) + pistelayerdroite = 1; + + /* -------------------- */ + /* ds ts les cas deport */ + /* -------------------- */ + + ptdernier->situe_deport = DEPORTD; + + if (mode_debug) + printf("deport droite con %s %s\n", ptdernier->nom_con, ((loins_list * )(ptdernier->con_lo)->ROOT)->INSNAME); + + trouve = 0; + + ptcoor = ptqueue; + while (ptcoor != NULL) { + trouve = (ptcoor->proprio == NULL); + if (trouve) + break; + ptcoor = ptcoor->prec; + } + + if (trouve) { + ptcoor->piste = piste; + ptcoor->proprio = (void * ) ptdernier; + piste--; + ptdernier->deport = ptcoor; + } else + ringerreur(ERR_ECHECDEPORT, ptdernier, NULL); + + ptdernier = ptdernier->prec; + } + + /*----------------------- TRT DES CONCOEUR, DEPORT LAYER UNIQUEMENT ----------------- */ + + while (liste_coeur != NULL) { + if ((liste_coeur->deport != NULL) && (liste_coeur->nom_con != eq_vdd) && (liste_coeur->nom_con != + eq_vss)) /* changement layer */ { + liste_coeur->situe_deport = DEPORTC; + liste_coeur->deport->yabs = (liste_coeur->coord)->yabs; + if (liste_coeur->largeur > largeurmin) + (liste_coeur->deport)->piste = (liste_coeur->largeur + pitch) / pitch; + else + (liste_coeur->deport)->piste = 1; /* premiere piste pour deport layer */ + if (mode_debug) + printf("Deport layer concoeur %s piste %ld largeur %ld\n", liste_coeur->nom_con, + liste_coeur->deport->piste, liste_coeur->largeur); + } + liste_coeur = liste_coeur->suiv; + } + + break; + } /* fin du switch , ouf */ + + } /* fin du for */ +} + +/*-------------------------------------------------------------------------------------------------------*/ +/* Allocation des segments pour les deports. Pour les deports en face du coeur on reste */ +/* dans le meme metal */ +/* bug corrige dans le cas de deport en face du coeur: existe_sig_equipo ajoute */ +/* 14 sept 92: nouveau bug corrige: pour les deports en dehors du coeur */ +/* les segments pistes ne sont plus tires de la largeur du connecteur,(erreur avec nouv pad12 et pad 15) */ +/* mais de la largeur du via si plus grand que le minimum. */ +/*-------------------------------------------------------------------------------------------------------*/ + +void pose_segdeport(BARRE_PLOTS tab_plots[NB_FACES], + LST_PSEUDO_CON tab_coeur[NB_FACES], COEUR lecoeur, LST_EQUIPO lst_equipo, + LST_SEGMENT segx_occ[NB_FACES], LST_SEGMENT segy_occ[NB_FACES]) +{ + LST_EQUIPO eq; + LST_PSEUDO_CON lp, lc; + PT_COORDONNEES c1, c2, deb, fin; + long p1 = 0, p2 = 0, largmetalpiste = 0, largmetalcol = 0, largcolvia = 0, largpistevia = 0, piste = 0, largeurseg = 0; + int face; + char niveaucol = 0, niveaupiste = 0; + LST_SEGMENT * segcol = NULL; + LST_SEGMENT * segpiste = NULL; + + alloue_coord(0L, 0, &deb); /* coordonnees pour reserver la piste de deport du coeur */ + alloue_coord(0L, 0, &fin); + deb->xabs = lecoeur.coord.xabs - 10; + fin->xabs = lecoeur.width + lecoeur.coord.xabs + 10; + deb->yabs = lecoeur.coord.yabs - 10; + fin->yabs = lecoeur.height + lecoeur.coord.yabs + 10; + ; + + for (face = 0; face < NB_FACES; face++) { + lp = tab_plots[face].lst_con; + lc = tab_coeur[face]; + +#ifdef COMMENT + /* ----------------------------------------------------------------- */ + /* init mises dans deport alim au lieu d'ici (pour deport plot alim) */ + /* ----------------------------------------------------------------- */ + + segx_occ[face] = NULL; /* INITIALISATION DES SEGMENTS */ + segy_occ[face] = NULL; +#endif + + switch (face) { + case NORD: + case SUD : + niveaucol = ymetal; + largcolvia = ymetal_wvia; + largmetalcol = ymetal_width; + niveaupiste = xmetal; + largmetalpiste = xmetal_width; + largpistevia = xmetal_wvia; + segcol = segy_occ; + segpiste = segx_occ; + break; + case EST : + case OUEST: + niveaucol = xmetal; + largcolvia = xmetal_wvia; + largmetalcol = xmetal_width; + niveaupiste = ymetal; + largmetalpiste = ymetal_width; + largpistevia = ymetal_wvia; + segcol = segx_occ; + segpiste = segy_occ; + break; + } + + while (NULL != lp) { + if ((NULL != lp->deport) && (lp->nom_con != eq_vdd) && (lp->nom_con != eq_vss)) { + + /* ------------- */ + /* trt du deport */ + /* ------------- */ + + if ((DEPORTG == lp->situe_deport) || (DEPORTD == lp->situe_deport)) { /* DEPORT GAUCHE OU DROIT */ + + eq = existe_sig_equipo(lst_equipo, ((lp->con_lo)->SIG)->INDEX); + if (NULL == eq) + ringerreur(ERR_INTERNE_EQ, NULL, NULL); + + if (lp->layer != niveaucol) { /* deport layer d'abord */ + c1 = c2 = lp->coord; /* segment col */ + p2 = (tab_plots[face].coord).piste; + p1 = p2 - 1; /* 1 piste pour dep layer */ + + if (segment_libre(c1, c2, p1, p2, face, SEG_COL, segcol, lp->layer)) + alloue_etchaine_segment(c1, c2, p1, p2, face, SEG_COL, segcol, lp->largeur, + lp->layer, VRAI_SEG, AVEC_VIA, eq); + else + ringerreur(ERR_SEGDEPORT, (void * )lp, NULL); + + /* ---------------------------- */ + /* ensuite seg col ds bon layer */ + /* ---------------------------- */ + + p2 = p1; + p1 = (lp->deport)->piste; + + if (lp->largeur > largcolvia) + largeurseg = largcolvia; + else if (lp->largeur < largmetalcol) + largeurseg = largmetalcol; + else + largeurseg = lp->largeur; + + if (segment_libre(c1, c2, p1, p2, face, SEG_COL, segcol, niveaucol)) + alloue_etchaine_segment(c1, c2, p1, p2, face, SEG_COL, segcol, largeurseg, + niveaucol, VRAI_SEG, AVEC_VIA, eq); + else + ringerreur(ERR_SEGDEPORT, (void * )lp, NULL); + } else + { /* seg col tire */ + c1 = c2 = lp->coord; /* segment col */ + p2 = (tab_plots[face].coord).piste; + p1 = (lp->deport)->piste; + + if (segment_libre(c1, c2, p1, p2, face, SEG_COL, segcol, lp->layer)) + alloue_etchaine_segment(c1, c2, p1, p2, face, SEG_COL, segcol, lp->largeur, + lp->layer, VRAI_SEG, AVEC_VIA, eq); + else + ringerreur(ERR_SEGDEPORT, (void * )lp, NULL); + } + + /* -------------- */ + /* seg piste tire */ + /* -------------- */ + + c1 = lp->coord; + c2 = lp->deport; + + p1 = p2 = (lp->deport)->piste; + + if (lp->largeur > largpistevia) + largeurseg = largpistevia; + else if (lp->largeur < largmetalpiste) + largeurseg = largmetalpiste; + else + largeurseg = lp->largeur; + + if (segment_libre(c1, c2, p1, p2, face, SEG_PISTE, segpiste, niveaupiste)) + alloue_etchaine_segment(c1, c2, p1, p2, face, SEG_PISTE, segpiste, largeurseg, + niveaupiste, VRAI_SEG, AVEC_VIA, eq); + else + ringerreur(ERR_SEGDEPORT, (void * )lp, NULL); + } else /* DEPORT DANS EN FACE DU COEUR */ { + + eq = existe_sig_equipo(lst_equipo, ((lp->con_lo)->SIG)->INDEX); + if (NULL == eq) + ringerreur(ERR_INTERNE_EQ, NULL, NULL); + + /* ------------ */ + /* seg col tire */ + /* ------------ */ + + c1 = c2 = lp->coord; /* segment col */ + p2 = (tab_plots[face].coord).piste; + p1 = (lp->deport)->piste; + + if (segment_libre(c1, c2, p1, p2, face, SEG_COL, segcol, lp->layer)) + alloue_etchaine_segment(c1, c2, p1, p2, face, SEG_COL, segcol, lp->largeur, + lp->layer, VRAI_SEG, AVEC_VIA, eq); + else + ringerreur(ERR_SEGDEPORT, (void * )lp, NULL); + + /* -------------- */ + /* seg piste tire */ + /* -------------- */ + + c1 = lp->coord; + c2 = lp->deport; + + p1 = p2 = (lp->deport)->piste; + + /* ------------------------------- */ + /* LES 2 SEGMENTS DS LE MEME METAL */ + /* ------------------------------- */ + + if (segment_libre(c1, c2, p1, p2, face, SEG_PISTE, segpiste, lp->layer)) + alloue_etchaine_segment(c1, c2, p1, p2, face, SEG_PISTE, segpiste, lp->largeur, + lp->layer, VRAI_SEG, AVEC_VIA, eq); + else + ringerreur(ERR_SEGDEPORT, (void * )lp, NULL); + } + } /* fin du if deport */ + + lp = lp->suiv; + } /* fin du while */ + + while (NULL != lc) { + if ((NULL != lc->deport) && (lc->nom_con != eq_vdd) && (lc->nom_con != eq_vss)) { /* deport layer uniquement */ + eq = existe_sig_equipo(lst_equipo, ((lc->con_lo)->SIG)->INDEX); + if (NULL == eq) + ringerreur(ERR_INTERNE_EQ, NULL, NULL); + + c1 = c2 = lc->coord; /* segment col */ + p2 = lc->deport->piste; /* piste pour deport coeur */ + p1 = 0; + + /* ------------------------------------------------------------------ */ + /* Allocation d'un faux segment au cas ou il existe des deports coeur */ + /* pour empecher de router dans la piste reservee au deport */ + /* ------------------------------------------------------------------ */ + + if (segment_libre(deb, fin, 1L, 1L, face, SEG_PISTE, segpiste, niveaupiste)) + alloue_etchaine_segment(deb, fin, 1L, 1L, face, SEG_PISTE, segpiste, lc->largeur, + niveaupiste, FAUX_SEG, AVEC_VIA, eq); + + /* ---------------------------------------------------- */ + /* Allocations de faux segments si largeur non standard */ + /* ---------------------------------------------------- */ + + if (p2 > 1) { + for (piste = 2; piste <= (p2 + (lc->largeur / 2 + pitch) / pitch); piste++) + alloue_etchaine_segment(c1, c2, piste, piste, face, SEG_PISTE, segpiste, + largmetalpiste, niveaupiste, FAUX_SEG, AVEC_VIA, eq); + } + + if (segment_libre(c1, c2, p1, p2, face, SEG_COL, segcol, lc->layer)) + alloue_etchaine_segment(c1, c2, p1, p2, face, SEG_COL, segcol, lc->largeur, lc->layer, + VRAI_SEG, AVEC_VIA, eq); + else + ringerreur(ERR_SEGDEPORT, (void * )lc, NULL); + } + lc = lc->suiv; + } + } /* fin du for */ +} diff --git a/alliance/src/ring/src/deport.h b/alliance/src/ring/src/deport.h new file mode 100644 index 00000000..cfcb3c1b --- /dev/null +++ b/alliance/src/ring/src/deport.h @@ -0,0 +1,21 @@ +#ifndef __DEPORT_H +#define __DEPORT_H + +#include "struct.h" + +extern void attribuer_couronne_alim(LST_EQUIPO lst_equipo, char **coursup, char **courinf); +extern char* existe_unique_deport_alim(LST_EQUIPO equipo_vdd, LST_EQUIPO equipo_vss); + +extern void deport_alim(LST_EQUIPO lst_equipo, BARRE_PLOTS tab_plots[NB_FACES], + char *coursup, char *courinf, LST_SEGMENT segx_occ[NB_FACES], + LST_SEGMENT segy_occ[NB_FACES]); + +void deport_connecteurs(BARRE_PLOTS tab_plots[NB_FACES], + LST_PSEUDO_CON tab_coeur[NB_FACES], + COEUR lecoeur, GRILLE tab_grilles[NB_FACES]); + +void pose_segdeport(BARRE_PLOTS tab_plots[NB_FACES], + LST_PSEUDO_CON tab_coeur[NB_FACES], COEUR lecoeur, LST_EQUIPO lst_equipo, + LST_SEGMENT segx_occ[NB_FACES], LST_SEGMENT segy_occ[NB_FACES]); + +#endif /* __DEPORT_H */ diff --git a/alliance/src/ring/src/distance.c b/alliance/src/ring/src/distance.c new file mode 100644 index 00000000..5835a746 --- /dev/null +++ b/alliance/src/ring/src/distance.c @@ -0,0 +1,323 @@ +/* + * 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 support : mailto:alliance-support@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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +/****************************************************************************/ +/* */ +/* Chaine de CAO & VLSI Alliance */ +/* */ +/* Produit : ring router */ +/* Fichier : distance.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 19 aout 92 DISTANCE.C */ +/*--------------------------------------------------------------------------*/ + +#include "distance.h" + +#include +#include + +/*-----------------------------------------------------------------------------------*/ +/* Calcul de la distance entre deux connecteurs */ +/* Si un des connecteurs n'est pas de largeur standard, on calcul la distance reelle.*/ +/* A ce moment on prend en compte l'encombrement d'un via */ +/* S'ils sont de largeur standard alors la distance est la diff des coordonnees */ +/*-----------------------------------------------------------------------------------*/ + +long distance_con_con(long x1, long y1, long w1, char l1, + long x2, long y2, long w2, char l2, int face) +{ + long dist, xa, ya, wa; + long largeurmin, dminmetalmetal; + char la; + + switch (face) { + case NORD: + case SUD : + + /* ------------------------------------------------- */ + /* on garde dans x1 ,y1 les plus petites coordonnees */ + /* ------------------------------------------------- */ + + if (x2 < x1) { + xa = x1; + ya = y1; + wa = w1; + la = l1; + x1 = x2; + y1 = y2; + w1 = w2; + l1 = l2; + x2 = xa; + y2 = ya; + w2 = wa; + l2 = la; + } + + dminmetalmetal = ymetal_dmin; + + if ((l1 != ymetal) || (l2 != ymetal)) { + if (ymetal_width < xmetal_width) + largeurmin = ymetal_width; + else + largeurmin = xmetal_width; + } else + { + largeurmin = ymetal_width; + } + + if ((w1 > largeurmin) || (w2 > largeurmin)) { + dist = x2 - x1 - w2 / 2 - w1 / 2; + if ((w1 < taille_via) && (w2 < taille_via)) + dist -= (taille_via - w1 / 2 - w2 / 2); + else if ((w1 < taille_via) && !(w2 < taille_via)) + dist -= (taille_via / 2 - w1 / 2); + else if (!(w1 < taille_via) && (w2 < taille_via)) + dist -= (taille_via / 2 - w2 / 2); + } else + dist = x2 - x1; + + return(dist); + + case EST : + case OUEST: + + /* ------------------------------------------------- */ + /* on garde dans x1 ,y1 les plus petites coordonnees */ + /* ------------------------------------------------- */ + + if (y2 < y1) { + xa = x1; + ya = y1; + wa = w1; + la = l1; + x1 = x2; + y1 = y2; + w1 = w2; + l1 = l2; + x2 = xa; + y2 = ya; + w2 = wa; + l2 = la; + } + + dminmetalmetal = xmetal_dmin; + + if ((l1 != xmetal) || (l2 != xmetal)) { + if (ymetal_width < xmetal_width) + largeurmin = ymetal_width; + else + largeurmin = xmetal_width; + } else + { + largeurmin = xmetal_width; + } + + if ((w1 > largeurmin) || (w2 > largeurmin)) { + dist = y2 - y1 - w2 / 2 - w1 / 2; + if ((w1 < taille_via) && (w2 < taille_via)) + dist -= (taille_via - w1 / 2 - w2 / 2); + else if ((w1 < taille_via) && !(w2 < taille_via)) + dist -= (taille_via / 2 - w1 / 2); + else if (!(w1 < taille_via) && (w2 < taille_via)) + dist -= (taille_via / 2 - w2 / 2); + } else + dist = y2 - y1; + + return(dist); + } + return 0; +} + +/*-----------------------------------------------------------------------------------------*/ +/* Cette fonction utilisee pour la fabrication de nouveaux pas de grille */ +/* parcoure toutes les coordonnees precedentes correspondant a des pseudo-connecteurs */ +/* pour donner la distance minimum qu'il existe entre le connecteur */ +/* et les connecteurs precedents d'alim. Ceci pour corriger un bug */ +/* qui vient du fait que des alim peuvent etre en vis a vis et que */ +/* si on calcule seulement la distance avec le connecteur precedent */ +/* on ne prend peut etre pas en compte un connecteur d'alim voisin */ +/* plus gros qui recouvre largement le connecteur precedent. */ +/* on retourne une coordonnee qui est soit la precedente soit */ +/* une autre qui rcouvre la coordonne precedente */ +/*-----------------------------------------------------------------------------------------*/ + +PT_COORDONNEES existe_con_precalim(long x2, long y2, long w2, char l2, int face, + PT_COORDONNEES liste_coor, long distance) +{ + long mindist = distance; + long dist; + LST_PSEUDO_CON con; + PT_COORDONNEES coordalim = NULL; + + if (mode_debug) + printf("Existeprecalim x %ld y %ld face %d ptcoor %d\n\n", x2, y2, face, (int)liste_coor); + + switch (face) { + case NORD: + case SUD: + while (NULL != liste_coor) { + if ((NULL != liste_coor->proprio) && ((eq_vdd == ((LST_PSEUDO_CON)liste_coor->proprio)->nom_con) || + (eq_vss == ((LST_PSEUDO_CON)liste_coor->proprio)->nom_con)) && (liste_coor->xabs < x2)) { + con = ((LST_PSEUDO_CON)liste_coor->proprio); + dist = distance_con_con(liste_coor->xabs, liste_coor->yabs, con->largeur, con->layer, x2, + y2, w2, l2, face); + + if (dist < mindist) { + mindist = dist; + coordalim = liste_coor; + } + } + + if (liste_coor->xabs >= x2) + break; + else + liste_coor = liste_coor->suiv; + } + + return(coordalim); + + break; + + case EST: + case OUEST: + while (NULL != liste_coor) { + if ((NULL != liste_coor->proprio) && ((eq_vdd == ((LST_PSEUDO_CON)liste_coor->proprio)->nom_con) || + (eq_vss == ((LST_PSEUDO_CON)liste_coor->proprio)->nom_con)) && (liste_coor->yabs < y2)) { + con = ((LST_PSEUDO_CON)liste_coor->proprio); + dist = distance_con_con(liste_coor->xabs, liste_coor->yabs, con->largeur, con->layer, x2, + y2, w2, l2, face); + + if (dist < mindist) { + mindist = dist; + coordalim = liste_coor; + } + } + + if (liste_coor->yabs >= y2) + break; + else + liste_coor = liste_coor->suiv; + } + + return(coordalim); + } + return NULL; +} + +/*-----------------------------------------------------------------------------------------*/ +/* Cette fonction utilisee pour la fabrication de nouveaux pas de grille */ +/* parcoure toutes les coordonnees suivantes correspondant a des pseudo-connecteurs */ +/* pour donner la distance minimum qu'il existe entre le connecteur */ +/* et les connecteurs suivants d'alim. Ceci pour corriger un bug */ +/* qui vient du fait que des alim peuvent etre en vis a vis et que */ +/* si on calcule seulement la distance avec le connecteur suivant */ +/* on ne prend peut etre pas en compte un connecteur d'alim voisin */ +/* plus gros qui recouvre largement le connecteur precedent. */ +/* on retourne une coordonnee soit la precedente soit une autre qui */ +/* recouvre la precedente. */ +/*-----------------------------------------------------------------------------------------*/ + +PT_COORDONNEES existe_con_suiv(long x1, long y1, long w1, char l1, + int face, PT_COORDONNEES liste_coor) +{ + long mindist = 0; + int first = 1; + long dist; + LST_PSEUDO_CON con; + PT_COORDONNEES coordalim = NULL; + + if (mode_debug) + printf("Existesuivalim x %ld y %ld face %d ptcoor %d\n\n", x1, y1, face, (int)liste_coor); + + switch (face) { + case NORD: + case SUD: + while (NULL != liste_coor) { + if (mode_debug) + printf("ptcoor %d proprio %d x %ld\n", (int) liste_coor, (int)liste_coor->proprio, liste_coor->xabs); + + if (NULL != liste_coor->proprio) { + con = ((LST_PSEUDO_CON)liste_coor->proprio); + dist = distance_con_con(x1, y1, w1, l1, liste_coor->xabs, liste_coor->yabs, con->largeur, + con->layer, face); + + if (first) { + mindist = dist; + first = 0; + coordalim = liste_coor; + } else if (dist < mindist) { + mindist = dist; + coordalim = liste_coor; + } + if (mode_debug) + printf("ptcoordalim %d\n", (int) coordalim); + } + + liste_coor = liste_coor->suiv; + } + + return(coordalim); + + break; + + case EST: + case OUEST: + while (NULL != liste_coor) { + if (mode_debug) + printf("ptcoor %d proprio %d x %ld\n", (int) liste_coor, (int)liste_coor->proprio, liste_coor->yabs); + + if (NULL != liste_coor->proprio) { + con = ((LST_PSEUDO_CON)liste_coor->proprio); + dist = distance_con_con(x1, y1, w1, l1, liste_coor->xabs, liste_coor->yabs, con->largeur, + con->layer, face); + + if (first) { + mindist = dist; + first = 0; + coordalim = liste_coor; + } else if (dist < mindist) { + mindist = dist; + coordalim = liste_coor; + } + if (mode_debug) + printf("ptcoordalim %d\n", (int) coordalim); + } + + liste_coor = liste_coor->suiv; + } + + return(coordalim); + } + return NULL; +} diff --git a/alliance/src/ring/src/distance.h b/alliance/src/ring/src/distance.h new file mode 100644 index 00000000..ce94d0c0 --- /dev/null +++ b/alliance/src/ring/src/distance.h @@ -0,0 +1,15 @@ +#ifndef __DISTANCE_H +#define __DISTANCE_H + +#include "struct.h" + +extern long distance_con_con(long x1, long y1, long w1, char l1, + long x2, long y2, long w2, char l2, int face); + +PT_COORDONNEES existe_con_precalim(long x2, long y2, long w2, char l2, int face, + PT_COORDONNEES liste_coor, long distance); + +extern PT_COORDONNEES existe_con_suiv(long x1, long y1, long w1, char l1, + int face, PT_COORDONNEES liste_coor); + +#endif /* __DISTANCE_H */ diff --git a/alliance/src/ring/src/lireplace.c b/alliance/src/ring/src/lireplace.c new file mode 100644 index 00000000..313a8d39 --- /dev/null +++ b/alliance/src/ring/src/lireplace.c @@ -0,0 +1,401 @@ +/* + * 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 support : mailto:alliance-support@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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/****************************************************************************/ +/* */ +/* Chaine de CAO & VLSI Alliance */ +/* */ +/* Produit : ring router */ +/* Fichier : lireplace.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 29 avril 92 LIREPLACE.C */ +/* PHASE 3 */ +/* */ +/* Lecture du fichier de placement afin de connaitre les plots, leur orientation, */ +/* ainsi que les signaux de largeur specifique. */ +/* */ +/* Pour la lecture et l'interpretation du fichier les outils lex et yacc sont */ +/* utilises */ +/*-----------------------------------------------------------------------------------*/ + +#include + +#include "lireplace.h" +#include "sesame.h" + +/*-----------------------------------------------------------------------------------*/ +/* Lecture et verification du fichier de parametres , suffixe .rin. Lancement de */ +/* l'analyseur syntaxique */ +/*-----------------------------------------------------------------------------------*/ + +void lecture_fic(char *nomfic, lofig_list *circuit_lo, + COEUR lecoeur, int nb_inst_plots) +{ + FILE * fichier; + long longueur; + chain_list * liste; + int i, cpt_liste = 0, cpt_plots = 0, larg_con; + char *nom_du_plot, *nom_con; + loins_list * ptinst; + + /* ------------------------------------------------------------------------- */ + /* Ouverture et verification du fichier de parametre (existence et longueur) */ + /* ------------------------------------------------------------------------- */ + + if ((fichier = mbkfopen(nomfic, NULL, READ_TEXT)) == NULL) + ringerreur(ERR_FICPARAM, nomfic, NULL); + + if (fseek(fichier, (long)0, SEEK_END)) + ringerreur(ERR_FICPARAM, nomfic, NULL); + + if ((longueur = ftell(fichier)) == -1) + ringerreur(ERR_FICPARAM, nomfic, NULL); + + if (longueur == 0) + ringerreur(ERR_VIDEFICPARAM, nomfic, NULL); + + fclose(fichier); + + if (mode_debug) + printf("Longueur fichier parametres: %ld\n", longueur); + + for (i = 0; i < NB_FACES; i++) + nom_plot[i] = NULL; + + liste_width = NULL; /* Initialisations des listes globales utilisees + par lex et yacc */ + + if (mode_debug) + printf("Avant analyse lex et yacc \n"); + + yyin = mbkfopen(nomfic, NULL, READ_TEXT); + + /* ------------------------------------------------------------------ */ + /* lancement de lex et yacc pour interpreter le fichier de parametres */ + /* ------------------------------------------------------------------ */ + + yyparse(); + if (mode_debug) + printf("Apres analyse lex et yacc\n"); + + /* ------------------------------------------------------------------ */ + /* inversion des listes pour respecter l'ordre du placement des plots */ + /* verification de la coherence des informations receuillies */ + /* ------------------------------------------------------------------ */ + + for (i = 0; i < NB_FACES; i++) { + nom_plot[i] = reverse(nom_plot[i]); + if (nom_plot[i] != NULL) + cpt_liste++; + } + + if (!cpt_liste) + ringerreur(ERR_AUCUNPLOTPARAM, NULL, NULL); + + /* -------------------------------------------------------------------------- */ + /* parcours des noms d'instances des plots et verif si existent ds circuit_lo */ + /* -------------------------------------------------------------------------- */ + + for (i = 0; i < NB_FACES; i++) { + if (mode_debug) + printf("---------numero face :%d\n", i); + + liste = nom_plot[i]; + + /*--------------------------------------------------------------------------- */ + /* De part la modification des chain_list de nom_plot, je verifie d'abord sur */ + /* l'ancienne structure (noms uniquement) qu'il y a une seule occurrence */ + /*--------------------------------------------------------------------------- */ + + while (liste != NULL) { + nom_du_plot = (char *)(liste->DATA); + if (mode_debug) + printf("VERIF nom plot: --%s--\n", nom_du_plot); + + /* ---------------------------------------------------- */ + /* une seule occurence dans la liste des faces de plots */ + /* ---------------------------------------------------- */ + + if (!uneseuleoccurence(nom_du_plot, nom_plot)) + ringerreur(ERR_PLUSPLOTPARAM, nom_du_plot, NULL); + + liste = liste->NEXT; + } + + liste = nom_plot[i]; + + while (liste != NULL) { + nom_du_plot = (char *)(liste->DATA); + if (mode_debug) + printf("VERIF nom plot: --%s--\n", nom_du_plot); + + /* --------------------------------------------------- */ + /* existence du plot dans la liste du circuit logique */ + /* --------------------------------------------------- */ + + if ((ptinst = existe_plot_circuit(nom_du_plot, circuit_lo)) == NULL) + ringerreur(ERR_NONPLOTPARAM, nom_du_plot, NULL); + + else /* Chain_list modifiee pointe maintenant sur l'instance logique */ + liste->DATA = (void * ) ptinst; + + cpt_plots++; + + liste = liste->NEXT; + } + } + + if (cpt_plots != nb_inst_plots) + ringerreur(ERR_NBPLOTPARAM, circuit_lo, NULL); + + liste = liste_width; + if (mode_debug) + printf("VERIF Liste width\n"); + + /* --------------------------------------------------------------- */ + /* verification sur la liste des connecteurs de largeur specifique */ + /* --------------------------------------------------------------- */ + + while (liste != NULL) { + nom_con = ((PTCEL)(liste->DATA))->chaine; + larg_con = ((PTCEL)(liste->DATA))->largeur; + if (mode_debug) + printf("Connecteur --%s-- largeur %d\n", nom_con, larg_con); + + /* -------------------------------------------------------------------------- */ + /* existence du connecteur dans la liste des connecteurs logiques du circuit */ + /* -------------------------------------------------------------------------- */ + + if (!existe_signal_circuit(liste, circuit_lo, lecoeur)) + ringerreur(ERR_NONCONWIDTHPARAM, nom_con, NULL); + + if (larg_con < SCALE_X) + ringerreur(ERR_WIDTHPARAM, (void * )nom_con, (void * ) & larg_con); + + liste = liste->NEXT; + } + +} + +/*-----------------------------------------------------------------------------------*/ +/* Erreur dans la syntaxe du fichier de parametre */ +/*-----------------------------------------------------------------------------------*/ + +void +yyerror(s) +char *s; +{ + ringerreur(ERR_SYNPARAM, NULL, NULL); +} + +/*-----------------------------------------------------------------------------------*/ +/* Fabrication de la liste des equipotentielles a partir de la vue logique du coeur */ +/* et circuit */ +/*-----------------------------------------------------------------------------------*/ + +void fabrique_equipo(chain_list *nomplot[NB_FACES], COEUR lecoeur, + LST_EQUIPO *lst_equipo, chain_list *liste_plotsph) +{ + + locon_list * pt_coeur, *tete_coeur, *con_coeur = (lecoeur.coeur_lo)->LOCON ; + locon_list * con_plot, *liste_con, *liste_con2; + losig_list * sig_coeur; + loins_list * plot, *plot2; + int face, i, j, signal_ok; + chain_list * liste_plots, *liste_plots2; + LST_EQUIPO liste, pt_eq; + + (*lst_equipo) = NULL; + + if (mode_debug) + printf("Fabrication des equipo\n"); + + /* ------------------------- */ + /* boucle des locon du coeur */ + /* ------------------------- */ + + while (con_coeur != NULL) { + sig_coeur = con_coeur->SIG; /* un signal unique par connecteur */ + if (mode_debug) + printf("pointeur Sigcoeur %d\n", (int) sig_coeur); + if (mode_debug) + printf("*******NOM concoeur %s signal %ld*********\n", con_coeur->NAME, sig_coeur->INDEX); + + /* ---------------------------- */ + /* Parcours des instances plots */ + /* ---------------------------- */ + + for (face = 0; face < NB_FACES; face++) { + + liste_plots = nomplot[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_coeur */ + /* ----------------------------------------------------------------------------------------------------------- */ + + if (mode_debug) printf("PLOT %s de la face %d\n",plot->INSNAME,face); + + if ((con_plot = existe_sig_plot(sig_coeur, plot, liste_plotsph)) != NULL) { + maj_equipo(con_coeur, con_plot, lst_equipo, COEUR_PLOT); + } + + liste_plots = liste_plots->NEXT; + } /* fin parcours instances plots d'une face */ + + } /* fin de parcours de toutes les faces */ + + con_coeur = con_coeur->NEXT; + + } /* fin de parcours des con du coeur */ + + /*------------------------- equipo PLOT_PLOT -----------------------------------------*/ + + for (i = 0; i < NB_FACES; i++) { + liste_plots = nomplot[i]; + while (liste_plots != NULL) { + + plot = (loins_list * ) liste_plots->DATA; + liste_con = plot->LOCON; + + while (liste_con != NULL) { + pt_eq = existe_sig_equipo((*lst_equipo), (liste_con->SIG)->INDEX); + signal_ok = ((pt_eq == NULL) || (pt_eq->type == PLOT_PLOT)); + + if ((signal_ok) + && existe_leconnecteur_faceplot(plot->FIGNAME, liste_con->NAME, SUD, liste_plotsph)){ + for (j = 0; j < NB_FACES; j++) { + liste_plots2 = nomplot[j]; + + while (liste_plots2 != NULL) { + plot2 = (loins_list * ) liste_plots2->DATA; + liste_con2 = plot2->LOCON; + + while (liste_con2 != NULL) { + if (existe_leconnecteur_faceplot(plot->FIGNAME, liste_con->NAME, SUD, liste_plotsph) + && (liste_con2 != liste_con) + && ((liste_con->SIG)->INDEX == (liste_con2->SIG)->INDEX)) { + if (mode_debug) + printf("TROUVE liste_con ->%s *** %s\n", liste_con->NAME, liste_con2->NAME); + maj_equipo(liste_con, liste_con2, lst_equipo, PLOT_PLOT); + } + liste_con2 = liste_con2->NEXT; + } + liste_plots2 = liste_plots2->NEXT; + } + } /* ffin du for */ + } /* fin du if */ + liste_con = liste_con->NEXT; + } + liste_plots = liste_plots->NEXT; /* fin du while */ + } + + } /* fin du 1er for */ + + /*-------------------- equipo de type COEUR_COEUR ----------------------------------*/ + + tete_coeur = con_coeur = (lecoeur.coeur_lo)->LOCON; + + while (con_coeur != NULL) { + pt_eq = existe_sig_equipo((*lst_equipo), (con_coeur->SIG)->INDEX); + signal_ok = ((pt_eq == NULL) || (pt_eq->type == COEUR_COEUR)); + + pt_coeur = tete_coeur; + if (signal_ok) + + while (pt_coeur != NULL) { + if ((pt_coeur != con_coeur) && ((con_coeur->SIG)->INDEX == (pt_coeur->SIG)->INDEX)) + maj_equipo(con_coeur, pt_coeur, lst_equipo, COEUR_COEUR); + + pt_coeur = pt_coeur->NEXT; + } + con_coeur = con_coeur->NEXT; + } + + /*-----------------------------------------------------------------------------------*/ + /* on inverse les chain list de pseudo connecteurs associes a chaque equipo, */ + /* ce qui a pour but de mettre le connecteur du coeur en tete de liste */ + /*-----------------------------------------------------------------------------------*/ + + liste = (*lst_equipo); + + while (liste != NULL) { + liste->lst_con = reverse(liste->lst_con); + liste = liste->suiv; + } + +} + +/*-----------------------------------------------------------------------------------*/ +/* Parcours des connecteurs de plots et des signaux associes */ +/* Retourne le connecteur si signal identique */ +/*-----------------------------------------------------------------------------------*/ + +locon_list *existe_sig_plot(losig_list *sig_coeur, loins_list *plot, + chain_list *liste_plotsph) +{ + + locon_list * con_plot = plot->LOCON; + losig_list * sig_plot; + + if (mode_debug) printf("Existe sig_plot\n"); + + /* -------------------------------- */ + /* Parcours des connecteurs du plot */ + /* -------------------------------- */ + + while (con_plot != NULL) { + + if (mode_debug) + printf("\tpointeur nom %d\n",(int)con_plot); + + sig_plot = con_plot->SIG; /* un signal unique par connecteur */ + + if (mode_debug) + printf("\tnom conplot %s signal %ld sigcoeur %ld\n",con_plot->NAME,sig_plot->INDEX, sig_coeur->INDEX); + + if (sig_plot->INDEX == sig_coeur->INDEX) + if ( ( !isvdd(con_plot->NAME) && !isvss(con_plot->NAME) ) + || ( ( isvdd(con_plot->NAME) || isvss(con_plot->NAME) ) + && ( existe_leconnecteur_faceplot(plot->FIGNAME, con_plot->NAME, SUD, liste_plotsph) + || existe_leconnecteur_faceplot(plot->FIGNAME, con_plot->NAME, NORD, liste_plotsph)))) + return(con_plot); + + con_plot = con_plot->NEXT; + } + + return(NULL); +} diff --git a/alliance/src/ring/src/lireplace.h b/alliance/src/ring/src/lireplace.h new file mode 100644 index 00000000..0eca82d0 --- /dev/null +++ b/alliance/src/ring/src/lireplace.h @@ -0,0 +1,14 @@ +#ifndef __LIREPLACE_H +#define __LIREPLACE_H + +#include "struct.h" + +extern void lecture_fic(char *nomfic, lofig_list *circuit_lo, + COEUR lecoeur, int nb_inst_plots); +extern void fabrique_equipo(chain_list *nomplot[NB_FACES], COEUR lecoeur, + LST_EQUIPO *lst_equipo, chain_list *liste_plotsph); + +extern locon_list *existe_sig_plot(losig_list *sig_coeur, loins_list *plot, + chain_list *liste_plotsph); + +#endif /* __LIREPLACE_H */ diff --git a/alliance/src/ring/src/lirevues.c b/alliance/src/ring/src/lirevues.c new file mode 100644 index 00000000..59bf33a9 --- /dev/null +++ b/alliance/src/ring/src/lirevues.c @@ -0,0 +1,317 @@ +/* + * 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 support : mailto:alliance-support@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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/****************************************************************************/ +/* */ +/* Chaine de CAO & VLSI Alliance */ +/* */ +/* Produit : ring router */ +/* Fichier : lirevues.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 28 juillet 92 LIREVUES.C */ +/* PHASE 2 */ +/* */ +/* Lecture des vues structurelles (circuit, coeur) et physiques (coeur, et chargement des */ +/* plots */ +/* Modif: suite a l'abandon d'utiliser des plots de fils, mais plutot tirer directement */ +/* les fils, on verifie les modeles de plots physiques / con est <=> con ouest */ +/*----------------------------------------------------------------------------------------*/ + +#include + +#include "lirevues.h" +#include "sesame.h" + +/*--------------------------------------------------------------------------------*/ +/* Lors d ela lecture des modeles physiques des plots, on renomme les connecteurs */ +/* vdd* et vss* en vdd et vss, sauf pour les connecteurs nord, car il s'agit */ +/* de vdde ou vsse (alim de plots) a ne pas confondre avec alim de coeur */ +/*--------------------------------------------------------------------------------*/ + +void lecture_vues(char *nom_circuit_lo, COEUR *lecoeur, lofig_list **circuit_lo, + chain_list **liste_plotsph, int *nbplots, chain_list **lst_conestouest) +{ + chain_list * lstph; + phfig_list * ptfig; + loins_list * circuit_inst; /* instances dans le circuit logique */ + loins_list * coeur_inst = NULL; /* instance du coeur */ + int nbcoeur = 0; /* nombres d'instances susceptibles d'etre le coeur */ + int retour; + + *circuit_lo = getlofig(nom_circuit_lo, 'A'); + + if (!(*circuit_lo)) + ringerreur(ERR_CIRCUITLO, nom_circuit_lo, NULL); + + /* viewlo(); */ + + circuit_inst = (*circuit_lo)->LOINS; + + if (!circuit_inst) + ringerreur(ERR_CIRCUITINST, nom_circuit_lo, NULL); + + /* ---------------------------------------------------------------------------------------------------------- */ + /* test la coherences des modeles logiques et physiques de toutes les modeles utilisee dans la figure logique */ + /* ---------------------------------------------------------------------------------------------------------- */ + + testcon_modelfig(*circuit_lo); + + /* ------------------------------------------------------------------------------------------------------------- */ + /* Parcours des instances pour distinguer celles qui sont des plots et les autres (normalement 1 seule: le coeur */ + /* ------------------------------------------------------------------------------------------------------------- */ + + *nbplots = 0; + + (*liste_plotsph) = NULL; /* Initialisation de la liste de plots physiques */ + + while (circuit_inst != NULL) { + retour = incatalog(circuit_inst->FIGNAME); + if (mode_debug) + printf("FIGNAME %s incatalog %d\n", circuit_inst->FIGNAME, retour); + + if (retour) { + (*nbplots)++; + + /* -------------------------------------- */ + /* Renommage des connecteurs vdd* et vss* */ + /* -------------------------------------- */ + + ajout_listeplotsph(circuit_inst->FIGNAME, liste_plotsph); + } else /* le coeur est reconnu */ { + nbcoeur++; + coeur_inst = circuit_inst; + } + + circuit_inst = circuit_inst->NEXT; + } + + if (mode_debug) + printf("Lirevues: nb inst plots %d\n", *nbplots); + + /* -------------------------------------------- */ + /* Verification sur le nombres de coeur trouves */ + /* -------------------------------------------- */ + + switch (nbcoeur) { + case 0: + ringerreur(ERR_NONCOEUR, NULL, NULL); /* aucun => ringerreur */ + break; + + case 1: + /* ------------------------------------------------------ */ + /* un seul coeur, on charge les vues logique et physique */ + /* ------------------------------------------------------ */ + + (*lecoeur).coeur_lo = coeur_inst; + if ((*lecoeur).coeur_lo == NULL) + ringerreur(ERR_COEURINSTLO, coeur_inst->FIGNAME, NULL); + + ptfig = (*lecoeur).coeur_ph = getphfig(coeur_inst->FIGNAME, 'A'); + (*lecoeur).coord.xabs = 0; + (*lecoeur).coord.yabs = 0; /* Coordonnees du coeur fixees a 0,0 par defaut */ + (*lecoeur).width = ptfig->XAB2 - ptfig->XAB1; + (*lecoeur).height = ptfig->YAB2 - ptfig->YAB1; + (*lecoeur).coord.piste = 0; + + (*lecoeur).rotation = NOSYM; /* pas de rotation par defaut */ + + /* viewphfig((*lecoeur).coeur_ph); */ + + if ((*lecoeur).coeur_ph == NULL) + ringerreur(ERR_COEURINSTPH, coeur_inst->FIGNAME, NULL); + + break; + default: + /* ------------------------------------------ */ + /* plusieurs candidats au coeur => ringerreur */ + /* ------------------------------------------ */ + + ringerreur(ERR_PLUSCOEUR, (*circuit_lo)->LOINS, NULL); + } + + /* ----------------------------------------------------- */ + /* verification des modeles pour connexion alim internes */ + /* ----------------------------------------------------- */ + + lstph = *liste_plotsph; + + while (NULL != lstph) { + verif_con_estouest(lstph, lst_conestouest); + lstph = lstph->NEXT; + } + + if (mode_debug) + affic_listeplotsph(*liste_plotsph); + +} + +/*---------------------------------------------------------------------------------*/ +/* Verification du nombre de connecteurs de leur position en est et ouest des alim */ +/* internse des plots. Une liste resultat lst_conestouest est fabriquee qui */ +/* contient: */ +/* - une liste de couples , connecteur ouest et connecteur est de meme nom et meme */ +/* position */ +/* Cette liste servira a relier les plots entre eux et finir la couronne de plots */ +/* Modif: les connecteurs lateraux de plots etant renommes, on a des */ +/* connecteurs de mem nom et meme index; il faut alors renumeroter */ +/* les connecteurs (changement du champ INDEX dans tous les modeles */ +/* de plots physiques */ +/*---------------------------------------------------------------------------------*/ + +void verif_con_estouest(chain_list *liste_plotsph, chain_list **lst_conestouest) +{ + + static phfig_list *firstfig = NULL; + phfig_list * figcour; + phcon_list * lstcon, *con; + chain_list * lst, *lstwork; + static int cptest = 0, cptouest = 0; + int cptestcour = 0, cptouestcour = 0; + int index = 0; /* renumeroter les connecteurs physiques */ + + if (mode_debug) + printf("modele plot %s\n", ((phfig_list * )liste_plotsph->DATA)->NAME); + + if (NULL == liste_plotsph) + ringerreur(ERR_INTERNE_CON, NULL, NULL); + + if (NULL == firstfig) { + (*lst_conestouest ) = NULL; + firstfig = (phfig_list * ) liste_plotsph->DATA; + lstcon = firstfig->PHCON; + + while (NULL != lstcon) { + if ('W' == lstcon->ORIENT) { + cptouest++; + if (mode_debug) + printf("REFERENCE con plot %s\n", lstcon->NAME); + (*lst_conestouest) = addchain((*lst_conestouest), (void * ) lstcon); + } + lstcon->INDEX = index; + index++; + lstcon = lstcon->NEXT; + } + + lstcon = firstfig->PHCON; + + while (NULL != lstcon) { + if ('E' == lstcon->ORIENT) + cptest++; + lstcon->INDEX = index; + index++; + lstcon = lstcon->NEXT; + } + + if (cptouest != cptest) + ringerreur(ERR_NBCONESTOUEST , firstfig, firstfig); + + lst = (*lst_conestouest); + + while (NULL != lst) { + con = (phcon_list * ) lst->DATA; + if (mode_debug) + printf("REFERENCE con plot figcour %s ycon %ld width %ld\n", con->NAME, con->YCON, con->WIDTH); + + lstcon = firstfig->PHCON; + while (NULL != lstcon) { + if (mode_debug) + printf("REFERENCE con plot figref %s ycon %ld width %ld\n", lstcon->NAME, lstcon->YCON, lstcon->WIDTH); + if (('E' == lstcon->ORIENT) + && (lstcon->NAME == con->NAME) + && (lstcon->YCON == con->YCON) + && (lstcon->WIDTH == con->WIDTH)) { + lstwork = addchain(lst->NEXT, (void * ) lstcon); + lst->NEXT = lstwork; + lst = lst->NEXT; + break; + } else + lstcon = lstcon->NEXT; + } + if (NULL == lstcon) + ringerreur(ERR_NOCONPH , con, firstfig); + lst = lst->NEXT; + } + + if (mode_debug) + printf("LISTE DES CONNECTEURS EST OUEST modele de reference\n"); + + lst = (*lst_conestouest); + while (NULL != lst) { + con = (phcon_list * ) lst->DATA; + if (mode_debug) + printf("con %s YCON %ld width %ld INDEX %ld face %c\n", con->NAME, con->YCON, con->WIDTH, + con->INDEX, con->ORIENT); + lst = lst->NEXT; + } + + } else { + + figcour = (phfig_list * ) liste_plotsph->DATA; + lstcon = figcour->PHCON; + + while (NULL != lstcon) { + if (mode_debug) + printf("PADCOUR lstcon plot %s ycon %ld width %ld index %ld\n", lstcon->NAME, (lstcon->YCON - figcour->YAB1) , lstcon->WIDTH, lstcon->INDEX); + + if (('W' == lstcon->ORIENT) || ('E' == lstcon->ORIENT)) { + if ('W' == lstcon->ORIENT) + cptouestcour++; + else + cptestcour++; + + lst = (*lst_conestouest); + while (NULL != lst) { + con = (phcon_list * ) lst->DATA; + if (mode_debug) + printf("\tREFERENCEcon plot %s ycon %ld width %ld index %ld\n", con->NAME, + (con->YCON - firstfig->YAB1), con->WIDTH, con->INDEX); + + if ((con->ORIENT == lstcon->ORIENT) + && (con->NAME == lstcon->NAME) + && ((con->YCON - firstfig->YAB1) == (lstcon->YCON - figcour->YAB1)) + && (con->WIDTH == lstcon->WIDTH)) { + lstcon->INDEX = con->INDEX; + break; + } else + lst = lst->NEXT; + } + if (NULL == lst) + ringerreur(ERR_NOCONPH , lstcon, figcour); + } + lstcon = lstcon->NEXT; + } + + if ((cptest != cptestcour) || (cptouest != cptouestcour)) + ringerreur(ERR_NBCONESTOUEST , figcour, firstfig); + } +} diff --git a/alliance/src/ring/src/lirevues.h b/alliance/src/ring/src/lirevues.h new file mode 100644 index 00000000..4c54dd93 --- /dev/null +++ b/alliance/src/ring/src/lirevues.h @@ -0,0 +1,11 @@ +#ifndef __LIREVUES_H +#define __LIREVUES_H + +#include "struct.h" + +extern void lecture_vues(char *nom_circuit_lo, COEUR *lecoeur, lofig_list **circuit_lo, + chain_list **liste_plotsph, int *nbplots, chain_list **lst_conestouest); + +extern void verif_con_estouest(chain_list *liste_plotsph, chain_list **lst_conestouest); + +#endif /* __LIREVUES_H */ diff --git a/alliance/src/ring/src/param.c b/alliance/src/ring/src/param.c new file mode 100644 index 00000000..a46ca9af --- /dev/null +++ b/alliance/src/ring/src/param.c @@ -0,0 +1,216 @@ +/* + * 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 support : mailto:alliance-support@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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/****************************************************************************/ +/* */ +/* Chaine de CAO & VLSI Alliance */ +/* */ +/* Produit : ring router */ +/* Fichier : param.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 28 avril 92 PARAM.C */ +/* PHASE 1 */ +/* Lecture des parametres et de l'environnement mbk */ +/*--------------------------------------------------------------------------*/ +#include +#include + +#include "param.h" +#include "sesame.h" + + +/*-----------------------------------------------------------------------------------*/ +/* lecture des arguments (ligne de commande), lecture envt mbk et */ +/* initialisations des variables globales. */ +/*-----------------------------------------------------------------------------------*/ + +void lecture_param(int nbarg, char** tab, char** nom_circuit_lo, + char** nom_circuit_ph, char** nom_fic_param) +{ + long max1, max2, pitchalu1, pitchalu2; + FILE* f_catal; + + /* ---------------------- */ + /* arguments du programme */ + /* ---------------------- */ + + if ((nbarg < 3) || (nbarg > 5)) + ringerreur(ERR_ARGUMENT, NULL, NULL); + + *nom_circuit_lo = tab[1]; + *nom_circuit_ph = tab[2]; + + *nom_fic_param = (char * ) mbkalloc ((unsigned int) strlen(*nom_circuit_lo) + 5); + strcpy(*nom_fic_param, *nom_circuit_lo); + strcat(*nom_fic_param, ".rin"); + + mode_debug = 0; + mode_stat = 0; + + if (nbarg == 4) { + if (!strcmp(tab[3], "debug")) { + mode_debug = 1; + if (mode_debug) + fprintf(stderr, "\n\t*** Debug mode ***\n\n"); + } + if (!strcmp(tab[3], "stat")) { + mode_stat = 1; + nomfic_stat = (char * ) mbkalloc ((unsigned int) strlen(*nom_circuit_ph) + 6); + strcpy(nomfic_stat, *nom_circuit_ph); + strcat(nomfic_stat, ".stat"); + if (mode_stat) + fprintf(stderr, "\n\t*** Statistic mode -> see the file < %s > ***\n\n", nomfic_stat); + } + if ((!mode_debug) && (!mode_stat)) + ringerreur(ERR_ARGUMENT, NULL, NULL); + } + + if (nbarg == 5) { + if ((!strcmp(tab[3], "debug")) || (!strcmp(tab[4], "debug"))) { + mode_debug = 1; + if (mode_debug) + fprintf(stderr, "\n\t*** Debug mode ***\n\n"); + } + if ((!strcmp(tab[3], "stat")) || (!strcmp(tab[4], "stat"))) { + mode_stat = 1; + nomfic_stat = (char * ) mbkalloc ((unsigned int) strlen(*nom_circuit_ph) + 6); + strcpy(nomfic_stat, *nom_circuit_ph); + strcat(nomfic_stat, ".stat"); + if (mode_stat) + fprintf(stderr, "\n\t*** Statistic mode -> see the file < %s > ***\n\n", nomfic_stat); + } + if (!(mode_debug && mode_stat)) + ringerreur(ERR_ARGUMENT, NULL, NULL); + } + + if (mode_debug) + printf("nbarg %d\n", nbarg); + if (mode_debug) + printf("circlo-%s-circph-%s-\n", *nom_circuit_lo, *nom_circuit_ph); + if (mode_debug) + printf("fic-paramr-%s-\n", *nom_fic_param); + + /*---------------------------- INITIALISATIONS ----------------------------------------*/ + + /* ---------------- */ + /* arguments de mbk */ + /* ---------------- */ + + mbkenv(); /* choix de l'utilisateur mis dans des variables UNIX */ + /* on recupere (long) SCALE_X */ + + if (mode_debug) + printf("CATALNAME is %s\n", CATAL); + + if (NULL == (f_catal = mbkfopen(CATAL, NULL, READ_TEXT))) + ringerreur(ERR_CATAL, CATAL, NULL); + + fclose(f_catal); + + /* ----------------------------------------------------------------- */ + /* Affectation des variables globales representnat les equipo d'alim */ + /* ----------------------------------------------------------------- */ + + eq_vdd = namealloc(VDD); + eq_vss = namealloc(VSS); + +#ifdef COMMENT + /* ------------------------------------------- */ + /* Directions privilegiees de metaux inversees */ + /* ------------------------------------------- */ + + ymetal = ALU1; /* Horizontal faces Est et Ouest */ + ymetal_width = WMIN_ALU1 * SCALE_X; + ymetal_wvia = WVIA_ALU1 * SCALE_X; + ymetal_dmin = DMIN_ALU1_ALU1 * SCALE_X; + + xmetal = ALU2; /* Vertical faces Nord et Sud */ + xmetal_width = WMIN_ALU2 * SCALE_X; + xmetal_wvia = WVIA_ALU2 * SCALE_X; + xmetal_dmin = DMIN_ALU2_ALU2 * SCALE_X; +#endif + + xmetal = ALU1; /* Horizontal faces Est et Ouest */ + xmetal_width = WMIN_ALU1 * SCALE_X; + xmetal_wvia = WVIA_ALU1 * SCALE_X; + xmetal_dmin = DMIN_ALU1_ALU1 * SCALE_X; + + ymetal = ALU2; /* Vertical faces Nord et Sud */ + ymetal_width = WMIN_ALU2 * SCALE_X; + ymetal_wvia = WVIA_ALU2 * SCALE_X; + ymetal_dmin = DMIN_ALU2_ALU2 * SCALE_X; + + lambda = 1 * SCALE_X; + + if (mode_debug) + printf("xmetal_width %ld ymetal_width %ld scale_x %ld\n", xmetal_width, ymetal_width, SCALE_X); + if (mode_debug) + printf("xmetal_DMIN %ld ymetal_DMIN %ld\n", xmetal_dmin, ymetal_dmin); + + vdd_width = 0; + vss_width = 0; + + /* pitcha1= dmina1a1 + max (wminalu1, wviaa1) */ + /* pitcha2= dmina2a2 + max (wminalu2, wviaa2) */ + + if (WMIN_ALU1 > WVIA_ALU1) + max1 = WMIN_ALU1; + else + max1 = WVIA_ALU1; + + pitchalu1 = DMIN_ALU1_ALU1 + max1; + + if (WMIN_ALU2 > WVIA_ALU2) + max2 = WMIN_ALU2; + else + max2 = WVIA_ALU2; + + pitchalu2 = DMIN_ALU2_ALU2 + max2; + + if (mode_debug) + printf("Pitch alu1 %ld Pitch alu2 %ld\n", pitchalu1, pitchalu2); + + if (pitchalu1 > pitchalu2) + pitch = pitchalu1 * SCALE_X; + else + pitch = pitchalu2 * SCALE_X; + + if (WVIA_ALU1 > WVIA_ALU2) + taille_via = WVIA_ALU1 * SCALE_X; + else + taille_via = WVIA_ALU2 * SCALE_X; + + if (mode_debug) + printf("pitch %ld taille_via %ld\n", pitch, taille_via); + +} diff --git a/alliance/src/ring/src/param.h b/alliance/src/ring/src/param.h new file mode 100644 index 00000000..ac880a8e --- /dev/null +++ b/alliance/src/ring/src/param.h @@ -0,0 +1,7 @@ +#ifndef __PARAM_H +#define __PARAM_H + +void lecture_param(int nbarg, char** tab, char** nom_circuit_lo, + char** nom_circuit_ph, char** nom_fic_param); + +#endif /* __PARAM_H */ diff --git a/alliance/src/ring/src/placement.c b/alliance/src/ring/src/placement.c new file mode 100644 index 00000000..6aec51e9 --- /dev/null +++ b/alliance/src/ring/src/placement.c @@ -0,0 +1,2255 @@ +/* + * 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 support : mailto:alliance-support@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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/****************************************************************************/ +/* */ +/* Chaine de CAO & VLSI Alliance */ +/* */ +/* Produit : ring router */ +/* Fichier : placement.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 15 juillet 92 PLACEMENT.C */ +/* PHASE 4 */ +/* */ +/* Les tableaux tab_plots tab_coeur et la liste des connecteurs speciaux sont remplies. */ +/*--------------------------------------------------------------------------------------*/ + +#include "placement.h" +#include "compress.h" +#include "distance.h" +#include "sesame.h" +#include "barre.h" + +/*-----------------------------------------------------------------------------------*/ +/* Cette procedure initialise les structures de donneees necessaires au barres */ +/* de plots . Elle prend les connecteurs de plots sur l'aboutement de la figure */ +/* physique de la barre construite precedemment. Si un connecteur n'existe pas */ +/* dans le niveau demande, on cree un deport, sera traite ulterieurement. */ +/*-----------------------------------------------------------------------------------*/ + +void remplir_tabplots(BARRE_PLOTS tab_plots[NB_FACES], LST_EQUIPO lst_equipo) +{ + int face, sansdeport = 0, avecdeport = 1; + phfig_list * ptfig; + phcon_list * liste_con; + char niveau = 0; + long x, y, xarr, yarr; + LST_PSEUDO_CON con; + + for (face = 0; face < NB_FACES; face++) { + switch (face) { + case NORD: + case SUD : + niveau = ymetal; + break; + case EST : + case OUEST: + niveau = xmetal; + break; + } + + if (tab_plots[face].width != 0) { + ptfig = getphfig(tab_plots[face].nomfig, 'A'); + liste_con = ptfig->PHCON; + + while (liste_con != NULL) { + + /* --------------------------------------------------------------- */ + /* 1ere passe, on ne prend que les connecteurs du layer de la face */ + /* --------------------------------------------------------------- */ + + if (liste_con->LAYER == niveau) { + +#ifdef COMMENT + /* --------------------------------- */ + /* ces 3 lignes uniquement pour test */ + /* --------------------------------- */ + + con = existe_conplot_lstequipo(liste_con->NAME, lst_equipo); + if ((con != NULL) && (con->nom_con == eq_vdd)) { +#endif + /* ------------------------- */ + /* Coordonnees du connecteur */ + /* ------------------------- */ + + x = liste_con->XCON; + y = liste_con->YCON; + + /* ------------------------------------------------------------------------ */ + /* Mise a plat des coordonnees par rapport a l'origine de la barre de plots */ + /* ------------------------------------------------------------------------ */ + + xyflat(&xarr, &yarr, x, y, 0L, 0L, ptfig->XAB1, ptfig->YAB1, ptfig->XAB2, + ptfig->YAB2, NOSYM); + + /* ------------------------------------------------------------------------ */ + /* Ajout du pseudo connecteur dans la liste associee a la face du plot */ + /* ------------------------------------------------------------------------ */ + + ajout_pseudo_con_plot(xarr, yarr, liste_con->WIDTH, liste_con->LAYER, liste_con->NAME, + face, sansdeport, tab_plots, lst_equipo); + +#ifdef COMMENT + } +#endif + } + + liste_con = liste_con->NEXT; + } /* fin du while parcours des conecteurs physiques */ + + /*-------------------------------------------------------------------*/ + /* 2eme passe : on traite les connecteurs qui n'ont pas le bon layer */ + /*-------------------------------------------------------------------*/ + + liste_con = ptfig->PHCON; + + while (liste_con != NULL) { + + if (liste_con->LAYER != niveau) { + + /* ------------------------- */ + /* Coordonnees du connecteur */ + /* ------------------------- */ + + con = existe_conplot_lstequipo(liste_con->NAME, lst_equipo); + + if ((con != NULL) && (con->largeur == 0)) /* non traite */ { + /* deport a effectuer */ + + if (mode_debug) + printf("Deport mauvais layer %d connecteur %s\n", (int) niveau, liste_con->NAME); + alloue_coord(0L, 0, &(con->deport)); + + /* con->deport = (PT_COORDONNEES) mbkalloc ((unsigned int) sizeof(COORDONNEES)); */ + + (con->deport)->piste = 1; /* C'est un mauvais layer */ + + con->deport->proprio = (void * ) con; + + x = liste_con->XCON; + y = liste_con->YCON; + + /* ------------------------------------------------------------------------ */ + /* Mise a plat des coordonnees par rapport a l'origine de la barre de plots */ + /* ------------------------------------------------------------------------ */ + + xyflat(&xarr, &yarr, x, y, 0L, 0L, ptfig->XAB1, ptfig->YAB1, ptfig->XAB2, + ptfig->YAB2, NOSYM); + + /* ------------------------------------------------------------------------ */ + /* Ajout du pseudo connecteur dans la liste associee a la face du plot */ + /* ------------------------------------------------------------------------ */ + + ajout_pseudo_con_plot(xarr, yarr, liste_con->WIDTH, liste_con->LAYER, liste_con->NAME, + face, avecdeport, tab_plots, lst_equipo); + } /* fin du 2eme if */ + } /* fin du 1er if */ + + liste_con = liste_con->NEXT; + } /* fin du while parcours des conecteurs physiques mauvais layer */ + + } /* fin du if */ else + tab_plots[face].lst_con = NULL; + + } /* fin du for */ + +} + +/*-----------------------------------------------------------------------------------*/ +/* Cette procedure remplir le tableau de pseudo connecteurs du coeur, en les rangeant*/ +/* par face et par abscisse, x ou y selon la face horizontale ou verticale */ +/*-----------------------------------------------------------------------------------*/ + +void remplir_tabcoeur(LST_PSEUDO_CON tabcoeur[NB_FACES], COEUR lecoeur, LST_EQUIPO lst_equipo) +{ + + long x, y, xarr, yarr; + phcon_list * liste_con = (lecoeur.coeur_ph)->PHCON; + phfig_list * coeurph = lecoeur.coeur_ph; + int face; + + /* ----------------------------------- */ + /* Initialisation du tableau de listes */ + /* ----------------------------------- */ + + for (face = 0; face < NB_FACES; face++) + tabcoeur[face] = NULL; + + if (mode_debug) + printf("REMplir tabcoeur\n"); + + if (liste_con == NULL) + ringerreur(ERR_CONCOEUREMPTY, &lecoeur, NULL); + + while (liste_con != NULL) { + + /* ------------------------- */ + /* Coordonnees du connecteur */ + /* ------------------------- */ + + x = liste_con->XCON; + y = liste_con->YCON; + + /* ------------------------------------------------------------ */ + /* Mise a plat des coordonnees par rapport a l'origine du coeur */ + /* ------------------------------------------------------------ */ + + xyflat(&xarr, &yarr, x, y, lecoeur.coord.xabs, lecoeur.coord.yabs, coeurph->XAB1, coeurph->YAB1, coeurph->XAB2, + coeurph->YAB2, lecoeur.rotation); + + /* ---------------------------------------------------------------------- */ + /* Reorientation eventuelle du connecteur si le coeur a subi une rotation */ + /* ---------------------------------------------------------------------- */ + + face = reorientation_con(liste_con->ORIENT, NOSYM); + + /* ---------------------------------------------------------------------- */ + /* Ajout du pseudo connecteur dans la liste associee a la face du coeur */ + /* ---------------------------------------------------------------------- */ + + ajout_pseudo_con_coeur(xarr, yarr, liste_con, face, tabcoeur, lst_equipo); + liste_con = liste_con->NEXT; + } + +} + +/*-----------------------------------------------------------------------------------*/ + +void affic_tabcoeur(LST_PSEUDO_CON tabcoeur[NB_FACES]) +{ + + int i; + + for (i = 0; i < NB_FACES; i++) { + printf("Affic lst face coeur no %d\n", i); + affic_lstcon(tabcoeur[i]); + } + +} + +/*-----------------------------------------------------------------------------------*/ + +void affic_tabplots(BARRE_PLOTS tabplot[NB_FACES]) +{ + + int i; + + for (i = 0; i < NB_FACES; i++) { + printf("Nomfig %s largeur %ld\n", tabplot[i].nomfig, tabplot[i].width); + printf("Affic lst face barre de plots no %d\n", i); + affic_lstcon(tabplot[i].lst_con); + } + +} + +/*-----------------------------------------------------------------------------------*/ +/* Calcul largeur des barres de plots et faces coeurs */ +/*-----------------------------------------------------------------------------------*/ + +void largeur_ab_plots(BARRE_PLOTS tab_plots[NB_FACES], + chain_list *nomplot[NB_FACES], chain_list *liste_plotsph) +{ + int face, first; + phfig_list * ptfig; + long largeur; + chain_list * liste; + + /* --------------------------------------------------------- */ + /* Initialisations et calcul largeur ab d'une barre de plots */ + /* --------------------------------------------------------- */ + + tab_plots[NORD].nomfig = namealloc(FBARRE_N); + tab_plots[NORD].nominst = namealloc(IBARRE_N); + tab_plots[SUD].nomfig = namealloc(FBARRE_S); + tab_plots[SUD].nominst = namealloc(IBARRE_S); + tab_plots[EST].nomfig = namealloc(FBARRE_E); + tab_plots[EST].nominst = namealloc(IBARRE_E); + tab_plots[OUEST].nomfig = namealloc(FBARRE_O); + tab_plots[OUEST].nominst = namealloc(IBARRE_O); + + for (face = 0; face < NB_FACES; face++) { + first = 1; + tab_plots[face].lst_con = NULL; + tab_plots[face].nb_deport = 0; + + liste = nomplot[face]; + + largeur = 0; + + while (liste != NULL) { + if (mode_debug) + printf("figure %s\n", ((loins_list * )liste->DATA)->FIGNAME); + + if ((ptfig = appartient_listeplotsph(((loins_list * )liste->DATA)->FIGNAME, liste_plotsph)) != NULL) { + if (first) { + first = 0; + tab_plots[face].height = ptfig->YAB2 - ptfig->YAB1; + } + + largeur += (ptfig->XAB2 - ptfig->XAB1); + if (mode_debug) + printf("largeur AB %ld plot %s \n", (ptfig->XAB2 - ptfig->XAB1), ((loins_list * )liste->DATA)->FIGNAME); + } + + liste = liste->NEXT; + } + + tab_plots[face].width = largeur; + } + +} + +/*-----------------------------------------------------------------------------------*/ + +void fabrique_barre_plots(BARRE_PLOTS tab_plots[NB_FACES], COEUR lecoeur, + chain_list *nomplot[NB_FACES], chain_list *liste_plotsph, + chain_list *lst_conestouest) +{ + int face, first; + long width_coeur, height_coeur, largeur = 0; + chain_list * liste; + phfig_list *barre, *lastfig; + long diff, each, touslesnb, nbplotsface, x, y; + long nbplotsvidetot, cptplot, cptplotvide; + double nbeachvide; + phins_list * firstinst, *lastinst, *lastinst2; + + /* ------------------------------------ */ + /* Il faudra traiter cas rotation coeur */ + /* ------------------------------------ */ + + width_coeur = lecoeur.width; + height_coeur = lecoeur.height; + + largeur_ab_plots(tab_plots, nomplot, liste_plotsph); + + /* ---------------------------------------- */ + /* Construction des quatres barres de plots */ + /* ---------------------------------------- */ + + for (face = 0; face < NB_FACES; face++) { + if (tab_plots[face].width != 0) { + + /* ---------------------- */ + /* Barre de plots definie */ + /* ---------------------- */ + + switch (face) { + case EST: + case OUEST: + largeur = height_coeur; + break; + case NORD: + case SUD: + largeur = width_coeur; + break; + } + + if (tab_plots[face].width >= largeur) { + if (mode_debug) + printf("face %d plots abutes simplement\n", face); + + liste = nomplot[face]; + first = 1; + + definir_fig_ph(tab_plots[face].nomfig); + + while (liste != NULL) { + if (first) { + first = 0; + placer_instph(((loins_list * )liste->DATA)->FIGNAME, ((loins_list * )liste->DATA)->INSNAME, + NOSYM, 0L, 0L); + } else + abouteright_plot_fig(((loins_list * )liste->DATA)->FIGNAME, ((loins_list + *)liste->DATA)->INSNAME); + liste = liste->NEXT; + } + + definir_ab_fig(); + } else { + + /* -------------------------- */ + /* barre plot < face du coeur */ + /* -------------------------- */ + + if (mode_debug) + printf("Largeur barre < largeur coeur \n"); + + nbplotsface = compte_nbplotsface(nomplot[face]); + diff = largeur - tab_plots[face].width; + nbplotsvidetot = diff / lambda; + + if (nbplotsvidetot < 1) { + touslesnb = 1; + each = 0; + } else { + + /* -------------------------- */ + /* pas de plots vide a ajoute */ + /* -------------------------- */ + + if (1 != nbplotsface) + nbeachvide = nbplotsvidetot / (float) (nbplotsface - 1); + else + nbeachvide = nbplotsvidetot / (float) nbplotsface; + if (nbeachvide >= 1) { + touslesnb = 1; + each = (long) nbeachvide; + } else { + touslesnb = (long) ((1 / nbeachvide) + 1); + each = 1; + } + } + + if (mode_debug) + printf("On ajoute %ld lambda de fils tous les %ld plots\n", each, touslesnb); + + liste = nomplot[face]; + cptplot = cptplotvide = 0; + first = 1; + + definir_fig_ph(tab_plots[face].nomfig); + barre = getphfig(tab_plots[face].nomfig, 'A'); + + while (liste != NULL) { + if ((NULL != liste) && (0 != cptplot) && (0 == cptplot % touslesnb)) { + firstlastinst_barre(barre, &firstinst, &lastinst); + + lastfig = getphfig(lastinst->FIGNAME, 'A'); + + x = lastinst->XINS + lastfig->XAB2 - lastfig->XAB1 ; + y = lastinst->YINS; + cptplot++; + cptplotvide++; + + placer_instph(((loins_list * )liste->DATA)->FIGNAME, ((loins_list * )liste->DATA)->INSNAME + , NOSYM, (x + each * lambda) / SCALE_X , y / SCALE_X); + + firstlastinst_barre(barre, &firstinst, &lastinst2); + + relier_plots_wire1(lastinst, lastinst2, lst_conestouest); + + liste = liste->NEXT; + } else + { + if (first) { + first = 0; + placer_instph(((loins_list * )liste->DATA)->FIGNAME, ((loins_list + *)liste->DATA)->INSNAME, NOSYM, 0L, 0L); + } else + abouteright_plot_fig(((loins_list * )liste->DATA)->FIGNAME, ((loins_list + *)liste->DATA)->INSNAME); + cptplot++; + liste = liste->NEXT; + } + } + + definir_ab_fig(); + + /* ---------------------------------------------- */ + /* mise a jour de la largeur de la barre de plots */ + /* ---------------------------------------------- */ + + tab_plots[face].width += cptplotvide * each * lambda; + + } + + } /* fin du if largeur <> 0 */ else if /* largeur =0 else du 1er if */ + (mode_debug) + printf("barre face %d vide\n", face); + + } /* fin du for */ + + /* -------------------------------------------------------------- */ + /* ON reprend chaque figure de plot et on remonte les connecteurs */ + /* -------------------------------------------------------------- */ + + for (face = 0; face < NB_FACES; face++) { + if (tab_plots[face].width != 0) { + liste = nomplot[face]; + + definir_fig_ph(tab_plots[face].nomfig); + + while (liste != NULL) { + if (existe_connecteur_faceplot(((loins_list * )liste->DATA)->FIGNAME, SUD, liste_plotsph)) + remonter_consud_instph(((loins_list * )liste->DATA)->INSNAME); + liste = liste->NEXT; + } + + if (mode_debug) + sauver_fig_ph(); + } + } + + /* for (face=0; face < NB_FACES; face++) { + if (tab_plots[face].largeur != 0) { + ptfig = getphfig(tab_plots[face].nomfig,'A'); + viewphfig(ptfig); + } + } + */ + +} + +/*----------------------------------------------------------------------------*/ +/* Fabrication de la grille primaire a partir des connecteurs du coeur. */ +/* Verification de la distance des conecteurs entre eux leur largeur et leur */ +/* niveau */ +/*----------------------------------------------------------------------------*/ + +void fabrique_grille_primaire(LST_PSEUDO_CON tab_coeur[NB_FACES], + GRILLE tab_grilles[NB_FACES]) +{ + LST_PSEUDO_CON liste; + int face; + char niveau = 0; + long largeurmin = 0, largeurmax; + + if (WVIA_ALU1 > WVIA_ALU2) + largeurmax = WVIA_ALU1 * lambda; + else + largeurmax = WVIA_ALU2 * lambda; + + if (mode_debug) + printf("Fabrique grille primaire \n"); + if (mode_debug) + printf("alu1 %d alu2 %d\n", ALU1, ALU2); + + for (face = 0; face < NB_FACES; face++) { + liste = tab_coeur[face]; + + if (mode_debug) + printf("Face %d\n", face); + + /* --------------------------- */ + /* Initialisation de la grille */ + /* --------------------------- */ + + tab_grilles[face].lst_pas = NULL; + tab_grilles[face].lst_deportg = NULL; + tab_grilles[face].lst_deportd = NULL; + + switch (face) { + case NORD: + case SUD : + niveau = ymetal; + largeurmin = ymetal_width; + tab_grilles[face].piste.largeur_pas = pitch; + break; + + case EST: + case OUEST: + niveau = xmetal; + largeurmin = xmetal_width; + tab_grilles[face].piste.largeur_pas = pitch; + break; + } + + while (liste != NULL) { + if (mode_debug) + printf("connecteur %s\n", liste->nom_con); + if (mode_debug) + printf("width connecteur %ld largeurmin %ld niveau requis %d\n", liste->largeur, largeurmin, + (int) niveau); + + if(!isvdd(liste->nom_con) && !isvss(liste->nom_con) && (liste->largeur > largeurmax)) + ringerreur(ERR_CONLARGEUR, liste, NULL); + + if (liste->layer != niveau) /* deport a effectuer */ { + if (mode_debug) + printf("Deport mauvais layer %d connecteur %s\n", (int) liste->layer, liste->nom_con); + alloue_coord(0L, 0, &(liste->deport)); + + (liste->deport)->piste = 1; /* mauvais layer */ + liste->deport->proprio = (void * ) liste; + + switch (liste->layer) { + case ALU1: + if (liste->largeur < WMIN_ALU1) /* ringerreur largeur connecteur */ + ringerreur(ERR_CONLARGEUR, liste, NULL); + break; + case ALU2: + if (liste->largeur < WMIN_ALU2) /* ringerreur largeur connecteur */ + ringerreur(ERR_CONLARGEUR, liste, NULL); + + break; + } + + } else if (liste->largeur < largeurmin) /* ringerreur largeur connecteur */ + ringerreur(ERR_CONLARGEUR, liste, NULL); + + if (moins_dun_pitch_preccon(liste)) + ringerreur(ERR_CONDISTANCE, liste, NULL); + + ajout_coordonnees_grille(liste->coord, &(tab_grilles[face].lst_pas), face); + + liste = liste->suiv; + } /* fin du while */ + + } /* fin du for */ + +} + +/*-----------------------------------------------------------------------------*/ +/* Cette procedure place chaque barre de plots par rapport a la face du coeur. */ +/* Elle essaye plusieurs positions possibles pour chaque barre calule son cout */ +/* en nombre de deports et garde la meilleure et la plus centree */ +/*-----------------------------------------------------------------------------*/ + +void place_et_cout_barreplot(LST_PSEUDO_CON tab_coeur[NB_FACES], + BARRE_PLOTS tab_plots[NB_FACES], COEUR lecoeur, + LST_EQUIPO lst_equipo) +{ + + int face, gauche, droite, haut, bas, cout, first = 0; + long diff, barrexmilieu, barreymilieu, barrexcourant, barreycourant; + + if (mode_debug) + printf("PLACE barre plots\n"); + + for (face = 0; face < NB_FACES; face++) { + if (mode_debug) + printf("\n******************** FACE %d *************************\n", face); + + if (tab_plots[face].width != 0) { + switch (face) { + case NORD: + case SUD : + + diff = tab_plots[face].width - lecoeur.width; + + if (mode_debug) + printf("diff barre - face coeur %ld\n", diff); + + if (diff >= 0) + barrexmilieu = tab_plots[face].coord.xabs = ((lecoeur.coord.xabs - diff / 2) / SCALE_X) * + SCALE_X; + + /* --------------------------------------- */ + /* Largeur barre de plots >= largeur coeur */ + /* --------------------------------------- */ + + else + barrexmilieu = tab_plots[face].coord.xabs = ((lecoeur.coord.xabs - diff / 2) / SCALE_X) * + SCALE_X; + + /*---------------------------------------------------------------- */ + /* Largeur barre de plots < largeur coeur */ + /* La barre de plots est centree sur le coeur */ + /* Nb iterations a effectuer en deplacant la barre vers la gauche */ + /* puis vers la droite, on garde la position la plus centree avec */ + /* le moins de deports */ + /*---------------------------------------------------------------- */ + + if (mode_debug) + printf("face %d debutbarremilieu %ld\n", face, barrexmilieu); + first = 1; + + for (gauche = 0; gauche <= (NB_ITERATIONS / 2); gauche++) { + barrexcourant = barrexmilieu - (gauche * lambda); + if (mode_debug) + printf("\tbarrexcourant %ld", barrexcourant); + if (conplotalim_dans_coeur(lst_equipo, lecoeur, barrexcourant, face)) + { + + if (first) { + if (mode_debug) + printf("first place barre alim sont ok\n"); + first = 0; + tab_plots[face].nb_deport = calcul_nbdeport(tab_plots, tab_coeur, + lecoeur, lst_equipo, barrexcourant, face); + tab_plots[face].coord.xabs = barrexcourant; + } + else + { + if (mode_debug) + printf("place barre alim sont ok\n"); + if ((cout = calcul_nbdeport(tab_plots, tab_coeur, lecoeur, lst_equipo, + barrexcourant, face)) < tab_plots[face].nb_deport) { + if (mode_debug) + printf("Nouveau cout bestg %d barrexcourant %ld\n", cout, barrexcourant); + tab_plots[face].nb_deport = cout; + tab_plots[face].coord.xabs = barrexcourant; + } + } + } + } + + /* ----------------------------------- */ + /* parcours droit, on repart du milieu */ + /* ----------------------------------- */ + + for (droite = 1; droite <= (NB_ITERATIONS / 2); droite++) { + barrexcourant = barrexmilieu + (droite * lambda); + if (mode_debug) + printf("\tbarrexcourant %ld", barrexcourant); + if (conplotalim_dans_coeur(lst_equipo, lecoeur, barrexcourant, face)) + { + + if (first) { + if (mode_debug) + printf("first place barre alim sont ok\n"); + first = 0; + tab_plots[face].nb_deport = calcul_nbdeport(tab_plots, tab_coeur, + lecoeur, lst_equipo, barrexcourant, face); + tab_plots[face].coord.xabs = barrexcourant; + } + else + { + if (mode_debug) + printf("place barre alim sont ok\n"); + if ((cout = calcul_nbdeport(tab_plots, tab_coeur, lecoeur, lst_equipo, + barrexcourant, face)) < tab_plots[face].nb_deport) { + if (mode_debug) + printf("Nouveau cout bestd %d barrexcourant %ld\n", cout, barrexcourant); + tab_plots[face].nb_deport = cout; + tab_plots[face].coord.xabs = barrexcourant; + } else + if ((cout == tab_plots[face].nb_deport) + && (tab_plots[face].coord.xabs <= barrexmilieu) + && ((barrexcourant - barrexmilieu) < (barrexmilieu - tab_plots[face].coord.xabs))) { + + /* ------------------------------------------------------------------ */ + /* test egalite et proximite du milieu */ + /* vrai si egalite et position retenue precedemment etait a gauche */ + /* du milieu et si position courante droite est plus proche du milieu */ + /* que la gauche, on garde la plus centree, uggh ! */ + /* ------------------------------------------------------------------ */ + + if (mode_debug) + printf("Nouveau cout bestd centree %d barrexcourant %ld\n", cout, barrexcourant); + tab_plots[face].coord.xabs = barrexcourant; + } + } /* fin du else */ + } + } /* fin du for */ + + break; /* Fin Nord Sud */ + + case EST : + case OUEST: + + diff = tab_plots[face].width - lecoeur.height; + if (mode_debug) + printf("diff barre - face coeur %ld\n", diff); + + if (diff >= 0) + barreymilieu = tab_plots[face].coord.yabs = ((lecoeur.coord.yabs - diff / 2) / SCALE_X) * + SCALE_X; + + /*---------------------------------------- */ + /* Hauteur barre de plots >= Hauteur coeur */ + /*---------------------------------------- */ + + else + barreymilieu = tab_plots[face].coord.yabs = ((lecoeur.coord.yabs - diff / 2) / SCALE_X) * + SCALE_X; + + /* ------------------------------------------------------------ */ + /* Hauteur barre de plots < Hauteur coeur */ + /* La barre de plots est centree sur le coeur */ + /* Nb iterations a effectuer en deplacant la barre vers le bas */ + /* puis vers le haut, on garde la position la plus centree avec */ + /* le moins de deports */ + /* ------------------------------------------------------------ */ + + if (mode_debug) + printf("face %d debutbarremilieu %ld\n", face, barreymilieu); + + first = 1; + + for (bas = 0; bas <= (NB_ITERATIONS / 2); bas++) { + barreycourant = barreymilieu - (bas * lambda); + if (mode_debug) + printf("\tbarreycourant %ld", barreycourant); + + if (conplotalim_dans_coeur(lst_equipo, lecoeur, barreycourant, face)) + { + + if (first) { + if (mode_debug) + printf("first place barre alim sont ok\n"); + first = 0; + tab_plots[face].nb_deport = calcul_nbdeport(tab_plots, tab_coeur, + lecoeur, lst_equipo, barreycourant, face); + tab_plots[face].coord.yabs = barreycourant; + } + else + { + if (mode_debug) + printf("place barre alim sont ok\n"); + if ((cout = calcul_nbdeport(tab_plots, tab_coeur, lecoeur, lst_equipo, + barreycourant, face)) < tab_plots[face].nb_deport) { + if (mode_debug) + printf("Nouveau cout bestb %d barreycourant %ld\n", cout, barreycourant); + tab_plots[face].nb_deport = cout; + tab_plots[face].coord.yabs = barreycourant; + } + } + } + } + + /* ---------------------------------- */ + /* parcours haut, on repart du milieu */ + /* ---------------------------------- */ + + for (haut = 1; haut <= (NB_ITERATIONS / 2); haut++) { + barreycourant = barreymilieu + (haut * lambda); + if (mode_debug) + printf("\tbarreycourant %ld", barreycourant); + + if (conplotalim_dans_coeur(lst_equipo, lecoeur, barreycourant, face)) + { + + if (first) { + if (mode_debug) + printf("first place barre alim sont ok\n"); + first = 0; + tab_plots[face].nb_deport = calcul_nbdeport(tab_plots, tab_coeur, + lecoeur, lst_equipo, barreycourant, face); + tab_plots[face].coord.yabs = barreycourant; + } + else + { + if (mode_debug) + printf("place barre alim sont ok\n"); + + if ((cout = calcul_nbdeport(tab_plots, tab_coeur, lecoeur, lst_equipo, + barreycourant, face)) < tab_plots[face].nb_deport) { + if (mode_debug) + printf("Nouveau cout besth %d barreycourant %ld\n", cout, barreycourant); + tab_plots[face].nb_deport = cout; + tab_plots[face].coord.yabs = barreycourant; + } else + if ((cout == tab_plots[face].nb_deport) + && (tab_plots[face].coord.yabs <= barreymilieu) + && ((barreycourant - barreymilieu) < (barreymilieu - tab_plots[face].coord.yabs))) { + + /* ----------------------------------------------------------------- */ + /* test egalite et proximite du milieu */ + /* vrai si egalite et position retenue precedemment etait en bas */ + /* du milieu et si position courante haute est plus proche du milieu */ + /* que celle du bas, on garde la plus centree, uggh ! */ + /* ----------------------------------------------------------------- */ + + if (mode_debug) + printf("Nouveau cout besth centre %d barreycourant %ld\n", cout, barreycourant); + tab_plots[face].coord.yabs = barreycourant; + } + } + } + } + + break; /* Fin Est Ouest */ + } /* Fin du switch */ + + if (first) + /* ------------------------------------------------------------------------ */ + /* Ce qui veut dire qu'on a pas pu placer la barre de plot a cause des alim */ + /* ------------------------------------------------------------------------ */ + ringerreur(ERR_BARREALIM, (void * ) & face, NULL); + + if (mode_debug) + printf("Placement de la barre %d xabs %ld yabs %ld\n", face, tab_plots[face].coord.xabs, tab_plots[face].coord.yabs); + } /* Fin du if barre existante */ + + } /* Fin du for */ + + place_vertical_barreplot(tab_plots, tab_coeur, lecoeur, lst_equipo); +} + +/*--------------------------------------------------------------------------------*/ +/* Placement vertical des barres de plots = maximum des 4 faces. Pour chaque face */ +/* nb connect coeur + nb connect plot + 2 fois largalim */ +/*--------------------------------------------------------------------------------*/ + +void place_vertical_barreplot(BARRE_PLOTS tab_plots[NB_FACES], + LST_PSEUDO_CON tab_coeur[NB_FACES], COEUR lecoeur, + LST_EQUIPO lst_equipo) +{ + LST_EQUIPO equipo_vdd, equipo_vss; + LST_PSEUDO_CON liste; + int face; + long largvdd, largvss, diff1, diff2, diff; + + long cptcon = 0, maxcoeur = 0, maxplot = 0, largalim, dist; + + recherche_equipo_alim(&equipo_vdd, &equipo_vss, lst_equipo); + + largeur_vddvss(equipo_vdd, equipo_vss, &largvdd, &largvss); + + if (largvdd < largvss) + largalim = largvss; + else + largalim = largvdd; + + for (face = 0; face < NB_FACES; face++) { + + if (tab_plots[face].width != 0) { + liste = tab_plots[face].lst_con; + cptcon = 0; + + while (liste != NULL) { + cptcon++; + liste = liste->suiv; + } + if (cptcon > maxplot) + maxplot = cptcon; + + liste = tab_coeur[face]; + cptcon = 0; + + while (liste != NULL) { + cptcon++; + liste = liste->suiv; + } + + if (cptcon > maxcoeur) + maxcoeur = cptcon; + } + } + + dist = (maxcoeur * pitch + maxplot * pitch + 2 * largalim) * 2; + + for (face = 0; face < NB_FACES; face++) + (tab_plots[face].coord).piste = dist / pitch; + + if (tab_plots[NORD].width != 0) + (tab_plots[NORD].coord).yabs = (lecoeur.coord).yabs + lecoeur.height + dist; + if (tab_plots[SUD].width != 0) + (tab_plots[SUD].coord).yabs = (lecoeur.coord).yabs - dist; + if (tab_plots[OUEST].width != 0) + (tab_plots[OUEST].coord).xabs = (lecoeur.coord).xabs - dist; + if (tab_plots[EST].width != 0) + (tab_plots[EST].coord).xabs = (lecoeur.coord).xabs + lecoeur.width + dist; + + if (mode_debug) + printf("**** nord x%ld y%ld sud x%ld y%ld ouest x%ld y%ld est x%ld y%ld\n", (tab_plots[NORD].coord).xabs, + (tab_plots[NORD].coord).yabs, (tab_plots[SUD].coord).xabs, (tab_plots[SUD].coord).yabs, (tab_plots[OUEST].coord).xabs, + (tab_plots[OUEST].coord).yabs, (tab_plots[EST].coord).xabs, (tab_plots[EST].coord).yabs); + + /*------------- VERIFICATION DU NON CROISEMEMT DES BARRES MITOYENNES ----------*/ + + for (face = 0; face < NB_FACES; face++) { + diff1 = diff2 = 0; + + if (0 != tab_plots[face].width) + switch (face) { + case NORD: + if (mode_debug) + printf("nord\t"); + if (0 != tab_plots[EST].width) + diff1 = ((lecoeur.coord.yabs + lecoeur.height + tab_plots[NORD].coord.piste * pitch) + -(tab_plots[EST].coord.yabs + tab_plots[EST].width)); + if (0 != tab_plots[OUEST].width) + diff2 = ((lecoeur.coord.yabs + lecoeur.height + tab_plots[NORD].coord.piste * pitch) + -(tab_plots[OUEST].coord.yabs + tab_plots[OUEST].width)); + + if (diff1 < diff2) + diff = diff1; + else + diff = diff2; + if (diff < 0) + tab_plots[NORD].coord.piste += ((-diff + pitch) / pitch); + + break; + + case SUD: + if (mode_debug) + printf("sud\t"); + if (0 != tab_plots[EST].width) + diff1 = ( -(lecoeur.coord.yabs - tab_plots[SUD].coord.piste * pitch) + (tab_plots[EST].coord.yabs)); + if (0 != tab_plots[OUEST].width) + diff2 = ( -(lecoeur.coord.yabs - tab_plots[SUD].coord.piste * pitch) + (tab_plots[OUEST].coord.yabs)); + + if (diff1 < diff2) + diff = diff1; + else + diff = diff2; + if (diff < 0) + tab_plots[SUD].coord.piste += ((-diff + pitch) / pitch); + + break; + + case EST: + if (mode_debug) + printf("est\t"); + if (0 != tab_plots[NORD].width) + diff1 = ((lecoeur.coord.xabs + lecoeur.width + tab_plots[EST].coord.piste * pitch) - + (tab_plots[NORD].coord.xabs + tab_plots[NORD].width)); + if (0 != tab_plots[SUD].width) + diff2 = ((lecoeur.coord.xabs + lecoeur.width + tab_plots[EST].coord.piste * pitch) - + (tab_plots[SUD].coord.xabs + tab_plots[SUD].width)); + + if (diff1 < diff2) + diff = diff1; + else + diff = diff2; + if (diff < 0) + tab_plots[EST].coord.piste += ((-diff + pitch) / pitch); + break; + + case OUEST: + if (mode_debug) + printf("ouest\t"); + if (0 != tab_plots[NORD].width) + diff1 = (-(lecoeur.coord.xabs - tab_plots[OUEST].coord.piste * pitch ) + (tab_plots[NORD].coord.xabs)); + + if (0 != tab_plots[SUD].width) + diff2 = (-(lecoeur.coord.xabs - tab_plots[OUEST].coord.piste * pitch ) + (tab_plots[SUD].coord.xabs)); + + if (diff1 < diff2) + diff = diff1; + else + diff = diff2; + if (diff < 0) + tab_plots[OUEST].coord.piste += ((-diff + pitch) / pitch); + break; + } + } /* fin du for */ + + if (tab_plots[NORD].width != 0) + (tab_plots[NORD].coord).yabs = tab_plots[NORD].coord.piste * pitch + lecoeur.height; + if (tab_plots[SUD].width != 0) + (tab_plots[SUD].coord).yabs = (lecoeur.coord).yabs - tab_plots[SUD].coord.piste * pitch; + if (tab_plots[OUEST].width != 0) + (tab_plots[OUEST].coord).xabs = (lecoeur.coord).xabs - tab_plots[OUEST].coord.piste * pitch; + if (tab_plots[EST].width != 0) + (tab_plots[EST].coord).xabs = (lecoeur.coord).xabs + lecoeur.width + tab_plots[EST].coord.piste * pitch; + + if (mode_debug) + printf("**** nord x%ld y%ld sud x%ld y%ld ouest x%ld y%ld est x%ld y%ld\n", (tab_plots[NORD].coord).xabs, + (tab_plots[NORD].coord).yabs, (tab_plots[SUD].coord).xabs, (tab_plots[SUD].coord).yabs, (tab_plots[OUEST].coord).xabs, + (tab_plots[OUEST].coord).yabs, (tab_plots[EST].coord).xabs, (tab_plots[EST].coord).yabs); + +} + +/*-----------------------------------------------------------------------------------*/ +/* Cette procedure calcule le nombre total de deport de la barre de plot placee */ +/* a barrecourant. Cout des alim, connecteurs de plots a deporter, calcul du nombres */ +/* de cycles. */ +/* nb: la fonction moins_dun_pitch_confacecoeur met a jour la liste des vis a vis */ +/*-----------------------------------------------------------------------------------*/ + +int calcul_nbdeport(BARRE_PLOTS tab_plots[NB_FACES], + LST_PSEUDO_CON tab_coeur[NB_FACES], COEUR lecoeur, + LST_EQUIPO lst_equipo, long barrecourant, int face) +{ + int nbdepalim = 0, nbdepplots = 0, nbdepcycles = 0, nbdeptotal; + long position; + LST_PSEUDO_CON liste_plots, liste_coeur; + LST_EQUIPO liste_eq; + + /* -------------------------------------------------------------------- */ + /* Calcul du nombre de deport provoques par l'alim par rapport au pitch */ + /* -------------------------------------------------------------------- */ + + if (mode_debug) + printf("\tCalcul_nbdeport\n"); + + nbdepalim = calcul_nbdeport_equipo_alim(lst_equipo, barrecourant, face); + + liste_eq = lst_equipo; + liste_plots = tab_plots[face].lst_con; + liste_coeur = tab_coeur[face]; + + /* ----------------------------------------------- */ + /* Mise a nulle des listes de vis a vis des equipo */ + /* ----------------------------------------------- */ + + while (liste_eq) { + liste_eq->lst_visavis = NULL; /* prevoir desallocation */ + liste_eq = liste_eq->suiv; + } + + switch (face) { + case NORD: + case SUD : + + while (liste_plots != NULL) { + if (mode_debug) + printf("\t%s\n", liste_plots->nom_con); + + if(!isvdd(liste_plots->nom_con) && !isvss(liste_plots->nom_con)) { + position = (liste_plots->coord)->xabs + barrecourant; + + if (mode_debug) + printf("position %ld du connecteur %s face %d\n", position, liste_plots->nom_con, + face); + + /* --------------------------- */ + /* en dehors du coeur = deport */ + /* --------------------------- */ + + if ((position < lecoeur.coord.xabs) || (position > (lecoeur.coord.xabs + lecoeur.width))) { + if (mode_debug) + printf("deport en dehors coeur\t"); + nbdepplots++; + } else if (moins_dun_pitch_confacecoeur(position, liste_plots , liste_coeur, lst_equipo, + face)) { + if (mode_debug) + printf("deport - 1 pitch\t"); + nbdepplots++; + } + + } /* fin du if */ + + liste_plots = liste_plots->suiv; + } /* fin du while */ + + break; + + case EST : + case OUEST: + + while (liste_plots != NULL) { + if (mode_debug) + printf("\t%s\n", liste_plots->nom_con); + + if(!isvdd(liste_plots->nom_con) && !isvss(liste_plots->nom_con)) { + position = (liste_plots->coord)->yabs + barrecourant; + + if (mode_debug) + printf("position %ld du connecteur %s face %d\n", position, liste_plots->nom_con, + face); + + /* --------------------------- */ + /* en dehors du coeur = deport */ + /* --------------------------- */ + + if ((position < lecoeur.coord.yabs) || (position > (lecoeur.coord.yabs + lecoeur.height))) { + if (mode_debug) + printf("deport en dehors coeur\t"); + nbdepplots++; + } else if (moins_dun_pitch_confacecoeur(position, liste_plots , liste_coeur, lst_equipo, + face)) { + if (mode_debug) + printf("deport - 1 pitch\n"); + nbdepplots++; + } + + } + + liste_plots = liste_plots->suiv; + } + + break; + } /* Fin du switch() */ + + if (mode_debug) + printf("\tNb depplots %d", nbdepplots); + + /* --------------------------------------------------------------------------------------------------- */ + /* Par la methode deroutage , il n'y aura pas de cycles, donc inutile de calculer les cycles eventuels */ + /* nbdepcycles = calcul_nbdeport_cyclesface(lst_equipo); */ + /* --------------------------------------------------------------------------------------------------- */ + + nbdeptotal = nbdepalim + nbdepplots + nbdepcycles; + + if (nbdeptotal < 0) + nbdeptotal = 0; + + if (mode_debug) + printf("Nombre total de deport %d pour face %d et barrecourant %ld\n", nbdeptotal, face, barrecourant); + + return(nbdeptotal); + +} + +/*------------------------------------------------------------------------------------*/ +/* Cette fonction retourne vrai 1 si la position du connecteur plot est a moins d'un */ +/* pitch d'un connecteur quelconque du coeur, sinon 0; et mets a jour la liste des */ +/* vis a vis des equipo pour calcul ulterieur du nombre de cycle pour la face */ +/* Utilisation de la fonction calcul distance entre 2 connecteurs */ +/*------------------------------------------------------------------------------------*/ + +int moins_dun_pitch_confacecoeur(long position, LST_PSEUDO_CON plotcon, + LST_PSEUDO_CON liste_coeur, LST_EQUIPO lst_equipo, + int face) +{ + long dist, largcon = 0, largconprec = 0, largeurmin = 0, dminmetalmetal = 0; + long coordcon = 0, coordconprec = 0; + + if (liste_coeur == NULL) + return(0); /* pas de connecteurs coeurs donc grille + formee par les con de plots */ + + switch (face) { + case NORD: + case SUD : + if ((liste_coeur->layer != ymetal) || (plotcon->layer != ymetal)) { + if (ymetal_width < xmetal_width) + largeurmin = ymetal_width; + else + largeurmin = xmetal_width; + /* dminmetalmetal = xmetal_dmin; */ + dminmetalmetal = ymetal_dmin; + } else + { + largeurmin = ymetal_width; + dminmetalmetal = ymetal_dmin; + } + + while (liste_coeur != NULL) { + dist = distance_con_con(liste_coeur->coord->xabs, 0L, liste_coeur->largeur, liste_coeur->layer, position, + 0L, plotcon->largeur, plotcon->layer, face); + + if ((liste_coeur->largeur > largeurmin) || (plotcon->largeur > largeurmin)) { + + if (mode_debug) + printf("confacecoeur coordcon %ld coordconprec %ld largcon %ld largconprec %ld dist %ld\n", + coordcon,coordconprec,largcon,largconprec,dist); + + if (dist < dminmetalmetal) { + ajout_visavis(lst_equipo, liste_coeur, ((plotcon->con_lo)->SIG)->INDEX); + if(!isvdd(plotcon->nom_con) && !isvss(plotcon->nom_con)) + return(1); + + /* ------------------------------------------------------------- */ + /* pas de deport s'il s'agit d'une alim, on continue a parcourir */ + /* ------------------------------------------------------------- */ + } + } else { + if (dist < pitch) { + if (mode_debug) + printf("visavis posconcoeur %ld position %ld\n", (liste_coeur->coord)->xabs, + position); + + ajout_visavis(lst_equipo, liste_coeur, ((plotcon->con_lo)->SIG)->INDEX); + return(1); /* deport a faire */ + } + } /* fin du else */ + + liste_coeur = liste_coeur->suiv; + } /* fin du while */ + + return(0); /* Pas d'ringerreur c'est lesieur */ + + break; + + case EST : + case OUEST: + if ((liste_coeur->layer != xmetal) || (plotcon->layer != xmetal)) { + if (ymetal_width < xmetal_width) + largeurmin = ymetal_width; + else + largeurmin = xmetal_width; + dminmetalmetal = xmetal_dmin; + } else + { + largeurmin = xmetal_width; + dminmetalmetal = xmetal_dmin; + } + + while (liste_coeur != NULL) { + dist = distance_con_con(0L, liste_coeur->coord->yabs, liste_coeur->largeur, liste_coeur->layer, 0L, + position, plotcon->largeur, plotcon->layer, face); + + if ((liste_coeur->largeur > largeurmin) || (plotcon->largeur > largeurmin)) { + + if (mode_debug) + printf("confacecoeur coordcon %ld coordconprec %ld largcon %ld largconprec %ld dist %ld\n", + coordcon,coordconprec,largcon,largconprec,dist); + + if (dist < dminmetalmetal) { + ajout_visavis(lst_equipo, liste_coeur, ((plotcon->con_lo)->SIG)->INDEX); + if(!isvdd(plotcon->nom_con) && !isvss(plotcon->nom_con)) + return(1); + + /* ------------------------------------------------------------- */ + /* pas de deport s'il s'agit d'une alim, on continue a parcourir */ + /* ------------------------------------------------------------- */ + } + } else { + if (dist < pitch) { + ajout_visavis(lst_equipo, liste_coeur, ((plotcon->con_lo)->SIG)->INDEX); + return(1); /* deport a faire */ + } + } /* fin */ + + liste_coeur = liste_coeur->suiv; + } + + return(0); /* Pas d'ringerreur c'est lesieur */ + } + return(0); + +} + +/*--------------------------------------------------------------------------------*/ +/* Calcul du nombre de cycles avec la liste des visavis des equipo */ +/* Prevoir liberation des ptype liste allouees. */ +/*--------------------------------------------------------------------------------*/ + +int calcul_nbdeport_cyclesface(LST_EQUIPO lst_equipo) +{ + int nbdeport = 0; + ptype_list * liste; + + while (lst_equipo != NULL) { + liste = lst_equipo->lst_visavis; + + while (liste != NULL) { + if (existe_visavis(lst_equipo->index, liste->TYPE, lst_equipo)) { + nbdeport++; + } + + liste = liste->NEXT; + } + lst_equipo = lst_equipo->suiv; + } + + if (mode_debug) + printf("Nb deports cycles trouves %d\n", nbdeport); + + return(nbdeport); +} + +/*---------------------------------------------------------------------------------*/ +/* Calcul du nombre de deports possibles engendres par le placement de la barre */ +/*---------------------------------------------------------------------------------*/ + +int calcul_nbdeport_equipo_alim(LST_EQUIPO lst_equipo, long barrecourant, int face) +{ + LST_EQUIPO equipo_vdd, equipo_vss; + LST_PSEUDO_CON con; + chain_list * ptvdd = NULL , *ptvss = NULL, *ptcour; + int nbdeport = 0, bonus , malus; + + recherche_equipo_alim(&equipo_vdd, &equipo_vss, lst_equipo); + + ptvdd = equipo_vdd->lst_con; + ptvss = equipo_vss->lst_con; + + /* ------------------ */ + /* trt des equipo vdd */ + /* ------------------ */ + + if (mode_debug) + printf("trt eq VDD\n"); + ptcour = ptvdd; + + while (ptcour != NULL) { + con = (LST_PSEUDO_CON) ptcour->DATA; + + if ((bonus = croisement_con(ptcour, ptvdd, barrecourant, face)) != 0) { + if (mode_debug) + printf("bonus con %s de %d\n", con->nom_con, bonus); + nbdeport -= (bonus / pitch) ; + } + + if ((malus = croisement_con(ptcour, ptvss, barrecourant, face)) != 0) { + if (mode_debug) + printf("malus con %s de %ld\n", con->nom_con, ((vdd_width / pitch) + (vdd_width % pitch))); + nbdeport += ((vdd_width / pitch) + (vdd_width % pitch)) ; + } + + ptcour = ptcour->NEXT; + } + + /* ------------------ */ + /* trt des equipo vss */ + /* ------------------ */ + + ptcour = ptvss; + + if (mode_debug) + printf("trt eq VSS\n"); + + while (ptcour != NULL) { + con = (LST_PSEUDO_CON) ptcour->DATA; + + bonus = croisement_con(ptcour, ptvss, barrecourant, face); + + if (bonus != 0) { + if (mode_debug) + printf("bonus con %s de %d\n", con->nom_con, bonus); + nbdeport -= (bonus / pitch) ; + } + + ptcour = ptcour->NEXT; + } + + if (mode_debug) + printf("Nb deports total alim %d \n", nbdeport); + + return(nbdeport); +} + +/*--------------------------------------------------------------------------------*/ +/* Parcours de la liste des connecteurs d'alim pour voir s'il existe des vis */ +/* a vis. Si aucun vis a vis retour 0, sinon retour du croisement des 2 */ +/* connecteurs */ +/*--------------------------------------------------------------------------------*/ + +int croisement_con(chain_list *ptcour, chain_list *ptalim, + long barrecourant, int face) +{ + + LST_PSEUDO_CON con, concour; + long position = 0, positioncour = 0, dminmetalmetal = 0, diff = 0; + + concour = (LST_PSEUDO_CON) ptcour->DATA; + + /* + if (mode_debug) + printf("\tCroisement con %s larg %ld face %d x %ld y %ld\n",concour->nom_con, + concour->largeur,face,(concour->coord)->xabs,(concour->coord)->yabs); + */ + + switch (face) { + case NORD: + case SUD : + positioncour = (concour->coord)->xabs + barrecourant; + dminmetalmetal = ymetal_dmin; + break; + case EST : + case OUEST: + positioncour = (concour->coord)->yabs + barrecourant; + dminmetalmetal = xmetal_dmin; + break; + } + + while (ptalim != NULL) { + con = (LST_PSEUDO_CON) ptalim->DATA; + + if ((ptalim != ptcour) && (con->face == face) && (con->coeur_plot != concour->coeur_plot)) { + switch (face) { + case NORD: + case SUD : + position = (con->coord)->xabs + barrecourant; + break; + case EST : + case OUEST: + position = (con->coord)->yabs + barrecourant; + break; + } + + /* --------------------------------------- */ + /* meme layer car on ne s'en preoccupe pas */ + /* --------------------------------------- */ + + diff = distance_con_con(position, position, con->largeur, con->layer, positioncour, positioncour, + concour->largeur, con->layer, face); + + /* diff = position - (con->width / 2) - (con->width % 2) + - (positioncour + (concour->width / 2) + (concour->width % 2)); + Avant simplification */ + + if ((diff < 0) || (diff < dminmetalmetal)) + if (mode_debug) + printf("\tposition cour %ld nom %s position %ld ***diffcrois %ld larg %ld\n", positioncour, + con->nom_con, position, diff, con->largeur); + + if (diff < 0) + return((int) -diff); + if (diff < dminmetalmetal) + return ((int) pitch); + } /* fin du if */ + + ptalim = ptalim->NEXT; + } + + return((int) 0); /* Aucun croisement trouve */ +} + +/*-----------------------------------------------------------------------------------*/ +/* procedure qui retourne les equipotentielles d'alim */ +/*-----------------------------------------------------------------------------------*/ + +void recherche_equipo_alim(LST_EQUIPO *equipo_vdd, + LST_EQUIPO *equipo_vss, + LST_EQUIPO lst_equipo) +{ + LST_PSEUDO_CON con; + + (*equipo_vdd) = NULL; + (*equipo_vss) = NULL; + + while (lst_equipo != NULL) { + con = (LST_PSEUDO_CON) ((lst_equipo->lst_con)->DATA); + if (lst_equipo->type == ALIM) { + con = (LST_PSEUDO_CON) ((lst_equipo->lst_con)->DATA); + + if (isvdd(con->nom_con)) + (*equipo_vdd) = lst_equipo; + else + (*equipo_vss) = lst_equipo; + + if (((*equipo_vss) != NULL) && ((*equipo_vdd) != NULL)) + break; + } + lst_equipo = lst_equipo->suiv; + } + + if (((*equipo_vss) == NULL) || ((*equipo_vdd) == NULL)) + ringerreur(ERR_MANQUEALIM, NULL, NULL); +} + +/*-----------------------------------------------------------------------------------*/ +/* Verification si les connecteurs d'alim sont dans la face du coeur */ +/*-----------------------------------------------------------------------------------*/ + +int conplotalim_dans_coeur(LST_EQUIPO lst_equipo, COEUR coeur, + long barrecourant, int face) +{ + LST_EQUIPO equipo_vdd, equipo_vss; + LST_PSEUDO_CON con; + chain_list * liste_vdd; + chain_list * liste_vss; + long alasoupe; + + recherche_equipo_alim(&equipo_vdd, &equipo_vss, lst_equipo); + + liste_vdd = equipo_vdd->lst_con; + liste_vss = equipo_vss->lst_con; + + if (mode_debug) + printf("barrecourant %ld coeurheight %ld coeurwidth %ld\n", barrecourant, coeur.height, coeur.width); + + while (liste_vdd != NULL) { + con = (LST_PSEUDO_CON) liste_vdd->DATA; + if ((con->coeur_plot == PLOT_CON) && (con->face == face)) + + switch (con->face) { + case NORD: + case SUD : + if (((barrecourant + con->coord->xabs - con->largeur / 2) < (coeur.coord).xabs) || ((barrecourant + + con->coord->xabs + con->largeur / 2) > ((coeur.coord).xabs + coeur.width))) + return(0); /* le connecteur n'est pas en face du coeur */ + + break; + + case EST : + case OUEST: + alasoupe = ((barrecourant + con->coord->yabs - con->largeur / 2)); + if (mode_debug) + printf("binf %ld\t", alasoupe); + alasoupe = ((barrecourant + con->coord->yabs + con->largeur / 2)); + if (mode_debug) + printf("bsup %ld\t", alasoupe); + + if (mode_debug) + printf("plot %s coord x %ld y %ld larg %ld\n", con->nom_con, con->coord->xabs, con->coord->yabs, + con->largeur); + if (((barrecourant + con->coord->yabs - con->largeur / 2) < (coeur.coord).yabs) || ((barrecourant + + con->coord->yabs + con->largeur / 2) > ((coeur.coord).yabs + coeur.height))) + return(0); /* le connecteur n'est pas en face du coeur */ + + break; + } + liste_vdd = liste_vdd->NEXT; + } + + while (liste_vss != NULL) { + con = (LST_PSEUDO_CON) liste_vss->DATA; + if ((con->coeur_plot == PLOT_CON) && (con->face == face)) + + switch (con->face) { + case NORD: + case SUD : + if (((barrecourant + con->coord->xabs - con->largeur / 2) < (coeur.coord).xabs) || ((barrecourant + + con->coord->xabs + con->largeur / 2) > ((coeur.coord).xabs + coeur.width))) + return(0); /* le connecteur n'est pas en face du coeur */ + + break; + + case EST : + case OUEST: + alasoupe = ((barrecourant + con->coord->yabs - con->largeur / 2)); + if (mode_debug) + printf("binf %ld\t", alasoupe); + alasoupe = ((barrecourant + con->coord->yabs + con->largeur / 2)); + if (mode_debug) + printf("bsup %ld\t", alasoupe); + + if (mode_debug) + printf("plot %s coord x %ld y %ld larg %ld\n", con->nom_con, con->coord->xabs, con->coord->yabs, + con->largeur); + if (((barrecourant + con->coord->yabs - con->largeur / 2) < (coeur.coord).yabs) || ((barrecourant + + con->coord->yabs + con->largeur / 2) > ((coeur.coord).yabs + coeur.height))) + return(0); /* le connecteur n'est pas en face du coeur */ + + break; + } + liste_vss = liste_vss->NEXT; + } + + /* ningun problema */ + return(1); + +} + +/*--------------------------------------------------------------------------------*/ +/* Apres le placement de la barre de plots, on mets a jour les coordonnes des */ +/* connecteurs */ +/*--------------------------------------------------------------------------------*/ + +void maj_coordplots(BARRE_PLOTS tab_plots[NB_FACES], LST_EQUIPO lst_equipo) +{ + LST_EQUIPO liste_eq = lst_equipo; + LST_PSEUDO_CON liste; + int face; + char niveau; + long position, largeurmin, largeurmax; + + if (WVIA_ALU1 > WVIA_ALU2) + largeurmax = WVIA_ALU1 * lambda; + else + largeurmax = WVIA_ALU2 * lambda; + + if (mode_debug) + printf("Largeurmax = %ld\n", largeurmax); + + /* ----------------------------------------------- */ + /* Mise a nulle des listes de vis a vis des equipo */ + /* ----------------------------------------------- */ + + while (liste_eq) { + liste_eq->lst_visavis = NULL; /* prevoir desallocation */ + liste_eq = liste_eq->suiv; + } + + for (face = 0; face < NB_FACES; face++) { + liste = tab_plots[face].lst_con; + + if (mode_debug) + printf("Face %d\n", face); + + switch (face) { + + case NORD: + case SUD : + niveau = ymetal; + largeurmin = ymetal_width; + + while (liste != NULL) { + if (mode_debug) + printf("\t%s width = %ld\n", liste->nom_con, liste->largeur); + + if(!isvdd(liste->nom_con) && !isvss(liste->nom_con) && (liste->largeur > largeurmax)) + ringerreur(ERR_CONLARGEUR, liste, NULL); + + switch (liste->layer) { + case ALU1: + if (liste->largeur < WMIN_ALU1) /* ringerreur largeur connecteur */ + ringerreur(ERR_CONLARGEUR, liste, NULL); + break; + case ALU2: + if (liste->largeur < WMIN_ALU2) /* ringerreur largeur connecteur */ + ringerreur(ERR_CONLARGEUR, liste, NULL); + break; + default : + ringerreur(ERR_CONLARGEUR, liste, NULL); + } + + position = (liste->coord)->xabs + (tab_plots[face].coord).xabs; + (liste->coord)->xabs = position; + (liste->coord)->yabs = tab_plots[face].coord.yabs; + (liste->coord)->piste = (tab_plots[face].coord).piste; + + if (mode_debug) + printf("position %ld du connecteur %s face %d\n", position, liste->nom_con, face); + + liste = liste->suiv; + } /* fin du while */ + break; + + case EST : + case OUEST: + niveau = xmetal; + largeurmin = xmetal_width; + + while (liste != NULL) { + if (mode_debug) + printf("\t%s width=%ld y %ld ybarre %ld \n", liste->nom_con, liste->largeur, liste->coord->yabs, + tab_plots[face].coord.yabs); + if(!isvdd(liste->nom_con) && !isvss(liste->nom_con) && (liste->largeur > largeurmax)) + ringerreur(ERR_CONLARGEUR, liste, NULL); + + switch (liste->layer) { + case ALU1: + if (liste->largeur < WMIN_ALU1) /* ringerreur largeur connecteur */ + ringerreur(ERR_CONLARGEUR, liste, NULL); + break; + case ALU2: + if (liste->largeur < WMIN_ALU2) /* ringerreur largeur connecteur */ + + ringerreur(ERR_CONLARGEUR, liste, NULL); + break; + default : + ringerreur(ERR_CONLARGEUR, liste, NULL); + } + + position = (liste->coord)->yabs + (tab_plots[face].coord).yabs; + (liste->coord)->yabs = position; + (liste->coord)->xabs = (tab_plots[face].coord).xabs; + (liste->coord)->piste = (tab_plots[face].coord).piste; + + if (mode_debug) + printf("position %ld du connecteur %s face %d\n", position, liste->nom_con, face); + + liste = liste->suiv; + } /* fin du while */ + break; + } /* fin du switch */ + + } /* fin du for */ +} + +/*------------------------------------------------------------------------------------*/ +/* Fabrication de la grille finale a partir des connecteurs de plots. */ +/* Verification de la distance des connecteurs entre eux leur largeur */ +/* Mise a jour des futurs deports. */ +/* */ +/* Rq: la dmin a1 a1 est de 3 cad 30 avec le SCALE_X actuel, pour faire les nouveaux */ +/* pas de grille, on se sert de dmin/2, mais les pas doivent etre multiples de */ +/* scale_x, donc pour les calculs des nouveaux pas on prend */ +/* ((pos + scale_x/2) /scale_x) *scale_x */ +/*------------------------------------------------------------------------------------*/ + +void fabrique_grille_finale(BARRE_PLOTS tab_plots[NB_FACES], + LST_PSEUDO_CON tab_coeur[NB_FACES], COEUR lecoeur, + LST_EQUIPO lst_equipo, GRILLE tab_grilles[NB_FACES]) +{ + LST_PSEUDO_CON liste, liste_coeur; + int face; + char niveau; + long position, largeurmin; + + if (mode_debug) + printf("Fabrique grille finale\n"); + if (mode_debug) + printf("Coord coeur x%ld y%ld w%ld h%ld\n", lecoeur.coord.xabs, lecoeur.coord.yabs, lecoeur.width, lecoeur.height); + + for (face = 0; face < NB_FACES; face++) { + liste = tab_plots[face].lst_con; + liste_coeur = tab_coeur[face]; + + if (mode_debug) + printf("Face %d\n", face); + + switch (face) { + case NORD: + case SUD : + niveau = ymetal; + largeurmin = ymetal_width; + + while (liste != NULL) { + if (mode_debug) + printf("\t%s\n", liste->nom_con); + + if (moins_dun_pitch_preccon(liste)) + ringerreur(ERR_CONDISTANCE, liste, NULL); + + position = (liste->coord)->xabs; + + if (mode_debug) + printf("position %ld du connecteur %s face %d\n", position, liste->nom_con, face); + + if(!isvdd(liste->nom_con) && !isvss(liste->nom_con)) { + + /* --------------------------- */ + /* en dehors du coeur = deport */ + /* --------------------------- */ + + if (position < (lecoeur.coord).xabs) { + if (mode_debug) + printf("Deportg connecteur %s %ld\n", liste->nom_con, position); + alloue_coord(0L, 0, &(liste->deport)); + /* liste->deport = (PT_COORDONNEES) mbkalloc ((unsigned int) sizeof(COORDONNEES)); */ + + (liste->deport)->piste = 0; /* deport uniquement pour differencier du layer */ + + ajout_coordonnees_grille(liste->coord, &(tab_grilles[face].lst_deportg), + face); + } else if (position > ((lecoeur.coord).xabs + lecoeur.width)) { + if (mode_debug) + printf("Deportd connecteur %s %ld\n", liste->nom_con, position); + alloue_coord(0L, 0, &(liste->deport)); + /* liste->deport = (PT_COORDONNEES) mbkalloc ((unsigned int) sizeof(COORDONNEES)); */ + + (liste->deport)->piste = 0; /* deport uniquement pour differencier du layer */ + + ajout_coordonnees_grille(liste->coord, &(tab_grilles[face].lst_deportd), + face); + } else if (moins_dun_pitch_confacecoeur(position, liste, liste_coeur, lst_equipo, + face)) { /* Ne forme pas un nouveau pas de grille */ + if (mode_debug) + printf("Deport connecteur %s\n", liste->nom_con); + alloue_coord(0L, 0, &(liste->deport)); + /* liste->deport = (PT_COORDONNEES) mbkalloc ((unsigned int) sizeof(COORDONNEES)); */ + + (liste->deport)->piste = 0; /* deport uniquement pour differencier du layer */ + } else + { + if (mode_debug) + printf("Nouveau pas connecteur %s %ld\n", liste->nom_con, position); + + ajout_coordonnees_grille(liste->coord, &(tab_grilles[face].lst_pas), face); + } + + } /* fin du if */ else { + + /* ------------------------------------------------------------------------- */ + /* Il s'agit d'un plot d'alimentation, c'est un pas obligatoire de la grille */ + /* si ringerreur ici => ringerreur dans le placement de la barre de plot! */ + /* ------------------------------------------------------------------------- */ + + if (position < (lecoeur.coord).xabs) + ringerreur(ERR_BARREALIM, (void * ) & face, NULL); + if (position > ((lecoeur.coord).xabs + lecoeur.width)) + ringerreur(ERR_BARREALIM, (void * ) & face, NULL); + + moins_dun_pitch_confacecoeur(position, liste, liste_coeur, lst_equipo, face); + if (mode_debug) + printf("Nouveau pas ALIM connecteur %s %ld\n", liste->nom_con, position); + + ajout_coordonnees_grille(liste->coord, &(tab_grilles[face].lst_pas), face); + } + + liste = liste->suiv; + } /* fin du while */ + break; + + case EST : + case OUEST: + niveau = xmetal; + largeurmin = xmetal_width; + + while (liste != NULL) { + if (mode_debug) + printf("\t%s y %ld ybarre %ld \n", liste->nom_con, liste->coord->yabs, tab_plots[face].coord.yabs); + + if (moins_dun_pitch_preccon(liste)) + ringerreur(ERR_CONDISTANCE, liste, NULL); + + position = (liste->coord)->yabs; + if (mode_debug) + printf("position %ld du connecteur %s face %d\n", position, liste->nom_con, face); + + if(!isvdd(liste->nom_con) && !isvss(liste->nom_con)) { + + /* --------------------------- */ + /* en dehors du coeur = deport */ + /* --------------------------- */ + + if (position < (lecoeur.coord).yabs) { + if (mode_debug) + printf("Deport connecteur %s %ld\n", liste->nom_con, position); + alloue_coord(0L, 0, &(liste->deport)); + /* liste->deport = (PT_COORDONNEES) mbkalloc ((unsigned int) sizeof(COORDONNEES)); */ + (liste->deport)->piste = 0; /* deport uniquement pour differencier du layer */ + + ajout_coordonnees_grille(liste->coord, &(tab_grilles[face].lst_deportg), + face); + } else if (position > ((lecoeur.coord).yabs + lecoeur.height)) { + if (mode_debug) + printf("Deport connecteur %s %ld\n", liste->nom_con, position); + alloue_coord(0L, 0, &(liste->deport)); + /* liste->deport = (PT_COORDONNEES) mbkalloc ((unsigned int) sizeof(COORDONNEES)); */ + (liste->deport)->piste = 0; /* deport uniquement pour differencier du layer */ + + ajout_coordonnees_grille(liste->coord, &(tab_grilles[face].lst_deportd), + face); + } else if (moins_dun_pitch_confacecoeur(position, liste, liste_coeur, lst_equipo, + face)) { + if (mode_debug) + printf("Deport connecteur %s %ld\n", liste->nom_con, position); + alloue_coord(0L, 0, &(liste->deport)); + /* liste->deport = (PT_COORDONNEES) mbkalloc ((unsigned int) sizeof(COORDONNEES)); */ + (liste->deport)->piste = 0; /* deport uniquement pour differencier du layer */ + } else + { + if (mode_debug) + printf("Nouveau pas connecteur %s %ld\n", liste->nom_con, position); + + ajout_coordonnees_grille(liste->coord, &(tab_grilles[face].lst_pas), face); + } + + } /* fin du if */ else { + + /* ------------------------------------------------------------------------- */ + /* Il s'agit d'un plot d'alimentation, c'est un pas obligatoire de la grille */ + /* si ringerreur ici => ringerreur dans le placement de la barre de plot! */ + /* ------------------------------------------------------------------------- */ + + if (position < (lecoeur.coord).yabs) + ringerreur(ERR_BARREALIM, (void * ) & face, NULL); + if (position > ((lecoeur.coord).yabs + lecoeur.height)) + ringerreur(ERR_BARREALIM, (void * ) & face, NULL); + + moins_dun_pitch_confacecoeur(position, liste, liste_coeur, lst_equipo, face); + if (mode_debug) + printf("Nouveau pas ALIM connecteur %s %ld\n", liste->nom_con, position); + + ajout_coordonnees_grille(liste->coord, &(tab_grilles[face].lst_pas), face); + } + + liste = liste->suiv; + } /* fin du while */ + + break; + } /* Fin du switch() */ + + /*------------- AJOUT DE PAS SUPPLEMENTAIRES SI DIST ENTRE PAS >= 2 PITCH --------*/ + + ajout_pas_grille(tab_grilles, lecoeur, face); + + } /* fin du for */ +} + +/*------------------------------------------------------------------------------------*/ +/* Ajout de nouveaux pas de grille si distance entre connecteur est suffisante */ +/* Rq: la dmin a1 a1 est de 3 cad 30 avec le SCALE_X actuel, pour faire les nouveaux */ +/* pas de grille, on se sert de dmin/2, mais les pas doivent etre multiples de */ +/* scale_x, donc pour les calculs des nouveaux pas on prend pour a1 ou a2 */ +/* ((pos + scale_x) /scale_x) *scale_x */ +/* ceci est utilise quand connecteurs de largeur non standard sinon pas de pb */ +/* */ +/* bug corrige au niveau des calculs de pas (+lamda / lambda * lambda) */ +/* 13 sept 92: autre bug corrige. */ +/* Les connecteurs d'alim peuvent etre en vis a vis et se recouvrir, ce qui */ +/* faisait creer des nouveaux pas dans les alim ! */ +/* Les fonctions existe_con_prec et existe_con_suiv trouve le */ +/* connecteur le plus proche de celui qu'on cherche, donc une alim */ +/* recouvrant si elle existe, et repousse les nouveaux pas dans une */ +/* zone de routage vraiment libre. */ +/* */ +/* Attention: Le reglage pour les pas de grille est tres precis! */ +/* si modif, verifier a la main qu'on respecte les distances ds ts les cas ! */ +/*------------------------------------------------------------------------------------*/ + +void ajout_pas_grille(GRILLE tab_grilles[NB_FACES], COEUR lecoeur, int face) +{ + PT_COORDONNEES coordalim, nouveau, c1, c2, liste_coor; + long np = 0, enleve = 0, coordcon = 0, coordconprec = 0, largcon = 0, largconprec = 0; + long debut1 = 0, fin1 = 0, dist = 0, largeurmin = 0, dminmetalmetal = 0; + char layercon, layerconprec; + + if (mode_debug) + printf("FACE a completer %d\n", face); + + liste_coor = tab_grilles[face].lst_pas; + + /* --------------*/ + /* pour les vias */ + /* --------------*/ + + if (ymetal_dmin > xmetal_dmin) + dminmetalmetal = ymetal_dmin; + else + dminmetalmetal = xmetal_dmin; + + /*------------------ DEBUT DE GRILLE ----------------------------------------*/ + if (liste_coor != NULL) + switch (face) { + case NORD : + case SUD : + if (mode_debug) + printf("1er coordonnee %ld\n", liste_coor->xabs); + largeurmin = ymetal_wvia; + + /* ----------------------------------------------------------- */ + /* on recherche si alim suivante recouvrant connecteur existe */ + /* ----------------------------------------------------------- */ + + liste_coor = existe_con_suiv(0L, 0L, ymetal_width, ymetal, face, tab_grilles[face].lst_pas); + if (NULL == liste_coor) + ringerreur(ERR_GRILLEINTERNE, NULL, NULL); + + if (mode_debug) + printf("1ER CONNECTEUR x %ld y %ld face %d\n\n", liste_coor->xabs, liste_coor->yabs, face); + + if (((LST_PSEUDO_CON)liste_coor->proprio)->largeur > largeurmin) { + enleve = ((LST_PSEUDO_CON)liste_coor->proprio)->largeur / 2 + dminmetalmetal + taille_via / + 2; + if (((LST_PSEUDO_CON)liste_coor->proprio)->largeur < taille_via) + enleve += ( taille_via / 2 - ((LST_PSEUDO_CON)liste_coor->proprio)->largeur / 2); + + enleve = ((enleve + lambda) / lambda) * lambda; + } else + enleve = pitch; + + for (np = (lecoeur.coord).xabs + pitch; np <= (liste_coor->xabs - enleve); np = np + pitch) { + + /* ----------------------------------------- */ + /* ce for calcule les nouveaux pas de grille */ + /* ----------------------------------------- */ + + alloue_coord(np, face, &nouveau); + ajout_coordonnees_grille(nouveau, &(tab_grilles[face].lst_pas), face); + } + break; + case EST : + case OUEST: + if (mode_debug) + printf("1er coordonnee %ld\n", liste_coor->yabs); + largeurmin = xmetal_wvia; + + /* ----------------------------------------------------------- */ + /* on recherche si alim suivante recouvrant connecteur existe */ + /* ----------------------------------------------------------- */ + + liste_coor = existe_con_suiv(0L, 0L, xmetal_width, xmetal, face, tab_grilles[face].lst_pas); + if (NULL == liste_coor) + ringerreur(ERR_GRILLEINTERNE, NULL, NULL); + + if (mode_debug) + printf("1ER CONNECTEUR x %ld y %ld face %d\n\n", liste_coor->xabs, liste_coor->yabs, face); + + if (((LST_PSEUDO_CON)liste_coor->proprio)->largeur > largeurmin) { + enleve = ((LST_PSEUDO_CON)liste_coor->proprio)->largeur / 2 + dminmetalmetal + taille_via / + 2; + if (((LST_PSEUDO_CON)liste_coor->proprio)->largeur < taille_via) + enleve += ( taille_via / 2 - ((LST_PSEUDO_CON)liste_coor->proprio)->largeur / 2); + + enleve = ((enleve + lambda) / lambda) * lambda; + } else + enleve = pitch; + + for (np = (lecoeur.coord).yabs + pitch; np <= (liste_coor->yabs - enleve); np = np + pitch) { + + /* ----------------------------------------- */ + /* ce for calcule les nouveaux pas de grille */ + /* ----------------------------------------- */ + + alloue_coord(np, face, &nouveau); + ajout_coordonnees_grille(nouveau, &(tab_grilles[face].lst_pas), face); + } + break; + } + + /*------------------------- GRILLE COURANTE --------------------------------*/ + + if (mode_debug) + printf("Grille courante\n\n"); + + while ((liste_coor != NULL) && (liste_coor->suiv != NULL)) { + c1 = liste_coor; + c2 = liste_coor->suiv; + + switch (face) { + case NORD: + case SUD : + if (mode_debug) + printf("grille courante 1er %ld\n", liste_coor->xabs); + coordcon = c2->xabs; + coordconprec = c1->xabs; + break; + case EST : + case OUEST: + coordcon = c2->yabs; + coordconprec = c1->yabs; + break; + } + + largcon = ((LST_PSEUDO_CON)c2->proprio)->largeur; + layercon = ((LST_PSEUDO_CON)c2->proprio)->layer; + largconprec = ((LST_PSEUDO_CON)c1->proprio)->largeur; + layerconprec = ((LST_PSEUDO_CON)c1->proprio)->layer; + + dist = distance_con_con(coordcon, coordcon, largcon, layercon, coordconprec, coordconprec, largconprec, layerconprec, + face); + + /* ---------------------------------------------------------------------- */ + /* on recherche si alim precedente recouvrant connecteur precedent existe */ + /* ---------------------------------------------------------------------- */ + + coordalim = existe_con_precalim(coordcon, coordcon, largcon, layercon, face, tab_grilles[face].lst_pas, dist); + + if (NULL != coordalim) { + if (mode_debug) + printf("RECOUVRE TROUVE x %ld y %ld coordcon x %ld y %ld face %d DIST= %ld\n\n", coordalim->xabs, + coordalim->yabs, coordcon, coordcon, face, dist); + if ((NORD == face) || (SUD == face)) + coordconprec = coordalim->xabs; + else + coordconprec = coordalim->yabs; + largconprec = ((LST_PSEUDO_CON)coordalim->proprio)->largeur; + layerconprec = ((LST_PSEUDO_CON)coordalim->proprio)->layer; + } + + dist = distance_con_con(coordcon, coordcon, largcon, layercon, coordconprec, coordconprec, largconprec, layerconprec, + face); + + if ((largcon > largeurmin) || (largconprec > largeurmin)) { + if (mode_debug) + printf("largeur non standard\n %ld %ld", largconprec, largcon); + + if (largconprec <= largeurmin) + debut1 = pitch; + else + { + debut1 = largconprec / 2 + dminmetalmetal + taille_via / 2; + if (largconprec < taille_via) + debut1 += (taille_via / 2 - largconprec / 2); + debut1 = ((debut1 + lambda) / lambda) * lambda; + } + + if (largcon <= largeurmin) + fin1 = pitch; + else + { + fin1 = largcon / 2 + dminmetalmetal + taille_via / 2; + if (largcon < taille_via) + fin1 += (taille_via / 2 - largcon / 2); + + fin1 = ((fin1 + lambda) / lambda) * lambda; + + } + + if (dist >= (2 * dminmetalmetal + largeurmin)) + for (np = coordconprec + debut1; np <= (coordcon - fin1); np = np + pitch) { + + /* ------------------------------------------------- */ + /* ce for costaud calcule les nouveaux pas de grille */ + /* ------------------------------------------------- */ + + alloue_coord(np, face, &nouveau); + ajout_coordonnees_grille(nouveau, &(tab_grilles[face].lst_pas), face); + } + } else + { + if (dist >= (2 * pitch)) + for (np = coordconprec + pitch; np <= (coordcon - pitch); np = np + pitch) { + alloue_coord(np, face, &nouveau); + ajout_coordonnees_grille(nouveau, &(tab_grilles[face].lst_pas), face); + } + } + + /* ----------------------------------------------------------------------------------------------- */ + /* Si on a inserer de nouveaux elements il faut pas les traiter donc on prend c2 comme pas suivant */ + /* ----------------------------------------------------------------------------------------------- */ + + liste_coor = c2; + } /*fin du while */ + + if (liste_coor != NULL) { + + /*------------------------------- FIN DE GRILLE ----------------------------*/ + + switch (face) { + case NORD : + case SUD : + /* ----------------------------------------------------------- */ + /* on recherche si alim suivante recouvrant connecteur existe */ + /* ----------------------------------------------------------- */ + + liste_coor = existe_con_suiv(lecoeur.width + lecoeur.coord.xabs, lecoeur.height + lecoeur.coord.yabs, + ymetal_width, ymetal, face, tab_grilles[face].lst_pas); + if (NULL == liste_coor) + ringerreur(ERR_GRILLEINTERNE, NULL, NULL); + + if (mode_debug) + printf("Fin de grille dernier %ld\n", liste_coor->xabs); + + if (((LST_PSEUDO_CON)liste_coor->proprio)->largeur > largeurmin) { + enleve = ((LST_PSEUDO_CON)liste_coor->proprio)->largeur / 2 + dminmetalmetal + taille_via / + 2; + if (((LST_PSEUDO_CON)liste_coor->proprio)->largeur < taille_via) + enleve += ( taille_via / 2 - ((LST_PSEUDO_CON)liste_coor->proprio)->largeur / 2); + + enleve = ((enleve + lambda) / lambda) * lambda; + } else + enleve = pitch; + + for (np = liste_coor->xabs + enleve; np <= ((lecoeur.coord).xabs + lecoeur.width - pitch); np = np + pitch) { + /* ------------------------------------------------ */ + /* ce for calcule les nouveaux pas en fin de grille */ + /* ------------------------------------------------ */ + + alloue_coord(np, face, &nouveau); + ajout_coordonnees_grille(nouveau, &(tab_grilles[face].lst_pas), face); + } + break; + case EST : + case OUEST: + + /* ----------------------------------------------------------- */ + /* on recherche si alim suivante recouvrant connecteur existe */ + /* ----------------------------------------------------------- */ + + liste_coor = existe_con_suiv(lecoeur.width + lecoeur.coord.xabs, lecoeur.height + lecoeur.coord.yabs, + xmetal_width, xmetal, face, tab_grilles[face].lst_pas); + if (NULL == liste_coor) + ringerreur(ERR_GRILLEINTERNE, NULL, NULL); + + if (mode_debug) + printf("Fin de grille dernier %ld\n", liste_coor->yabs); + + if (((LST_PSEUDO_CON)liste_coor->proprio)->largeur > largeurmin) { + enleve = ((LST_PSEUDO_CON)liste_coor->proprio)->largeur / 2 + dminmetalmetal + taille_via / + 2; + if (((LST_PSEUDO_CON)liste_coor->proprio)->largeur < taille_via) + enleve += ( taille_via / 2 - ((LST_PSEUDO_CON)liste_coor->proprio)->largeur / 2); + + enleve = ((enleve + lambda) / lambda) * lambda; + } else + enleve = pitch; + + for (np = liste_coor->yabs + enleve; np <= ((lecoeur.coord).yabs + lecoeur.height - pitch); np = np + pitch) { + /* ------------------------------------------------ */ + /* ce for calcule les nouveaux pas en fin de grille */ + /* ------------------------------------------------ */ + + alloue_coord(np, face, &nouveau); + ajout_coordonnees_grille(nouveau, &(tab_grilles[face].lst_pas), face); + } + break; + } + + } /* fin du if != NULL */ + +} + +/*----------------------------------------------------------------------------*/ +/* Cette procedure relie les plots eloignes par fabrique_barre avec la liste */ +/* lst_conestouest, cad relie les alim internes faces ouest et est */ +/*----------------------------------------------------------------------------*/ + +void relier_plots_wire1(phins_list *lastinst, phins_list *lastinst2, chain_list *lst) +{ + phcon_list * con1, *con2; + + while (NULL != lst) { + con2 = (phcon_list * ) lst->DATA; + con1 = (phcon_list * ) lst->NEXT->DATA; + + poser_wire1(con1->LAYER, con1->WIDTH / SCALE_X, lastinst->INSNAME, con1->NAME, con1->INDEX, lastinst2->INSNAME, + con2->NAME, con2->INDEX); + + lst = lst->NEXT->NEXT; + } + +} diff --git a/alliance/src/ring/src/placement.h b/alliance/src/ring/src/placement.h new file mode 100644 index 00000000..662616cc --- /dev/null +++ b/alliance/src/ring/src/placement.h @@ -0,0 +1,51 @@ +#ifndef __PLACEMENT_H +#define __PLACEMENT_H + +#include "struct.h" + +extern void remplir_tabplots(BARRE_PLOTS tab_plots[NB_FACES], LST_EQUIPO lst_equipo); +extern void remplir_tabcoeur(LST_PSEUDO_CON tabcoeur[NB_FACES], COEUR lecoeur, LST_EQUIPO lst_equipo); +extern void affic_tabcoeur(LST_PSEUDO_CON tabcoeur[NB_FACES]); +extern void affic_tabplots(BARRE_PLOTS tabplot[NB_FACES]); +extern void largeur_ab_plots(BARRE_PLOTS tab_plots[NB_FACES], + chain_list *nomplot[NB_FACES], chain_list *liste_plotsph); +extern void fabrique_barre_plots(BARRE_PLOTS tab_plots[NB_FACES], COEUR lecoeur, + chain_list *nomplot[NB_FACES], chain_list *liste_plotsph, + chain_list *lst_conestouest); +extern void fabrique_grille_primaire(LST_PSEUDO_CON tab_coeur[NB_FACES], + GRILLE tab_grilles[NB_FACES]); +extern void place_et_cout_barreplot(LST_PSEUDO_CON tab_coeur[NB_FACES], + BARRE_PLOTS tab_plots[NB_FACES], COEUR lecoeur, + LST_EQUIPO lst_equipo); +extern void place_vertical_barreplot(BARRE_PLOTS tab_plots[NB_FACES], + LST_PSEUDO_CON tab_coeur[NB_FACES], COEUR lecoeur, + LST_EQUIPO lst_equipo); +extern int calcul_nbdeport(BARRE_PLOTS tab_plots[NB_FACES], + LST_PSEUDO_CON tab_coeur[NB_FACES], COEUR lecoeur, + LST_EQUIPO lst_equipo, long barrecourant, int face); +extern int moins_dun_pitch_confacecoeur(long position, LST_PSEUDO_CON plotcon, + LST_PSEUDO_CON liste_coeur, LST_EQUIPO lst_equipo, + int face); +extern int calcul_nbdeport_cyclesface(LST_EQUIPO lst_equipo); +extern int calcul_nbdeport_equipo_alim(LST_EQUIPO lst_equipo, long barrecourant, int face); +extern int croisement_con(chain_list *ptcour, chain_list *ptalim, + long barrecourant, int face); + +extern void recherche_equipo_alim(LST_EQUIPO *equipo_vdd, + LST_EQUIPO *equipo_vss, + LST_EQUIPO lst_equipo); + +extern int conplotalim_dans_coeur(LST_EQUIPO lst_equipo, COEUR coeur, + long barrecourant, int face); + +extern void maj_coordplots(BARRE_PLOTS tab_plots[NB_FACES], LST_EQUIPO lst_equipo); + +extern void fabrique_grille_finale(BARRE_PLOTS tab_plots[NB_FACES], + LST_PSEUDO_CON tab_coeur[NB_FACES], COEUR lecoeur, + LST_EQUIPO lst_equipo, GRILLE tab_grilles[NB_FACES]); + +extern void ajout_pas_grille(GRILLE tab_grilles[NB_FACES], COEUR lecoeur, int face); + +extern void relier_plots_wire1(phins_list *lastinst, phins_list *lastinst2, chain_list *lst); + +#endif /* __PLACEMENT_H */ diff --git a/alliance/src/ring/src/posercircuit.c b/alliance/src/ring/src/posercircuit.c new file mode 100644 index 00000000..5cb2a6d2 --- /dev/null +++ b/alliance/src/ring/src/posercircuit.c @@ -0,0 +1,1013 @@ +/* + * 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 support : mailto:alliance-support@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., 675 Mass Ave, Cambridge, MA 02139, 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" + +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 %d face %d\n",(int) precseg,(int)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 %d layer %d ptc1 %d ptc2 %d piste1 %ld piste2 %ld\n", (int) seg, (int)seg->layer, + (int)seg->c1, (int)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 %d layer %d x1 %ld y1 %ld x2 %ld y2 %ld\n", (int) seg, (int)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 %d layer %d x1 %ld y1 %ld x2 %ld y2 %ld\n", (int) seg2, (int)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 %d\n", (int) 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 %d layer %d ptc1 %d ptc2 %d piste1 %ld piste2 %ld\n", (int) seg, (int)seg->layer, + (int)seg->c1, (int)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 %d layer %d x1 %ld y1 %ld x2 %ld y2 %ld\n", (int) seg, (int)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 %d layer %d x1 %ld y1 %ld x2 %ld y2 %ld\n", (int) seg2, (int)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 */ + +} diff --git a/alliance/src/ring/src/posercircuit.h b/alliance/src/ring/src/posercircuit.h new file mode 100644 index 00000000..793c98d9 --- /dev/null +++ b/alliance/src/ring/src/posercircuit.h @@ -0,0 +1,34 @@ +#ifndef __POSERCIRCUIT_H +#define __POSERCIRCUIT_H + +#include "struct.h" + +extern void poser_blocs(phfig_list **circuit_ph, char *nomcircuit, + BARRE_PLOTS tab_plots[NB_FACES], COEUR lecoeur); +extern void poser_segments(LST_EQUIPO lst_equipo, COEUR lecoeur, + lofig_list *circuit_lo, phfig_list *circuit_ph); +extern void poser_segments_eq(LST_EQUIPO equipo, COEUR lecoeur, + lofig_list *circuit_lo); +extern void poser_vias_eq(LST_EQUIPO equipo, COEUR lecoeur, phfig_list *circuit_ph); + +extern 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); + +extern 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); + +extern void remonte_con(locon_list *con_circuit, locon_list *con_plot, + chain_list *liste_plotsph, phfig_list *circuit_ph); + +extern void tirer_coins(phfig_list *circuit_ph, BARRE_PLOTS tab_plots[NB_FACES], + chain_list *lst_conestouest); + +extern void ajout_coin(long x, long y, long wx, long wy, char layer); +extern void poser_vias_visavisalim(LST_EQUIPO equipo, COEUR lecoeur, + phfig_list *circuit_ph); + +#endif /* __POSERCIRCUIT_H */ diff --git a/alliance/src/ring/src/ring2.c b/alliance/src/ring/src/ring2.c new file mode 100644 index 00000000..d8029eec --- /dev/null +++ b/alliance/src/ring/src/ring2.c @@ -0,0 +1,298 @@ +/* + * 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 support : mailto:alliance-support@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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/****************************************************************************/ +/* */ +/* Chaine de CAO & VLSI Alliance */ +/* */ +/* Produit : ring router */ +/* Fichier : ring2.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 : 13/11/92 */ +/* Modifie par : Franck Wajsburt le : 9/11/94 */ +/* */ +/****************************************************************************/ + +#ident "@(#)ring 2.8 9/11/94 ALLIANCE 3.0 pad ring router" +/*----------------------------------------------------------------------------------- */ +/* RING 27 avril 92 RING2.C */ +/* Programme principal: declarations des variables (globales et locales) */ +/*----------------------------------------------------------------------------------- */ + +#include +#include +#include "struct.h" +#include "param.h" +#include "sesame.h" +#include "lirevues.h" +#include "lireplace.h" +#include "placement.h" +#include "deport.h" +#include "routalim.h" +#include "routage.h" +#include "compress.h" +#include "posercircuit.h" +#include "stat.h" + +/*----------------------------------------------------------------------------------- */ +/* Variables globales */ +char mode_debug; /* si debug alors mode_debug=1, 0 sinon */ +char mode_stat; /* si stat alors mode_stat=1, 0 sinon */ +char *nomfic_stat; /* nom du fichier stat */ +char xmetal; /* metal horizontal, faces est et Ouest */ +char ymetal; /* metal vertical, faces Nord et Sud */ +long xmetal_width, ymetal_width; /* largeur des metaux x, y */ +long xmetal_dmin, ymetal_dmin; /* dist minimum entre 2 meme metaux */ +long xmetal_wvia, ymetal_wvia; /* taille des contacts pour chaque metal */ +long pitch; /* pitch a calculer */ +long lambda; /* lambda (=SCALE_X) */ +long taille_via; /* taille du via a calculer */ +long vdd_width; /* largeur couronnes d'alim */ +long vss_width; +char *eq_vdd; +char *eq_vss; + + +char *nom_fic_param; /* nom du fichier parametre */ + +chain_list *nom_plot[NB_FACES]; /* liste pour l'analyseur des noms de plots */ + /* contiendra aussi les instances logiques de plots */ +chain_list *liste_width; /* liste pour l'analyseur des noms + et largeurs des connecteurs speciaux */ + +long bigvias = 0, ringvias = 0; /* nombres de vias poses en total par bigvia + ou en couronne (mode debug). car pb versatil + si bcp de vias (fichier .cif enorme) */ + +/*----------------------------------------------------------------------------------- */ + +int +main (argc, argv) +int argc; +char **argv; +{ + + /* declarations des variables locales */ + + BARRE_PLOTS tab_plots[NB_FACES]; /* nbfaces barres de plots */ + LST_PSEUDO_CON tab_coeur[NB_FACES]; /* nbfaces listes de connecteurs du coeur */ + + chain_list * liste_plotsph; /* liste de pointeurs sur les modeles physiques + des plots */ + chain_list * lst_conestouest; /* liste des con estouest alim */ + + int nb_inst_plots; /* nombres d'instances de plots rencontrees */ + + GRILLE tab_grilles[NB_FACES]; /* une grille symbolique par face */ + + LST_EQUIPO eq_interne; /* liste des equipo. internes (coeur/plots) */ + + LST_SEGMENT segx_occ[NB_FACES]; /* liste des segments occupes */ + LST_SEGMENT segy_occ[NB_FACES]; /* liste des segments occupes */ + + long piste_supalim[NB_FACES]; /* No des pistes alim couronnes inf et sup */ + + long piste_infalim[NB_FACES]; + long tabpiste[NB_FACES]; /* No des 1eres pistes libres en partant + de la barre de plots, sert pour les couronnes d'alim */ + + char * nom_circuit_lo, *nom_circuit_ph; /* nom du circuit logique et resultat (physique) */ + + COEUR lecoeur; /* structure contenant les informations du coeur */ + + lofig_list * circuit_lo; /* pointeur sur la figure logique du coeur */ + phfig_list * circuit_ph; /* pointeur sur la figure physique du coeur */ + + char * coursup, *courinf; /* nom des couronnes d'alim */ + long firstlibre[NB_FACES], nblibres[NB_FACES]; /* tab des 1eres pistes libres et nbre de piste */ + + /* ---------------------------------------------------------------------------------- */ + /* PHASE 1 */ + /* lecture et verification du nombre de parametres */ + /* ---------------------------------------------------------------------------------- */ + + lecture_param(argc, argv, &nom_circuit_lo, &nom_circuit_ph, &nom_fic_param); + banner(); + + /* ---------------------------------------------------------------------------------- */ + /* PHASE 2 */ + /* lecture vues structurelles circuit et coeur */ + /* ---------------------------------------------------------------------------------- */ + + fprintf(stderr, "\to reading netlists, layout views of core and pads.\n"); + lecture_vues(nom_circuit_lo, &lecoeur, &circuit_lo , &liste_plotsph, &nb_inst_plots, &lst_conestouest); + + /* ---------------------------------------------------------------------------------- */ + /* PHASE 3 */ + /* ---------------------------------------------------------------------------------- */ + + fprintf(stderr, "\to reading file of parameters, including the placements of pads.\n"); + lecture_fic(nom_fic_param, circuit_lo, lecoeur, nb_inst_plots); + if (mode_debug) + affic_plotwidth(); + + fprintf(stderr, "\to making equipotential list.\n"); + fabrique_equipo(nom_plot, lecoeur, &eq_interne, liste_plotsph); + if (mode_debug) + affic_equipo(eq_interne); + + /* ---------------------------------------------------------------------------------- */ + /* verification de la liste des equipotentielles internes */ + /* ---------------------------------------------------------------------------------- */ + verif_eq_interne(eq_interne, liste_plotsph); + + /* ---------------------------------------------------------------------------------- */ + /* PHASE 4 */ + /* ---------------------------------------------------------------------------------- */ + + fprintf(stderr, "\to making the first placement of pads.\n"); + fabrique_barre_plots(tab_plots, lecoeur, nom_plot, liste_plotsph, lst_conestouest); + + remplir_tabcoeur(tab_coeur, lecoeur, eq_interne); + + if (mode_debug) { + printf("afficher tab_coeur\n"); + affic_tabcoeur(tab_coeur); + } + + fprintf(stderr, "\to filling data internal structures.\n"); + remplir_tabplots(tab_plots, eq_interne); + if (mode_debug) + affic_tabplots(tab_plots); + + if (mode_debug) + printf("*** (larg plot alim) vdd_width: %ld vss_width: %ld\n", vdd_width, vss_width); + + fprintf(stderr, "\to reading the connectors positions of the core.\n"); + fabrique_grille_primaire(tab_coeur, tab_grilles); + if (mode_debug) + affic_grille(tab_grilles); + + fprintf(stderr, "\to computing the best placement of the pads.\n"); + place_et_cout_barreplot(tab_coeur, tab_plots, lecoeur, eq_interne); + maj_coordplots(tab_plots, eq_interne); + + fprintf(stderr, "\to reading the connectors positions of the pads.\n"); + fabrique_grille_finale(tab_plots, tab_coeur, lecoeur, eq_interne, tab_grilles); + if (mode_debug) + affic_grille(tab_grilles); + if (mode_debug) + affic_tabplots(tab_plots); + + if (mode_debug) + affic_grille(tab_grilles); + + /* ---------------------------------------------------------------------------------- */ + /* PHASE 5 */ + /* ---------------------------------------------------------------------------------- */ + + fprintf(stderr, "\to routing deportation of connectors.\n"); + attribuer_couronne_alim(eq_interne, &coursup, &courinf); + + /* ---------------------------------------------------------------------------------- */ + /* initialisations de segx-occ[] et segy_occ[] */ + /* on alloue exceptionnellement des faux segments pour deport plot alim ! */ + /* ---------------------------------------------------------------------------------- */ + + deport_alim(eq_interne, tab_plots, coursup, courinf, segx_occ, segy_occ); + + deport_connecteurs(tab_plots, tab_coeur, lecoeur, tab_grilles); + if (mode_debug) + affic_equipo(eq_interne); + + pose_segdeport(tab_plots, tab_coeur, lecoeur, eq_interne, segx_occ, segy_occ); + + fprintf(stderr, "\to routing supply tracks.\n"); + + /* ---------------------------------------------------------------------------------- */ + /* tabpiste va contenir les no des 1eres pistes libres en partant des plots */ + /* qui vont servir pour poser les couronnes d'alim */ + /* ---------------------------------------------------------------------------------- */ + + pose_couralim(coursup, piste_supalim, piste_infalim, eq_interne, lecoeur, tab_plots, segx_occ, segy_occ, tabpiste); + + /* ---------------------------------------------------------------------------------- */ + /* On peut se servir de tabpiste pour poser des faux segments, au cas ou on */ + /* tire une alim ds le mauvais layer, ceci pour eviter des croisements */ + /* (courts-circuits) avec les deports eventuels de plots */ + /* ---------------------------------------------------------------------------------- */ + + tire_etdeport_alim(coursup, piste_supalim, piste_infalim, eq_interne, tab_plots, segx_occ, segy_occ, tabpiste); + + if (mode_debug) + printf("*** vdd_width: %ld vss_width: %ld\n", vdd_width, vss_width); + if (mode_debug) + affic_equipo(eq_interne); + + /* ---------------------------------------------------------------------------------- */ + /* PHASE 6 */ + /* ---------------------------------------------------------------------------------- */ + + fprintf(stderr, "\to routing equipotentials.\n"); + remplit_eq_curv(eq_interne, lecoeur); + ordonne_equipotentielles(&eq_interne); + + route_equipo(piste_infalim, eq_interne, lecoeur, segx_occ, segy_occ); + + if (mode_debug) + affic_equipo(eq_interne); + + if (mode_debug) { + printf("------------------------------------------------------------------\n\n\n"); + printf("SEGMENT YMETAL\n"); + affic_listeseg(segy_occ); + printf("SEGMENT XMETAL\n"); + affic_listeseg(segx_occ); + } + + /* ---------------------------------------------------------------------------------- */ + /* PHASE 7 */ + /* ---------------------------------------------------------------------------------- */ + + fprintf(stderr, "\to compressing channels.\n"); + calcul_nbpiste_libre(tab_plots, lecoeur, segx_occ, segy_occ, nblibres, firstlibre); + compression_canaux(tab_plots, lecoeur, segx_occ, segy_occ, nblibres, firstlibre); + + /* ---------------------------------------------------------------------------------- */ + /* PHASE 8 */ + /* ---------------------------------------------------------------------------------- */ + + fprintf(stderr, "\to saving in MBK data structure.\n"); + poser_blocs(&circuit_ph, nom_circuit_ph, tab_plots, lecoeur); + poser_segments(eq_interne, lecoeur, circuit_lo, circuit_ph); + + remonte_con_circuit(nom_plot, liste_plotsph, tab_plots, lecoeur, circuit_lo, circuit_ph, nom_circuit_ph, lst_conestouest); + + if (mode_stat) + finir_stat(eq_interne); + + fprintf(stderr, "lucky, no error.\n"); + exit(0); /* fin correcte du routeur */ + +} + diff --git a/alliance/src/ring/src/ringram.y b/alliance/src/ring/src/ringram.y new file mode 100644 index 00000000..1d8a4f81 --- /dev/null +++ b/alliance/src/ring/src/ringram.y @@ -0,0 +1,48 @@ + +%{ +#include +#include "struct.h" +%} +%token M_NORTH, M_SOUTH, M_WEST, M_EAST, M_WIDTH +%token NOMBRE +%token IDENT +%union { + long i; + char *s; + } +%type NOMBRE +%type IDENT +%start programme +%% +programme: ldirective {if (mode_debug) printf("yacc: programme \n");} + ; +ldirective: ldirective directive {if (mode_debug) printf("yacc: ldirective \n");} + | directive + ; +directive: M_NORTH '(' lnom_n ')' {if (mode_debug) printf("yacc: north \n");} + | M_NORTH '(' ')' {if (mode_debug) printf("yacc: north \n");} + | M_SOUTH '(' lnom_s ')' {if (mode_debug) printf("yacc: south \n");} + | M_SOUTH '(' ')' {if (mode_debug) printf("yacc: south \n");} + | M_WEST '(' lnom_w ')' {if (mode_debug) printf("yacc: west \n");} + | M_WEST '(' ')' {if (mode_debug) printf("yacc: west \n");} + | M_EAST '(' lnom_e ')' {if (mode_debug) printf("yacc: east \n");} + | M_EAST '(' ')' {if (mode_debug) printf("yacc: east \n");} + | M_WIDTH '(' lnomchiffre ')' {if (mode_debug) printf("yacc: width \n");} + | M_WIDTH '(' ')' {if (mode_debug) printf("yacc: width \n");} + ; +lnom_n: lnom_n IDENT { declaration_plot_n($2);if (mode_debug) printf("yacc: ident \n"); } + | IDENT { declaration_plot_n($1);if (mode_debug) printf("yacc: ident \n");} + ; +lnom_s: lnom_s IDENT { declaration_plot_s($2); if (mode_debug) printf("yacc: ident \n");} + | IDENT { declaration_plot_s($1);if (mode_debug) printf("yacc: ident \n");} + ; +lnom_w: lnom_w IDENT { declaration_plot_w($2);if (mode_debug) printf("yacc: ident \n");} + | IDENT { declaration_plot_w($1);if (mode_debug) printf("yacc: ident \n");} + ; +lnom_e: lnom_e IDENT { declaration_plot_e($2);if (mode_debug) printf("yacc: ident \n");} + | IDENT { declaration_plot_e($1);if (mode_debug) printf("yacc: ident \n");} + ; +lnomchiffre: lnomchiffre IDENT NOMBRE { declaration_width($2,$3);if (mode_debug) printf("yacc lnomchiffre \n");} + | IDENT NOMBRE { declaration_width($1,$2);if (mode_debug) printf("yacc lnomchiffre \n");} + ; + diff --git a/alliance/src/ring/src/rinscan.l b/alliance/src/ring/src/rinscan.l new file mode 100644 index 00000000..4ecb2af2 --- /dev/null +++ b/alliance/src/ring/src/rinscan.l @@ -0,0 +1,34 @@ +%{ +#include "ringram.h" +#include "struct.h" +#undef yywrap +%} +delim [ \n\t] +esp [ \t] +rc [\n] +pct [\.\,\;\:\'\"\?\/\~\`\@\^<>\!\&\*\(\)\-\_\=\+\{\}\[\]\$\%\\\|] +blanc {delim}+ +chiffre [0-9] +nombre {chiffre}+ +lettre [a-zA-Z_] +ident {lettre}({lettre}*{chiffre}*)* +comment [#]({lettre}*{chiffre}*{esp}*{pct}*)*{rc} +%% +{blanc} {if (mode_debug) ECHO;} +"north" {if (mode_debug) ECHO; return(M_NORTH);} +"south" {if (mode_debug) ECHO; return(M_SOUTH);} +"west" {if (mode_debug) ECHO; return(M_WEST) ;} +"east" {if (mode_debug) ECHO; return(M_EAST) ;} +"width" {if (mode_debug) ECHO; return(M_WIDTH);} +{nombre} {if (mode_debug) ECHO; sscanf(yytext,"%ld",&yylval.i); + return(NOMBRE); + } +{ident} {if (mode_debug) ECHO; yylval.s = namealloc(yytext); + return(IDENT); + } +{comment} {if (mode_debug) {ECHO; printf("commentaire\n");}} +. { return(*yytext);} +%% +int yywrap() + {return(1);} + diff --git a/alliance/src/ring/src/routage.c b/alliance/src/ring/src/routage.c new file mode 100644 index 00000000..b1ec33ad --- /dev/null +++ b/alliance/src/ring/src/routage.c @@ -0,0 +1,805 @@ +/* + * 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 support : mailto:alliance-support@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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/****************************************************************************/ +/* */ +/* Chaine de CAO & VLSI Alliance */ +/* */ +/* Produit : ring router */ +/* Fichier : routage.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 22 juillet 92 ROUTAGE.C */ +/* routage des equipotentielles sauf alim (deja fait) */ +/*-----------------------------------------------------------------------------------*/ + +#include "routage.h" +#include "placement.h" +#include "sesame.h" + +/*-----------------------------------------------------------------------------------*/ +/* Remplit les ptype listes de projetes des equipotentielles, par calcul de leur */ +/* abscisse curviligne, puis reordonnancement des coordonnees pour garder le bipoint */ +/* le plus grand */ +/*-----------------------------------------------------------------------------------*/ + +void remplit_eq_curv(LST_EQUIPO lst_equipo, COEUR lecoeur) +{ + LST_EQUIPO equipo_vdd, equipo_vss; + + recherche_equipo_alim(&equipo_vdd, &equipo_vss, lst_equipo); + + while (NULL != lst_equipo) { + if ((lst_equipo != equipo_vdd) && (lst_equipo != equipo_vss)) { + calcul_eq_proj(lst_equipo, lecoeur); + ordonne_eq_proj(lst_equipo, lecoeur); + } + + lst_equipo = lst_equipo->suiv; + } + +} + +/*-----------------------------------------------------------------------------------*/ +/* Remplit la ptype liste de coordonnees avec valeur de l'abscisse curviligne, en */ +/* triant ds l'ordre croissant. */ +/*-----------------------------------------------------------------------------------*/ + +void calcul_eq_proj(LST_EQUIPO equipo, COEUR lecoeur) +{ + LST_PSEUDO_CON con; + chain_list * lst_con; + PT_COORDONNEES coord; + long valcurv; + + lst_con = equipo->lst_con; + (equipo->cour).lst_projetes = NULL; + + while (lst_con) { + con = (LST_PSEUDO_CON) lst_con->DATA; + if (NULL != con->deport) + coord = con->deport; + else + coord = con->coord; + + valcurv = calcul_curv(con, lecoeur); + insere_valcurv(valcurv, coord, equipo); + + lst_con = lst_con->NEXT; + } +} + +/*-----------------------------------------------------------------------------------*/ +/* Calcul de l'abscisse curviligne en fonctions des coordonnees et de la face */ +/*-----------------------------------------------------------------------------------*/ + +long calcul_curv(LST_PSEUDO_CON con, COEUR lecoeur) +{ + long valcurv = 0; + PT_COORDONNEES coord; + + if (NULL != con->deport) + coord = con->deport; + else + coord = con->coord; + + switch (con->face) { + case OUEST : + valcurv = coord->yabs - lecoeur.coord.yabs; + break; + + case NORD : + valcurv = lecoeur.height + coord->xabs - lecoeur.coord.xabs; + break; + + case EST : + valcurv = lecoeur.height + lecoeur.width + lecoeur.height - (coord->yabs - lecoeur.coord.yabs); + break; + + case SUD : + valcurv = lecoeur.height + lecoeur.width + lecoeur.height + lecoeur.width - (coord->xabs - lecoeur.coord.xabs); + break; + } + + if (mode_debug) + printf("Valcurv %ld con %s face %d \n", valcurv, con->nom_con, con->face); + + return(valcurv); +} + +/*-------------------------------------------------------------------------------------*/ +/* cette procedure insere les coord et sa valeur curviligne dans la ptype list en */ +/* triant par ordre croissant */ +/*-------------------------------------------------------------------------------------*/ + +void insere_valcurv(long valcurv, PT_COORDONNEES coord, LST_EQUIPO equipo) +{ + + ptype_list * lst_proj, *prec_proj; + + prec_proj = lst_proj = (equipo->cour).lst_projetes; + + if (NULL == lst_proj) + (equipo->cour).lst_projetes = addptype(lst_proj, valcurv, (void * ) coord); + + else { + while (NULL != lst_proj) { + if (valcurv <= lst_proj->TYPE) { + if (lst_proj == (equipo->cour).lst_projetes) /* tete de liste */ + (equipo->cour).lst_projetes = addptype(lst_proj, valcurv, (void * ) coord); + else + { + lst_proj = addptype(lst_proj, valcurv, (void * ) coord); + prec_proj->NEXT = lst_proj; + } + break; + } + + prec_proj = lst_proj; + lst_proj = lst_proj->NEXT; + } + + if (NULL == lst_proj) { + lst_proj = addptype(lst_proj, valcurv, (void * ) coord); + prec_proj->NEXT = lst_proj; + } + } /* fin du else */ + +} + +/*------------------------------------------------------------------------------------*/ +/* Cette procedure ordonne les coordonnees des projetes en prenant pour depart et fin */ +/* le bipoint le plus grand , ceci en utilisant les distances curvilignes calculees */ +/* precedemment. */ +/*------------------------------------------------------------------------------------*/ + +void ordonne_eq_proj(LST_EQUIPO equipo, COEUR lecoeur) +{ + + ptype_list * lst_proj = NULL, *prec_proj = NULL, *prem = NULL, *deux = NULL, *precprem = NULL; + long delta = 0, deltamax = 0; + + prec_proj = lst_proj = (equipo->cour).lst_projetes; + + if (mode_debug) + printf("Equipo no %ld\n", equipo->index); + + while ((NULL != lst_proj) && (NULL != lst_proj->NEXT)) { + delta = (lst_proj->NEXT)->TYPE - lst_proj->TYPE; + if (mode_debug) + printf("Delta %5ld\n", delta); + if (delta > deltamax) { + prem = lst_proj; + precprem = prec_proj; + deux = lst_proj->NEXT; + deltamax = delta; + } + + prec_proj = lst_proj; + lst_proj = lst_proj->NEXT; + } + + /* -------------------------------------------------- */ + /* dist curviligne entre le 1er et le dernier projete */ + /* -------------------------------------------------- */ + + if (prec_proj == (equipo->cour).lst_projetes) /* tete liste */ + prec_proj = ((equipo->cour).lst_projetes)->NEXT; + + /* ---------------------------------------- */ + /* prec_proj pointe sur la derniere cellule */ + /* ---------------------------------------- */ + + delta = 2 * lecoeur.height + 2 * lecoeur.width + ((equipo->cour).lst_projetes)->TYPE - prec_proj->TYPE; + ; + if (mode_debug) + printf("Delta entre 1er et der %5ld deltamax %5ld\n", delta, deltamax); + + if (delta < deltamax) /* sinon deja ordonne on bouge pas (>=) */ { + + /* ----------------------------------------------------------------------------- */ + /* on remplit la valeur perimetre de la couronne , servira pour trier les equipo */ + /* ----------------------------------------------------------------------------- */ + + (equipo->cour).perimetre = lecoeur.width * 2 + lecoeur.height * 2 - deltamax; + + if (mode_debug) + printf("Deltamax trouve %ld\n", deltamax); + lst_proj = deux; + while (NULL != deux->NEXT) + deux = deux->NEXT; /* on va en fin de liste */ + + /* ----------------------------------------------- */ + /* et on chaine avec le debut de la liste suivante */ + /* ----------------------------------------------- */ + + deux->NEXT = (equipo->cour).lst_projetes; + + prem->NEXT = NULL; /* fin de la liste */ + + (equipo->cour).lst_projetes = lst_proj; /* tete de liste */ + + } else { + + /* ----------------------------------------------------------------------------- */ + /* on remplit la valeur perimetre de la couronne , servira pour trier les equipo */ + /* ----------------------------------------------------------------------------- */ + + (equipo->cour).perimetre = lecoeur.width * 2 + lecoeur.height * 2 - delta; + } + +} + +/*-------------------------------------------------------------------------------------*/ +/* Cette procedure route toutes les equipotentielles (sauf alim) en 2 phases: */ +/* - routage de la couronne associee */ +/* - routage des colonnes a partir des connecteurs de l'equipotentielle */ +/*-------------------------------------------------------------------------------------*/ + +void route_equipo(long piste_infalim[NB_FACES], LST_EQUIPO lst_equipo, + COEUR lecoeur, LST_SEGMENT segx_occ[NB_FACES], + LST_SEGMENT segy_occ[NB_FACES]) +{ + + long piste_cour[NB_FACES]; + + LST_EQUIPO equipo_vdd, equipo_vss; + + recherche_equipo_alim(&equipo_vdd, &equipo_vss, lst_equipo); + + while (NULL != lst_equipo) { + if ((lst_equipo != equipo_vdd) && (lst_equipo != equipo_vss)) { + if (mode_debug) + printf("Routage des equipotentielles (sauf alim) %ld \n", lst_equipo->index); + construit_couronne(piste_cour, piste_infalim, lst_equipo, lecoeur, segx_occ, segy_occ); + poseseg_colonnes(piste_cour, lst_equipo, segx_occ, segy_occ); + } + + lst_equipo = lst_equipo->suiv; + } + +} + +/*------------------------------------------------------------------------------------*/ +/* Cette procedure contruit la couronne associee a l'equipotentielle a partir de la */ +/* liste des projetes construite. */ +/*------------------------------------------------------------------------------------*/ + +void construit_couronne(long piste_cour[NB_FACES], long piste_infalim[NB_FACES], + LST_EQUIPO equipo, COEUR lecoeur, LST_SEGMENT segx_occ[NB_FACES], + LST_SEGMENT segy_occ[NB_FACES]) +{ + + PT_COORDONNEES coin = NULL, nouveaucoin = NULL, debut_coor; + LST_PSEUDO_CON prec_con = NULL, con = NULL; + LST_SEGMENT * segpiste = NULL; + long pistealim = 0, largmetalpiste = 0, pistedebut = 0; + ptype_list * lst_proj, *prec_proj; + int change_face = 0, firstface = 1, segpiste_enplus = 0; + char metalpiste = 0; + + lst_proj = (equipo->cour).lst_projetes; + + while (NULL != lst_proj) { + if (!firstface) + + if (segpiste_enplus) { + debut_coor = nouveaucoin; + segpiste_enplus = 0; + switch (prec_con->face) /* mise a jour de la fin du segment supplementaire */ { + case SUD: + nouveaucoin->xabs = lecoeur.coord.xabs - piste_cour[OUEST] * pitch; + break; + case NORD: + nouveaucoin->xabs = lecoeur.coord.xabs + lecoeur.width + piste_cour[EST] * pitch; + break; + case EST: + nouveaucoin->yabs = lecoeur.coord.yabs - piste_cour[SUD] * pitch; + break; + case OUEST: + nouveaucoin->yabs = lecoeur.coord.xabs + lecoeur.height + piste_cour[NORD] * pitch; + break; + } + if (mode_debug) + printf("construit cour face %d debutcoorx %ld nouveaucoin x %ld debpt %d coinpt%d\n", + (int)prec_con->face, debut_coor->xabs, nouveaucoin->xabs, (int)debut_coor, (int)nouveaucoin); + } /* fin du if */ + + else { + debut_coor = coin; + + switch (prec_con->face) /* mise a jour des coord du coin pour la face suivante */ { + case SUD: + coin->yabs = lecoeur.coord.yabs - pistedebut * pitch; + break; + case NORD: + coin->yabs = lecoeur.height + lecoeur.coord.yabs + pistedebut * pitch; + break; + case EST: + coin->xabs = lecoeur.width + lecoeur.coord.xabs + pistedebut * pitch; + break; + case OUEST: + coin->xabs = lecoeur.coord.xabs - pistedebut * pitch; + break; + } + } /* fin du else */ + + else + debut_coor = (PT_COORDONNEES)lst_proj->DATA; /* c'est la 1ere fois */ + + prec_proj = lst_proj ; + prec_con = (LST_PSEUDO_CON)((PT_COORDONNEES)lst_proj->DATA)->proprio; + lst_proj = lst_proj->NEXT; + change_face = 0; + + if (mode_debug) + printf("prec-con-pt %d\n", (int)prec_con); + + while ((NULL != lst_proj) && (!change_face)) { + con = (LST_PSEUDO_CON)((PT_COORDONNEES)lst_proj->DATA)->proprio; + if (mode_debug) + printf("con-pt %d\n", (int)con); + change_face = prec_con->face != con->face; + if (!change_face) { + prec_con = con; + prec_proj = lst_proj; + lst_proj = lst_proj->NEXT; + } + } + + switch (prec_con->face) { + case SUD : + case NORD: + segpiste = segx_occ; + metalpiste = xmetal; + largmetalpiste = xmetal_width; + break; + case EST : + case OUEST: + segpiste = segy_occ; + metalpiste = ymetal; + largmetalpiste = ymetal_width; + break; + } + + if (change_face) { + + alloue_coord(0L, 0, &coin); + switch (prec_con->face) { + + /* ---------------------------------------------------------------------- */ + /* Au plus un seul segment piste est rajoute */ + /* les valeurs 10 ajoutees ou enlevees sont totalement arbitraires, mais */ + /* sont destinees pour les connecteurs placees en face des coins du coeur */ + /* sinon mauvais tri des coordonnes ds alloue_etchainesegment */ + /* cas tres rare mais POSSIBLE ! */ + /* ---------------------------------------------------------------------- */ + + case SUD : + coin->xabs = lecoeur.coord.xabs - 10; + if (con->face != OUEST) { + segpiste_enplus = 1; + ajout_segmentpiste(coin, &nouveaucoin, OUEST, piste_cour, piste_infalim, equipo, + lecoeur, segx_occ, segy_occ); + } + break; + case NORD: + coin->xabs = lecoeur.width + lecoeur.coord.xabs + 10; + if (con->face != EST) { + segpiste_enplus = 1; + ajout_segmentpiste(coin, &nouveaucoin, EST, piste_cour, piste_infalim, equipo, lecoeur, + segx_occ, segy_occ); + } + break; + case EST : + coin->yabs = lecoeur.coord.yabs - 10; + if (con->face != SUD) { + segpiste_enplus = 1; + ajout_segmentpiste(coin, &nouveaucoin, SUD, piste_cour, piste_infalim, equipo, lecoeur, + segx_occ, segy_occ); + } + break; + case OUEST: + coin->yabs = lecoeur.height + lecoeur.coord.yabs + 10; + if (con->face != NORD) { + segpiste_enplus = 1; + ajout_segmentpiste(coin, &nouveaucoin, NORD, piste_cour, piste_infalim, equipo, lecoeur, + segx_occ, segy_occ); + } + break; + } + } /* fin du if */ else + coin = (PT_COORDONNEES)prec_proj->DATA; + + pistedebut = 1; + pistealim = piste_infalim[prec_con->face]; + + while ((pistedebut != pistealim) && (!segment_libre(debut_coor, coin, pistedebut, pistedebut, prec_con->face, + SEG_PISTE, segpiste, metalpiste))) + pistedebut++; + + if (pistedebut == pistealim) + ringerreur(ERR_NOPISTE, &(prec_con->face), NULL); + piste_cour[prec_con->face] = pistedebut; + + alloue_etchaine_segment(debut_coor, coin, pistedebut, pistedebut, prec_con->face, SEG_PISTE, segpiste, largmetalpiste, + metalpiste, VRAI_SEG, AVEC_VIA, equipo); + + if (segpiste_enplus) { + switch (prec_con->face) /* mise a jour du debut segment supplementaire */ { + case SUD: + coin->yabs = lecoeur.coord.yabs - pistedebut * pitch; + coin->xabs = lecoeur.coord.xabs - piste_cour[OUEST] * pitch; + break; + case NORD: + coin->yabs = lecoeur.height + lecoeur.coord.yabs + pistedebut * pitch; + coin->xabs = lecoeur.coord.xabs + lecoeur.width + piste_cour[EST] * pitch; + break; + case EST: + coin->xabs = lecoeur.width + lecoeur.coord.xabs + pistedebut * pitch; + coin->yabs = lecoeur.coord.yabs - piste_cour[SUD] * pitch; + break; + case OUEST: + coin->xabs = lecoeur.coord.xabs - pistedebut * pitch; + coin->yabs = lecoeur.coord.yabs + lecoeur.height + piste_cour[NORD] * pitch; + break; + } + } /* fin du if */ + + if (firstface) + firstface = 0 ; + else /* mise a jour des coordonnees du precedent coin de la face precedente */ { + switch (prec_con->face) { + case SUD: + debut_coor->yabs = lecoeur.coord.yabs - pistedebut * pitch; + break; + case NORD: + debut_coor->yabs = lecoeur.height + lecoeur.coord.yabs + pistedebut * pitch; + break; + case EST: + debut_coor->xabs = lecoeur.width + lecoeur.coord.xabs + pistedebut * pitch; + break; + case OUEST: + debut_coor->xabs = lecoeur.coord.xabs - pistedebut * pitch; + break; + } + } /* fin du else */ + + if (mode_debug) + printf("construit cour face %d debutcoorx %ld coin x %ld debpt %d coinpt%d\n", (int)prec_con->face, + debut_coor->xabs, coin->xabs, (int)debut_coor, (int)coin); + + } /* fin du 1er while */ + +} + +/*----------------------------------------------------------------------------------*/ +/* Cette procedure tire un segment de type seg_piste pour completer une couronne. */ +/* Rq: on ajoutera au maximum un segment de ce type par couronne, sinon ca veut dire*/ +/* qu'il existe un plus court chemin dans l'autre sens. */ +/*----------------------------------------------------------------------------------*/ + +void ajout_segmentpiste(PT_COORDONNEES coin, PT_COORDONNEES *nouveaucoin, + int face, long piste_cour[NB_FACES], long piste_infalim[NB_FACES], + LST_EQUIPO equipo, COEUR lecoeur, LST_SEGMENT segx_occ[NB_FACES], + LST_SEGMENT segy_occ[NB_FACES]) +{ + LST_SEGMENT * segpiste = NULL; + long pistealim = 0, largmetalpiste = 0, pistedebut = 0; + char metalpiste = 0; + alloue_coord(0L, 0, nouveaucoin); + + switch (face) { + + /* ---------------------------------------------------------------------- */ + /* les valeurs 10 ajoutees ou enlevees sont totalement arbitraires, mais */ + /* sont destinees pour les connecteurs placees en face des coins du coeur */ + /* sinon mauvais tri des coordonnes ds alloue_etchainesegment */ + /* cas tres rare mais POSSIBLE ! */ + /* ---------------------------------------------------------------------- */ + + case SUD : + coin->xabs = lecoeur.coord.xabs + lecoeur.width + 10; + (*nouveaucoin)->xabs = lecoeur.coord.xabs - 10; + segpiste = segx_occ; + metalpiste = xmetal; + largmetalpiste = xmetal_width; + break; + case NORD: + coin->xabs = lecoeur.coord.xabs - 10; + (*nouveaucoin)->xabs = lecoeur.width + lecoeur.coord.xabs + 10; + segpiste = segx_occ; + metalpiste = xmetal; + largmetalpiste = xmetal_width; + break; + case EST : + coin->yabs = lecoeur.coord.yabs + lecoeur.height + 10; + (*nouveaucoin)->yabs = lecoeur.coord.yabs - 10; + segpiste = segy_occ; + metalpiste = ymetal; + largmetalpiste = ymetal_width; + break; + case OUEST: + coin->yabs = lecoeur.coord.yabs - 10; + (*nouveaucoin)->yabs = lecoeur.height + lecoeur.coord.yabs + 10; + segpiste = segy_occ; + metalpiste = ymetal; + largmetalpiste = ymetal_width; + break; + } + + pistedebut = 1; + pistealim = piste_infalim[face]; + + while ((pistedebut != pistealim) && (!segment_libre(coin, (*nouveaucoin), pistedebut, pistedebut, face, SEG_PISTE, + segpiste, metalpiste))) + pistedebut++; + + if (pistedebut == pistealim) + ringerreur(ERR_NOPISTE, &face, NULL); + piste_cour[face] = pistedebut; + + alloue_etchaine_segment(coin, (*nouveaucoin), pistedebut, pistedebut, face, SEG_PISTE, segpiste, largmetalpiste, + metalpiste, VRAI_SEG, AVEC_VIA, equipo); + +} + +/*--------------------------------------------------------------------------------------*/ +/* Une fois la couronne partielle de l'equipotentielle posee, on tire les colonnes */ +/* issues des connecteurs, no de piste sont dans piste_cour */ +/* Modif Verif de la largeur metal colonne pour eviter bug avec pad12 et pad15 */ +/*--------------------------------------------------------------------------------------*/ + +void poseseg_colonnes(long piste_cour[NB_FACES], LST_EQUIPO equipo, + LST_SEGMENT segx_occ[NB_FACES], LST_SEGMENT segy_occ[NB_FACES]) +{ + + PT_COORDONNEES debut_coor; + LST_PSEUDO_CON con; + LST_SEGMENT * segcol = NULL; + long largeurmin = 0, largeurvia = 0, largeurseg = 0; + char metalcol = 0; + ptype_list * lst_proj; + + lst_proj = (equipo->cour).lst_projetes; + + while (NULL != lst_proj) { + con = (LST_PSEUDO_CON) ((PT_COORDONNEES)lst_proj->DATA)->proprio; + if (NULL == con) + ringerreur(ERR_INTERNE_EQ, NULL, NULL); + debut_coor = (PT_COORDONNEES) lst_proj->DATA; + + switch (con->face) { + case SUD : + case NORD: + segcol = segy_occ; + metalcol = ymetal; + largeurmin = ymetal_width; + largeurvia = ymetal_wvia; + break; + case EST : + case OUEST: + segcol = segx_occ; + metalcol = xmetal; + largeurvia = xmetal_wvia; + largeurmin = xmetal_width; + break; + } + + if (segment_libre(debut_coor, debut_coor, debut_coor->piste, piste_cour[con->face], con->face, SEG_COL, segcol, + metalcol)) { + if (con->largeur > largeurvia) + largeurseg = largeurvia; + else if (con->largeur < largeurmin) + largeurseg = largeurmin; + else + largeurseg = con->largeur; + + alloue_etchaine_segment(debut_coor, debut_coor, debut_coor->piste, piste_cour[con->face], con->face, + SEG_COL, segcol, largeurseg, metalcol, VRAI_SEG, AVEC_VIA, equipo); + } else + ringerreur(ERR_NOCOL, (void * )con, NULL); + + lst_proj = lst_proj->NEXT; + } + +} + +/*----------------------------------------------------------------------------------*/ +/* Cette procedure ordonne les equipotentielles selon les criteres: */ +/* -- les alim en tete (pour acces plus rapide */ +/* -- les coeur-coeur par ordre curviligne decroissant */ +/* -- les coeur-plot par ordre curviligne decroissant */ +/* -- les plot-plot par ordre curviligne decroissant */ +/* -- les autres equipotentielles restantes */ +/*----------------------------------------------------------------------------------*/ + +void ordonne_equipotentielles(LST_EQUIPO *lst_equipo) +{ + LST_EQUIPO eq, lst_eq = *lst_equipo; + chain_list * lst_alim = NULL, *lst_coeurcoeur = NULL, *lst_coeurplot = NULL; + chain_list * lst_plotplot = NULL, *lst_reste = NULL, *lst, *prec_lst; + long perimetre; + + /* eclatement en 4 liste triees */ + + while (NULL != lst_eq) { + + switch (lst_eq->type) { + case ALIM: + lst_alim = addchain(lst_alim, (void * )lst_eq); + break; + case COEUR_COEUR: + perimetre = (lst_eq->cour).perimetre; + prec_lst = lst = lst_coeurcoeur; + + if (NULL == lst) + lst_coeurcoeur = addchain(lst_coeurcoeur, (void * )lst_eq); + else + { + while (NULL != lst) { + if (perimetre > (((LST_EQUIPO)lst->DATA)->cour).perimetre) { + if (lst == lst_coeurcoeur) /* tete de liste */ + lst_coeurcoeur = addchain(lst_coeurcoeur, (void * )lst_eq); + else + { + lst = addchain(lst, (void * ) lst_eq); + prec_lst->NEXT = lst; + } + break; + } + prec_lst = lst; + lst = lst->NEXT; + } + if (NULL == lst) { + lst = addchain(lst, (void * ) lst_eq); + prec_lst->NEXT = lst; + } + } /* fin du else */ + break; + + case COEUR_PLOT: + perimetre = (lst_eq->cour).perimetre; + prec_lst = lst = lst_coeurplot; + + if (NULL == lst) + lst_coeurplot = addchain(lst_coeurplot, (void * )lst_eq); + else + { + while (NULL != lst) { + if (perimetre > (((LST_EQUIPO)lst->DATA)->cour).perimetre) { + if (lst == lst_coeurplot) /* tete de liste */ + lst_coeurplot = addchain(lst_coeurplot, (void * )lst_eq); + else + { + lst = addchain(lst, (void * ) lst_eq); + prec_lst->NEXT = lst; + } + break; + } + prec_lst = lst; + lst = lst->NEXT; + } + if (NULL == lst) { + lst = addchain(lst, (void * ) lst_eq); + prec_lst->NEXT = lst; + } + } /* fin du else */ + break; + + case PLOT_PLOT: + perimetre = (lst_eq->cour).perimetre; + prec_lst = lst = lst_plotplot; + + if (NULL == lst) + lst_plotplot = addchain(lst_plotplot, (void * )lst_eq); + else + { + while (NULL != lst) { + if (perimetre > (((LST_EQUIPO)lst->DATA)->cour).perimetre) { + if (lst == lst_plotplot) /* tete de liste */ + lst_plotplot = addchain(lst_plotplot, (void * )lst_eq); + else + { + lst = addchain(lst, (void * ) lst_eq); + prec_lst->NEXT = lst; + } + break; + } + prec_lst = lst; + lst = lst->NEXT; + } + if (NULL == lst) { + lst = addchain(lst, (void * ) lst_eq); + prec_lst->NEXT = lst; + } + } /* fin du else */ + break; + + default: + lst_reste = addchain(lst_reste, (void * )lst_reste); + break; + } + + lst_eq = lst_eq->suiv; + } + + /* --------------------------------------------------- */ + /* fusion des listes triees selon les criteres choisis */ + /* --------------------------------------------------- */ + + if ((NULL == lst_alim) || (NULL == lst_alim->NEXT)) + ringerreur(ERR_INTERNE_EQ, NULL, NULL); + + eq = lst_eq = (LST_EQUIPO) lst_alim->DATA; + + lst = lst_alim->NEXT; + eq->suiv = (LST_EQUIPO) lst->DATA; + eq = eq->suiv; + + lst = lst_coeurcoeur; + + while (NULL != lst) { + eq->suiv = (LST_EQUIPO) lst->DATA; + eq = eq->suiv; + lst = lst->NEXT; + } + + lst = lst_coeurplot; + + while (NULL != lst) { + eq->suiv = (LST_EQUIPO) lst->DATA; + eq = eq->suiv; + lst = lst->NEXT; + } + + lst = lst_plotplot; + + while (NULL != lst) { + eq->suiv = (LST_EQUIPO) lst->DATA; + eq = eq->suiv; + lst = lst->NEXT; + } + + lst = lst_reste; + + while (NULL != lst) { + eq->suiv = (LST_EQUIPO) lst->DATA; + eq = eq->suiv; + lst = lst->NEXT; + } + + eq->suiv = NULL; + + (*lst_equipo) = lst_eq; + +} diff --git a/alliance/src/ring/src/routage.h b/alliance/src/ring/src/routage.h new file mode 100644 index 00000000..6aff2735 --- /dev/null +++ b/alliance/src/ring/src/routage.h @@ -0,0 +1,28 @@ +#ifndef __ROUTAGE_H +#define __ROUTAGE_H + +#include "struct.h" +extern void remplit_eq_curv(LST_EQUIPO lst_equipo, COEUR lecoeur); +extern void insere_valcurv(long valcurv, PT_COORDONNEES coord, LST_EQUIPO equipo); +extern void ordonne_eq_proj(LST_EQUIPO equipo, COEUR lecoeur); +extern void route_equipo(long piste_infalim[NB_FACES], LST_EQUIPO lst_equipo, + COEUR lecoeur, LST_SEGMENT segx_occ[NB_FACES], + LST_SEGMENT segy_occ[NB_FACES]); +extern void construit_couronne(long piste_cour[NB_FACES], long piste_infalim[NB_FACES], + LST_EQUIPO equipo, COEUR lecoeur, LST_SEGMENT segx_occ[NB_FACES], + LST_SEGMENT segy_occ[NB_FACES]); + +extern void ajout_segmentpiste(PT_COORDONNEES coin, PT_COORDONNEES *nouveaucoin, + int face, long piste_cour[NB_FACES], long piste_infalim[NB_FACES], + LST_EQUIPO equipo, COEUR lecoeur, LST_SEGMENT segx_occ[NB_FACES], + LST_SEGMENT segy_occ[NB_FACES]); + +extern void poseseg_colonnes(long piste_cour[NB_FACES], LST_EQUIPO equipo, + LST_SEGMENT segx_occ[NB_FACES], LST_SEGMENT segy_occ[NB_FACES]); + +extern void ordonne_equipotentielles(LST_EQUIPO *lst_equipo); + +void calcul_eq_proj(LST_EQUIPO equipo, COEUR lecoeur); +long calcul_curv(LST_PSEUDO_CON con, COEUR lecoeur); + +#endif /* __ROUTAGE_H */ diff --git a/alliance/src/ring/src/routalim.c b/alliance/src/ring/src/routalim.c new file mode 100644 index 00000000..3c2244c9 --- /dev/null +++ b/alliance/src/ring/src/routalim.c @@ -0,0 +1,688 @@ +/* + * 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 support : mailto:alliance-support@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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/****************************************************************************/ +/* */ +/* Chaine de CAO & VLSI Alliance */ +/* */ +/* Produit : ring router */ +/* Fichier : routalim.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 21 juillet 92 ROUTALIM.C */ +/* routage des alim : couronne + colonnes + deports eventuels */ +/*-----------------------------------------------------------------------------------*/ + +#include "routalim.h" +#include "placement.h" +#include "sesame.h" + +/*-------------------------------------------------------------------------------------*/ +/* Cette joyeuse procedure pose les couronnes d'alimentation superieures et inferieures*/ +/* et retourne les numeros des pistes d'alim dans 2 tableaux coursup[] et courinf[] */ +/*-------------------------------------------------------------------------------------*/ + +void pose_couralim(char *coursup, long piste_sup[NB_FACES], long piste_inf[NB_FACES], + LST_EQUIPO lst_equipo, COEUR lecoeur, BARRE_PLOTS tab_plots[NB_FACES], + LST_SEGMENT segx_occ[NB_FACES], LST_SEGMENT segy_occ[NB_FACES], + long tabpiste[NB_FACES]) +{ + long wtheovdd, wtheovss, wreelvdd_ymetal, wreelvdd_xmetal, wreelvss_xmetal; + long wreelvss_ymetal, maxlarg_y, maxlarg_x; + long nbpistemoinsvdd_ymetal, nbpistemoinsvdd_xmetal; + long nbpistemoinsvss_ymetal, nbpistemoinsvss_xmetal; + long nbpistemoinsalim_sup = 0, wreelalim_sup = 0, nbpistemoinsalim_inf = 0, wreelalim_inf = 0, pistealim = 0; + long largmetalpiste = 0, pistefin = 0, pistefinpardefaut = 0; + + /* ------------------------------------------------ */ + /* stocker la derniere piste libre pour chaque face */ + /* ------------------------------------------------ */ + + int face; + char metalpiste = 0; + + LST_SEGMENT * segpiste = NULL; + LST_EQUIPO equipo_vdd = NULL, equipo_vss = NULL, eqalim_sup = NULL, eqalim_inf = NULL; + PT_COORDONNEES c1alim_sup = NULL, c2alim_sup = NULL, c1alim_inf = NULL, c2alim_inf = NULL; + PT_COORDONNEES c1horalim_sup, c2horalim_sup, c1horalim_inf, c2horalim_inf; + PT_COORDONNEES c1veralim_sup, c2veralim_sup, c1veralim_inf, c2veralim_inf; + + recherche_equipo_alim(&equipo_vdd, &equipo_vss, lst_equipo); + + largeur_vddvss(equipo_vdd, equipo_vss, &wtheovdd, &wtheovss); + + if (ymetal_width > ymetal_wvia) + maxlarg_y = ymetal_width; + else + maxlarg_y = ymetal_wvia; + + if (xmetal_width > xmetal_wvia) + maxlarg_x = xmetal_width; + else + maxlarg_x = xmetal_wvia; + + + /* ---------------------------------------------------------- */ + /* ON se debrouille pour tomber sur un nombre de pistes paire */ + /* ---------------------------------------------------------- */ + + wreelvdd_ymetal = ((wtheovdd + pitch) / (2 * pitch )) * (2 * pitch) + maxlarg_y; + wreelvdd_xmetal = ((wtheovdd + pitch) / (2 * pitch )) * (2 * pitch) + maxlarg_x; + + wreelvss_ymetal = ((wtheovss + pitch) / (2 * pitch )) * (2 * pitch) + maxlarg_y; + wreelvss_xmetal = ((wtheovss + pitch) / (2 * pitch )) * (2 * pitch) + maxlarg_x; + + if (mode_debug) + printf("VDD largeury %5ld largeurx %5ld\n", wreelvdd_ymetal, wreelvdd_xmetal); + if (mode_debug) + printf("VSS largeury %5ld largeurx %5ld\n", wreelvss_ymetal, wreelvss_xmetal); + + if (mode_debug) + printf("VDDpitch largeury %5ld largeurx %5ld\n", wreelvdd_ymetal / pitch, wreelvdd_xmetal / pitch); + if (mode_debug) + printf("VSSpitch largeury %5ld largeurx %5ld\n", wreelvss_ymetal / pitch, wreelvss_xmetal / pitch); + + if (mode_debug) + printf("COEUR width %ld height %ld\n", lecoeur.width, lecoeur.height); + + nbpistemoinsvdd_ymetal = ((wtheovdd + pitch) / (2 * pitch )); + nbpistemoinsvdd_xmetal = ((wtheovdd + pitch) / (2 * pitch )); + nbpistemoinsvss_ymetal = ((wtheovdd + pitch) / (2 * pitch )); + nbpistemoinsvss_xmetal = ((wtheovdd + pitch) / (2 * pitch )); + + if (mode_debug) + printf("VDDretirepiste largeury %5ld largeurx %5ld\n", nbpistemoinsvdd_ymetal, nbpistemoinsvdd_xmetal); + if (mode_debug) + printf("VSSretirepiste largeury %5ld largeurx %5ld\n", nbpistemoinsvss_ymetal, nbpistemoinsvss_xmetal); + + /*-------------------------- POSE DES COURONNES D'ALIM -------------------------------*/ + + /* ---------------------------------------------------------- */ + /* recherche de la derniere piste libre vers la barre de plot */ + /* ---------------------------------------------------------- */ + + alloue_coord(0L, 0, &c1horalim_sup); + alloue_coord(0L, 0, &c2horalim_sup); + alloue_coord(0L, 0, &c1veralim_sup); + alloue_coord(0L, 0, &c2veralim_sup); + alloue_coord(0L, 0, &c1horalim_inf); + alloue_coord(0L, 0, &c2horalim_inf); + alloue_coord(0L, 0, &c1veralim_inf); + alloue_coord(0L, 0, &c2veralim_inf); + + /*-----------------------------------------------------------------------------------*/ + /* REPRESENTATION DES 2 COURONNES D ALIM SUPERIEURE ET INFERIEURE */ + /* */ + /*c1horalim_sup alim_sup c2horalim_sup */ + /*c2veralim_sup +-------------------------------------------+c2veralim_sup */ + /* | | */ + /* | alim_inf | */ + /* |c1horalim_inf +--------------+c2horalim_inf| */ + /* |c2veralim_inf | |c2horalim_inf| */ + /* | | | | */ + /* | | | | */ + /* | | | | */ + /* | | | | */ + /* | | | | */ + /* |c1horalim_inf | |c2horalim_inf| */ + /* |c1veralim_sup +--------------+c1horalim_inf| */ + /*c1horalim_sup | |c2horalim_sup */ + /*c1veralim_sup +-------------------------------------------+c1veralim_sup */ + /*-----------------------------------------------------------------------------------*/ + + for (face = 0 ; face < NB_FACES; face++) { + if (0 != tab_plots[face].width) { + pistefin = tab_plots[face].coord.piste - 2; /* On part de apres le deport */ + + switch (face) { + case NORD: + case SUD : + segpiste = segx_occ; + c1horalim_sup->xabs = lecoeur.coord.xabs; + c2horalim_sup->xabs = lecoeur.coord.xabs + lecoeur.width; + metalpiste = xmetal; + largmetalpiste = xmetal_width; + break; + + case EST : + case OUEST: + segpiste = segy_occ; + c1horalim_sup->yabs = lecoeur.coord.yabs; + c2horalim_sup->yabs = lecoeur.coord.yabs + lecoeur.height; + metalpiste = ymetal; + largmetalpiste = ymetal_width; + break; + } + + while ((0 != pistefin) && (!segment_libre(c1horalim_sup, c2horalim_sup, pistefin, pistefin, face, + SEG_PISTE, segpiste, metalpiste))) + pistefin--; + + if (0 == pistefin) + ringerreur(ERR_NOPISTE, &face, NULL); + tabpiste[face] = pistefinpardefaut = pistefin; + } else + tabpiste[face] = 0; /* pas de barre de plots, on ne sait pas */ + + } + + for (face = 0; face < NB_FACES; face++) /* maintenant on sait, valeur par defaut */ + if (0 == tabpiste[face]) + tabpiste[face] = pistefinpardefaut; + + /*----------------------- PLACEMENT DES COURONNES -------------------------------------*/ + + for (face = 0 ; face < NB_FACES; face++) { + switch (face) { + case NORD: + case SUD : + segpiste = segx_occ; + metalpiste = xmetal; + largmetalpiste = xmetal_width; + if (coursup == eq_vdd) { + nbpistemoinsalim_sup = nbpistemoinsvdd_xmetal; + wreelalim_sup = wreelvdd_xmetal; + eqalim_sup = equipo_vdd; + nbpistemoinsalim_inf = nbpistemoinsvss_xmetal; + wreelalim_inf = wreelvss_xmetal; + eqalim_inf = equipo_vss; + } else + { + nbpistemoinsalim_sup = nbpistemoinsvss_xmetal; + wreelalim_sup = wreelvss_xmetal; + eqalim_sup = equipo_vss; + nbpistemoinsalim_inf = nbpistemoinsvdd_xmetal; + wreelalim_inf = wreelvdd_xmetal; + eqalim_inf = equipo_vdd; + } + c1veralim_sup->yabs = lecoeur.coord.yabs - ((tabpiste[SUD] - nbpistemoinsalim_sup) * pitch); + c1veralim_sup->xabs = 0; + c2veralim_sup->yabs = lecoeur.coord.yabs + lecoeur.height + ((tabpiste[NORD] - nbpistemoinsalim_sup) * + pitch); + c2veralim_sup->xabs = 0; + + c1veralim_inf->yabs = c1veralim_sup->yabs + ((nbpistemoinsalim_sup + nbpistemoinsalim_inf + 2) * + pitch); + c1veralim_inf->xabs = 0; + c2veralim_inf->yabs = c2veralim_sup->yabs - ((nbpistemoinsalim_sup + nbpistemoinsalim_inf + 2) * + pitch); + c2veralim_inf->xabs = 0; + + c1alim_sup = c1horalim_sup; + c2alim_sup = c2horalim_sup; + c1alim_inf = c1horalim_inf; + c2alim_inf = c2horalim_inf; + break; + + case EST : + case OUEST: + segpiste = segy_occ; + metalpiste = ymetal; + largmetalpiste = ymetal_width; + if (coursup == eq_vdd) { + nbpistemoinsalim_sup = nbpistemoinsvdd_ymetal; + wreelalim_sup = wreelvdd_ymetal; + eqalim_sup = equipo_vdd; + nbpistemoinsalim_inf = nbpistemoinsvss_ymetal; + wreelalim_inf = wreelvss_ymetal; + eqalim_inf = equipo_vss; + } else + { + nbpistemoinsalim_sup = nbpistemoinsvss_ymetal; + wreelalim_sup = wreelvss_ymetal; + eqalim_sup = equipo_vss; + nbpistemoinsalim_inf = nbpistemoinsvdd_ymetal; + wreelalim_inf = wreelvdd_ymetal; + eqalim_inf = equipo_vdd; + } + c1horalim_sup->xabs = lecoeur.coord.xabs - ((tabpiste[OUEST] - nbpistemoinsalim_sup) * pitch); + c1horalim_sup->yabs = 0 ; + c2horalim_sup->xabs = lecoeur.coord.xabs + lecoeur.width + ((tabpiste[EST] - nbpistemoinsalim_sup) * + pitch); + c2horalim_sup->yabs = 0; + c1horalim_inf->xabs = c1horalim_sup->xabs + ((nbpistemoinsalim_sup + nbpistemoinsalim_inf + 2) * + pitch); + c1horalim_inf->yabs = 0; + c2horalim_inf->xabs = c2horalim_sup->xabs - ((nbpistemoinsalim_sup + nbpistemoinsalim_inf + 2) * + pitch); + c2horalim_inf->yabs = 0; + + c1alim_sup = c1veralim_sup; + c2alim_sup = c2veralim_sup; + c1alim_inf = c1veralim_inf; + c2alim_inf = c2veralim_inf; + + break; + } /* fin du switch */ + + pistefin = tabpiste[face]; /* derniere piste libre */ + piste_sup[face] = pistealim = pistefin - nbpistemoinsalim_sup ; + + /*----------------------------- ALIM COURONNE SUPERIEURE ------------------------------*/ + + /* ------------ */ + /* faux segment */ + /* ------------ */ + + for (; pistefin > pistealim; pistefin--) + alloue_etchaine_segment(c1alim_sup, c2alim_sup, pistefin, pistefin, face, SEG_PISTE, segpiste, largmetalpiste, + metalpiste, FAUX_SEG, AVEC_VIA, eqalim_sup); + + /* ------------ */ + /* vrai segment */ + /* ------------ */ + + alloue_etchaine_segment(c1alim_sup, c2alim_sup, pistealim, pistealim, face, SEG_PISTE, segpiste, wreelalim_sup, + metalpiste, VRAI_SEG, AVEC_VIA, eqalim_sup); + + /* ------------ */ + /* faux segment */ + /* ------------ */ + + for (pistefin = pistealim - 1; pistefin >= pistealim - nbpistemoinsalim_sup; pistefin--) + alloue_etchaine_segment(c1alim_sup, c2alim_sup, pistefin, pistefin, face, SEG_PISTE, segpiste, largmetalpiste, + metalpiste, FAUX_SEG, AVEC_VIA, eqalim_sup); + + /*----------------------------- ALIM COURONNE INFERIEURE ------------------------------*/ + + pistefin --; + piste_inf[face] = pistealim = pistefin - nbpistemoinsalim_inf; + + /* ------------ */ + /* faux segment */ + /* ------------ */ + + for (; pistefin > pistealim; pistefin--) + alloue_etchaine_segment(c1alim_inf, c2alim_inf, pistefin, pistefin, face, SEG_PISTE, segpiste, largmetalpiste, + metalpiste, FAUX_SEG, AVEC_VIA, eqalim_inf); + + /* ------------ */ + /* vrai segment */ + /* ------------ */ + + alloue_etchaine_segment(c1alim_inf, c2alim_inf, pistealim, pistealim, face, SEG_PISTE, segpiste, wreelalim_inf, + metalpiste, VRAI_SEG, AVEC_VIA, eqalim_inf); + + /* ------------ */ + /* faux segment */ + /* ------------ */ + + for (pistefin = pistealim - 1; pistefin > pistealim - nbpistemoinsalim_inf - 1; pistefin--) + alloue_etchaine_segment(c1alim_inf, c2alim_inf, pistefin, pistefin, face, SEG_PISTE, segpiste, largmetalpiste, + metalpiste, FAUX_SEG, AVEC_VIA, eqalim_inf); + } /* fin du for */ + +} + +/*-------------------------------------------------------------------------------------*/ + +void tire_etdeport_alim(char *coursup, long piste_sup[NB_FACES], + long piste_inf[NB_FACES], LST_EQUIPO lst_equipo, + BARRE_PLOTS tab_plots[NB_FACES], LST_SEGMENT segx_occ[NB_FACES], + LST_SEGMENT segy_occ[NB_FACES], long tabpiste[NB_FACES]) +{ + LST_EQUIPO equipo_vdd, equipo_vss; + + recherche_equipo_alim(&equipo_vdd, &equipo_vss, lst_equipo); + tire_etdeport_unealim(coursup, eq_vdd, piste_sup, piste_inf, equipo_vdd, tab_plots, segx_occ, segy_occ, tabpiste); + tire_etdeport_unealim(coursup, eq_vss, piste_sup, piste_inf, equipo_vss, tab_plots, segx_occ, segy_occ, tabpiste); + +} + +/*----------------------------------------------------------------------------------------*/ +/* cette procedure tire les fils d'une alim sur la couronne precedemment posees et traite */ +/* les deports eventuels */ +/* On peut se servir de tabpiste pour poser des faux segments, au cas ou on */ +/* tire une alim ds le mauvais layer, ceci pour eviter des croisements */ +/* (courts-circuits) avec les deports eventuels de plots */ +/*----------------------------------------------------------------------------------------*/ + +void tire_etdeport_unealim(char *coursup, char *eq_alim, long piste_sup[NB_FACES], + long piste_inf[NB_FACES], LST_EQUIPO equipo, BARRE_PLOTS tab_plots[NB_FACES], + LST_SEGMENT segx_occ[NB_FACES], LST_SEGMENT segy_occ[NB_FACES], + long tabpiste[NB_FACES]) +{ + chain_list * ptcour; + LST_PSEUDO_CON con; + PT_COORDONNEES c1, c2; + long p1 = 0, p2 = 0, *tabpistealim = NULL, pistealim = 0, largmetalpiste = 0, nbpistemoinsfil = 0, pistefin = 0; + long largmetalcol = 0, piste = 0, largeur = 0; + char niveaucol = 0, niveaupiste = 0; + LST_SEGMENT * segcol = NULL; + LST_SEGMENT * segpiste = NULL; + int visavis; + + /* ---------------------- */ + /* traitement de une alim */ + /* ---------------------- */ + + if (mode_debug) + printf("Traitement segment alim %s\n", eq_alim); + + ptcour = equipo->lst_con; + + if (coursup == eq_alim) + tabpistealim = piste_sup; + else + tabpistealim = piste_inf; + + while (ptcour != NULL) { + con = (LST_PSEUDO_CON) ptcour->DATA; + switch (con->face) { + case NORD: + case SUD : + niveaucol = ymetal; + niveaupiste = xmetal; + segcol = segy_occ; + segpiste = segx_occ; + largmetalpiste = xmetal_width; + largmetalcol = ymetal_width; + break; + + case EST : + case OUEST: + niveaucol = xmetal; + niveaupiste = ymetal; + segcol = segx_occ; + segpiste = segy_occ; + largmetalpiste = ymetal_width; + largmetalcol = xmetal_width; + break; + } /* FIN DU SWITCH */ + + if ((con->coeur_plot == PLOT_CON) && (con->deport != NULL)) { + if (con->nom_con != coursup) /* foutu, on est oblige de deporter arghh */ { + + /* ----------------------- */ + /* deport layer uniquement */ + /* ----------------------- */ + + if (mode_debug) + printf("POSEDEPORTALIM %s\n", con->nom_con); + + c1 = c2 = con->coord; /* segment col */ + p1 = con->deport->piste; /* piste calculee precedemment */ + p2 = tab_plots[con->face].coord.piste; + + /* ------------------------------------------------------------- */ + /* ici ce n'est pas la peine de poser des faux segments, car ils */ + /* ont deja ete poses dans deport_alim() */ + /* ------------------------------------------------------------- */ + + if (segment_libre(c1, c2, p1, p2, con->face, SEG_COL, segcol, con->layer)) + alloue_etchaine_segment(c1, c2, p1, p2, con->face, SEG_COL, segcol, con->largeur, + con->layer, VRAI_SEG, AVEC_VIA, equipo) ; + else + ringerreur(ERR_SEGDEPORT, (void * )con, NULL); + + /* -------------------------------- */ + /* reste du fil jusqu'a la couronne */ + /* -------------------------------- */ + + p2 = p1; + p1 = tabpistealim[con->face]; + + if (segment_libre(c1, c2, p1, p2, con->face, SEG_COL, segcol, niveaucol)) + alloue_etchaine_segment(c1, c2, p1, p2, con->face, SEG_COL, segcol, con->largeur, + niveaucol, VRAI_SEG, AVEC_VIA, equipo); + else + ringerreur(ERR_SEGDEPORT, (void * )con, NULL); + } /* fin trt deport layer plot */ else { + + /* ----------------------------------------- */ + /* on tire le fil d'alim ds le mauvais layer */ + /* ----------------------------------------- */ + + c1 = c2 = con->coord; + p1 = tabpistealim[con->face]; + p2 = tab_plots[con->face].coord.piste; + + /* -------------------------------- */ + /* reste du fil jusqu'a la couronne */ + /* -------------------------------- */ + + /* -------------------------------------------------- */ + /* ALLOCATION DE FAUX SEGMENTS CAR MAUVAIS LAYER TIRE */ + /* -------------------------------------------------- */ + + for (piste = tab_plots[con->face].coord.piste; piste > (tabpiste[con->face] + 1); piste--) + if (segment_libre(c1, c2, piste, piste, con->face, SEG_PISTE, segpiste, niveaupiste)) + alloue_etchaine_segment(c1, c2, piste, piste, con->face, SEG_PISTE, segpiste, + largmetalpiste, niveaupiste, FAUX_SEG, AVEC_VIA, equipo); + else + ringerreur(ERR_TIREALIM, con, NULL); + + if (segment_libre(c1, c2, p1, p2, con->face, SEG_COL, segcol, con->layer)) + alloue_etchaine_segment(c1, c2, p1, p2, con->face, SEG_COL, segcol, con->largeur, + con->layer, VRAI_SEG, AVEC_VIA, equipo); + else + ringerreur(ERR_SEGDEPORT, (void * )con, NULL); + } /* fin du else */ + } /* fin trt deport plot */ else { + if ((COEUR_CON == con->coeur_plot) && (con->deport != NULL)) /* deport coeur */ { + if (mode_debug) + printf("deport coeur %s xdep %ld ydep %ld piste %ld face %d width %ld\n", con->nom_con, + con->deport->xabs, con->deport->yabs, con->deport->piste, (int)con->face, con->largeur); + if (con->layer != niveaucol) /* deport layer */ { + if (mode_debug) + printf("SEGPOSEDEPORTALIM %s\n", con->nom_con); + + c1 = c2 = con->coord; /* segment col */ + p1 = 0; + p2 = con->deport->piste; + + if ((con->face == NORD) || (con->face == SUD)) { + if ((con->deport)->xabs == (con->coord)->xabs) + p2 = con->deport->piste; /* piste calculee precedemment */ + else + p2 = (con->largeur + pitch) / pitch; + } else + { + if ((con->deport)->yabs == (con->coord)->yabs) + p2 = con->deport->piste; /* piste calculee precedemment */ + else + p2 = (con->largeur + pitch) / pitch; + } + + if (segment_libre(c1, c2, p1, p2, con->face, SEG_COL, segcol, con->layer)) + alloue_etchaine_segment(c1, c2, p1, p2, con->face, SEG_COL, segcol, con->largeur, + con->layer, VRAI_SEG, AVEC_VIA, equipo); + else + ringerreur(ERR_SEGDEPORT, (void * )con, NULL); + + if (mode_debug) + printf("seg colonne mauvais layer tire \n"); + + /* --------------------------- */ + /* Allocation de faux segments */ + /* --------------------------- */ + + if (con->largeur > largmetalcol) { + for (piste = 1; piste <= (p2 + (con->largeur / 2 + pitch) / pitch); piste++) + alloue_etchaine_segment(c1, c2, piste, piste, con->face, SEG_PISTE, + segpiste, largmetalpiste, niveaupiste, FAUX_SEG, AVEC_VIA, equipo); + } + + } /* fin trt changement layer */ else { + p1 = 0; + p2 = 0; + c1 = c2 = con->coord; + } + + /* ------------------------------------------- */ + /* pose du reste de fil sur la couronne d'alim */ + /* ------------------------------------------- */ + + if (con->largeur < largmetalcol) + largeur = largmetalcol; + else + largeur = con->largeur; + + if ((con->face == NORD) || (con->face == SUD)) { + if ((con->deport)->xabs == (con->coord)->xabs) /* fil direct sur couronne */ { + p1 = p2; + p2 = tabpistealim[con->face]; + visavis = 0; + } else + visavis = 1; /* vis a vis d'alim */ + + } else { + if ((con->deport)->yabs == (con->coord)->yabs) /* fil direct sur couronne */ { + p1 = p2; + p2 = tabpistealim[con->face]; + visavis = 0; + } else + visavis = 1; /* vis a vis d'alim */ + + } + + if (!visavis) /* pas d'autre deport */ { + if (segment_libre(c1, c2, p1, p2, con->face, SEG_COL, segcol, niveaucol)) { + if (!croisementok_alimequi(con, equipo->lst_con, AVEC_TESTLAYER)) + alloue_etchaine_segment(c1, c2, p1, p2, con->face, SEG_COL, segcol, + largeur, niveaucol, VRAI_SEG, AVEC_VIA, equipo); + else + alloue_etchaine_segment(c1, c2, p1, p2, con->face, SEG_COL, segcol, + largeur, niveaucol, VRAI_SEG, SANS_VIA, equipo); + if (mode_debug) + printf("seg colonne layer tire sans vis a vis \n"); + } else + ringerreur(ERR_SEGDEPORT, (void * )con, NULL); + } else /* Pas de chance , il faut traiter vis a vis d'alim */ { + if (mode_debug) + printf("vis a vis d'alim a traiter\n"); + pistefin = piste_inf[con->face]; + c1 = con->coord; + c2 = con->deport; + + while ((0 != pistefin) && (!segment_libre(c1, c2, pistefin, pistefin, con->face, + SEG_PISTE, segpiste, niveaupiste))) + pistefin--; + + if (0 == pistefin) + ringerreur(ERR_NOPISTE, &(con->face), NULL); + + nbpistemoinsfil = ((con->largeur + pitch) / (2 * pitch )); + pistealim = pistefin - nbpistemoinsfil; + + c2 = con->coord; + p1 = p2; + p2 = pistealim; /* colonne tiree */ + if (segment_libre(c1, c2, p1, p2, con->face, SEG_COL, segcol, niveaucol)) + alloue_etchaine_segment(c1, c2, p1, p2, con->face, SEG_COL, segcol, largeur, + niveaucol, VRAI_SEG, AVEC_VIA, equipo); + else + ringerreur(ERR_SEGDEPORT, (void * )con, NULL); + + c2 = con->deport; + + /* ------------ */ + /* deport piste */ + /* faux segment */ + /* ------------ */ + + for (; pistefin > pistealim; pistefin--) + alloue_etchaine_segment(c1, c2, pistefin, pistefin, con->face, SEG_PISTE, + segpiste, largmetalpiste, niveaupiste, FAUX_SEG, AVEC_VIA, equipo); + + /* ------------ */ + /* vrai segment */ + /* ------------ */ + + alloue_etchaine_segment(c1, c2, pistealim, pistealim, con->face, SEG_PISTE, segpiste, + largeur, niveaupiste, VRAI_SEG, AVEC_VIA, equipo); + + /* ------------ */ + /* faux segment */ + /* ------------ */ + + for (pistefin = pistealim - 1; pistefin >= (pistealim - nbpistemoinsfil); pistefin--) + alloue_etchaine_segment(c1, c2, pistefin, pistefin, con->face, SEG_PISTE, + segpiste, largmetalpiste, niveaupiste, FAUX_SEG, AVEC_VIA, equipo); + + /* ----------------- */ + /* dernier col tiree */ + /* ----------------- */ + + c1 = c2 = con->deport; + p1 = pistealim; + p2 = tabpistealim[con->face]; + if (segment_libre(c1, c2, p1, p2, con->face, SEG_COL, segcol, niveaucol)) + alloue_etchaine_segment(c1, c2, p1, p2, con->face, SEG_COL, segcol, largeur, + niveaucol, VRAI_SEG, AVEC_VIA, equipo); + else + ringerreur(ERR_SEGDEPORT, (void * )con, NULL); + } /* fin trt vis a vis */ + } /* fin trt du fil deporte du coeur */ else { + + /* ----------------------------------- */ + /* trt du fil d'alim sans aucun deport */ + /* reste du fil jusqu'a la couronne */ + /* ----------------------------------- */ + + c1 = c2 = con->coord; + + if (con->coeur_plot == PLOT_CON) { + p2 = tab_plots[con->face].coord.piste; + p1 = tabpistealim[con->face]; + } else { + p1 = 0; + p2 = tabpistealim[con->face]; + } + + if (COEUR_CON == con->coeur_plot) { + if (segment_libre(c1, c2, p1, p2, con->face, SEG_COL, segcol, con->layer)) { + if (!croisementok_alimequi(con, equipo->lst_con, AVEC_TESTLAYER)) + alloue_etchaine_segment(c1, c2, p1, p2, con->face, SEG_COL, segcol, + con->largeur, con->layer, VRAI_SEG, AVEC_VIA, equipo); + else + alloue_etchaine_segment(c1, c2, p1, p2, con->face, SEG_COL, segcol, + con->largeur, con->layer, VRAI_SEG, SANS_VIA, equipo); + } else + ringerreur(ERR_SEGDEPORT, (void * )con, NULL); + } else + { + if (segment_libre(c1, c2, p1, p2, con->face, SEG_COL, segcol, con->layer)) + alloue_etchaine_segment(c1, c2, p1, p2, con->face, SEG_COL, segcol, con->largeur, + con->layer, VRAI_SEG, AVEC_VIA, equipo); + + else + ringerreur(ERR_SEGDEPORT, (void * )con, NULL); + } + + } /* fin trt plot ou coeur alim sans deport */ + } /* fin du if coeur */ + + ptcour = ptcour->NEXT; + } /* fin du while */ + +} diff --git a/alliance/src/ring/src/routalim.h b/alliance/src/ring/src/routalim.h new file mode 100644 index 00000000..e0893be7 --- /dev/null +++ b/alliance/src/ring/src/routalim.h @@ -0,0 +1,22 @@ +#ifndef __ROUTALIM_H +#define __ROUTALIM_H + +#include "struct.h" + +extern void pose_couralim(char *coursup, long piste_sup[NB_FACES], + long piste_inf[NB_FACES], + LST_EQUIPO lst_equipo, COEUR lecoeur, BARRE_PLOTS tab_plots[NB_FACES], + LST_SEGMENT segx_occ[NB_FACES], LST_SEGMENT segy_occ[NB_FACES], + long tabpiste[NB_FACES]); + +extern void tire_etdeport_alim(char *coursup, long piste_sup[NB_FACES], + long piste_inf[NB_FACES], LST_EQUIPO lst_equipo, + BARRE_PLOTS tab_plots[NB_FACES], LST_SEGMENT segx_occ[NB_FACES], + LST_SEGMENT segy_occ[NB_FACES], long tabpiste[NB_FACES]); + +void tire_etdeport_unealim(char *coursup, char *eq_alim, long piste_sup[NB_FACES], + long piste_inf[NB_FACES], LST_EQUIPO equipo, BARRE_PLOTS tab_plots[NB_FACES], + LST_SEGMENT segx_occ[NB_FACES], LST_SEGMENT segy_occ[NB_FACES], + long tabpiste[NB_FACES]); + +#endif /* __ROUTALIM_H */ diff --git a/alliance/src/ring/src/sesame.c b/alliance/src/ring/src/sesame.c new file mode 100644 index 00000000..0240ea52 --- /dev/null +++ b/alliance/src/ring/src/sesame.c @@ -0,0 +1,608 @@ +/* + * 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 support : mailto:alliance-support@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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/****************************************************************************/ +/* */ +/* Chaine de CAO & VLSI Alliance */ +/* */ +/* Produit : ring router */ +/* Fichier : sesame.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 28 avril 92 SESAME.C */ +/* sesame: verification de la coherence des donnees fournies (parametres, netlist, */ +/* fichier parametre) et affichage de message d'ringerreur */ +/*---------------------------------------------------------------------------------*/ + +#include + +#include "sesame.h" + +/*---------------------------------------------------------------------------------*/ + +void ringerreur(int code, void *pt_liste, void *pt_liste2) +{ + loins_list * circuit_inst, *liste_inst; + locon_list * con_lo; + chain_list * liste; + int i, trouve, face; + char car; + LST_PSEUDO_CON con; + long largeurmax; + + switch (code) { + case ERR_CONPH_SANS_LO: + fprintf(stderr, "The physical connector <%s> in model <%s> has no logical corresponding\n",(char *)pt_liste,(char *)pt_liste2); + break; + + case ERR_CONLO_SANS_PH: + fprintf(stderr, "The logical connector <%s> in model <%s> has no physical corresponding\n",(char *)pt_liste,(char *)pt_liste2); + break; + + case ERR_CONCOEUREMPTY: + fprintf(stderr, "The physical core <%s> has no connectors\n",(char *)(((COEUR *)pt_liste)->coeur_lo->INSNAME)); + break; + + case ERR_ARGUMENT: + usage(); + break; + + case ERR_CATAL: + fprintf(stderr, "The catalog file <%s> hasn't been found in MBK_WORK_LIB, and MBK_CATA_LIB path.\n", (char + *) pt_liste); + fprintf(stderr, "See your environment (command \"env\").\n"); + break; + + case ERR_NONCOEUR: + fprintf(stderr, "The instance of the core wasn't found.\n"); + fprintf(stderr, "be carefull: logical figure core and physical figure core\n"); + fprintf(stderr, " must have the same name.\n"); + fprintf(stderr, "The core must not be in the catalog (see MBK_CATAL_NAME in your environment).\n"); + break; + + case ERR_PLUSCOEUR: + fprintf(stderr, "Several instances of the core have been found:\n"); + + circuit_inst = (loins_list * ) pt_liste; + + while (circuit_inst != NULL) { + if (!incatalog(circuit_inst->FIGNAME)) + fprintf(stderr, "\tcore name: %s\n", circuit_inst->INSNAME); + + circuit_inst = circuit_inst->NEXT; + } + break; + + case ERR_CIRCUITLO: + fprintf(stderr, "The figure named <%s> hasn't been found.\n", (char *) pt_liste); + break; + + case ERR_CIRCUITINST: + fprintf(stderr, "The figure named <%s> doesn't own any instance.\n", (char *) pt_liste); + break; + + case ERR_COEURINSTLO: + fprintf(stderr, "The logical instance core which name is <%s>, hasn't been found.\n", (char *) pt_liste); + fprintf(stderr, "Logical and physical figure core must have the same name.\n"); + + break; + + case ERR_COEURINSTPH: + fprintf(stderr, "The physical instance core which name is <%s>, hasn't been found.\n", (char *) pt_liste); + fprintf(stderr, "Logical and physical figure core must have the same name.\n"); + break; + + case ERR_FICPARAM: + fprintf(stderr, "The parameter file <%s> doesn't exist.\n", (char *) pt_liste); + fprintf(stderr, "It must be present in your MBK path.\n"); + break; + + case ERR_VIDEFICPARAM: + fprintf(stderr, "The parameter file <%s> is empty.\n", (char *) pt_liste); + break; + + case ERR_SYNPARAM: + fprintf(stderr, "Syntax error from the analysis of the parameter file .rin <%s>\n: ", + nom_fic_param); +#if 0 + if ((fichier = mbkfopen(nom_fic_param, NULL, READ_TEXT)) != NULL) { + tmp = (char *) mbkalloc (800 * (unsigned int) sizeof(char)); + for (i = 0; i < (*((int *) pt_liste)); i++) + ret = fgets(tmp, 799, fichier); + if (NULL != ret) + fprintf(stderr, "%s\n", tmp); + fclose(fichier); + } +#endif + fprintf(stderr, "Warning: if you use # for comments, the rest of the line will be ignored.\n"); + + break; + + case ERR_WIDTHPARAM: + fprintf(stderr, "the width track <%d> of <%s> is too small.\n", *((int *)pt_liste2), (char *)pt_liste); + break; + + case ERR_AUCUNPLOTPARAM: + fprintf(stderr, "No pad has been founded in the paramater file .rin.\n"); + fprintf(stderr, "You must define at least one group of pads.\n"); + break; + + case ERR_NONPLOTPARAM: + fprintf(stderr, "The instance pad <%s> hasn't been found in the logical figure.\n", (char *) pt_liste); + break; + + case ERR_PLUSPLOTPARAM: + fprintf(stderr, "The instance of the pad <%s>, has been found\n", (char *) pt_liste); + fprintf(stderr, "in different sections of pads in the parameter file .rin.\n"); + break; + + case ERR_NBPLOTPARAM: + fprintf(stderr, "Some instance pads of the logical figure\n"); + fprintf(stderr, "haven't been found in the parameter file.\n"); + + /* ---------------------------------------------------------------------------------- */ + /* Affichage des plots de la figure logique non trouves dans le fichier de parametres */ + /* ---------------------------------------------------------------------------------- */ + + liste_inst = ((lofig_list * ) pt_liste)->LOINS; + + /* ------------------------------- */ + /* Parcours des instances logiques */ + /* ------------------------------- */ + + while (liste_inst != NULL) { + trouve = 0; + + /* -------------------------------------------------------- */ + /* Parcours des noms d'instances definis dans fichier param */ + /* -------------------------------------------------------- */ + + for (i = 0; ((i < NB_FACES) && (!trouve)); i++) { + liste = nom_plot[i]; + + while (liste != NULL) { + + /* ------------------------------------------------------------------------- */ + /* si trouve , on sort du while et du for, et on passe a l'instance suivante */ + /* modif : chain_list pointe sur des loins maintenant */ + /* ------------------------------------------------------------------------- */ + + if ((trouve = liste_inst->INSNAME == ((loins_list * ) liste->DATA)->INSNAME )) + break; + + liste = liste->NEXT; + } + } + + if ((!trouve) && (incatalog(liste_inst->FIGNAME))) + fprintf(stderr, "\tInstance not found: <%s>\n", liste_inst->INSNAME); + + liste_inst = liste_inst->NEXT; + } + + break; + + case ERR_NONCONWIDTHPARAM: + fprintf(stderr, "The connector <%s> from the parameter file hasn't been found\n", (char *) pt_liste); + fprintf(stderr, "as a logical connector of a pad, or as a physical connector\n"); + fprintf(stderr, "of the core.\n"); + break; + + case ERR_INTERNE_CON: + fprintf(stderr, "Internal error from the connector list.\n"); + break; + + case ERR_INTERNE_FIG: + fprintf(stderr, "Internal error from the physical figure list.\n"); + break; + + case ERR_INTERNE_EQ: + fprintf(stderr, "Internal error from the equipotential list.\n"); + break; + + case ERR_GRILLEINTERNE: + fprintf(stderr, "Internal error from the gate list.\n"); + break; + + case ERR_CONCOEUR_ENLAIR : + fprintf(stderr, "Connector <%s> of the core isn't connected.\n", (char *) pt_liste); + break; + + case ERR_CONPLOT_ENLAIR : + fprintf(stderr, "Connector <%s> of the pad isn't connected.\n", (char *) pt_liste); + break; + + case ERR_CONLARGEUR: + if (ymetal_width > xmetal_width) + largeurmax = ymetal_width; + else + largeurmax = xmetal_width; + + if (((LST_PSEUDO_CON) pt_liste)->coeur_plot == COEUR_CON) { + fprintf(stderr, "Width of the connector <%s> is <%ld> of the core ", ((LST_PSEUDO_CON) pt_liste)->nom_con, + ((LST_PSEUDO_CON) pt_liste)->largeur / SCALE_X); + if (((LST_PSEUDO_CON) pt_liste)->largeur > largeurmax) + fprintf(stderr, "is too big.\n"); + else + fprintf(stderr, "isn't big enough.\n"); + } else { + fprintf(stderr, "Width of the connector <%s> is <%ld> of the pad <%s> ", ((LST_PSEUDO_CON) pt_liste)->nom_con, + ((LST_PSEUDO_CON) pt_liste)->largeur / SCALE_X, ((loins_list * )((LST_PSEUDO_CON) pt_liste)->con_lo->ROOT)->INSNAME); + if (((LST_PSEUDO_CON) pt_liste)->largeur > largeurmax) + fprintf(stderr, "is too big.\n"); + else + fprintf(stderr, "isn't big enough.\n"); + } + + break; + case ERR_CONDISTANCE: + con = (LST_PSEUDO_CON) pt_liste; + if (con->coeur_plot == COEUR_CON) { + if (con->prec != NULL) + fprintf(stderr, "Distance between connector <%s> and connector <%s> of the core isn't big enough.\n", + (con->prec)->nom_con, con->nom_con); + /* con->prec si pas d'ringerreur c'est lesieur */ + else + fprintf(stderr, "Distance between connector <%s> and... of the core isn't big enough.\n", con->nom_con); + } else { + if (con->prec != NULL) + fprintf(stderr, "Distance between connector <%s> of the pad <%s>, and connector <%s> of the pad <%s> isn't big enough.\n", + (con->prec)->nom_con, ((loins_list * )(con->prec)->con_lo->ROOT)->INSNAME, con->nom_con, + ((loins_list * )con->con_lo->ROOT)->INSNAME); + /* con->prec si pas d'ringerreur c'est lesieur */ + else + fprintf(stderr, "Distance between connector <%s> of the pad <%s> and... of the core isn't big enough.\n", + con->nom_con, ((loins_list * ) con->con_lo->ROOT)->INSNAME); + } + + break; + + case ERR_MANQUEALIM: + fprintf(stderr, "Power supply and/or weren't found in the chip.\n"); + break; + + case ERR_BARREALIM : + face = *((int *) pt_liste); + switch (face) { + case NORD: + car = 'N'; + break; + case SUD : + car = 'S'; + break; + case EST: + car = 'E'; + break; + case OUEST: + car = 'W'; + break; + default: + car = 'X'; + break; + } + + fprintf(stderr, "The pads and/or aren't place in front of the side '%c' of the core.\n", car); + fprintf(stderr, "You may place again the supply pads, in order to center them in front of the core.\n"); + break; + + case ERR_ECHECDEPORT : + con = (LST_PSEUDO_CON) pt_liste; + fprintf(stderr, "No space hasn't been found for the connector <%s> of the instance <%s>.\n", con->nom_con, + ((loins_list * )(con->con_lo)->ROOT)->INSNAME); + break; + + case ERR_SEGDEPORT : + con = (LST_PSEUDO_CON) pt_liste; + fprintf(stderr, "No space hasn't been found for the deport of the connector <%s> of the instance <%s>.\n", + con->nom_con, ((loins_list * )(con->con_lo)->ROOT)->INSNAME); + break; + + case ERR_NOPISTE : + face = *((int *) pt_liste); + switch (face) { + case NORD: + car = 'N'; + break; + case SUD : + car = 'S'; + break; + case EST: + car = 'E'; + break; + case OUEST: + car = 'W'; + break; + default: + car = 'X'; + break; + } + + fprintf(stderr, "No space has been found in side %c to put the power supply and around the core.\n", + car); + break; + + case ERR_NOCOL : + con = (LST_PSEUDO_CON) pt_liste; + face = con->face; + switch (face) { + case NORD: + car = 'N'; + break; + case SUD : + car = 'S'; + break; + case EST: + car = 'E'; + break; + case OUEST: + car = 'W'; + break; + default: + car = 'X'; + break; + } + + fprintf(stderr, "No space has been found in side '%c', in order to put the connector <%s> of the instance <%s> on the ring.\n", + car, con->nom_con, ((loins_list * ) (con->con_lo)->ROOT)->INSNAME); + break; + + case ERR_INSTPH_PLOT: + fprintf(stderr, "The physical instance of the pad <%s> hasn't been found in the circuit.\n", (char *) pt_liste); + break; + + case ERR_NOCONPH_PLOT: + con_lo = (locon_list * ) pt_liste; + fprintf(stderr, "The connector <%s> hasn't been found as an external connector of the pad <%s>.\n", con_lo->NAME, + ((loins_list * )con_lo->ROOT)->INSNAME); + break; + + case ERR_FIGPH_PLOT: + fprintf(stderr, "The physical figure of pad <%s> hasn't been found.\n", (char *) pt_liste); + break; + + case ERR_CONEXT_ENLAIR: + fprintf(stderr, "The connector <%s> of the circuit isn't connected to a pad.\n", (char *) pt_liste); + break; + + case ERR_NBCONESTOUEST: + fprintf(stderr, "There isn't the same number of physical connectors on side east and west from the model of pad <%s>\n", + (char *) ((phfig_list * ) pt_liste)->NAME) ; + fprintf(stderr, "It's impossible to link this pad to the others.\n"); + break; + + case ERR_NOCONPH: + fprintf(stderr, "The connector <%s> of the figure pad <%s> hasn't been found or doesn't have the physical features required.\n", + (char *) ((phcon_list * )pt_liste)->NAME, (char *) ((phfig_list * )pt_liste2)->NAME); + break; + + case ERR_EQINTERNE: + liste = (chain_list * ) pt_liste; + fprintf(stderr, "Some errors have been found in the internal equipotential list, pad connectors must be on the internal side of pads.\n"); + fprintf(stderr, "That's to say, your C file using GENLIB functions may be wrong.\n"); + fprintf(stderr, "The following connector names do not belong to the SOUTH side of the figure of pads.\n"); + + while (NULL != liste) { + fprintf(stderr, "- The connector <%s> of the instance pad <%s> isn't placed on the SOUTH side.\n", + (char *)liste->NEXT->DATA, (char *)liste->DATA); + liste = liste->NEXT->NEXT; + } + + break; + + case ERR_EQEXTERNE: + liste = (chain_list * ) pt_liste; + fprintf(stderr, "Some errors have been found in the external equipotential list, pad connectors must be on the external side of pads.\n"); + fprintf(stderr, "That's to say, your C file using GENLIB functions may be wrong.\n"); + fprintf(stderr, "The following connector names do not belong to the NORTH side of the figure of pads.\n"); + + while (NULL != liste) { + fprintf(stderr, "- The connector <%s> of the instance pad <%s> isn't placed on the NORTH side.\n", + (char *)liste->NEXT->NEXT->DATA, (char *)liste->NEXT->DATA); + fprintf(stderr, "- It isn't possible to link it with the connector <%s> of the circuit.\n", (char + *)liste->DATA); + liste = liste->NEXT->NEXT->NEXT; + } + + break; + + case ERR_TIREALIM: + fprintf(stderr, "The supply connector <%s> of the pad <%s> cannot be routed, there's no place.\n", ((LST_PSEUDO_CON) pt_liste)->nom_con, + ((loins_list * )((LST_PSEUDO_CON) pt_liste)->con_lo->ROOT)->INSNAME); + fprintf(stderr, "You may center this pad, in the pad section of your parameter file .rin.\n"); + break; + + default: + fprintf(stderr, "Unknown error code: <%d>.\n", code); + } + + exit(code); +} + +/*---------------------------------------------------------------------------------*/ +void usage () +{ + fprintf(stderr, "Usage : ring source result [stat]\n"); + EXIT(1); +} + +/*------------------------------------------------------------------------*/ +void banner() +{ + alliancebanner("RinG", VERSION, "PAD ring router", "1991", "5.0"); +} + +/*----------------------------------------------------------------------*/ +/* cette procedure verifie les equipotentielles internes, c'est a dire */ +/* que tous les connecteurs de plot doivent etre des connnecteurs */ +/* sud du modele physique, sinon ca veut dire qu'il a des equipo */ +/* interdites qui ont ete fabriquees par genlib dans le fichier */ +/* de description C. */ +/*----------------------------------------------------------------------*/ + +void verif_eq_interne(LST_EQUIPO lst_equipo, chain_list *liste_plotsph) +{ + chain_list * lst_con, *lsterr = NULL; + LST_PSEUDO_CON con; + + while (NULL != lst_equipo) { + lst_con = lst_equipo->lst_con; + + while (NULL != lst_con) { + con = (LST_PSEUDO_CON) lst_con->DATA; + + if (con->coeur_plot == PLOT_CON) { + if (!existe_leconnecteur_faceplot(((loins_list * )con->con_lo->ROOT)->FIGNAME, con->con_lo->NAME, SUD, liste_plotsph)) { + lsterr = addchain(lsterr, (void * ) con->con_lo->NAME); + lsterr = addchain(lsterr, (void * ) (((loins_list * )con->con_lo->ROOT)->INSNAME)); + } + } + lst_con = lst_con->NEXT; + } + lst_equipo = lst_equipo->suiv; + } + + if (NULL != lsterr) + ringerreur(ERR_EQINTERNE, (void * )lsterr, (void*) NULL); + +} + +/* ---------------------------------------------------------------------------------------- */ +/* Fonction qui regarde si le modele physique possede des connecteurs sur une certaine face */ +/* ---------------------------------------------------------------------------------------- */ + +int existe_leconnecteur_faceplot(char* figure, char* conname, int face, + chain_list *liste_plotsph) +{ + phfig_list * modele; + phcon_list * liste_con; + char orient = '0'; + + if (mode_debug) + printf("Existe-t-il le con %s au %d figure %s\n", conname, face, figure); + + switch (face) { + case NORD: + orient = 'N'; + break; + + case SUD : + orient = 'S'; + break; + + case OUEST: + orient = 'W'; + break; + + case EST : + orient = 'E'; + break; + } + + if ((modele = appartient_listeplotsph(figure, liste_plotsph)) != NULL) { + + liste_con = modele->PHCON; + + while (liste_con != NULL) { + if ((liste_con->NAME == conname) && (liste_con->ORIENT == orient)) { + if (mode_debug) + printf("Il existe ok\n."); + return (1); + } + + liste_con = liste_con->NEXT; + } + + if (mode_debug) + printf("Il n'existe PAS\n."); + return(0); /* connecteur de la face non trouve */ + } + + if (mode_debug) + printf("Il n'existe PAS\n."); + return(0); /* Modele physique non existant ! */ + +} + +/*-------------------------------------------------------------*/ +/* testcon_modelfig() */ +/* check for all instanciated models in logic figure: */ +/* - if each logical connector has at least one corresponding */ +/* physical connector. */ +/* - if each physical connector has one corresponding */ +/* logical connector. */ +/*-------------------------------------------------------------*/ + +void testcon_modelfig(lofig_list* ptfiglo) +{ + chain_list * ptcmodel; + char *ptmodel; + lofig_list * ptfigins_lo; + phfig_list * ptfigins_ph; + locon_list * ptconlo; + phcon_list * ptconph; + char *loconname; + char *phconname; + + for (ptcmodel = ptfiglo->MODELCHAIN; ptcmodel; ptcmodel = ptcmodel->NEXT) { + ptmodel = (char *)ptcmodel->DATA; + ptfigins_lo = getlofig(ptmodel, 'P'); + ptfigins_ph = getphfig(ptmodel, 'P'); + for (ptconlo = ptfigins_lo->LOCON; ptconlo; ptconlo = ptconlo->NEXT) { + loconname = ptconlo->NAME; + if (isvdd(loconname)) loconname = eq_vdd; + if (isvss(loconname)) loconname = eq_vss; + for (ptconph = ptfigins_ph->PHCON; ptconph; ptconph = ptconph->NEXT) { + phconname = ptconph->NAME; + if (isvdd(phconname)) phconname = eq_vdd; + if (isvss(phconname)) phconname = eq_vss; + if (phconname == loconname) break; + } + if (!ptconph) { + ringerreur(ERR_CONLO_SANS_PH, loconname, ptmodel); + } + } + for (ptconph = ptfigins_ph->PHCON; ptconph; ptconph = ptconph->NEXT) { + phconname = ptconph->NAME; + if (isvdd(phconname)) phconname = eq_vdd; + if (isvss(phconname)) phconname = eq_vss; + for (ptconlo = ptfigins_lo->LOCON; ptconlo; ptconlo = ptconlo->NEXT) { + loconname = ptconlo->NAME; + if (isvdd(loconname)) loconname = eq_vdd; + if (isvss(loconname)) loconname = eq_vss; + if (phconname == loconname) break; + } + if (!ptconlo) { + ringerreur(ERR_CONPH_SANS_LO, phconname, ptmodel); + } + } + } +} diff --git a/alliance/src/ring/src/sesame.h b/alliance/src/ring/src/sesame.h new file mode 100644 index 00000000..914176b0 --- /dev/null +++ b/alliance/src/ring/src/sesame.h @@ -0,0 +1,13 @@ +#ifndef __SESAME_H +#define __SESAME_H + +#include "struct.h" +extern void ringerreur(int code, void *pt_liste, void *pt_liste2); +extern void usage (); +extern void banner(); +extern void verif_eq_interne(LST_EQUIPO lst_equipo, chain_list *liste_plotsph); +extern int existe_leconnecteur_faceplot(char* figure, char* conname, int face, + chain_list *liste_plotsph); +extern void testcon_modelfig(lofig_list* ptfiglo); + +#endif /* __SESAME_H */ diff --git a/alliance/src/ring/src/stat.c b/alliance/src/ring/src/stat.c new file mode 100644 index 00000000..f40173fe --- /dev/null +++ b/alliance/src/ring/src/stat.c @@ -0,0 +1,135 @@ +/* + * 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 support : mailto:alliance-support@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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +/****************************************************************************/ +/* */ +/* Chaine de CAO & VLSI Alliance */ +/* */ +/* Produit : ring router */ +/* Fichier : status.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 28 aout 92 STAT.C */ +/* Emission de statistiques sur les equipotentielles, un fichier de stat est cree */ +/*--------------------------------------------------------------------------------*/ + +#include "stat.h" +#include "sesame.h" + +extern long bigvias, ringvias; + +/*-----------------------------------------------------------------------------------*/ +void remplit_stat(LST_SEGMENT seg, LST_EQUIPO eq) +{ + + switch (seg->layer) { + case ALU1: + if (seg->c1 == seg->c2) { + eq->status.lg_a1 += ((seg->piste2 - seg->piste1) * pitch / lambda); + eq->status.su_a1 += (((seg->piste2 - seg->piste1) * pitch / lambda) * (seg->largeur / lambda)); + } else if ((seg->face == NORD) || (seg->face == SUD)) { + eq->status.lg_a1 += ((seg->c2->xabs - seg->c1->xabs) / lambda); + eq->status.su_a1 += (((seg->c2->xabs - seg->c1->xabs) / lambda) * (seg->largeur / lambda)); + } else + { + eq->status.lg_a1 += ((seg->c2->yabs - seg->c1->yabs) / lambda); + eq->status.su_a1 += (((seg->c2->yabs - seg->c1->yabs) / lambda) * (seg->largeur / lambda)); + } + break; + + case ALU2: + if (seg->c1 == seg->c2) { + eq->status.lg_a2 += ((seg->piste2 - seg->piste1) * pitch / lambda); + eq->status.su_a2 += (((seg->piste2 - seg->piste1) * pitch / lambda) * (seg->largeur / lambda)); + } else if ((seg->face == NORD) || (seg->face == SUD)) { + eq->status.lg_a2 += ((seg->c2->xabs - seg->c1->xabs) / lambda); + eq->status.su_a2 += (((seg->c2->xabs - seg->c1->xabs) / lambda) * (seg->largeur / lambda)); + } else + { + eq->status.lg_a2 += ((seg->c2->yabs - seg->c1->yabs) / lambda); + eq->status.su_a2 += (((seg->c2->yabs - seg->c1->yabs) / lambda) * (seg->largeur / lambda)); + } + break; + } /* fin switch */ + +} + +void finir_stat(LST_EQUIPO eq) +{ + FILE * ficstat; + static long totlga1, totlga2, totsua1, totsua2, totnbvias; + + if ((ficstat = mbkfopen(nomfic_stat, NULL, WRITE_TEXT)) == NULL) + ringerreur(ERR_FICSTAT, nomfic_stat, NULL); + + fprintf(ficstat, "#\t\t\t *** STATISTIC FILE < %s > ***\n\n\n", nomfic_stat); + fprintf(ficstat, "\t\t\t Equipotential list : \n\n"); + + fprintf(ficstat, " index | name | length alu1 | length alu2 | area alu1 | area alu2 | nb vias\n\n"); + + fprintf(ficstat, "__________________________________________________________________________________________________________________\n"); + while (NULL != eq) { + fprintf(ficstat, " %3ld | %20s |", eq->index, ((LST_PSEUDO_CON)eq->lst_con->DATA)->nom_con); + + fprintf(ficstat, " %7ld | %7ld | %10ld | %10ld | %7ld\n\n", eq->status.lg_a1, eq->status.lg_a2, + eq->status.su_a1, eq->status.su_a2, eq->status.nb_vias); + + if (((LST_PSEUDO_CON)eq->lst_con->DATA)->coeur_plot == PLOT_CON) + fprintf(ficstat, " (%20s)\n", ((loins_list * )((LST_PSEUDO_CON)eq->lst_con->DATA)->con_lo->ROOT)->INSNAME); + fprintf(ficstat, "__________________________________________________________________________________________________________________\n"); + totlga1 += eq->status.lg_a1; + totlga2 += eq->status.lg_a2; + totsua1 += eq->status.su_a1; + totsua2 += eq->status.su_a2; + totnbvias += eq->status.nb_vias; + eq = eq->suiv; + } + + fprintf(ficstat, "\n\nTotal length alu1 : %10ld (lambdas)\n", totlga1); + fprintf(ficstat, "Total length alu2 : %10ld (lambdas)\n", totlga2); + fprintf(ficstat, "Total area alu1 : %10ld (lambdas * lambdas)\n", totsua1); + fprintf(ficstat, "Total area alu2 : %10ld (lambdas * lambdas)\n", totsua2); + fprintf(ficstat, "Total of vias : %10ld\n", totnbvias); + + fclose(ficstat); + +} + +void maj_stat_vias(LST_EQUIPO eq, long ancr, long ancp, long r, long p) +{ + + if (mode_debug) + eq->status.nb_vias += (r - ancr); /* maj couronne nb vias */ + else + eq->status.nb_vias += (p - ancp); /* maj pave nb vias */ +} diff --git a/alliance/src/ring/src/stat.h b/alliance/src/ring/src/stat.h new file mode 100644 index 00000000..ca1138d5 --- /dev/null +++ b/alliance/src/ring/src/stat.h @@ -0,0 +1,10 @@ +#ifndef __STAT_H +#define __STAT_H + +#include "struct.h" + +extern void remplit_stat(LST_SEGMENT seg, LST_EQUIPO eq); +extern void finir_stat(LST_EQUIPO eq); +extern void maj_stat_vias(LST_EQUIPO eq, long ancr, long ancp, long r, long p); + +#endif /* __STAT_H */ diff --git a/alliance/src/ring/src/struct.c b/alliance/src/ring/src/struct.c new file mode 100644 index 00000000..0f2a813c --- /dev/null +++ b/alliance/src/ring/src/struct.c @@ -0,0 +1,1646 @@ +/* + * 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 support : mailto:alliance-support@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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/****************************************************************************/ +/* */ +/* Chaine de CAO & VLSI Alliance */ +/* */ +/* Produit : ring router */ +/* Fichier : struct.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 15 juillet 92 STRUCT.C */ +/* Fonctions qui manipulent les structures de donnees definies ds struct.h */ +/*-----------------------------------------------------------------------------------*/ + +#include + +#include "struct.h" +#include "sesame.h" +#include "placement.h" + +/*-----------------------------------------------------------------------------------*/ +/* Ajout d'un modele physique de plot dans la liste s'il n'existe pas deja */ +/* Renommage des connecyteurs vdd et vss */ +/*-----------------------------------------------------------------------------------*/ + +void ajout_listeplotsph(modele_plot, liste_plotsph) +char *modele_plot; +chain_list **liste_plotsph; +{ + static char first = 1; + /* first indique que c'est la premiere fois: liste non initialisee */ + + if (first) { + first = 0; + *liste_plotsph = NULL; + ignoble_multiple_ck_delete_from_south_side(modele_plot); + *liste_plotsph = addchain(*liste_plotsph, (void * ) getphfig(modele_plot, 'A')); + rename_vddxvssx(modele_plot); + } else if (appartient_listeplotsph(modele_plot, *liste_plotsph) == NULL) { + ignoble_multiple_ck_delete_from_south_side(modele_plot); + *liste_plotsph = addchain(*liste_plotsph, (void * ) getphfig(modele_plot, 'A')); + rename_vddxvssx(modele_plot); + } +} + +/*-----------------------------------------------------------------------------------*/ +/* Cette fonction renomme tous les connecteurs physiques MBK vdd* vss* */ +/* en vdd et vss, ceci pour uniformiser les noms d'alim interne */ +/*-----------------------------------------------------------------------------------*/ + +void rename_vddxvssx(modele_plot) +char *modele_plot; +{ + phfig_list * ptplot = getphfig(modele_plot, 'A'); + phcon_list * ptcon; + + ptcon = ptplot->PHCON; + + while (NULL != ptcon) { + if ((ptcon->ORIENT != 'S') && (ptcon->ORIENT != 'N')) + { + if (isvdd(ptcon->NAME)) + ptcon->NAME = eq_vdd; + else if (isvss(ptcon->NAME)) + ptcon->NAME = eq_vss; + } + ptcon = ptcon->NEXT; + } + +} + + +/*-----------------------------------------------------------------------------------*/ +/* this function deletes multiple occurences of ck connector placed at the south */ +/* side. It should be suppressed from the future verions (02/16/95) */ +/*-----------------------------------------------------------------------------------*/ + +void ignoble_multiple_ck_delete_from_south_side(modele_plot) +char *modele_plot; +{ + phfig_list * ptplot = getphfig(modele_plot, 'A'); + phcon_list * ptcon, * ptcon_next; + + int already_one_alu1 = 0; + int already_one_alu2 = 0; + + ptcon = ptplot->PHCON; + while (NULL != ptcon) { + ptcon_next = ptcon->NEXT; + if (mode_debug) + printf("CONNECTOR %s %ld %ld\n",ptcon->NAME,ptcon->XCON,ptcon->YCON); + if ((ptcon->ORIENT == 'S') && (ptcon->NAME == namealloc("cko"))) { + if (ptcon->LAYER == ALU1) { + if (already_one_alu1) { + delphcon( ptplot, ptcon); + if (mode_debug) + printf("delete %s %ld %ld\n",ptcon->NAME,ptcon->XCON,ptcon->YCON); + } else { + already_one_alu1++; + } + } else { + if (ptcon->LAYER == ALU2) { + if (already_one_alu2) { + delphcon( ptplot, ptcon); + if (mode_debug) + printf("delete %s %ld %ld\n",ptcon->NAME,ptcon->XCON,ptcon->YCON); + } else { + already_one_alu2++; + } + } + } + } + ptcon = ptcon_next; + } +} + +/*------------------------------------------------------------------------------------------*/ +/* Fonction qui regarde si le modele physique possede des connecteurs sur une certaine face */ +/*------------------------------------------------------------------------------------------*/ + +int existe_connecteur_faceplot(figure, face, liste_plotsph) +char *figure; +int face; +chain_list *liste_plotsph; +{ + phfig_list * modele; + phcon_list * liste_con; + char orient = 0; + + switch (face) { + case NORD: + orient = 'N'; + break; + + case SUD : + orient = 'S'; + break; + + case OUEST: + orient = 'W'; + break; + case EST : + orient = 'E'; + break; + } + + if ((modele = appartient_listeplotsph(figure, liste_plotsph)) != NULL) { + + liste_con = modele->PHCON; + + while (liste_con != NULL) { + if (liste_con->ORIENT == orient) + return (1); + liste_con = liste_con->NEXT; + } + + return(0); /* connecteur de la face non trouve */ + } + + return(0); /* Modele physique non existant ! */ + +} + +/*----------------------------------------------------------------------------------------*/ +/* cette fonction retourne la figure physique si le modele appartient a la liste, 0 sinon */ +/*----------------------------------------------------------------------------------------*/ + +phfig_list * appartient_listeplotsph(modele, liste) +char *modele; +chain_list *liste; +{ + + while (liste != NULL) /* strcmp inutile, comparaison de pointeurs */ { + if (((phfig_list * ) liste->DATA)->NAME == modele) + return((phfig_list * )liste->DATA); + liste = liste->NEXT; + } + + return(NULL); +} + +/*-----------------------------------------------------------------------------------*/ +/* affichage de la liste des modeles de plots */ +/*-----------------------------------------------------------------------------------*/ + +void affic_listeplotsph(liste) +chain_list *liste; +{ + printf("\n"); + printf("Listeplotsph *****************************\n"); + while (liste != NULL) { + printf("Plot: %s\n", ((phfig_list * )liste->DATA)->NAME); + /* viewphfig((phfig_list*)liste->DATA); */ + liste = liste->NEXT; + } + +} + +/*------------------------------------------------------------------------------------*/ +/* cette fonction retourne le pointeur sur l'instance logique si le nom de l'instance */ +/* du plot appartient a la figure logique et est un plot , NULL sinon */ +/*------------------------------------------------------------------------------------*/ + +loins_list*existe_plot_circuit(nom, circuit_lo) +char *nom; +lofig_list *circuit_lo; + +{ + loins_list * circuit_inst = circuit_lo->LOINS; + + while (circuit_inst != NULL) { + /* if (mode_debug) printf("nom %s %d instance %s %d\n",nom,(int) nom,circuit_inst->INSNAME,(int) + circuit_inst->INSNAME); + */ + + if ((nom == circuit_inst->INSNAME) && (incatalog(circuit_inst->FIGNAME))) + return(circuit_inst); /* plot et nom d'instance trouve */ + + circuit_inst = circuit_inst->NEXT; + } + + return(NULL); /* plot avec nom d'instance non trouve */ +} + +/*-----------------------------------------------------------------------------------*/ +/* cette fonction retourne 1 s'il existe une seule occurence du nom plot */ +/* dans le tableau des faces du plots, sinon 0 si plusieurs fois le meme nom */ +/*-----------------------------------------------------------------------------------*/ + +int uneseuleoccurence(nom, tab) +char *nom; +chain_list *tab[NB_FACES]; +{ + + int i; + chain_list * liste; + char *nomplot; + int cptoccur = 0; + + for (i = 0; i < NB_FACES; i++) { + + liste = tab[i]; + while (liste != NULL) { + nomplot = (char *)(liste->DATA); + + if (nom == nomplot) + cptoccur++; /* nombre d'occurrence du nom */ + liste = liste->NEXT; + } + + } + + if (cptoccur == 1) + return(1); /* une seule occurence trouvee */ + + return(0); /* plusieurs occurences du meme nom */ + +} + +/*--------------------------------------------------------------------------------------*/ +/* cette fonction rend 1 si le nom correspond a un connecteur du coeur ou des instances */ +/* plots. Si le nom n'existe pas retourne 0. On travaille avec les vues logiques coeur */ +/* et circuit */ +/*--------------------------------------------------------------------------------------*/ + +int existe_signal_circuit(cell, circuit_lo, lecoeur) +chain_list *cell; +lofig_list *circuit_lo; +COEUR lecoeur; +{ + + locon_list * coeur_con = (lecoeur.coeur_lo)->LOCON; + loins_list * circuit_instlo = circuit_lo->LOINS; + locon_list * liste_con; + char *nom; + + nom = ((PTCEL) cell->DATA)->chaine; + + /* ------------------------ */ + /* On commence par le coeur */ + /* ------------------------ */ + + while (coeur_con != NULL) { + if (nom == coeur_con->NAME) { + ((PTCEL)cell->DATA)->con_lo = coeur_con; /* pointeur sur connecteur physique */ + return(1); /* connecteur trouve */ + } + + coeur_con = coeur_con->NEXT; + } + + while (circuit_instlo != NULL) { + liste_con = circuit_instlo->LOCON; + + while (liste_con != NULL) { + if (nom == liste_con->NAME) { + ((PTCEL)cell->DATA)->con_lo = liste_con; + return(1); /* connecteur trouve */ + } + + liste_con = liste_con->NEXT; + } + circuit_instlo = circuit_instlo->NEXT; + } + + return(0); /* le connecteur correspondant n'a pas ete trouve */ + +} + +/*-----------------------------------------------------------------------------------*/ +/* procedure appellee par yacc, declaration de plots face nord, Tableau de listes */ +/* de chaine de caracteres declaree en globale */ +/*-----------------------------------------------------------------------------------*/ + +void declaration_plot_n(ident) +char *ident; +{ + static int first = 1; + + if (mode_debug) + printf("declaration plot nord\n"); + + if (first) { + first = 0; + nom_plot[NORD] = NULL; + } + + nom_plot[NORD] = addchain(nom_plot[NORD], (void * ) namealloc(ident)); +} + +/*-----------------------------------------------------------------------------------*/ +/* procedure appellee par yacc, declaration de plots face sud, Tableau de listes */ +/* de chaine de caracteres declaree en globale */ +/*-----------------------------------------------------------------------------------*/ + +void declaration_plot_s(ident) +char *ident; +{ + static int first = 1; + + if (mode_debug) + printf("declaration plot sud\n"); + if (first) { + first = 0; + nom_plot[SUD] = NULL; + } + + nom_plot[SUD] = addchain(nom_plot[SUD], (void * ) namealloc(ident)); +} + +/*-----------------------------------------------------------------------------------*/ +/* procedure appellee par yacc, declaration de plots face west, Tableau de listes */ +/* de chaine de caracteres declaree en globale */ +/*-----------------------------------------------------------------------------------*/ + +void declaration_plot_w(ident) +char *ident; +{ + static int first = 1; + + if (mode_debug) + printf("declaration plot west\n"); + + if (first) { + first = 0; + nom_plot[OUEST] = NULL; + } + + nom_plot[OUEST] = addchain(nom_plot[OUEST], (void * ) namealloc(ident)); +} + +/*-----------------------------------------------------------------------------------*/ +/* procedure appellee par yacc, declaration de plots face est, Tableau de listes */ +/* de chaine de caracteres declaree en globale */ +/*-----------------------------------------------------------------------------------*/ + +void declaration_plot_e(ident) +char *ident; +{ + static int first = 1; + + if (mode_debug) + printf("declaration plot est\n"); + + if (first) { + first = 0; + nom_plot[EST] = NULL; + } + + nom_plot[EST] = addchain(nom_plot[EST], (void * ) namealloc(ident)); +} + +/*-----------------------------------------------------------------------------------*/ +/* procedure appellee par yacc, declaration de plots dont la taille des connecteurs */ +/* est speciale , liste_width variable globale: liste de cellules contenant nom */ +/* et largeur connecteur */ +/*-----------------------------------------------------------------------------------*/ + +void declaration_width(ident, largeur) +char *ident; +long largeur; +{ + static int first = 1; + PTCEL cellule; + + if (mode_debug) + printf("declaration width \n"); + if (mode_debug) + printf("ident --%s-- width --%ld--\n", ident, (long) largeur); + if (first) { + first = 0; + liste_width = NULL; + } + + cellule = (PTCEL) mbkalloc ((unsigned int) sizeof(CEL)); + cellule->chaine = namealloc(ident); + cellule->largeur = (long) largeur; + + liste_width = addchain(liste_width, (void * ) cellule); +} + +/*-----------------------------------------------------------------------------------*/ +/* affichages des listes remplies par l'analyseur syntaxique */ +/*-----------------------------------------------------------------------------------*/ + +void affic_plotwidth() +{ + chain_list * liste; + int i; + + if (mode_debug) + printf("tableau nom des instances plots\n"); + + for (i = 0; i < NB_FACES; i++) { + if (mode_debug) + printf("---------numero face :%d\n", i); + + liste = nom_plot[i]; + while (liste != NULL) { + + /* ---------------------------------------------------------------- */ + /* chain_list modifiee pointe sur des instances logiques maintenant */ + /* ---------------------------------------------------------------- */ + + if (mode_debug) + printf("nom plot: --%s--\n", ((loins_list * )liste->DATA)->INSNAME); + liste = liste->NEXT; + } + + } + + liste = liste_width; + + if (mode_debug) + printf("Liste width\n"); + + while (liste != NULL) { + if (mode_debug) + printf("Connecteur --%s-- largeur %ld\n", ((PTCEL)(liste->DATA))->chaine, ((PTCEL)(liste->DATA))->largeur); + liste = liste->NEXT; + } +} + +/*-----------------------------------------------------------------------------------*/ +/* Cette fonction reoriente la direction du connectueur en fonction de la rotation */ +/* transmise. */ +/*-----------------------------------------------------------------------------------*/ + +int reorientation_con(orientation, rotation) +char orientation; +char rotation; +{ + int face = 0; + + switch (rotation) { + case NOSYM : + switch (orientation) { + case 'N' : + face = NORD; + break; + case 'E' : + face = EST; + break; + case 'S' : + face = SUD; + break; + case 'W' : + face = OUEST; + break; + } + break; + + case ROT_P : + switch (orientation) { + case 'N' : + face = OUEST; + break; + case 'E' : + face = NORD; + break; + case 'S' : + face = EST; + break; + case 'W' : + face = SUD; + break; + } + break; + case SYMXY : + switch (orientation) { + case 'N' : + face = SUD; + break; + case 'E' : + face = OUEST; + break; + case 'S' : + face = NORD; + break; + case 'W' : + face = EST; + break; + } + break; + case ROT_M : + switch (orientation) { + case 'N' : + face = EST; + break; + case 'E' : + face = SUD; + break; + case 'S' : + face = OUEST; + break; + case 'W' : + face = NORD; + break; + } + break; + case SYM_X : + switch (orientation) { + case 'N' : + face = NORD; + break; + case 'E' : + face = OUEST; + break; + case 'S' : + face = SUD; + break; + case 'W' : + face = EST; + break; + } + break; + case SY_RM : + switch (orientation) { + case 'N' : + face = OUEST; + break; + case 'E' : + face = SUD; + break; + case 'S' : + face = EST; + break; + case 'W' : + face = NORD; + break; + } + break; + case SYM_Y : + switch (orientation) { + case 'N' : + face = SUD; + break; + case 'E' : + face = EST; + break; + case 'S' : + face = NORD; + break; + case 'W' : + face = OUEST; + break; + } + break; + case SY_RP : + switch (orientation) { + case 'N' : + face = EST; + break; + case 'E' : + face = NORD; + break; + case 'S' : + face = OUEST; + break; + case 'W' : + face = SUD; + break; + } + break; + } + + return(face); +} + +/*-----------------------------------------------------------------------------------*/ +/* recherche d'un connecteur logique d'alim dans un liste d'equipo */ +/*-----------------------------------------------------------------------------------*/ + +locon_list*vraifaux_conlogic(lst_con) +chain_list *lst_con; +{ + LST_PSEUDO_CON con; + + while (lst_con != NULL) { + con = (LST_PSEUDO_CON) lst_con->DATA; + if ((con->coeur_plot == COEUR_CON) && (con->con_lo != NULL)) + return (con->con_lo); + + lst_con = lst_con->NEXT; + } + + if (mode_debug) + printf("\nWarning pas de connecteur alim logique coeur dans liste des equipo ?!\n"); + return(NULL); +} + +/*-----------------------------------------------------------------------------------*/ +/* 15 juilet bug corrige: rech con logique avant d'inserer le pseudo con dans le */ +/* tableau des con du coeur */ +/* */ +/* ajout d'un pseudo connecteur avec ses principales caracteristiques physiques */ +/* dans un tableau de listes. Une liste par face et soit coeur, soit plot. */ +/* Modification: si l'on trouve des connecteurs coeurs en l'air de type */ +/* vdd.x ou vss.x, on change le nom dans la structure mbk et */ +/* on ajoute ces connecteurs dans la liste des equipotentielles. */ +/* nb: il existe 2 pseudo connecteurs qui existent deja qu'on utilise pour les */ +/* premier vdd et vss trouves */ +/*-----------------------------------------------------------------------------------*/ + +void ajout_pseudo_con_coeur(x, y, liste_con, face, tab_coeur, lst_equipo) +long x; +long y; +phcon_list *liste_con; +int face; +LST_PSEUDO_CON tab_coeur[NB_FACES]; +LST_EQUIPO lst_equipo; +{ + long width = liste_con->WIDTH; + char layer = liste_con->LAYER, *name = liste_con->NAME; + + static int first = 1; + static int firstvdd = 1, firstvss = 1; /* premiere fois ou l'on rencontre ces eq */ + LST_PSEUDO_CON con, new_con, liste; + LST_EQUIPO equipo_vdd, equipo_vss, new_lst_equipo; + locon_list * con_lo; + int trouve = 0, i; + + /* --------------------------------------------------------------------------- */ + /* Les pseudo connecteurs ont deja ete alloues par la procedure de fabrication */ + /* des equipotentielles. Il suffit de retrouver le connecteur et de le chainer */ + /* dans la liste des pseudo connecteurs */ + /* --------------------------------------------------------------------------- */ + + if (first) { + for (i = 0; i < NB_FACES; i++) + tab_coeur[i] = NULL; + first = 0; + } + + if (mode_debug) + printf("nom connecteur %s larg %ld face %d x %ld y %ld\n", name, width, face, x, y); + + if (((con = existe_concoeur_lstequipo(name, lst_equipo)) == NULL) /* n'existe pas */ + || (name == eq_vdd) || (name == eq_vss)) /* ajoute pour vti */ + { + + /* --------------------------------------- */ + /* Connecteur en l'air */ + /* on verifie si il s'agit d'un vdd ou vss */ + /* --------------------------------------- */ + + if (!strncmp(name, eq_vdd, 3)) /* vddxx reconnu */ { + if (mode_debug) + printf("vddxxxx nom connecteur %s larg %ld face %d\n", name, width, face); + + recherche_equipo_alim(&equipo_vdd, &equipo_vss, lst_equipo); + + liste_con->NAME = eq_vdd; + con_lo = vraifaux_conlogic(equipo_vdd->lst_con); + + if (firstvdd) { /* on utilise la cellule deja cree */ + if (mode_debug) + printf("firstvdd\n"); + con = (LST_PSEUDO_CON) (equipo_vdd->lst_con)->DATA; + firstvdd = 0; + } else /* creation d'un nouveau pseudo connecteur */ { + con = (LST_PSEUDO_CON) mbkalloc ((unsigned int) sizeof (PSEUDO_CON)); + alloue_coord(0L, 0, &(con->coord)); + + /* --------------------- */ + /* chainage du con_coeur */ + /* --------------------- */ + + equipo_vdd->lst_con = addchain(equipo_vdd->lst_con, (void * ) con); + } + + con->coeur_plot = COEUR_CON; + con->nom_con = liste_con->NAME; + + /* ------------------------------------------------------------------------------ */ + /* Il n'existe pas de connecteur logique associe au con physique, mais on prendi */ + /* celui du coeur existant , pour que les structures de donnees soient coherentes */ + /* ------------------------------------------------------------------------------ */ + + con->con_lo = con_lo; + + } else + if (!strncmp(name, eq_vss, 3)) /* connecteur vssxxx reconnu */ { + if (mode_debug) + printf("vssxxx nom connecteur %s larg %ld face %d\n", name, width, face); + + recherche_equipo_alim(&equipo_vdd, &equipo_vss, lst_equipo); + + liste_con->NAME = eq_vss; + con_lo = vraifaux_conlogic(equipo_vss->lst_con); + + if (firstvss) { /* on utilise la cellule deja cree */ + if (mode_debug) + printf("firstvss\n"); + con = (LST_PSEUDO_CON) (equipo_vss->lst_con)->DATA; + firstvss = 0; + } else /* creation d'un nouveau pseudo connecteur */ { + con = (LST_PSEUDO_CON) mbkalloc ((unsigned int) sizeof (PSEUDO_CON)); + alloue_coord(0L, 0, &(con->coord)); + + /* --------------------- */ + /* chainage du con_coeur */ + /* --------------------- */ + + equipo_vss->lst_con = addchain(equipo_vss->lst_con, (void * ) con); + } + + con->coeur_plot = COEUR_CON; + con->nom_con = liste_con->NAME; + + /* ------------------------------------------------------------------------------ */ + /* Il n'existe pas de connecteur logique associe au con physique, mais on prend */ + /* celui du coeur existant , pour que les structures de donnees soient coherentes */ + /* ------------------------------------------------------------------------------ */ + + con->con_lo = con_lo; + + } + + else + ringerreur(ERR_CONCOEUR_ENLAIR, name, NULL); + } + + if ((con->coord)->proprio == NULL) { /* Caracteristiques physiques completees */ + (con->coord)->xabs = x; + (con->coord)->yabs = y; + (con->coord)->suiv = NULL; + (con->coord)->prec = NULL; + (con->coord)->proprio = (void * ) con; + con->deport = NULL; + con->face = face; + con->deport = NULL; + con->largeur = width; + con->layer = layer; + con->suiv = NULL; + con->prec = NULL; + } else { + printf("Connecteurs multiples de nom %s sur le coeur\n", con->nom_con); + new_con = (LST_PSEUDO_CON) mbkalloc ((unsigned int) sizeof (PSEUDO_CON)); + new_lst_equipo= (LST_EQUIPO) existe_concoeur_lstequipo2(name, lst_equipo); + new_lst_equipo->lst_con = addchain(new_lst_equipo->lst_con, (void * ) new_con); + alloue_coord(0L, 0, &(new_con->coord)); + (new_con->coord)->xabs = x; + (new_con->coord)->yabs = y; + (new_con->coord)->suiv = NULL; + (new_con->coord)->prec = NULL; + (new_con->coord)->proprio = (void * ) new_con; + new_con->deport = NULL; + new_con->face = face; + new_con->deport = NULL; + new_con->largeur = width; + new_con->layer = layer; + new_con->suiv = NULL; + new_con->prec = NULL; + new_con->con_lo = con->con_lo; + new_con->coeur_plot = con->coeur_plot; + new_con->nom_con = con->nom_con; + new_con->situe_deport = con->situe_deport; + con=new_con; + } + + if (mode_debug) + printf("INSNAME %s face %d ptcon %d\n", ((loins_list * ) (con->con_lo)->ROOT)->INSNAME, (int)face, (int)con); + + if (tab_coeur[face] == NULL) { + if (mode_debug) + printf("Premier passage liste %d vide\n", face); + tab_coeur[face] = con; + } else { + liste = tab_coeur[face]; + + switch (face) { + case NORD : + case SUD : + while (liste->suiv != NULL) { + if ((trouve = x < (liste->coord)->xabs)) { + inserer_avant_lstcon(con, liste, &(tab_coeur[face])); + break; + } + + liste = liste->suiv; + } + + if (!trouve) { + if (x < (liste->coord)->xabs) + inserer_avant_lstcon(con, liste, &(tab_coeur[face])); + else + inserer_apres_lstcon(con, liste); + } + + break; + + case EST : + case OUEST: + while (liste->suiv != NULL) { + if ((trouve = y < (liste->coord)->yabs)) { + inserer_avant_lstcon(con, liste, &(tab_coeur[face])); + break; + } + + liste = liste->suiv; + } + + if (!trouve) { + if (y < (liste->coord)->yabs) + inserer_avant_lstcon(con, liste, &(tab_coeur[face])); + else + inserer_apres_lstcon(con, liste); + } + + break; + + } + } +} + +/*--------------------------------------------------------------------------------*/ +/* ajout d'un pseudo connecteur avec ses principales caracteristiques physiques */ +/* dans un tableau de listes. Une liste par face et plot. */ +/*--------------------------------------------------------------------------------*/ + +void ajout_pseudo_con_plot(x, y, width, layer, name, face, deport, tab_plots, lst_equipo) +long x; +long y; +long width; +char layer; +int deport; +char *name; +int face; +BARRE_PLOTS tab_plots[NB_FACES]; +LST_EQUIPO lst_equipo; +{ + + static int first = 1; + LST_PSEUDO_CON con, liste; + int trouve = 0, i; + long aux; + + /* --------------------------------------------------------------------------- */ + /* Les pseudo connecteurs ont deja ete alloues par la procedure de fabrication */ + /* des equipotentielles. Il suffit de retrouver le connecteur et de le chainer */ + /* dans la liste des pseudo connecteurs */ + /* --------------------------------------------------------------------------- */ + + if (first) { + for (i = 0; i < NB_FACES; i++) + tab_plots[i].lst_con = NULL; + first = 0; + } + + if ((con = existe_conplot_lstequipo(name, lst_equipo)) == NULL) + ringerreur(ERR_CONPLOT_ENLAIR, name, NULL); + + /* ------------------------------------- */ + /* Caracteristiques physiques completees */ + /* ------------------------------------- */ + + if (mode_debug) + printf("INSNAME %s\n", ((loins_list * ) (con->con_lo)->ROOT)->INSNAME); + + if ((EST == face) || (OUEST == face)) { + (con->coord)->xabs = y; + (con->coord)->yabs = x; + aux = x; + x = y; + y = aux; + /* echange des coordonnees */ } else { + (con->coord)->xabs = x; + (con->coord)->yabs = y; + } + + (con->coord)->suiv = NULL; + (con->coord)->prec = NULL; + (con->coord)->proprio = (void * ) con; + con->face = face; + if (!deport) + con->deport = NULL; /* sinon deport deja alloue ds remplir_tabplots() */ + con->largeur = width; + con->layer = layer; + con->suiv = NULL; + con->prec = NULL; + + if (con->nom_con == eq_vdd) /* mise a jour de vdd et vss width */ + vdd_width = width; + + else if (con->nom_con == eq_vss) + vss_width = width; + + if (mode_debug) + printf("plot con %s x %ld y %ld larg %ld\n", con->nom_con, (con->coord)->xabs, (con->coord)->yabs, con->largeur); + + /* ----------------------------------------------------------------- */ + /* Les barres de plots physiques ont ete construites sans rotation, */ + /* mais pour les barres est et ouest on prend les y en consideration */ + /* ----------------------------------------------------------------- */ + + if (tab_plots[face].lst_con == NULL) { + if (mode_debug) + printf("Premier passage liste %d vide\n", face); + tab_plots[face].lst_con = con; + } else + { + if (mode_debug) + printf("trouve %s par pseudo %s\n", name, con->nom_con); + liste = tab_plots[face].lst_con; + + switch (face) { + case NORD: + case SUD: + while (liste->suiv != NULL) { + if ((trouve = x < (liste->coord)->xabs)) { + inserer_avant_lstcon(con, liste, &(tab_plots[face].lst_con)); + break; + } + + liste = liste->suiv; + } + + if (!trouve) { + if (x < (liste->coord)->xabs) + inserer_avant_lstcon(con, liste, &(tab_plots[face].lst_con)); + else + inserer_apres_lstcon(con, liste); + } + break; + + case OUEST: + case EST: + while (liste->suiv != NULL) { + if ((trouve = y < (liste->coord)->yabs)) { + inserer_avant_lstcon(con, liste, &(tab_plots[face].lst_con)); + break; + } + + liste = liste->suiv; + } + + if (!trouve) { + if (y < (liste->coord)->yabs) + inserer_avant_lstcon(con, liste, &(tab_plots[face].lst_con)); + else + inserer_apres_lstcon(con, liste); + } + break; + } /* fin du switch */ + + } /* Fin du else */ +} + +/*-----------------------------------------------------------------------------------*/ + +void inserer_apres_lstcon(con, pt) +LST_PSEUDO_CON con; +LST_PSEUDO_CON pt; +{ + + LST_PSEUDO_CON ptsuiv; + + if (pt == NULL) + ringerreur(ERR_INTERNE_CON, NULL, NULL); + + ptsuiv = pt->suiv; + + /* ------------ */ + /* fin de liste */ + /* ------------ */ + + if (ptsuiv == NULL) { + pt->suiv = con; + con->prec = pt; + } else + { + pt->suiv = con; + con->prec = pt; + con->suiv = ptsuiv; + ptsuiv->prec = con; + } + +} + +/*-----------------------------------------------------------------------------------*/ + +void inserer_avant_lstcon(con, pt, liste) +LST_PSEUDO_CON con; +LST_PSEUDO_CON pt; +LST_PSEUDO_CON *liste; +{ + + LST_PSEUDO_CON ptprec; + + if ((pt == NULL) || ((*liste) == NULL)) + ringerreur(ERR_INTERNE_CON, NULL, NULL); + + /* -------------------------------------------- */ + /* si pt==null ou *liste ==null ringerreur */ + /* insertion dans l'ordre ptprec <-> con <-> pt */ + /* -------------------------------------------- */ + + ptprec = pt->prec; /* cellule precedente */ + + /* ------------------------------------------ */ + /* si ptprec == null changement tete de liste */ + /* ------------------------------------------ */ + + if (ptprec == NULL) { + con->suiv = *liste; + (*liste)->prec = con; + (*liste) = con; + } else { + con->suiv = pt; + con->prec = ptprec; + ptprec->suiv = con; + pt->prec = con; + } + +} + +/*-----------------------------------------------------------------------------------*/ + +void affic_lstcon(liste) +LST_PSEUDO_CON liste; +{ + LST_PSEUDO_CON fin_liste; + + while (liste != NULL) { + if (liste->coeur_plot == COEUR_CON) + printf("COEUR *** "); + else + printf("PLOT ***"); + + printf("Con %20s face %d xabs %5ld yabs %5ld largeur %3ld layer %d root %10s\n", liste->nom_con, liste->face, + liste->coord->xabs, liste->coord->yabs, liste->largeur, (int) liste->layer, ((loins_list * )liste->con_lo->ROOT)->INSNAME); + + if (liste->suiv == NULL) + fin_liste = liste; + liste = liste->suiv; + } + + liste = fin_liste; + /* + printf("Parcours de la meme liste en sens inverse\n"); + + while (liste!= NULL) { + if (liste->coeur_plot == COEUR_CON) + printf("COEUR *** "); + else printf("PLOT ***"); + + printf("Con %s face %d xabs %ld yabs %ld largeur %d layer %d\n", + liste->nom_con, liste->face, liste->coord->xabs, liste->coord->yabs, liste->largeur,(int) liste->layer); + + liste= liste->prec; + } + */ +} + +/*-----------------------------------------------------------------------------------*/ +/* Recherche d'un connecteur du coeur dans la liste des equipo. Le connecteur coeur */ +/* est toujous en tete d'equipo. Modification: il faut considerer qu'il peut */ +/* avoir plusieurs connecteurs du coeur qui portent le meme signal; alors */ +/* l'equipo contient +sieurs concoeur, rend la liste d'equipotentielle */ +/* ou le connecteur a ete trouve */ +/*-----------------------------------------------------------------------------------*/ + +LST_EQUIPO existe_concoeur_lstequipo2(name, lst_equipo) +char *name; +LST_EQUIPO lst_equipo; +{ + LST_PSEUDO_CON pseudo_con; + chain_list * lst_con; + + while (lst_equipo != NULL) { + lst_con = lst_equipo->lst_con; + + while (lst_con != NULL) { + pseudo_con = (LST_PSEUDO_CON) lst_con->DATA; + if ((pseudo_con->coeur_plot == COEUR_CON) && (pseudo_con->nom_con == name)) + return( lst_equipo); + + lst_con = lst_con->NEXT; + } + + lst_equipo = lst_equipo->suiv; + } + + return(NULL); +} + +/*-----------------------------------------------------------------------------------*/ +/* Recherche d'un connecteur coeur dans la liste des equipo. Le connecteur coeur */ +/* est toujous en tete d'equipo. Modification: il faut considerer qu'il peut */ +/* avoir plusieurs connecteurs du coeur qui portent le meme signal; alors */ +/* l'equipo contient +sieurs concoeur */ +/*-----------------------------------------------------------------------------------*/ + +LST_PSEUDO_CON existe_concoeur_lstequipo(name, lst_equipo) +char *name; +LST_EQUIPO lst_equipo; +{ + LST_PSEUDO_CON pseudo_con; + chain_list * lst_con; + + while (lst_equipo != NULL) { + lst_con = lst_equipo->lst_con; + + while (lst_con != NULL) { + pseudo_con = (LST_PSEUDO_CON) lst_con->DATA; + /* + if (mode_debug) printf("existeconcoeur equiponom_con %s name %s\n",pseudo_con->nom_con, name); + */ + if ((pseudo_con->coeur_plot == COEUR_CON) && (pseudo_con->nom_con == name)) + return(pseudo_con); + + lst_con = lst_con->NEXT; + } + + lst_equipo = lst_equipo->suiv; + } + + return(NULL); +} + +/*---------------------------------------------------------------------------------*/ +/* Recherche d'un connecteur logique plot dans la liste des equipo. par son nom */ +/* d'instance et son nom de connecteur */ +/*---------------------------------------------------------------------------------*/ + +LST_PSEUDO_CON existe_conlogicplot_lstequipo(conlo, lst_equipo) +locon_list *conlo; +LST_EQUIPO lst_equipo; +{ + char *nom_inst, *nom_inst2; + LST_PSEUDO_CON pseudo_con; + chain_list * lst_con; + + nom_inst2 = ((loins_list * )conlo->ROOT)->INSNAME; + + while (lst_equipo != NULL) { + lst_con = lst_equipo->lst_con; + + while (lst_con != NULL) { + pseudo_con = (LST_PSEUDO_CON) lst_con->DATA; + + if (pseudo_con->coeur_plot == PLOT_CON) { + + nom_inst = ((loins_list * )(pseudo_con->con_lo)->ROOT)->INSNAME; + + if (mode_debug) + printf("nom_instance %s name %s nominst2 %s name2 %s\n", nom_inst, pseudo_con->nom_con, + nom_inst2, conlo->NAME); + + if ((nom_inst == nom_inst2) && (pseudo_con->nom_con == conlo->NAME)) + return(pseudo_con); + } + + lst_con = lst_con->NEXT; + + } /* fin de la liste coeurante d'equipo */ + + lst_equipo = lst_equipo->suiv; + } + + return(NULL); +} + +/*-----------------------------------------------------------------------------------*/ +/* Recherche d'un connecteur plot dans la liste des equipo. avec concatenation */ +/* du nom d'instance */ +/*-----------------------------------------------------------------------------------*/ + +LST_PSEUDO_CON existe_conplot_lstequipo(name, lst_equipo) +char *name; +LST_EQUIPO lst_equipo; +{ + char *nom_con; + LST_PSEUDO_CON pseudo_con; + chain_list * lst_con; + + while (lst_equipo != NULL) { + lst_con = lst_equipo->lst_con; + + while (lst_con != NULL) { + + /* ----------------------------------------------------------------------- */ + /* on concatene le nom d'instance avec le nom du connecteur separe */ + /* par MBK_SEPAR, pointeur rendu est dans la hash table, pour comparaison */ + /* avec nom dans la figure de la barre de plots */ + /* ----------------------------------------------------------------------- */ + + pseudo_con = (LST_PSEUDO_CON) lst_con->DATA; + + if (pseudo_con->coeur_plot == PLOT_CON) { + + nom_con = concatname(((loins_list * )(pseudo_con->con_lo)->ROOT)->INSNAME, pseudo_con->nom_con); + + /* + if (mode_debug) + printf("EXISTE PLOT ? nom_con %s name %s*** %d ***** %d\n ",nom_con, name, (int) nom_con, (int) name); + */ + + if (nom_con == name) + return(pseudo_con); + } + + lst_con = lst_con->NEXT; + + } /* fin de la liste coeurante d'equipo */ + + lst_equipo = lst_equipo->suiv; + } + + return(NULL); +} + +/*-----------------------------------------------------------------------------------*/ +/* Mise a jour de la liste des eq avec les connecteurs plots ou coeur */ +/*-----------------------------------------------------------------------------------*/ + +void maj_equipo(conlo1, conlo2, lst_equipo, type) +locon_list *conlo1; +locon_list *conlo2; +LST_EQUIPO *lst_equipo; +int type; +{ + static int first = 1; + LST_EQUIPO eq, pt_eq; + LST_PSEUDO_CON con1, con2; + + int type1 = 0, type2 = 0; + LST_PSEUDO_CON ret1 = NULL, ret2 = NULL; + + if (mode_debug) + printf("Maj equipo\n"); + + switch (type) { + case COEUR_PLOT: + type1 = COEUR_CON; + type2 = PLOT_CON; + break; + case COEUR_COEUR: + type1 = COEUR_CON; + type2 = COEUR_CON; + break; + case PLOT_PLOT: + type1 = PLOT_CON; + type2 = PLOT_CON; + break; + } + + if (first) { + (*lst_equipo) = NULL; + first = 0; + } + + if ((pt_eq = existe_sig_equipo((*lst_equipo), (conlo1->SIG)->INDEX)) == NULL) { + + /* -------------------------- */ + /* creation d'une nouvelle eq */ + /* -------------------------- */ + + if (mode_debug) + printf("Nouvelle equipo index %ld con_coeur %s con_plot %s\n", (conlo1->SIG)->INDEX, conlo1->NAME, + conlo2->NAME); + + eq = (LST_EQUIPO) mbkalloc ((unsigned int) sizeof (EQUIPO)); + eq->index = (conlo1->SIG)->INDEX; + eq->lst_con = NULL; + eq->lst_seg = NULL; + eq->lst_visavis = NULL; + (eq->cour).lst_projetes = NULL; + + /* bug corrige, apres le malloc ! */ + + if (mode_stat) { + eq->status.lg_a1 = 0; + eq->status.lg_a2 = 0; + eq->status.su_a1 = 0; + eq->status.su_a2 = 0; + eq->status.nb_vias = 0; + } + + if ((conlo1->NAME == eq_vdd) || (conlo1->NAME == eq_vss)) + eq->type = ALIM; + else + eq->type = type; + + /* ------------------------- */ + /* creation pseudo_con coeur */ + /* ------------------------- */ + + con1 = (LST_PSEUDO_CON) mbkalloc ((unsigned int) sizeof (PSEUDO_CON)); + alloue_coord(0L, 0, &(con1->coord)); + con1->deport = NULL; + con1->coeur_plot = type1; + con1->nom_con = conlo1->NAME; + con1->con_lo = conlo1; + con1->largeur = 0; + con1->suiv = NULL; + con1->prec = NULL; + + /* ------------------------- */ + /* creation pseudo_con plot */ + /* ------------------------- */ + + con2 = (LST_PSEUDO_CON) mbkalloc ((unsigned int) sizeof (PSEUDO_CON)); + alloue_coord(0L, 0, &(con2->coord)); + con2->deport = NULL; + con2->coeur_plot = type2; + con2->nom_con = conlo2->NAME; + con2->con_lo = conlo2; + con2->largeur = 0; + con2->suiv = NULL; + con2->prec = NULL; + + /* --------------------- */ + /* chainage du con_coeur */ + /* --------------------- */ + eq->lst_con = addchain(eq->lst_con, (void * ) con1); + + /* -------------------- */ + /* chainage du con_plot */ + /* -------------------- */ + eq->lst_con = addchain(eq->lst_con, (void * ) con2); + + /* -------------------------------- */ + /* chainage avant de la nouvelle eq */ + /* -------------------------------- */ + + eq->suiv = (*lst_equipo); + + (*lst_equipo) = eq; + } else { + + /* ---------------------------------------------------------------------------- */ + /* Modification: il faut considerer qu'il peut avoir plusieurs connecteurs */ + /* du coeur qui portent le meme signal; alors l'equipo contient +sieurs concoeur*/ + /* ---------------------------------------------------------------------------- */ + + switch (type) { + case COEUR_PLOT: + ret1 = existe_concoeur_lstequipo(conlo1->NAME, pt_eq); + ret2 = existe_conlogicplot_lstequipo(conlo2, pt_eq); + break; + + case COEUR_COEUR: + ret1 = existe_concoeur_lstequipo(conlo1->NAME, pt_eq); + ret2 = existe_concoeur_lstequipo(conlo2->NAME, pt_eq); + break; + + case PLOT_PLOT: + ret1 = existe_conlogicplot_lstequipo(conlo1, pt_eq); + ret2 = existe_conlogicplot_lstequipo(conlo2, pt_eq); + break; + } + + if (ret1 == NULL) { /* N'existe pas */ + + if (mode_debug) + printf("Deuxieme con coeur dans l'equipo %s \n", conlo1->NAME); + + /* ------------------------- */ + /* creation pseudo_con coeur */ + /* ------------------------- */ + + con1 = (LST_PSEUDO_CON) mbkalloc ((unsigned int) sizeof (PSEUDO_CON)); + alloue_coord(0L, 0, &(con1->coord)); + con1->deport = NULL; + con1->coeur_plot = type1; + con1->nom_con = conlo1->NAME; + con1->con_lo = conlo1; + con1->largeur = 0; + con1->suiv = NULL; + con1->prec = NULL; + + /* --------------------- */ + /* chainage du con_coeur */ + /* --------------------- */ + + pt_eq->lst_con = addchain(pt_eq->lst_con, (void * ) con1); + } + + if (mode_debug) + printf("L'equipo index %ld conplot %s existe deja\n", (conlo1->SIG)->INDEX, conlo2->NAME); + + if (ret2 == NULL) { /* N'existe pas */ + + /* ------------------------ */ + /* creation pseudo_con plot */ + /* ------------------------ */ + + con2 = (LST_PSEUDO_CON) mbkalloc ((unsigned int) sizeof (PSEUDO_CON)); + alloue_coord(0L, 0, &(con2->coord)); + con2->deport = NULL; + con2->coeur_plot = type2; + con2->nom_con = conlo2->NAME; + con2->con_lo = conlo2; + con2->largeur = 0; + con2->suiv = NULL; + con2->prec = NULL; + + /* -------------------- */ + /* chainage du con_plot */ + /* -------------------- */ + + pt_eq->lst_con = addchain(pt_eq->lst_con, (void * ) con2); + } + + } /* fin du else */ + +} + +/*-----------------------------------------------------------------------------------*/ +/* Fonction retourne l'equi si signal existe deja NULL sinon */ +/*-----------------------------------------------------------------------------------*/ + +LST_EQUIPO existe_sig_equipo(lst_equipo, index) +LST_EQUIPO lst_equipo; +long index; +{ + + while (lst_equipo != NULL) { + if (lst_equipo->index == index) + return(lst_equipo); + + lst_equipo = lst_equipo->suiv; + } + + return(NULL); + +} + +/*-----------------------------------------------------------------------------------*/ + +void affic_equipo(lst_equipo) +LST_EQUIPO lst_equipo; +{ + LST_PSEUDO_CON con; + chain_list * liste; + ptype_list * listevav, *lst_proj; + chain_list * listeseg; + LST_SEGMENT lseg; + int cpt_equipo = 0; + static char a1[3] = "A1"; + static char a2[3] = "A2"; + static char er[3] = "ER"; + char *metal; + char car = 0; + + if (mode_debug) + printf("EQUIPO AFFIC\n"); + + while (lst_equipo != NULL) { + printf("\n\t------\n"); + printf("\tEQUIPO type %d index %5ld\n", lst_equipo->type, lst_equipo->index); + cpt_equipo++; + + liste = lst_equipo->lst_con; + + while (liste != NULL) { + con = (LST_PSEUDO_CON) liste->DATA; + if (con->coeur_plot == COEUR_CON) + printf("COEUR "); + else + printf("PLOT "); + + if (con->con_lo != NULL) { + + switch (con->face) { + case NORD: + car = 'N'; + break; + case SUD : + car = 'S'; + break; + case EST : + car = 'E'; + break; + case OUEST: + car = 'O'; + break; + } + + if (con->layer == ALU1) + metal = a1; + else if (con->layer == ALU2) + metal = a2; + else + metal = er; + + printf("\tface %c Con %16s root %10s * ", car, con->nom_con, ((loins_list * )(con->con_lo)->ROOT)->INSNAME); + printf("x %5ld y %5ld piste %5ld larg %3ld layer %s\n", (con->coord)->xabs, (con->coord)->yabs, + (con->coord)->piste, con->largeur, metal); + } else + printf("\tCon %s WARNING: pas de connecteur logique associe\n", con->nom_con); + + if (con->deport) { + if ((con->coord)->suiv) + printf("suiv x%ld y%ld\n", ((con->coord)->suiv)->xabs, ((con->coord)->suiv)->yabs); + if ((con->coord)->prec) + printf("prec x%ld y%ld\n", ((con->coord)->prec)->xabs, ((con->coord)->prec)->yabs); + + printf("\tDEPORT coord xabs %ld yabs %ld piste %ld\n", (con->deport)->xabs, (con->deport)->yabs, + (con->deport)->piste); + } + + liste = liste->NEXT; + } + + listevav = lst_equipo->lst_visavis; + if (listevav) + if (mode_debug) + printf("\tLISTE VISAVIS\n"); + + while (listevav != NULL) { + con = (LST_PSEUDO_CON) listevav->DATA; + printf("***VISAVIS %16s coeur_plot %d root %10s * ", con->nom_con, con->coeur_plot, ((loins_list + *)(con->con_lo)->ROOT)->INSNAME); + printf("x %5ld y %5ld larg %5ld face %d\n", (con->coord)->xabs, (con->coord)->yabs, con->largeur, + con->face); + listevav = listevav->NEXT; + } + + listeseg = lst_equipo->lst_seg; + + if (listeseg) + printf("\tLISTE SEGMENTS\n"); + + while (listeseg) { + + lseg = (LST_SEGMENT) listeseg->DATA; + if (lseg->layer == ALU1) + metal = a1; + else if (lseg->layer == ALU2) + metal = a2; + else + metal = er; + + switch (lseg->face) { + case NORD: + car = 'N'; + break; + case SUD : + car = 'S'; + break; + case EST : + car = 'E'; + break; + case OUEST: + car = 'O'; + break; + } + + printf("face %c x1 %5ld y1 %5ld x2 %5ld y2 %5ld -- piste1 %3ld piste2 %3ld -- larg %3ld layer %2s \n", + car, lseg->c1->xabs, lseg->c1->yabs, lseg->c2->xabs, lseg->c2->yabs, lseg->piste1, lseg->piste2, + lseg->largeur, metal); + listeseg = listeseg->NEXT; + } + + if ((lst_equipo->cour).lst_projetes) { + printf("\tLISTE PROJETES perimetre %ld\n", (lst_equipo->cour).perimetre); + lst_proj = (lst_equipo->cour).lst_projetes; + while (lst_proj) { + if (((PT_COORDONNEES)lst_proj->DATA)->proprio) + printf("valcurv %5ld con %s \n", lst_proj->TYPE, ((LST_PSEUDO_CON) ((PT_COORDONNEES) lst_proj->DATA)->proprio)->nom_con); + else + printf("valcurv%5ld \n",lst_proj->TYPE); + lst_proj = lst_proj->NEXT; + } + } + + lst_equipo = lst_equipo->suiv; + } + + printf("\tNOMBRE D'EQUIPO %d\n", cpt_equipo); + +} + diff --git a/alliance/src/ring/src/struct.h b/alliance/src/ring/src/struct.h new file mode 100644 index 00000000..f94d5e13 --- /dev/null +++ b/alliance/src/ring/src/struct.h @@ -0,0 +1,387 @@ +/* + * 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 support : mailto:alliance-support@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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*-----------------------------------------------------------------------------------*/ + +/* RING. 27 avril 92 */ + +/* Definition des types et structures de donnees utilisees par RING */ + + +#ifndef __STRUCT_H +#define __STRUCT_H + +#include +#include +#include + +#define NB_FACES 4 +#define NB_ITERATIONS 50 /* nb iterations a effectuer pour bon placement barre de plots */ + +#define SEG_PISTE 0 /* type segment parallele a face coeur */ +#define SEG_COL 1 /* type segment perpendiculaire face coeur */ + +#define VRAI_SEG 0 /* vrai segment qui sera a poser physiquement */ +#define FAUX_SEG 1 /* faux segment utile uniquement au routage */ + +#define AVEC_VIA 0 /* pose d'un via uniquement pour alim */ +#define SANS_VIA 1 /* pas de via uniquement pour alim */ + +#define AVEC_TESTLAYER 0 /* on teste le layer dans la fonction croisementok_alimequi() */ +#define SANS_TESTLAYER 1 /* on ne teste pas le layer dans la fonction croisementok_alimequi() */ + +#define AVEC_COMPRESS 0 /* coordonee deja compressee */ +#define SANS_COMPRESS 1 /* coordonne non compresse (par defaut) */ +#define DEPORTG 0 /* localisation deport gauche droite face par rapport au coeur */ +#define DEPORTD 1 /* des connecteurs plots ou coeur (centre uniquement) */ +#define DEPORTC 2 + +#define COEUR_PLOT 0 +#define COEUR_COEUR 1 +#define PLOT_PLOT 2 +#define ALIM 3 /* equipo de type alim */ +#define AUTRE 4 /* equipo de type autre que les precedents */ + +#define FBARRE_N "fzigopadn1992" /* Noms futiles pour definir les figures barres de plots*/ +#define FBARRE_S "fzigopads1992" +#define FBARRE_E "fzigopade1992" +#define FBARRE_O "fzigopado1992" + +#define IBARRE_N "izigopadn1992" /* Noms futiles pour definir les instances barres de plots*/ +#define IBARRE_S "izigopads1992" +#define IBARRE_E "izigopade1992" +#define IBARRE_O "izigopado1992" + +#define NORD 0 +#define SUD 1 +#define OUEST 2 +#define EST 3 +/* Nombres entiers obligatoires ! */ +#define WMIN_ALU1 2 /* largeur minimum de l'alu1,l'alu2,dist mini alu1<->alu2 */ +#define WMIN_ALU2 2 /* et largeur du via */ +#define DMIN_ALU1_ALU1 3 /* dmin en a1 a1 2.5 arrondi a 3 */ +#define DMIN_ALU2_ALU2 3 +#define WVIA_ALU1 2 /* largeur du via pour l'alu1 */ +#define WVIA_ALU2 3 /* largeur du via pour l'alu2 */ + +#define EXTENSION_ALU2 1 /* extension alu2 pour fignoler coin couronne */ + +#define BV_VIA_VIA 4 /* must be even, whatever! */ +#define BV_VIASIZE WVIA_ALU2 /* design rule for equipotential vias */ + +#define WALIM 60 /* largeur prdefinie des alim */ + +/*#define PISTE_DEP_ALIMPLOT 10 Nombre de piste a considerer pour une deport alim plot */ +/* code des ringerreurs traitees par ringerreur(code) */ +#define ERR_ARGUMENT 1 +#define ERR_NONCOEUR 2 +#define ERR_PLUSCOEUR 3 +#define ERR_COEURINSTLO 4 +#define ERR_COEURINSTPH 5 +#define ERR_CIRCUITLO 6 +#define ERR_CIRCUITINST 7 +#define ERR_FICPARAM 8 +#define ERR_VIDEFICPARAM 9 +#define ERR_SYNPARAM 10 +#define ERR_AUCUNPLOTPARAM 11 +#define ERR_NONPLOTPARAM 12 +#define ERR_PLUSPLOTPARAM 13 +#define ERR_NBPLOTPARAM 14 +#define ERR_NONCONWIDTHPARAM 15 +#define ERR_INTERNE_CON 16 +#define ERR_CONCOEUR_ENLAIR 17 +#define ERR_CONPLOT_ENLAIR 18 +#define ERR_CONLARGEUR 19 +#define ERR_CONDISTANCE 20 +#define ERR_MANQUEALIM 21 +#define ERR_BARREALIM 22 +#define ERR_ECHECDEPORT 23 +#define ERR_INTERNE_EQ 24 +#define ERR_SEGDEPORT 25 +#define ERR_NOPISTE 26 +#define ERR_NOCOL 27 +#define ERR_INSTPH_PLOT 28 +#define ERR_NOCONPH_PLOT 29 +#define ERR_FIGPH_PLOT 30 +#define ERR_CONEXT_ENLAIR 31 +#define ERR_INTERNE_FIG 32 +#define ERR_NBCONESTOUEST 33 +#define ERR_NOCONPH 34 +#define ERR_CATAL 35 +#define ERR_WIDTHPARAM 36 +#define ERR_EQINTERNE 37 +#define ERR_EQEXTERNE 38 +#define ERR_TIREALIM 39 +#define ERR_FICSTAT 40 +#define ERR_GRILLEINTERNE 41 +#define ERR_CONCOEUREMPTY 42 +#define ERR_CONLO_SANS_PH 43 +#define ERR_CONPH_SANS_LO 44 + +/*-----------------------------------------------------------------------------------*/ + +/* type liste de pseudo-connecteurs. Il sert pour les listes de plots et du + coeur */ + +#define COEUR_CON 1 +#define PLOT_CON 0 + +/* type coordonnees : contient les coordonnees absolues et symboliques */ + +typedef struct coord { + long piste; /* coordonnee piste (horizontal par rapport a la face) */ + long xabs; /* coordonnees x,y absolues dans la figure circuit physique */ + long yabs; + void * proprio; /* pointeur sur le pseudo-connecteur appartenant */ + int compress; /* coordonnees compressee ou pas */ + struct coord *suiv; /* chainage avant arriere sur la grille ou appartient */ + struct coord *prec; /* le point courant */ +} COORDONNEES, *PT_COORDONNEES; + +typedef struct pseudo_con { + char coeur_plot; /* soit COEUR, soit PLOT */ + PT_COORDONNEES coord; /* coordonnees symboliques et relatives */ + PT_COORDONNEES deport; /* pointeur sur coordonnees symboliques et relatives + d'un eventuel point de deport, si pointeur null + alors pas de deport , + deport-> piste = 1 si deport uniquement pour layer */ + int situe_deport; /* deport gauche droit ou centre */ + int face; /* face a laquelle appartient le pseudo_connecteur */ + long largeur; /* largeur du connecteur */ + char layer; /* niveau physique du connecteur */ + char *nom_con; /* nom du connecteur */ + locon_list * con_lo; /* pointeur sur connecteur logique de la figure */ + + struct pseudo_con *suiv; /* pointeur sur structure suivante */ + struct pseudo_con *prec; /* pointeur sur structure precedente */ +} PSEUDO_CON, *LST_PSEUDO_CON; + +/* type liste de segments. Il sert pour les placements des segments physiques + pour chaque equipotentielle et chaque direction (horizontal/vertical). Il renseigne + aussi pour les segments occupes. ON ne sert que exclusivement que des coordonnees + en xabs ou yabs. Il y a un champ piste associe au segment et a sa direction dans la + face. */ + +typedef struct segment { + int face; /* face a laquelle est associee le segment */ + long piste1; /* piste associee au segment de type SEG_COL et SEG_PISTE */ + long piste2; /* 2eme piste associee au segment de type SEG_COL */ + PT_COORDONNEES c1; /* coordonnees symboliques et absolues du debut segment */ + PT_COORDONNEES c2; /* coordonnees symboliques et absolues de fin segment */ + long largeur; /* largeur physique du segment */ + char layer; /* layer segment */ + int vraifaux; /* vraifaux segment. c'est un faux si largeur speciale */ + int via; /* pose d' un via ou pas, utile uniquement pour alim */ + struct segment *suiv; /* pointeur sur structure suivante ds liste segments occupes */ + struct segment *prec; /* pointeur sur structure precedente " " " */ +} SEGMENT, *LST_SEGMENT; + +/* type couronne: couronne (complete ou incomplete necessaires au + routage, les segments sont completes au fur et a mesure (projetes ...-> segments */ + +typedef struct couronne { + ptype_list *lst_projetes; /* liste de coordonnees projetees sur la cour + avec leur valeur curviligne */ + long perimetre; /* perimetre curviligne de la couronne */ +} COURONNE; + +/* type stat: caracteristiques de l'equipotentielles en + longueur, surface, nb vias */ + +typedef struct stat { + long lg_a1; /* longueur en lambdas en alu1 alu2 de l'equipo */ + long lg_a2; + long su_a1; /* surface en lamdas carres en alu1 alu2 de l'equipo */ + long su_a2; + long nb_vias; +} STAT; + +/* type equipotentielle: liste de pseudo-connecteurs portant le meme signal (nom+index) */ + +typedef struct equipo { + int type; /* type de l'eq: normal, alim, autre) */ + long index; + chain_list * lst_con; /* tete de chain-list pointant sur des pseudo connecteurs */ + chain_list * lst_seg; /* tete de liste des segments associes */ + ptype_list * lst_visavis; /* liste de pointeurs sur des connecteurs en vis a vis */ + COURONNE cour; /* structure couronne associee a l'equipo */ + STAT status; /* stats en longueur et surface */ + struct equipo *suiv; /* pointeur sur structure suivante */ +} EQUIPO, *LST_EQUIPO; + +/* type lst_piste_col: liste de segments occupes pour piste ou colonne */ + +typedef struct piste_col { + long numero; /* numero de la piste ou de la colonne */ + chain_list * lst_seg; /* liste de pointeurs sur segments */ + struct piste_col *suiv; /* pointeur sur structure suivante */ + struct piste_col *prec; /* pointeur sur structure precedente */ +} PISTE_COL, *LST_PISTE_COL; + +/* type barre_plots: contient les donnees necessaires a la construction de + la barre de plots */ + +typedef struct barre_plots { + LST_PSEUDO_CON lst_con; /* liste de pointeurs sur connecteurs de plots */ + COORDONNEES coord; /* coordonnees symboliques et absolues de la barre de plots */ + long width; /* longueur de la barre de plots */ + long height; /* hauteur de la barre de plots */ + int nb_deport; /* nombre de deports prevus par le placement de la barre */ + char *nomfig; /* nom de la figure physique */ + char *nominst; /* nom de l'instance physique */ +} BARRE_PLOTS; + +/* type grille_symbo_piste: grille des pistes (pas fixes definis par le pitch) */ + +typedef struct symbo_piste { + long premiere; /* coordonnee absolue de la premiere piste */ + int largeur_pas; /* valeur du pas de grille */ + long nb_pas; /* nombre de pas de grilles definis maximum */ +} GRILLE_SYMBO_PISTE; + +/* type grille: regroupe les 2 types precedents pour obtenir la grille qui permettra de + transformer les coordonnees symboliques en absolues et vice-versa */ + +typedef struct grille { + PT_COORDONNEES lst_pas; /* liste des points formant la grille */ + PT_COORDONNEES lst_deportg;/* liste des deports gauches de la grille */ + PT_COORDONNEES lst_deportd;/* liste des deports droits de la grille */ + GRILLE_SYMBO_PISTE piste; /* donnees pour le calcul des pas de piste */ +} GRILLE; + +/* type coeur: regroupe les informations le concernant */ + +typedef struct coeur { + loins_list *coeur_lo; /* pointeur sur figure logique du coeur */ + phfig_list *coeur_ph; /* pointeur sur figure physique du coeur */ + COORDONNEES coord; /* coordonnees symboliques(0,0) et absolues */ + long width; + long height; + char rotation; /* rotation du coeur */ + +} COEUR; + +/* type cel : cellule contient la largeur specifique d'un signal, fera parti de la + chain_list liste_width, remplie par l'analyseur syntaxique */ + +typedef struct cel { + char *chaine; + long largeur; + locon_list * con_lo; +} CEL, *PTCEL; + +/*-----------------------------------------------------------------------------------*/ + +/* Variables globales */ + +extern char mode_debug; /* si debug alors mode_debug=1, 0 sinon */ +extern char mode_stat; /* si stat alors mode_stat=1, 0 sinon */ +extern char *nomfic_stat; /* nom du fichier statistique */ + +extern char xmetal; /* metal utilise dans les x */ +extern char ymetal; /* metal utilise dans les y */ +extern long xmetal_width, ymetal_width; /* largeur des metaux x, y */ +extern long xmetal_dmin, ymetal_dmin; /* dist minimum entre 2 meme metaux */ +extern long xmetal_wvia, ymetal_wvia; /* taille des contacts pour chaque metal */ +extern long pitch; /* pitch a calculer */ +extern long lambda; /* lambda (= SCALE_X) */ +extern long taille_via; /* taille du via a calculer */ +extern long vdd_width; /* largeur couronnes d'alim */ +extern long vss_width; +extern char *eq_vdd; /* nom equipo alim */ +extern char *eq_vss; /* nom equipo alim */ +extern char *n_vdde; +extern char *n_vsse; +extern char *n_vddi; +extern char *n_vssi; +extern char *n_pad; +extern char *pvddi_p; +extern char *pvssi_p; + +extern char *nom_fic_param; /* nom du fichier parametre */ + +extern FILE *yyin; /* pointeur sur fichier lex */ +extern int yylineno; /* no de la ligne traitee par lex */ +extern chain_list *nom_plot[NB_FACES]; /* liste pour l'analyseur des noms de + plots */ +extern chain_list *liste_width; /* liste pour l'analyseur des noms + et largeurs des connecteurs speciaux */ + +extern long bigvias , ringvias ; /* nombres de vias poses en total par bigvia + ou en couronne (mode debug). car pb versatil + si bcp de vias (fichier .cif enorme) */ + +/*-----------------------------------------------------------------------------------*/ + +/* Declarations des fonctions */ + +/* Fichier struct.c */ +extern void ajout_listeplotsph(); +extern int existe_connecteur_faceplot(); +extern phfig_list*appartient_listeplotsph(); +extern void affic_listeplotsph(); +extern loins_list*existe_plot_circuit(); +extern int existe_signal_circuit(); +extern int uneseuleoccurence(); +extern void declaration_plot_n(); +extern void declaration_plot_s(); +extern void declaration_plot_w(); +extern void declaration_plot_e(); +extern void declaration_width(); +extern void affic_plotwidth(); +extern int reorientation_con(); +extern void ajout_pseudo_con_coeur(); +extern void ajout_pseudo_con_plot(); +extern void inserer_apres_lstcon(); +extern void inserer_avant_lstcon(); +extern void affic_lstcon(); +extern LST_PSEUDO_CON existe_concoeur_lstequipo(); +extern LST_EQUIPO existe_concoeur_lstequipo2(); +extern LST_PSEUDO_CON existe_conplot_lstequipo(); +extern void maj_equipo(); +extern LST_EQUIPO existe_sig_equipo(); +extern void affic_equipo(); +extern locon_list*vraifaux_conlogic(); +extern LST_PSEUDO_CON existe_conlogicplot_lstequipo(); +extern void rename_vddxvssx(); +extern void ignoble_multiple_ck_delete_from_south_side(); + +/* Fichier struct2.c */ +extern int moins_dun_pitch_preccon(); +extern void ajout_coordonnees_grille(); +extern void ajout_visavis(); +extern int existe_visavis(); +extern void affic_grille(); +extern void alloue_coord(); +extern PT_COORDONNEES cherche_deport_grille(); +extern void chaine_deportcon_grille(); +extern void alloue_etchaine_segment(); +extern int segment_libre(); +extern void affic_listeseg(); +extern phcon_list *cherche_conph_circuit(); +extern int croisement_con_alim(); +extern void largeur_vddvss(); +extern int croisementok_alimequi(); +extern long compte_nbplotsface(); + +#endif /* __STRUCT_H */ diff --git a/alliance/src/ring/src/struct2.c b/alliance/src/ring/src/struct2.c new file mode 100644 index 00000000..e499d095 --- /dev/null +++ b/alliance/src/ring/src/struct2.c @@ -0,0 +1,1195 @@ +/* + * 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 support : mailto:alliance-support@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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/****************************************************************************/ +/* */ +/* Chaine de CAO & VLSI Alliance */ +/* */ +/* Produit : ring router */ +/* Fichier : struct2.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 29 mai 92 STRUCT2.C */ +/* Fonctions qui manipulent les structures de donnees definies ds struct.h */ +/*-----------------------------------------------------------------------------------*/ + +#include + +#include "struct.h" +#include "distance.h" +#include "sesame.h" + + +/*-----------------------------------------------------------------------------------*/ +/* Cette fonction retourne VRAI (1) si la distance entre le connecteur courant et */ +/* le precedent est < au pitch, FAUX (0) sinon */ +/*-----------------------------------------------------------------------------------*/ + +int moins_dun_pitch_preccon(con) +LST_PSEUDO_CON con; +{ + long coordcon = 0, coordconprec = 0, largcon = 0, largconprec = 0, dist = 0, largeurmin = 0, dminmetalmetal = 0; + + if (con->prec == NULL) + return(0); /* pas de connect precedent donc pas de + pb de voisinage */ + if (isvdd(con->con_lo->NAME) || isvss(con->con_lo->NAME)) + return (0); + + switch (con->face) { + case NORD: + case SUD : + coordcon = (con->coord)->xabs; + coordconprec = ((con->prec)->coord)->xabs; + dminmetalmetal = ymetal_dmin; + + if ((con->layer != ymetal) || (con->prec->layer != ymetal)) { + if (ymetal_width < xmetal_width) + largeurmin = ymetal_width; + else + largeurmin = xmetal_width; + } else { + largeurmin = ymetal_width; + } + break; + case EST : + case OUEST: + coordcon = (con->coord)->yabs; + coordconprec = ((con->prec)->coord)->yabs; + dminmetalmetal = xmetal_dmin; + + if ((con->layer != xmetal) || (con->prec->layer != xmetal)) { + if (ymetal_width < xmetal_width) + largeurmin = ymetal_width; + else + largeurmin = xmetal_width; + } else { + largeurmin = xmetal_width; + } + break; + } + + largcon = con->largeur; + largconprec = (con->prec)->largeur; + + dist = distance_con_con(coordcon, coordcon, largcon, con->layer, coordconprec, coordconprec, largconprec, con->prec->layer, + con->face); + + if ((largcon > largeurmin) || (largconprec > largeurmin)) { + if ((largcon < taille_via) || (largconprec < taille_via)) + dminmetalmetal = DMIN_ALU2_ALU2; /* distance via-via */ + + if (mode_debug) + printf("%s coordprec %ld larg %ld ---- %s coordcon %ld larg %ld dist %ld dminmetal %ld\n", (con->prec)->nom_con, + coordconprec, largconprec, con->nom_con, coordcon, largcon, dist, dminmetalmetal); + return ((int) (dist < dminmetalmetal)); + } else { + if (mode_debug) + printf("%s coordprec %ld larg %ld ---- %s coordcon %ld larg %ld\n", (con->prec)->nom_con, coordconprec, + largconprec, con->nom_con, coordcon, largcon); + + return ((int) (dist < pitch)); + } +} + +/*-----------------------------------------------------------------------------------*/ +/* Cette procedure ajoute les coordonnees en fin de liste dans la liste des */ +/* pas de la grille symbolique */ +/*-----------------------------------------------------------------------------------*/ + +void ajout_coordonnees_grille(pt_coord, liste, face) +PT_COORDONNEES pt_coord; +PT_COORDONNEES *liste; +int face; +{ + + PT_COORDONNEES cell, liste_coor; + + /* -------------------------------------------------------------------------------- */ + /* Plus besoin d'allouer on prend directement les coord du connecteur qu'on chaine */ + /* dans la grille */ + /* -------------------------------------------------------------------------------- */ + + cell = pt_coord; + + if ((*liste) == NULL) { + cell->prec = NULL; + cell->suiv = NULL; + (*liste) = cell; + } else { + switch (face) { + case NORD: + case SUD: + liste_coor = *liste; + while (liste_coor->suiv != NULL) { + if ((liste_coor)->xabs > pt_coord->xabs) { + cell->suiv = liste_coor; + cell->prec = liste_coor->prec; + + if (liste_coor->prec == NULL) /* tete de liste modifiee */ + *liste = cell; + else + (cell->prec)->suiv = cell; + + liste_coor->prec = cell; + break; + } + + liste_coor = liste_coor->suiv; + } + + /* fin de liste */ + if (liste_coor->suiv == NULL) + { + if ((liste_coor)->xabs > pt_coord->xabs) { + cell->suiv = liste_coor; + cell->prec = liste_coor->prec; + if (liste_coor->prec == NULL) /* tete de liste modifiee */ + *liste = cell; + else + (cell->prec)->suiv = cell; + + liste_coor->prec = cell; + break; + } else { + liste_coor->suiv = cell; + cell->prec = liste_coor; + cell->suiv = NULL; + } + } + break; + + case EST : + case OUEST: + liste_coor = *liste; + while (liste_coor->suiv != NULL) { + if ((liste_coor)->yabs > pt_coord->yabs) { + cell->suiv = liste_coor; + cell->prec = liste_coor->prec; + + if (liste_coor->prec == NULL) /* tete de liste modifiee */ + *liste = cell; + else + (cell->prec)->suiv = cell; + + liste_coor->prec = cell; + break; + } + + liste_coor = liste_coor->suiv; + } + + /* fin de liste */ + if (liste_coor->suiv == NULL) + { + if ((liste_coor)->yabs > pt_coord->yabs) { + cell->suiv = liste_coor; + cell->prec = liste_coor->prec; + if (liste_coor->prec == NULL) /* tete de liste modifiee */ + *liste = cell; + else + (cell->prec)->suiv = cell; + + liste_coor->prec = cell; + break; + } else { + liste_coor->suiv = cell; + cell->prec = liste_coor; + cell->suiv = NULL; + } + } + + break; + + } /* fin du switch */ + + } /* fin du else */ + +} + +/*--------------------------------------------------------------------------------*/ +/* Ajout du vis a vis dans l'equipo de type index. Il s'agit d'une ptype liste */ +/* avec noindex et pointeur sur pseudo_con */ +/*--------------------------------------------------------------------------------*/ + +void ajout_visavis(lst_equipo, coeurcon, indexplot) +LST_EQUIPO lst_equipo; +LST_PSEUDO_CON coeurcon; +long indexplot; +{ + + while (lst_equipo != NULL) { + if (lst_equipo->index == indexplot) { + /* on ajoute le signal du connecteur coeur (indexplot) dans la liste des vis a vis du connecteur plot */ + + if (mode_debug) + printf("Ajout vis a vis con %s root %s indexplot %ld %s\n", coeurcon->nom_con, ((loins_list + *)(coeurcon->con_lo)->ROOT)->INSNAME, indexplot, ((LST_PSEUDO_CON) ((lst_equipo->lst_con)->NEXT)->DATA)->nom_con); + + lst_equipo->lst_visavis = addptype(lst_equipo->lst_visavis, ((coeurcon->con_lo)->SIG)->INDEX , (void + *) coeurcon); + break; + } + + lst_equipo = lst_equipo->suiv; + } + +} + +/*--------------------------------------------------------------------------------*/ +/* Retourne 1 si presence d'un cycle 0 sinon */ +/*--------------------------------------------------------------------------------*/ + +int existe_visavis(indexatrouver, indexequipo, lst_equipo) +long indexatrouver; +long indexequipo; +LST_EQUIPO lst_equipo; +{ + ptype_list * liste; + + while (lst_equipo != NULL) { + if (lst_equipo->index == indexequipo) { + liste = lst_equipo->lst_visavis; + + while (liste != NULL) { + if (liste->TYPE == indexatrouver) + return(1); /* cycle */ + + liste = liste->NEXT; + } + + return(0); /* pas de cycle */ + } + lst_equipo = lst_equipo->suiv; + } + + return(0); +} + +/*------------------------------------------------------------------------------------*/ + +void affic_grille(grille) +GRILLE grille[NB_FACES]; +{ + PT_COORDONNEES lp , lg, ld, der; + int face; + + printf("AFFIC GRILLE\n"); + + for (face = 0; face < NB_FACES; face++) { + + printf("FACE %d ----- Piste 1ere %ld Largeur pas %d Nb pas %ld\n", face, grille[face].piste.premiere, grille[face].piste.largeur_pas, + grille[face].piste.nb_pas); + + printf("Grille deportg\n"); + lg = grille[face].lst_deportg; + + while (lg != NULL) { + printf("x %5ld ----- y %5ld\n", lg->xabs, lg->yabs); + lg = lg->suiv; + } + + printf("Grille pas\n"); + lp = grille[face].lst_pas; + + while (lp != NULL) { + printf("x %5ld ----- y %5ld proprio %d\n", (lp)->xabs, (lp)->yabs, (int)lp->proprio); + if (lp->suiv == NULL) + der = lp; + lp = lp->suiv; + } + + lp = der; + /* printf("Parcours en sens inverse\n"); + + while (lp != NULL) + { + printf("x %5ld ----- y %5ld\n", (lp)->xabs, (lp)->yabs); + lp = lp->prec; + } +*/ + printf("Grille deportd\n"); + ld = grille[face].lst_deportd; + + while (ld != NULL) { + printf("x %5ld ----- y %5ld\n", (ld)->xabs, (ld)->yabs); + ld = ld->suiv; + } + + } + +} + +/*--------------------------------------------------------------------------------*/ + +void alloue_coord(val, face, nouv) +long val; +int face; +PT_COORDONNEES *nouv; +{ + + (*nouv) = (PT_COORDONNEES) mbkalloc ((unsigned int) sizeof(COORDONNEES)); + (*nouv)->suiv = NULL; + (*nouv)->prec = NULL; + (*nouv)->proprio = NULL; + (*nouv)->compress = SANS_COMPRESS; + (*nouv)->piste = 0; + + switch (face) { + case NORD: + case SUD: + (*nouv)->xabs = val; + (*nouv)->yabs = 0; + break; + + case EST : + case OUEST: + (*nouv)->xabs = 0; + (*nouv)->yabs = val; + break; + } + +} + +/*-------------------------------------------------------------------------------*/ +/* recherche d'un connecteur libre cad proprio == null, pas besoin de verifier */ +/* largeur speciale, car les pas calcules en tiennet compte normalement */ +/*-------------------------------------------------------------------------------*/ + +PT_COORDONNEES cherche_deport_grille(con, lst_conalim) +LST_PSEUDO_CON con; +chain_list *lst_conalim; +{ + int trouve = 0; + PT_COORDONNEES ptcoor; + + ptcoor = (con->coord)->prec; + /* gauche toute */ + + while (ptcoor != NULL) { + trouve = ((ptcoor->proprio == NULL) && (!croisement_con_alim(ptcoor, con, lst_conalim))); + if (trouve) + break; + ptcoor = ptcoor->prec; + } + + if (!trouve) { + ptcoor = (con->coord)->suiv; + + /* droite toute */ + while (ptcoor != NULL) { + trouve = ((ptcoor->proprio == NULL) && (!croisement_con_alim(ptcoor, con, lst_conalim))); + if (trouve) + break; + ptcoor = ptcoor->suiv; + } + } + + if (!trouve) + ringerreur(ERR_ECHECDEPORT, con, NULL); + else { + if (mode_debug) + printf("deport trouve con %ld %ld\n", ptcoor->xabs, ptcoor->yabs); + return(ptcoor); + } + return NULL; + +} + +/*-----------------------------------------------------------------------------------*/ +/* Cette procedure pose une 'pince' sur les coordonnees les plus proches du deport. */ +/* C'est comme si on inserait le deport dans la grille des pas, deport pointe sur */ +/* les coordonnees immediatement inferieur et superieur, mais le deport n'appartient */ +/* pas a la grille, donc la grille ou liste de pas n'est PAS MODIFIEE. */ +/*-----------------------------------------------------------------------------------*/ + +void chaine_deportcon_grille(pt_coord, liste, face) +PT_COORDONNEES pt_coord; +PT_COORDONNEES liste; +int face; +{ + + PT_COORDONNEES cell, liste_coor; + int type = 0; + + cell = pt_coord; + + if (liste == NULL) { + cell->prec = NULL; + cell->suiv = NULL; + } else { + switch (face) { + case NORD: + case SUD: + liste_coor = liste; + while (liste_coor->suiv != NULL) { + if ((liste_coor)->xabs > pt_coord->xabs) { + cell->suiv = liste_coor; + cell->prec = liste_coor->prec; + break; + } + + liste_coor = liste_coor->suiv; + } + + /* fin de liste */ + if (liste_coor->suiv == NULL) + { + if ((liste_coor)->xabs > pt_coord->xabs) { + cell->suiv = liste_coor; + cell->prec = liste_coor->prec; + break; + } else { + cell->prec = liste_coor; + cell->suiv = NULL; + } + } + + break; + + case EST : + case OUEST: + liste_coor = liste; + while (liste_coor->suiv != NULL) { + if ((liste_coor)->yabs > pt_coord->yabs) { + cell->suiv = liste_coor; + cell->prec = liste_coor->prec; + break; + } + + liste_coor = liste_coor->suiv; + } + + /* fin de liste */ + if (liste_coor->suiv == NULL) + { + if ((liste_coor)->yabs > pt_coord->yabs) { + cell->suiv = liste_coor; + cell->prec = liste_coor->prec; + break; + } else { + cell->prec = liste_coor; + cell->suiv = NULL; + } + } + + break; + + } /* fin du switch */ + + /* post traitement, on evite les coord dont proprio = coeur */ + if ((cell->suiv != NULL) && (NULL != cell->suiv->proprio)) + if (COEUR_CON == ((LST_PSEUDO_CON) cell->suiv->proprio)->coeur_plot) { + liste_coor = cell->suiv->suiv; + + while (NULL != liste_coor) { + if (NULL != liste_coor->proprio) + type = ((LST_PSEUDO_CON) liste_coor->proprio)->coeur_plot; + + if ((NULL == liste_coor->proprio) || (COEUR_CON != type)) { + cell->suiv = liste_coor; + break; + } + liste_coor = liste_coor->suiv; + } + } + + if ((cell->prec != NULL) && (NULL != cell->prec->proprio)) + if (COEUR_CON == ((LST_PSEUDO_CON) cell->prec->proprio)->coeur_plot) { + liste_coor = cell->prec->prec; + + while (NULL != liste_coor) { + if (NULL != liste_coor->proprio) + type = ((LST_PSEUDO_CON) liste_coor->proprio)->coeur_plot; + + if ((NULL == liste_coor->proprio) || (COEUR_CON != type)) { + cell->prec = liste_coor; + break; + } + liste_coor = liste_coor->prec; + } + } + + } /* fin du else */ + + if (mode_debug) { + if (cell->suiv) { + if (cell->suiv->proprio) + printf("proprio -> %s\n", ((LST_PSEUDO_CON) cell->suiv->proprio)->nom_con); + printf("chaine deportcon: suiv x %ld y %ld\t", cell->suiv->xabs, cell->suiv->yabs); + } + if (cell->prec) { + if (cell->suiv->proprio) + printf("proprio -> %s\n", ((LST_PSEUDO_CON) cell->suiv->proprio)->nom_con); + printf("chaine deportcon: prec x %ld y %ld\n", cell->prec->xabs, cell->prec->yabs); + } + } + +} + +/*-----------------------------------------------------------------------------------------*/ +/* Allocation d'un segment , chainage dans le tableau de segments occupes associes a */ +/* la face, et chainage dans la liste des segments de l'equipotentielle. */ +/* Le tableau de segments occupes est organise de 2 manieres: */ +/* - pour les seg de type SEG_PISTE le tableau de segment est ordonne par piste. De plus */ +/* les segments de meme piste sont contigus ds la liste. */ +/* - pour les seg de type SEG_COL le tableau n'est pas ordonnee. Seulement les segments */ +/* de meme colonne sont contigus dans la liste */ +/*-----------------------------------------------------------------------------------------*/ + +void alloue_etchaine_segment(c1, c2, piste1, piste2, face, typeseg, tab_seg, largeur, layer, vraifaux, via, equipo) +PT_COORDONNEES c1; +PT_COORDONNEES c2; +long piste1; +long piste2; +int face; +int typeseg; +LST_SEGMENT tab_seg[NB_FACES]; +long largeur; +char layer; +int vraifaux; +int via; +LST_EQUIPO equipo; +{ + static int first = 1; + int i; + LST_SEGMENT seg, liste_seg; + + if (first) { + for (i = 0; i < NB_FACES; i++) + tab_seg[i] = NULL; + first = 0; + } + + seg = (LST_SEGMENT) mbkalloc ((unsigned int) sizeof (SEGMENT)); + + seg->vraifaux = vraifaux; /* le segment est un vrai ou un faux segment (cf alim) */ + seg->via = via; /* pose d'un via ou pas (cf alim) */ + + /* on classe les colonnes et les pistes */ + + switch (face) { + case NORD: + case SUD : + if (c1->xabs <= c2->xabs) { + seg->c1 = c1; + seg->c2 = c2; + } else { + seg->c1 = c2; + seg->c2 = c1; + } + break; + case EST : + case OUEST: + if (c1->yabs <= c2->yabs) { + seg->c1 = c1; + seg->c2 = c2; + } else { + seg->c1 = c2; + seg->c2 = c1; + } + break; + } + + seg->face = face; + + if (piste1 <= piste2) { + seg->piste1 = piste1; + seg->piste2 = piste2; + } else { + seg->piste1 = piste2; + seg->piste2 = piste1; + } + + if (mode_debug) + printf("alloue et chaine face %d c1x %ld c2 x %ld c1pt %d c2pt%d\n", (int)face, seg->c1->xabs, seg->c2->xabs, + (int)seg->c1, (int)seg->c2); + seg->largeur = largeur; + seg->layer = layer; + + /* Chainage dans la liste des segments occupes */ + + if (NULL == tab_seg[face]) { + seg->prec = NULL; + seg->suiv = NULL; + tab_seg[face] = seg; + } else { + liste_seg = tab_seg[face]; + + switch (typeseg) { + case SEG_PISTE: /* trie sur numero de piste */ + + while (NULL != liste_seg->suiv) { + if ((liste_seg)->piste1 > seg->piste1) { + seg->suiv = liste_seg; + seg->prec = liste_seg->prec; + + if (NULL == liste_seg->prec) /* tete de liste modifiee */ + tab_seg[face] = seg; + else + (seg->prec)->suiv = seg; + + liste_seg->prec = seg; + break; + } + + liste_seg = liste_seg->suiv; + } + + /* fin de liste */ + if (NULL == liste_seg->suiv) + { + if ((liste_seg)->piste1 > seg->piste1) { + seg->suiv = liste_seg; + seg->prec = liste_seg->prec; + if (NULL == liste_seg->prec) /* tete de liste modifiee */ + tab_seg[face] = seg; + else + (seg->prec)->suiv = seg; + + liste_seg->prec = seg; + } else { + liste_seg->suiv = seg; + seg->prec = liste_seg; + seg->suiv = NULL; + } + } + break; + + case SEG_COL: + /* c1 = c2 au niveau des pointeurs (equivaut a c1->xabs = c2->xabs ou c2->yabs = c1->yabs) insertion meme pointeur colonne */ + + while (NULL != liste_seg) { + if (liste_seg->c1 == c1) /* meme colonne */ { + /* insertion apres liste_seg */ + seg->prec = liste_seg; + seg->suiv = liste_seg->suiv; + liste_seg->suiv = seg; + if (NULL != seg->suiv) + (seg->suiv)->prec = seg; + break; + } + + liste_seg = liste_seg->suiv; + } + + if (NULL == liste_seg) /* colonne n'existe pas */ { + /* chainage avant */ + seg->prec = NULL; + seg->suiv = tab_seg[face]; + (tab_seg[face])->prec = seg; + tab_seg[face] = seg; + } + break; + } /* fin du switch */ + } /* fin du else */ + + /* chainage en tete de la liste des segments de l'equipo */ + + equipo->lst_seg = addchain(equipo->lst_seg, (void * ) seg); + +} + +/*------------------------------------------------------------------------------------*/ +/* Cette fonction retourne 1 si le segment qu'on veut poser est libre dans la face */ +/* sinon 0 => parcours des listes de segments occupes */ +/*------------------------------------------------------------------------------------*/ + +int segment_libre(coor1, coor2, piste1, piste2, face, typeseg, tab_seg, layer) +PT_COORDONNEES coor1; +PT_COORDONNEES coor2; +long piste1; +long piste2; +int face; +int typeseg; +LST_SEGMENT tab_seg[NB_FACES]; +char layer; +{ + + PT_COORDONNEES c1 = NULL, c2 = NULL; + LST_SEGMENT liste_seg = tab_seg[face]; + int trouve = 0; + long aux; + + /* + if (mode_debug) printf("SEGMENT LIBRE tabseg %d listeseg %d\n",(int) tab_seg, (int) liste_seg); + */ + + /* on classe les colonnes et les pistes */ + + if (piste1 > piste2) { + aux = piste1; + piste1 = piste2; + piste2 = aux; + } + + switch (face) { + case NORD: + case SUD : + if (coor1->xabs <= coor2->xabs) { + c1 = coor1; + c2 = coor2; + } else { + c1 = coor2; + c2 = coor1; + } + break; + case EST : + case OUEST: + if (coor1->yabs <= coor2->yabs) { + c1 = coor1; + c2 = coor2; + } else { + c1 = coor2; + c2 = coor1; + } + break; + } + + switch (typeseg) { + case SEG_PISTE: + while ((NULL != liste_seg) && (!trouve)) { + while ((NULL != liste_seg) && (liste_seg->piste1 == piste1)) { + trouve = 1; + switch (face) { + case NORD: + case SUD : + if (liste_seg->layer == layer) { + if (((c1->xabs >= (liste_seg->c1)->xabs) && (c1->xabs <= (liste_seg->c2)->xabs)) + || ((c2->xabs >= (liste_seg->c1)->xabs) && (c2->xabs <= (liste_seg->c2)->xabs)) + || ((c1->xabs < (liste_seg->c1)->xabs) && (c2->xabs > (liste_seg->c2)->xabs))) + return(0); /* un des 2 points (c1,c2) appartient au segment */ + } else if /* layer different, les seg ne doivent pas se superposer */ + (((c1->xabs > (liste_seg->c1)->xabs) && (c1->xabs < (liste_seg->c2)->xabs)) || ((c2->xabs > + (liste_seg->c1)->xabs) && (c2->xabs < (liste_seg->c2)->xabs)) || ((c1->xabs < (liste_seg->c1)->xabs) && + (c2->xabs > (liste_seg->c2)->xabs))) + return(0); /* un des 2 points (c1,c2) appartient au segment */ + break; + + case EST : + case OUEST: + if (liste_seg->layer == layer) { + if (((c1->yabs >= (liste_seg->c1)->yabs) && (c1->yabs <= (liste_seg->c2)->yabs)) + || ((c2->yabs >= (liste_seg->c1)->yabs) && (c2->yabs <= (liste_seg->c2)->yabs)) + || ((c1->yabs < (liste_seg->c1)->yabs) && (c2->yabs > (liste_seg->c2)->yabs))) + + return(0); /* un des 2 points (c1,c2) appartient au segment */ + } else if (((c1->yabs > (liste_seg->c1)->yabs) && (c1->yabs < (liste_seg->c2)->yabs)) + || ((c2->yabs > (liste_seg->c1)->yabs) && (c2->yabs < (liste_seg->c2)->yabs)) || + ((c1->yabs < (liste_seg->c1)->yabs) && (c2->yabs > (liste_seg->c2)->yabs))) + return(0); /* un des 2 points (c1,c2) appartient au segment */ + + break; + } /* fin switch */ + + liste_seg = liste_seg->suiv; + } /* fin 2nd while */ + + if (NULL != liste_seg) + liste_seg = liste_seg->suiv; + } + break; + + case SEG_COL: + + while ((NULL != liste_seg) && (!trouve)) { + while ((NULL != liste_seg) && (liste_seg->c1 == c1)) { + trouve = 1; + if (liste_seg->layer == layer) { + if (((piste1 >= liste_seg->piste1) && (piste1 <= liste_seg->piste2)) || ((piste2 >= + liste_seg->piste1) && (piste2 <= liste_seg->piste2)) || ((piste1 < liste_seg->piste1) && + (piste2 > liste_seg->piste2))) + return(0); /* une des 2 pistes appartient au segment ou seg + grand */ + } else if /* layer <> les seg ne doivent pas se superposer */ + (((piste1 > liste_seg->piste1) && (piste1 < liste_seg->piste2)) || ((piste2 > liste_seg->piste1) && + (piste2 < liste_seg->piste2)) || ((piste1 < liste_seg->piste1) && (piste2 > liste_seg->piste2))) + return(0); /* une des 2 pistes appartient au segment ou seg + grand */ + + liste_seg = liste_seg->suiv; + } /* fin 2nd while */ + + if (NULL != liste_seg) + liste_seg = liste_seg->suiv; + } + break; + } + + return(1); /* eh oui elle est libre */ + +} + +/*-----------------------------------------------------------------------------------*/ + +void affic_listeseg(tab_seg) +LST_SEGMENT tab_seg[NB_FACES]; +{ + LST_SEGMENT lseg, der; + int face; + static char a1[3] = "A1"; + static char a2[3] = "A2"; + static char er[3] = "ER"; + char *metal; + + printf("LISTES DES SEGMENTS OCCUPES"); + for (face = 0; face < NB_FACES; face++) { + lseg = tab_seg[face]; + + printf("\nFACE %d\n", face); + + while (lseg) { + if (lseg->layer == ALU1) + metal = a1; + else if (lseg->layer == ALU2) + metal = a2; + else + metal = er; + + printf("face %d x1 %5ld y1 %5ld x2 %5ld y2 %5ld -- piste1 %3ld piste2 %3ld -- larg %3ld layer %2s \n", + lseg->face, lseg->c1->xabs, lseg->c1->yabs, lseg->c2->xabs, lseg->c2->yabs, lseg->piste1, lseg + ->piste2, lseg->largeur, metal); + if (NULL == lseg->suiv) + der = lseg; + + lseg = lseg->suiv; + } + + /* printf("PAR DERRIERE\n"); + while (der) { + printf("face %d x1 %5ld y1 %5ld x2 %5ld y2 %5ld ---- piste1 %3ld piste2 %3ld --- larg %3ld layer %d \n", + der->face,der->c1->xabs,der->c1->yabs,der->c2->xabs,der->c2->yabs,der->piste1,der->piste2,der->largeur,(int)der->layer); + der = der->prec; + } + */ + } + +} + +/*--------------------------------------------------------------------------------*/ + +phcon_list *cherche_conph_circuit(con_lo, liste_plotsph, circuit_ph) +locon_list *con_lo; +chain_list *liste_plotsph; +phfig_list *circuit_ph; +{ + phfig_list * modele; + phins_list * lst_instph = circuit_ph->PHINS; + phcon_list * liste_con; + char orientnord = 'N', *nominst = ((loins_list*)con_lo->ROOT)->INSNAME; + char orientplot, *figure = ((loins_list*)con_lo->ROOT)->FIGNAME; + + while (NULL != lst_instph) { + if (lst_instph->INSNAME == nominst) { + orientplot = lst_instph->TRANSF; + break; + } + + lst_instph = lst_instph->NEXT; + } + + if (NULL == lst_instph) + ringerreur(ERR_INSTPH_PLOT, nominst, NULL); + + if ((modele = appartient_listeplotsph(figure, liste_plotsph)) != NULL) { + + liste_con = modele->PHCON; + + while (liste_con != NULL) { + if ((liste_con->ORIENT == orientnord) && (liste_con->NAME == con_lo->NAME)) { + return(liste_con); + } + liste_con = liste_con->NEXT; + } + + ringerreur(ERR_NOCONPH_PLOT, con_lo, NULL); /* connecteur de la face non trouve */ + } else + ringerreur(ERR_FIGPH_PLOT, figure, NULL); /* Modele physique non existant ! */ + return NULL; + +} + +/*-----------------------------------------------------------------------------------*/ + +int croisement_con_alim(ptcoor, concoeur, ptalim) +PT_COORDONNEES ptcoor; +LST_PSEUDO_CON concoeur; +chain_list *ptalim; +{ + PT_COORDONNEES lst_coor; + LST_PSEUDO_CON con; + long position = 0, positioncour = 0, dminmetalmetal = 0, diff = 0; + long widthcour = concoeur->largeur; + int i, nbcolatrouver; + + if (mode_debug) + printf("\tCroisement con avec alim %s larg %ld face %d x %ld y %ld\n", concoeur->nom_con, concoeur->largeur, + concoeur->face, ptcoor->xabs, ptcoor->yabs); + + nbcolatrouver = (concoeur->largeur + pitch) / (2 * pitch); + + /* on regarde si les colonnes voisines necessaire pour la largeur du + deport sont disponibles */ + + lst_coor = ptcoor->suiv; + for (i = 0; i < nbcolatrouver; i++) { + if ((NULL != lst_coor) && (NULL == lst_coor->proprio)) + lst_coor = lst_coor->suiv; + else + return ((int) 1); + } + + lst_coor = ptcoor->prec; + for (i = 0; i < nbcolatrouver; i++) { + if ((NULL != lst_coor) && (NULL == lst_coor->proprio)) + lst_coor = lst_coor->prec; + else + return ((int) 1); + } + + switch (concoeur->face) { + case NORD: + case SUD : + positioncour = ptcoor->xabs; + dminmetalmetal = ymetal_dmin; + break; + case EST : + case OUEST: + positioncour = ptcoor->yabs; + dminmetalmetal = xmetal_dmin; + break; + } + + while (ptalim != NULL) { + con = (LST_PSEUDO_CON) ptalim->DATA; + + if ((con->face == concoeur->face) && (con->coeur_plot != concoeur->coeur_plot)) { + switch (concoeur->face) { + case NORD: + case SUD : + position = (con->coord)->xabs; + break; + case EST : + case OUEST: + position = (con->coord)->yabs; + break; + } + + diff = distance_con_con(position, position, con->largeur, concoeur->layer, positioncour, positioncour, + widthcour, concoeur->layer, concoeur->face); + + if ((diff < 0) || (diff < dminmetalmetal)) + if (mode_debug) + printf("\tposition cour %ld nom %s position %ld ***diffcrois %ld larg %ld\n", positioncour, + con->nom_con, position, diff, con->largeur); + + if (diff < 0) + return((int) -diff); + if (diff < dminmetalmetal) + return ((int) pitch); + + } + + ptalim = ptalim->NEXT; + } + + return((int) 0); +} + +/*-----------------------------------------------------------------------------------------*/ + +void largeur_vddvss(equipo_vdd, equipo_vss, largvdd, largvss) +LST_EQUIPO equipo_vdd, equipo_vss; +long *largvdd, *largvss; +{ + chain_list * ptvdd, *ptvss, *liste; + LST_PSEUDO_CON con; + char *nom_con; + long larg_con, largeurvdd, largeurvss; + int existevdd = 0, existevss = 0; + static int mess = 1; + + ptvdd = equipo_vdd->lst_con; + ptvss = equipo_vss->lst_con; + largeurvdd = 0; + largeurvss = 0; + + while (NULL != ptvdd) { + con = (LST_PSEUDO_CON) ptvdd->DATA; + if (con->coeur_plot == PLOT_CON) + largeurvdd += con->largeur; + + ptvdd = ptvdd->NEXT; + } + + while (NULL != ptvss) { + con = (LST_PSEUDO_CON) ptvss->DATA; + if (con->coeur_plot == PLOT_CON) + largeurvss += con->largeur; + + ptvss = ptvss->NEXT; + } + + if (mode_debug) + printf("Prise en compte width fic param\n"); + + /* verification sur la liste des connecteurs de largeur specifique */ + + liste = liste_width; + + while (liste != NULL) { + nom_con = ((PTCEL)(liste->DATA))->chaine; + larg_con = ((PTCEL)(liste->DATA))->largeur; + if (mode_debug) + printf("Connecteur --%s-- largeur %ld\n", nom_con, larg_con); + + if (eq_vss == nom_con) { + existevss = 1; + if (mode_debug) { + fprintf(stderr, "the default width track for is <%ld> and your request is <%ld>.\n", + (largeurvss / 2) / SCALE_X, larg_con); + } + (*largvss) = vss_width = larg_con * SCALE_X; + } + + if (eq_vdd == nom_con) { + existevdd = 1; + if (mode_debug) { + fprintf(stderr, "the default width track for is <%ld> and your request is <%ld>.\n", + (largeurvdd / 2) / SCALE_X, larg_con); + } + (*largvdd) = vdd_width = larg_con * SCALE_X; + } + + liste = liste->NEXT; + } + + mess = 0; + if (!existevdd) + vdd_width = (*largvdd) = largeurvdd / 2; + if (!existevss) + vss_width = (*largvss) = largeurvss / 2; +} + +/*-----------------------------------------------------------------------------------*/ +/* Cette fonction retourne 1 si le croisement est suffisant entre le fil d'alim */ +/* coeur et son homologue plot, sinon 0 (deport a faire gag!) */ +/* Modif: on verifie que le conplot alim est du meme layer le metalcol de routage */ +/* si testlayer =0 */ +/*-----------------------------------------------------------------------------------*/ + +int croisementok_alimequi(concoeur, ptalim, testlayer) +LST_PSEUDO_CON concoeur; +chain_list *ptalim; +char testlayer; +{ + LST_PSEUDO_CON con; + long position = 0, positioncour = 0; + char metalcol = 0; + + if (mode_debug) + printf("\tCroisement con avec alim equi %s larg %ld face %d x %ld y %ld\n", concoeur->nom_con, concoeur->largeur, + concoeur->face, concoeur->coord->xabs, concoeur->coord->yabs); + + switch (concoeur->face) { + case NORD: + case SUD : + positioncour = concoeur->coord->xabs; + metalcol = ymetal; + break; + case EST : + case OUEST: + positioncour = concoeur->coord->yabs; + metalcol = xmetal; + break; + } + + while (ptalim != NULL) { + con = (LST_PSEUDO_CON) ptalim->DATA; + + if ((con->face == concoeur->face) && (con->coeur_plot != concoeur->coeur_plot)) { + switch (concoeur->face) { + case NORD: + case SUD : + position = (con->coord)->xabs; + break; + case EST : + case OUEST: + position = (con->coord)->yabs; + break; + } + + if (mode_debug) + printf("\tCroisement conplot avec alim equi %s larg %ld face %d position%ld\n", con->nom_con, + con->largeur, con->face, position); + + if (position < positioncour) { + if (((position + con->largeur / 2) >= positioncour) && ((con->layer == metalcol) || (testlayer)) ) { + if (mode_debug) + printf("croisement trouve\n"); + return((int) 1); + } + } else if (position > positioncour) { + if (((position - con->largeur / 2) <= positioncour) && ((con->layer == metalcol) || (testlayer)) ) { + if (mode_debug) + printf("croisement trouve\n"); + return((int) 1); + } + } else if ((con->layer == metalcol) || (testlayer)) { + if (mode_debug) + printf("croisement trouve\n"); + return ((int) 1); + } + } + + ptalim = ptalim->NEXT; + } + + return((int) 0); +} + +/*----------------------------------------------------------------------------------*/ +/* Cette procedure compte le nombre de plots dans la liste */ +/*----------------------------------------------------------------------------------*/ + +long compte_nbplotsface(liste) +chain_list *liste; +{ + + long cpt = 0; + + while (NULL != liste) { + cpt++; + liste = liste->NEXT; + } + + return(cpt); +} +