From aa4706c9fc2262e20f626498cce5432b9ff42e3e Mon Sep 17 00:00:00 2001 From: Frederic Petrot Date: Wed, 13 Mar 2002 17:58:33 +0000 Subject: [PATCH] Importing MBKSPICE sources into the new CVS tree --- alliance/src/mbkspice/Makefile.am | 1 + alliance/src/mbkspice/configure.in | 52 + alliance/src/mbkspice/src/Makefile.am | 4 + alliance/src/mbkspice/src/msl.h | 58 + alliance/src/mbkspice/src/spi_drive.c | 944 +++++++ alliance/src/mbkspice/src/spi_drive.h | 73 + alliance/src/mbkspice/src/spi_global.c | 185 ++ alliance/src/mbkspice/src/spi_global.h | 14 + alliance/src/mbkspice/src/spi_hash.c | 238 ++ alliance/src/mbkspice/src/spi_hash.h | 87 + alliance/src/mbkspice/src/spi_int.c | 245 ++ alliance/src/mbkspice/src/spi_int.h | 68 + alliance/src/mbkspice/src/spi_msg.c | 188 ++ alliance/src/mbkspice/src/spi_msg.h | 50 + alliance/src/mbkspice/src/spi_parse.c | 3116 ++++++++++++++++++++++++ alliance/src/mbkspice/src/spi_parse.h | 187 ++ 16 files changed, 5510 insertions(+) create mode 100644 alliance/src/mbkspice/Makefile.am create mode 100644 alliance/src/mbkspice/configure.in create mode 100644 alliance/src/mbkspice/src/Makefile.am create mode 100644 alliance/src/mbkspice/src/msl.h create mode 100644 alliance/src/mbkspice/src/spi_drive.c create mode 100644 alliance/src/mbkspice/src/spi_drive.h create mode 100644 alliance/src/mbkspice/src/spi_global.c create mode 100644 alliance/src/mbkspice/src/spi_global.h create mode 100644 alliance/src/mbkspice/src/spi_hash.c create mode 100644 alliance/src/mbkspice/src/spi_hash.h create mode 100644 alliance/src/mbkspice/src/spi_int.c create mode 100644 alliance/src/mbkspice/src/spi_int.h create mode 100644 alliance/src/mbkspice/src/spi_msg.c create mode 100644 alliance/src/mbkspice/src/spi_msg.h create mode 100644 alliance/src/mbkspice/src/spi_parse.c create mode 100644 alliance/src/mbkspice/src/spi_parse.h diff --git a/alliance/src/mbkspice/Makefile.am b/alliance/src/mbkspice/Makefile.am new file mode 100644 index 00000000..af437a64 --- /dev/null +++ b/alliance/src/mbkspice/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = src diff --git a/alliance/src/mbkspice/configure.in b/alliance/src/mbkspice/configure.in new file mode 100644 index 00000000..93c85227 --- /dev/null +++ b/alliance/src/mbkspice/configure.in @@ -0,0 +1,52 @@ +dnl +dnl This file is part of the Alliance CAD System +dnl Copyright (C) Laboratoire LIP6 - Département ASIM +dnl Universite Pierre et Marie Curie +dnl +dnl Home page : http://www-asim.lip6.fr/alliance/ +dnl E-mail support : mailto:alliance-support@asim.lip6.fr +dnl +dnl This library is free software; you can redistribute it and/or modify it +dnl under the terms of the GNU Library General Public License as published +dnl by the Free Software Foundation; either version 2 of the License, or (at +dnl your option) any later version. +dnl +dnl Alliance VLSI CAD System is distributed in the hope that it will be +dnl useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +dnl Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License along +dnl with the GNU C Library; see the file COPYING. If not, write to the Free +dnl Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +dnl +dnl Purpose : Auto stuffing Alliance +dnl Almost ten years since I wrote this stuff, I just can't +dnl believe it +dnl Date : 01/02/2002 +dnl Author : Frederic Petrot +dnl $Id: configure.in,v 1.1 2002/03/13 17:58:33 fred Exp $ +dnl +dnl +AC_INIT(src/spi_parse.c) +AM_INIT_AUTOMAKE(mbkspice, 7.0) +AC_PROG_INSTALL +AC_PROG_CC +AC_HEADER_STDC +AC_CHECK_HEADERS(strings.h unistd.h) +AC_C_CONST +AC_PROG_RANLIB + +changequote(,)dnl +INCLUDES=-I${ALLIANCE_TOP}/include +LDFLAGS=-L${ALLIANCE_TOP}/lib +changequote([,])dnl + +AC_SUBST(INCLUDES) +AC_SUBST(LDFLAGS) + + +AC_OUTPUT([ +Makefile +src/Makefile +]) diff --git a/alliance/src/mbkspice/src/Makefile.am b/alliance/src/mbkspice/src/Makefile.am new file mode 100644 index 00000000..6a717cd5 --- /dev/null +++ b/alliance/src/mbkspice/src/Makefile.am @@ -0,0 +1,4 @@ +lib_LIBRARIES = libMsl.a +libMsl_a_SOURCES = spi_drive.c spi_drive.h spi_global.c spi_global.h \ + spi_hash.c spi_hash.h spi_int.c spi_int.h spi_msg.c \ + spi_msg.h spi_parse.c spi_parse.h diff --git a/alliance/src/mbkspice/src/msl.h b/alliance/src/mbkspice/src/msl.h new file mode 100644 index 00000000..3e6faf79 --- /dev/null +++ b/alliance/src/mbkspice/src/msl.h @@ -0,0 +1,58 @@ +/* + * 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 library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library 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. + */ + + +/******************************************************************************* +* * +* Tool : Spice parser / driver v 7.00 * +* Author(s) : Gregoire AVOT * +* Updates : March, 18th 1998 * +* * +*******************************************************************************/ +#ifndef MSLH +#define MSLH + +extern int msl_line; /* current line number */ +extern int msl_figloaded; /* TRUE if inside a SUBCKT */ +extern char *msl_figname; /* name of main SUBCKT */ +extern char *msl_subckt; /* name of current SUBCKT */ +extern lofig_list *msl_ptfig; /* last lofig parsed */ + +void mslAddExtension __P(( int(*)() )); /* add function called during parsing */ +void mslRmvExtension __P(( )); /* remove this function */ + +void mslAddCompletion __P(( int(*)() )); /* add function called after parsing */ +void mslRmvCompletion __P(( )); /* remove this function */ + +#ifndef TRUE +#define TRUE (1==1) /* c'est ben vrai */ +#endif + +#ifndef FALSE +#define FALSE (1==0) /* tout faux */ +#endif + +extern int SPI_LANG; + +#endif + diff --git a/alliance/src/mbkspice/src/spi_drive.c b/alliance/src/mbkspice/src/spi_drive.c new file mode 100644 index 00000000..d519a397 --- /dev/null +++ b/alliance/src/mbkspice/src/spi_drive.c @@ -0,0 +1,944 @@ +/* + * 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 library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library 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. + */ + + +/******************************************************************************* +* * +* Tool : Spice parser / driver v 7.00 * +* Author(s) : Gregoire AVOT * +* Updates : August, 17th 1998 * +* * +*******************************************************************************/ + +#define SPI_MAX_COL 80 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "msl.h" +#include "spi_drive.h" +#include "spi_int.h" +#include "spi_msg.h" +#include "spi_global.h" + +static char *TNMOS, + *TPMOS; +char *SPI_NETNAME; +char SPI_NAMEDNODES; + +#define SPI_NONODES (-1l) +#define SPI_MAXSTATICNAME 16 + +char* spinamednode( losig, node ) +losig_list *losig; +long node; +{ + static char names[SPI_MAXSTATICNAME][255]; + static int curnames = 0; + + ptype_list *ptptype; + convindex *cvx; + + curnames++; + if( curnames == SPI_MAXSTATICNAME ) + curnames=0; + + if( SPI_NAMEDNODES == TRUE ) { + if( node == SPI_NONODES ) { + if( losig->NAMECHAIN ) + sprintf( names[curnames], "%s", (char*)(losig->NAMECHAIN->DATA) ); + else + sprintf( names[curnames], "sig%ld", losig->INDEX ); + } + else { + if( losig->NAMECHAIN ) { + sprintf( names[curnames], "%s%c%ld", (char*)(losig->NAMECHAIN->DATA), + SEPAR, + node + ); + } + else { + sprintf( names[curnames], "sig%ld%c%ld", losig->INDEX, + SEPAR, + node + ); + } + } + } + else { + ptptype = getptype( losig->USER, SPI_DRIVER_PTYPE ); + cvx = (convindex*)(ptptype->DATA); + if( node == SPI_NONODES ) + sprintf( names[curnames], "%d", cvx->premier ); + else + sprintf( names[curnames], "%ld", cvx->premier + node - 1 ); + } + + return( names[curnames] ); +} + +void cherche_alim( ptfig, vdd, vss ) +lofig_list *ptfig; +char **vdd; +char **vss; +{ + locon_list *scancon; + losig_list *signal; + static char stvss[255], stvdd[255]; + + *vdd = 0; + *vss = 0; + + for( scancon = ptfig->LOCON ; + scancon && !(*vdd && *vss) ; + scancon = scancon->NEXT + ) + { + if( isvdd( scancon->NAME ) ) + { + signal = scancon->SIG; + if( scancon->PNODE ) + strcpy( stvdd, spinamednode( signal, scancon->PNODE->DATA ) ); + else + strcpy( stvdd, spinamednode( signal, SPI_NONODES ) ); + + *vdd = stvdd; + } + + if( isvss( scancon->NAME ) ) + { + signal = scancon->SIG; + if( scancon->PNODE ) + strcpy( stvss, spinamednode( signal, scancon->PNODE->DATA ) ); + else + strcpy( stvss, spinamednode( signal, SPI_NONODES ) ); + + *vss = stvss; + } + } +} + +void sortrcn( ptfig, df, vss ) +lofig_list *ptfig; +FILE *df; +char *vss; +{ + losig_list *scanlosig; + int nbr; + convindex *cvx; + ptype_list *ptptype; + lowire_list *scanlowire; + int nbctc; + chain_list *scanchain; + chain_list *headctc; + loctc_list *ptctc; + + nbctc = 0; + + for( scanlosig = ptfig->LOSIG ; scanlosig ; scanlosig = scanlosig->NEXT ) + { + if( !scanlosig->PRCN ) + continue; + + ptptype = getptype( scanlosig->USER, SPI_DRIVER_PTYPE ); + cvx = (convindex*)(ptptype->DATA); + + if( scanlosig->PRCN->PWIRE || scanlosig->PRCN->PCTC ) + { + nbr = 1; + + + for( scanlowire = scanlosig->PRCN->PWIRE ; + scanlowire ; + scanlowire = scanlowire->NEXT ) + { + tooutput( df, + "R%d_%d %s %s %g\n", + scanlosig->INDEX, + nbr, + spinamednode( scanlosig, scanlowire->NODE1 ), + spinamednode( scanlosig, scanlowire->NODE2 ), + scanlowire->RESI < RESIMINI ? RESIMINI : scanlowire->RESI + ); + + /* HSpice ne supporte pas 1e-6P : Il ne prendra pas en compte le P, et + * on aura 1 micron au lieu de 1e-18. */ + + if( scanlowire->CAPA / 2.0 >= CAPAMINI ) + { + tooutput( df, + "C%d_%d1 %s %s %g\n", + scanlosig->INDEX, + nbr, + spinamednode( scanlosig, scanlowire->NODE1 ), + vss, + scanlowire->CAPA / 2.0 * 1e-12 + ); + + tooutput( df, + "C%d_%d2 %s %s %g\n", + scanlosig->INDEX, + nbr, + spinamednode( scanlosig, scanlowire->NODE2 ), + vss, + scanlowire->CAPA / 2.0 * 1e-12 + ); + } + + nbr++; + } + } + + /* On ne sort la capa totale que si on a ni RCN, ni CTC */ + + if( !scanlosig->PRCN->PWIRE && !scanlosig->PRCN->PCTC ) + { + if( scanlosig->PRCN->CAPA >= CAPAMINI ) + { + tooutput( df, + "C%d %s %s %g\n", + scanlosig->INDEX, + spinamednode( scanlosig, SPI_NONODES ), + vss, + scanlosig->PRCN->CAPA * 1e-12 + ); + } + } + } + + headctc = getallctc( ptfig ); + + for( scanchain = headctc ; scanchain ; scanchain = scanchain->NEXT ) + { + ptctc = (loctc_list*)scanchain->DATA ; + + if( ptctc->CAPA >= CAPAMINI ) + { + tooutput( df, + "C_ctc_%d %s %s %g\n", + nbctc, + spinamednode( ptctc->SIG1, ptctc->NODE1 > 0 ? ptctc->NODE1 : + SPI_NONODES ), + spinamednode( ptctc->SIG2, ptctc->NODE2 > 0 ? ptctc->NODE2 : + SPI_NONODES ), + ptctc->CAPA * 1e-12 + ); + } + + nbctc++; + } + + freechain( headctc ); +} + +void signalnoeud( ptfig ) +lofig_list *ptfig; +{ + losig_list *scanlosig; + convindex *nouveau; + int dernier; + + dernier = 1; + + for( scanlosig = ptfig -> LOSIG ; scanlosig ; scanlosig = scanlosig->NEXT ) + { + nouveau = ( convindex* ) mbkalloc( sizeof( convindex ) ); + nouveau->sig = scanlosig; + nouveau->premier = dernier; + + if( scanlosig->PRCN && scanlosig->PRCN->NBNODE > 0 ) + dernier += scanlosig->PRCN->NBNODE ; + else + dernier++; + + scanlosig->USER = addptype( scanlosig->USER, SPI_DRIVER_PTYPE, nouveau ); + } +} + +int sortconnecteur( df, c, position ) +FILE *df; +locon_list *c; +int position; +{ + losig_list *signal; + ptype_list *pt; + convindex *noeudbase; + num_list *tetenum,*scannum; + char v[1024]; + int lgmot; + + signal = c->SIG; + pt = getptype( signal->USER, SPI_DRIVER_PTYPE ); + noeudbase = (convindex*)(pt->DATA); + + if( c->PNODE ) + { + tetenum = c->PNODE; + for( scannum = tetenum ; scannum ; scannum = scannum->NEXT ) + { + sprintf( v,"%s ", spinamednode( signal, scannum->DATA) ); + lgmot = strlen(v); + if( lgmot + position >= SPI_MAX_COL - 2 ) + { + tooutput( df, "\n+ " ); + position = lgmot+2; + } + else + position = position + lgmot; + + tooutput( df, v ); + } + } + else + { + lgmot = strlen(v); + if( lgmot + position >= SPI_MAX_COL - 2 ) + { + tooutput( df, "\n+ " ); + position = lgmot+2; + } + else + position = position + lgmot; + sprintf( v, "%s ", spinamednode( signal, SPI_NONODES ) ); + tooutput( df, v ); + } + + return( position ); +} + +int sortconnecteur_ordre( df, ordre, liste, position ) +FILE *df; +chain_list *ordre; +locon_list *liste; +int position; +{ + chain_list *scanordre; + locon_list *scanlocon; + int num; + int n; + chain_list *cpteordre; + losig_list *signal; + ptype_list *pt; + convindex *noeudbase; + num_list *scannum; + num_list *tetenum; + char v[1024]; + int lgmot; + + for( scanordre = ordre ; scanordre ; scanordre = scanordre->NEXT ) + { + for( scanlocon = liste ; scanlocon ; scanlocon = scanlocon->NEXT ) + if( scanlocon->NAME == ((char*)(scanordre->DATA)) ) + break; + + if( !scanlocon ) + { + fflush( stdout ); + fprintf( stderr, "%s.\n", SPIMSG(5) ); + EXIT(1); + } + + num = 0; + for( cpteordre = ordre ; + cpteordre != scanordre ; + cpteordre = cpteordre->NEXT + ) + if( ((char*)(cpteordre->DATA)) == scanlocon->NAME ) + num++; + + signal = scanlocon->SIG; + pt = getptype( signal->USER, SPI_DRIVER_PTYPE ); + noeudbase = (convindex*)(pt->DATA); + + if( scanlocon->PNODE ) + { + tetenum = scanlocon->PNODE; + for( scannum = tetenum, n=0 ; nNEXT, n++ ); + sprintf( v, "%s ", spinamednode( signal, scannum->DATA ) ); + } + else + sprintf( v, "%s ", spinamednode( signal, SPI_NONODES ) ); + + lgmot = strlen(v); + if( lgmot + position >= SPI_MAX_COL ) + { + tooutput( df, "\n+ " ); + position = lgmot + 2; + } + else + position = position + lgmot; + + tooutput( df, v ); + } + + return( position ); +} + +void sortnet( ptfig, df ) +lofig_list *ptfig; +FILE *df; +{ + losig_list *scanlosig; + locon_list *scanlocon; + chain_list *scanchain; + ptype_list *ptl; + convindex *conv; + num_list *scannum; + loctc_list *ptctc; + int i; + + for( scanlosig = ptfig->LOSIG ; scanlosig ; scanlosig = scanlosig->NEXT ) + { + ptl = getptype(scanlosig->USER,SPI_DRIVER_PTYPE); + conv = (convindex*)(ptl->DATA); + if( scanlosig->TYPE == EXTERNAL ) + { + + if( scanlosig->TYPE == EXTERNAL ) + { + ptl = getptype( scanlosig->USER, LOFIGCHAIN ); + + if( !ptl ) + { + fflush( stdout ); + fprintf( stderr, "*** spi error *** : LOFIGCHAIN missing.\n" ); + EXIT(1); + } + + for( scanchain = (chain_list*)(ptl->DATA) ; + scanchain ; + scanchain = scanchain->NEXT + ) + { + scanlocon = (locon_list*)scanchain->DATA ; + if( scanlocon->ROOT == ptfig ) + { + if( scanlocon->PNODE ) + { + for( scannum = scanlocon->PNODE ; + scannum ; + scannum = scannum->NEXT + ) + { + spi_vect( scanlocon->NAME ); + tooutput( df, + "* %s %d = %s\n", + SPI_NETNAME, + scannum->DATA + conv->premier - 1 , + scanlocon->NAME + ); + } + } + else + { + spi_vect( scanlocon->NAME ); + tooutput( df, + "* %s %d = %s\n", + SPI_NETNAME, + conv->premier, + scanlocon->NAME + ); + } + } + } + } + } + else + if( scanlosig->NAMECHAIN ) + { + i = 0 ; + if( scanlosig->PRCN ) + { + if( scanlosig->PRCN->PWIRE ) + i = scanlosig->PRCN->PWIRE->NODE1 ; + else + if( scanlosig->PRCN->PCTC ) + { + ptctc = (loctc_list*)scanlosig->PRCN->PCTC->DATA; + if( ptctc->SIG1 == scanlosig ) + i = ptctc->NODE1; + else + i = ptctc->NODE2; + } + + if( i != 0 ) + i = i + conv->premier - 1 ; + } + + if( i == 0 ); + i = conv->premier ; + + spi_vect( (char*)scanlosig->NAMECHAIN->DATA ); + tooutput( df, + "* %s %d = %s\n", + SPI_NETNAME, + i, + (char*)scanlosig->NAMECHAIN->DATA + ) ; + } + } +} + +void sortinstance( ptfig, df ) +lofig_list *ptfig; +FILE *df; +{ + loins_list *scanloins; + locon_list *scanloconins; + ptype_list *pt; + char v[1024]; + int lgmot; + int colonne; + + for( scanloins = ptfig->LOINS ; scanloins ; scanloins = scanloins->NEXT ) + { + sprintf( v, "x%s ", scanloins->INSNAME ); + colonne = strlen( v ); + tooutput( df, v ); + + /* L'ordre des connecteurs entre la lofig et sa version instanciée n'est + pas le meme */ + + pt = getptype( scanloins->USER, PH_INTERF ); + if( pt ) + colonne = sortconnecteur_ordre( df, + (chain_list*)(pt->DATA), + scanloins->LOCON, + colonne + ); + else + for( scanloconins = scanloins->LOCON ; + scanloconins ; + scanloconins = scanloconins->NEXT + ) + colonne = sortconnecteur( df, scanloconins, colonne ); + + sprintf( v, "%s\n", scanloins->FIGNAME ); + lgmot = strlen(v); + if( lgmot+colonne >= SPI_MAX_COL -2 ) + tooutput( df, "\n+" ); + tooutput( df, v ); + } +} + +void sorttransistormos( ptfig, df, vss, vdd ) +lofig_list *ptfig; +FILE *df; +char *vss; +char *vdd; +{ + lotrs_list *scantrs; + int nb; + ht *trname; + char name[1024], *ptr ; + + for( scantrs = ptfig->LOTRS, nb=1 ; scantrs ; scantrs = scantrs->NEXT, nb++ ); + + trname = addht(nb); + + nb = 0; + + for( scantrs = ptfig->LOTRS; scantrs; scantrs = scantrs->NEXT ) + { + if( scantrs->TRNAME ) + { + if( gethtitem( trname, scantrs->TRNAME ) != EMPTYHT ) + { + do + { + nb++; + sprintf( name, "%s_%d", scantrs->TRNAME, nb ); + ptr = namealloc( name ); + } + while( gethtitem( trname, ptr ) != EMPTYHT ); + addhtitem( trname, ptr, 1 ); + tooutput( df, "M%s ", name ); + } + else + { + tooutput( df, "M%s ", scantrs->TRNAME ); + addhtitem( trname, scantrs->TRNAME, 1 ); + } + } + else + { + do + { + nb++; + sprintf( name, "%d", nb ); + ptr = namealloc( name ); + } + while( gethtitem( trname, ptr ) != EMPTYHT ); + tooutput( df, "M%s ", name ); + addhtitem( trname, ptr, 1 ); + } + + sortconnecteur( df, scantrs->DRAIN,1 ); + sortconnecteur( df, scantrs->GRID,1 ); + sortconnecteur( df, scantrs->SOURCE,1 ); + if( scantrs->BULK->SIG ) + { + sortconnecteur( df, scantrs->BULK,1 ); + } + else + { + if( IsTransN(scantrs->TYPE) ) + { + if( !vss ) + { + fflush( stdout ); + fprintf( stderr, + "*** spi error *** : Can't find signal VSS on figure %s.\n", + ptfig->NAME + ); + EXIT(1); + } + + tooutput( df, "%s ", vss ); + } + else + { + if( !vdd ) + { + fflush( stdout ); + fprintf( stderr, + "*** spi error *** : Can't find signal VDD on figure %s.\n", + ptfig->NAME + ); + EXIT(1); + } + + tooutput( df, "%s ", vdd ); + } + } + + tooutput( df, "%s ", spitransmodel( scantrs->TYPE ) ); + + if(scantrs->LENGTH!=0) + tooutput( df, "L=%gU ", (float)scantrs->LENGTH/SCALE_X ); + + if(scantrs->WIDTH!=0) + tooutput( df, "W=%gU ", (float)scantrs->WIDTH/SCALE_X ); + + if( scantrs->XS != 0 ) + tooutput( df, + "AS=%gP ", + (float) scantrs->XS * scantrs->WIDTH / ( SCALE_X * SCALE_X ) + ); + + if( scantrs->XD != 0 ) + tooutput( df, + "AD=%gP ", + (float) scantrs->XD * scantrs->WIDTH / ( SCALE_X * SCALE_X ) + ); + + if( scantrs->PS != 0 ) + tooutput( df, "PS=%gU ", (float)scantrs->PS/SCALE_X ); + + if( scantrs->PD != 0 ) + tooutput( df, "PD=%gU ", (float)scantrs->PD/SCALE_X ); + + tooutput( df, "\n" ); + } + + delht( trname ); +} + +void sortcircuit( ptfig, df ) +lofig_list *ptfig; +FILE *df; +{ + char *vdd, *vss; + locon_list *scancon; + ptype_list *pt; + int colonne; + char v[1024]; + + cherche_alim( ptfig, &vdd, &vss ); + + /* Sortie des instances et des transistors */ + + sprintf( v, "\n.subckt %s ", ptfig->NAME ); + colonne = strlen( v ); + + tooutput( df, v ); + + pt = getptype( ptfig->USER, PH_INTERF ); + if( pt ) + colonne = sortconnecteur_ordre( df, + (chain_list*)(pt->DATA), + ptfig->LOCON, + colonne + ); + else + for( scancon = ptfig->LOCON ; scancon ; scancon = scancon->NEXT ) + colonne = sortconnecteur( df, scancon, colonne ); + + tooutput( df,"\n" ); + + if( SPI_NAMEDNODES == FALSE ) { + sortnet( ptfig, df ); + } + + sortinstance( ptfig, df ); + sorttransistormos( ptfig, df, vss, vdd); + sortrcn( ptfig, df, vss ); + + tooutput( df, ".ends %s\n\n", ptfig->NAME ); +} + +void spicesavelofig( ptfig ) +lofig_list *ptfig; +{ + FILE *df; /* descripteur de fichier de sortie */ + chain_list *scanchain; + locon_list *scancon; + num_list *scannum; + char v[1024]; + ptype_list *pt; + char *nom; + time_t secondes; + struct tm *jours; + char *env; + int colonne; + int lgmot; + + env = mbkgetenv( "MBK_SPI_TN" ); + + if(env) + TNMOS = env; + else + TNMOS = "TN"; + + env = mbkgetenv( "MBK_SPI_TP" ); + + if(env) + TPMOS = env; + else + TPMOS = "TP"; + + env = mbkgetenv( "MBK_SPI_NETNAME" ); + + if( env ) + SPI_NETNAME = env; + else + SPI_NETNAME = "NET"; + + env = mbkgetenv( "MBK_SPI_NAMEDNODES" ); + + if( env ) + SPI_NAMEDNODES = TRUE ; + else + SPI_NAMEDNODES = FALSE ; + + spi_init_lang(); + + /* Ouverture du fichier de sortie */ + df = mbkfopen( ptfig->NAME, OUT_LO, WRITE_TEXT ); + if( !df ) + { + fflush( stdout ); + fprintf( stderr, "*** mbk error : savelofig impossible.\n" ); + fprintf( stderr, + "Can't open file %s.%s for writing.\n", + ptfig->NAME, + OUT_LO + ); + EXIT(1); + } + + + time( &secondes ); + jours = localtime( &secondes ); + + tooutput( df, "* Spice description of %s\n", ptfig->NAME ); + tooutput( df, "* Spice driver version %d\n",VERSION ); + tooutput( df, + "* Date ( dd/mm/yyyy hh:mm:ss ): %2d/%02d/%04d at %2d:%02d:%02d\n\n", + jours->tm_mday, + jours->tm_mon+1, + jours->tm_year+1900, + jours->tm_hour, + jours->tm_min, + jours->tm_sec + ); + + /* On va travailler sur les fonctions RCN : */ + lofigchain( ptfig ); + + signalnoeud( ptfig ); /* Calcule les noeuds Spice */ + + /* Sort la ligne *interf */ + + colonne = strlen( "* INTERF " ); + tooutput( df, "* INTERF " ); + + pt = getptype( ptfig->USER, PH_INTERF ); + if( pt ) + { + for( scanchain = (chain_list*)(pt->DATA) ; + scanchain ; + scanchain = scanchain->NEXT + ) + { + nom = ((char*)(scanchain->DATA)); + strcpy( v, nom ); + spi_vect( v ); + + lgmot = strlen(v)+1; + if( colonne+lgmot >= SPI_MAX_COL-2 ) + { + colonne = strlen( "* INTERF " ); + tooutput( df, "\n* INTERF " ); + } + colonne = colonne + lgmot; + + tooutput( df, "%s ", v ); + + } + } + else + { + for( scancon = ptfig->LOCON ; scancon ; scancon = scancon->NEXT ) + { + if( scancon->PNODE ) + { + for( scannum = scancon->PNODE ; scannum ; scannum = scannum->NEXT ) + { + strcpy( v, scancon->NAME ); + spi_vect( v ); + + lgmot = strlen(v)+1; + if( colonne+lgmot >= SPI_MAX_COL-2 ) + { + colonne = strlen( "* INTERF " ); + tooutput( df, "\n* INTERF " ); + } + colonne = colonne + lgmot; + + tooutput( df, "%s ", v ); + + } + } + else + { + strcpy( v, scancon->NAME ); + spi_vect( v ); + + lgmot = strlen(v)+1; + if( colonne+lgmot >= SPI_MAX_COL-2 ) + { + colonne = strlen( "* INTERF " ); + tooutput( df, "\n* INTERF " ); + } + colonne = colonne + lgmot; + + tooutput( df, "%s ", v ); + } + } + } + + tooutput( df, "\n\n" ); + + /* Sort les .include */ + + for( scanchain = ptfig->MODELCHAIN; scanchain; scanchain = scanchain->NEXT ) + { + tooutput( df, ".INCLUDE %s.%s\n", (char*)scanchain->DATA, OUT_LO ); + } + + sortcircuit( ptfig, df ); + + if( fclose(df) == -1 ) + { + fflush( stdout ); + fprintf( stderr, + "*** mbk error *** : Can't close file %s.\n,", + ptfig->NAME + ); + EXIT(1); + } +} + +void tooutput( va_alist ) +va_dcl +{ + va_list index; + FILE *fd; + char *fmt; + + va_start( index ); + + fd = va_arg( index, FILE* ); + fmt = va_arg( index, char* ); + + if( vfprintf( fd, fmt, index ) < 0 ) + { + fflush( stdout ); + fprintf( stderr, "*** spi error *** : Error while writing file.\n" ); + perror( "System say " ); + EXIT( 1 ); + } +} + +void spi_vect( s ) +char *s; +{ + int i,p1; + + if( s == NULL ) + return; + if( s[0] == '\0' ) + return; + + + /* Positionne i sur le premier caractere non espace a la fin de la chaine */ + i = strlen( s ) ; + do + i--; + while( s[i] == ' ' && i >0 ); + + /* passe un eventuel paquet de nombres */ + if( i ) + { + p1 = i; + while( isdigit( (int)s[i] ) && i >0 ) + i--; + if( p1 != i && s[i] == ' ' ) + { + s[i] = '['; + s[p1+1] = ']'; + s[p1+2] = '\0' ; + } + } +} diff --git a/alliance/src/mbkspice/src/spi_drive.h b/alliance/src/mbkspice/src/spi_drive.h new file mode 100644 index 00000000..3198393d --- /dev/null +++ b/alliance/src/mbkspice/src/spi_drive.h @@ -0,0 +1,73 @@ +/* + * 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 library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library 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. + */ + + +/******************************************************************************* +* * +* Tool : Spice parser / driver v 7.00 * +* Author(s) : Gregoire AVOT * +* Updates : March, 18th 1998 * +* * +*******************************************************************************/ + +#ifndef SPI_DRIVER +#define SPI_DRIVER + +#define SPI_DRIVER_PTYPE 6809 + +/* Capacite minimum acceptable par Spice en pf */ +#define CAPAMINI 0.000001 +/* Resistance minimum acceptable par Spice en ohm */ +#define RESIMINI 0.001 + +typedef struct sconvindex +{ + losig_list *sig; /* Pointeur sur le signal */ + int premier; /* Index du premier noeud sur le signal */ +} convindex; + +/* NOTE : + Le champs premier contient le numerot du premier noeud dans le fichier + Spice. Dans les vues RCN, le premier numérot de noeud est le 1. Le numérot + de noeud Spice est donc donné par la relation : + noeud_spice = noeud_rcn + premier - 1 +*/ + +char* spinamednode __P(( losig_list *losig, long node )); +void spi_vect __P(( char* )); +void cherche_alim __P(( lofig_list *ptfig, char **vdd, char **vss )); +void sortrcn __P(( lofig_list *ptfig, FILE *df, char *vss )); +void signalnoeud __P(( lofig_list *ptfig )); +int sortconnecteur __P(( FILE *df, locon_list *c, int )); +void sortnet __P(( lofig_list *ptfig, FILE *df )); +void sortinstance __P(( lofig_list *ptfig, FILE *df )); +void sorttransistormos __P(( lofig_list *ptfig, + FILE *df, + char *vss, + char *vdd + )); +void sortcircuit __P(( lofig_list *ptfig, FILE *df )); +void tooutput __P(()); /* va_list. */ +int sortconnecteur_ordre __P(( FILE *df, chain_list*, locon_list*, int )); + +#endif diff --git a/alliance/src/mbkspice/src/spi_global.c b/alliance/src/mbkspice/src/spi_global.c new file mode 100644 index 00000000..a68ac588 --- /dev/null +++ b/alliance/src/mbkspice/src/spi_global.c @@ -0,0 +1,185 @@ +#include +#include +#include + +#include +#include +#include +#include "spi_global.h" + +spimodel *SPIHEADMODEL = NULL; + +void spiloaderror( char*, int, char* ); + +void spiloadmodel( void ) +{ + char *env, place[80], word[80], *pt, *buffer; + FILE *ptf; + int line; + spimodel *new; + + env = mbkgetenv( "MBK_SPI_MODEL" ); + + if( !env ) + { + fflush( stdout ); + fprintf( stderr, "*** ERROR *** : Variable MBK_SPI_MODEL not found.\n" ); + fprintf( stderr, " try ""man spi""\n"); + EXIT(1); + } + + ptf = fopen( env, "r" ); + if( !ptf ) + { + fflush( stdout ); + fprintf( stderr, "*** ERROR *** : Can't open file %s.\n", env ); + EXIT(1); + } + + line = 0; + while( ! feof( ptf ) ) + { + line++; + fgets( place, 80, ptf ); + + /* On remplace le \n par un caractere de fin de chaine */ + buffer=place; + while( *buffer ) + { + if( *buffer=='\n' ) + { + *buffer=0; + break; + } + buffer++; + } + + buffer=place; + /* On passe les espaces en tête de fichier */ + while( *buffer==' ' && *buffer ) + buffer++; + + if( !*buffer ) + continue; + if( *buffer == '#' ) + continue; + + /* On recopie le nom */ + pt=word; + while( *buffer!=' ' && *buffer ) + { + *pt=*buffer; + pt++; + buffer++; + } + *pt=0; + + new = mbkalloc( sizeof( spimodel ) ); + new->NEXT = SPIHEADMODEL ; + new->MODEL = namealloc( word ); + new->TYPE = 0; + SPIHEADMODEL = new; + + while( *buffer==' ' && *buffer ) + buffer++; + if( !*buffer ) + spiloaderror( env, line, "No type found" ); /*le type est obligatoire */ + + /* La suite est le type, N ou P */ + + switch( *buffer ) + { + case 'N': + case 'n': + new->TYPE = new->TYPE | TRANSN ; + break; + case 'P': + case 'p': + new->TYPE = new->TYPE | TRANSP ; + break; + default : + spiloaderror( env, line, "Bad type" ); + } + buffer++; + + if( *buffer!=' ' && *buffer!='\0' ) + spiloaderror( env, line, "Bad type" ); + + while( *buffer==' ' && *buffer ) + buffer++; + + while( *buffer ) + { + pt=word; + while( *buffer!=' ' && *buffer ) + { + *pt=*buffer; + pt++; + buffer++; + } + *pt=0; + + if( strcasecmp( word, "FAST" ) == 0 ) + new->TYPE = new->TYPE | TRANSFAST; + else + if( strcasecmp( word, "HVIO" ) == 0 ) + new->TYPE = new->TYPE | TRANSHVIO; + else + spiloaderror( env, line, "Unknown option" ); + + while( *buffer==' ' && *buffer ) + buffer++; + } + } + + fclose( ptf ); +} + +void spiloaderror( char *name, int line, char *reason ) +{ + fflush( stdout ); + fprintf( stderr, "*** ERROR *** bad model file %s line %d\n", name, line ); + fprintf( stderr, "Reason is : %s.\n", reason ); + EXIT(1); +} + +char* spitransmodel( char type ) +{ + spimodel *scan; + + if( !SPIHEADMODEL ) + spiloadmodel(); + + for( scan = SPIHEADMODEL ; scan ; scan = scan->NEXT ) + { + if( scan->TYPE == type ) + return( scan->MODEL ); + } + + fflush( stdout ); + fprintf( stderr, "*** ERROR *** No known type.\n" ); + fprintf( stderr, "Flags : %c %s %s\n", + IsTransN(type)?'N':'P', + IsTransFast(type)?"FAST":"---", + IsTransHvio(type)?"HVIO":"---" + ); + EXIT(1); + + return(0); +} + +char spitranstype( char *model ) +{ + spimodel *scan; + + if( !SPIHEADMODEL ) + spiloadmodel(); + + for( scan = SPIHEADMODEL ; scan ; scan = scan->NEXT ) + { + if( strcasecmp(scan->MODEL, model) == 0 ) + return( scan->TYPE ); + } + + return(SPI_UNK_TRANS_TYPE); +} diff --git a/alliance/src/mbkspice/src/spi_global.h b/alliance/src/mbkspice/src/spi_global.h new file mode 100644 index 00000000..b683c7a2 --- /dev/null +++ b/alliance/src/mbkspice/src/spi_global.h @@ -0,0 +1,14 @@ +typedef struct spimodel { + struct spimodel *NEXT; + char *MODEL; + char TYPE; +}spimodel ; + +void spiloadmodel __P(( void )); +char spitranstype __P(( char* )); +char* spitransmodel __P(( char )); + +/* Valeur pour dire que le nom de modele de transistor passé à la fonction + * spitranstype n'est pas défini. Ce nombre doit être une valeur impossible + * pour le champs type des transistors */ +#define SPI_UNK_TRANS_TYPE 64 diff --git a/alliance/src/mbkspice/src/spi_hash.c b/alliance/src/mbkspice/src/spi_hash.c new file mode 100644 index 00000000..a8bbc21f --- /dev/null +++ b/alliance/src/mbkspice/src/spi_hash.c @@ -0,0 +1,238 @@ +/* + * 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 library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library 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. + */ + + +/******************************************************************************* +* * +* Tool : Spice parser / driver v 7.00 * +* Author(s) : Gregoire AVOT * +* Updates : March, 18th 1998 * +* * +*******************************************************************************/ + +#include +#include +#include "spi_hash.h" + +/* 2^n elements dans la table de hash */ +#define HASH_MINI 4 +#define HASH_MAXI 15 + +/* 2^n Seuil d'augmentation */ +#define HASH_DELTA 1 + +thash* creatthash( ) +{ + thash *new; + int i; + int n; + + new = ( thash* )mbkalloc( sizeof( thash ) ); + new->entree = HASH_MINI ; + n = 1 << new->entree; + new->table = ( hashelem** )mbkalloc( sizeof( hashelem* ) * n ); + new->nbelem = 0; + new->tete = NULL; + new->libere = NULL; + + for( i = 0 ; i < n ; i++ ) + new->table[i] = NULL; + + return( new ); +} + +void freethash( pt ) +thash *pt; +{ + chain_list *scanchain; + + mbkfree( pt->table ); + /* + if( pt->tete ) + mbkfree( pt->tete ); + */ + + for( scanchain = pt->libere ; scanchain ; scanchain = scanchain->NEXT ) + mbkfree( scanchain->DATA ); + freechain( pt->libere ); + + mbkfree( pt ); +} + +hashelem* nouvhashelem( table ) +thash *table; +{ + int i; + hashelem *elem; + + if( ! table->tete ) + { + table->tete = ( hashelem* ) mbkalloc ( sizeof( hashelem ) * 64 ); + table->libere = addchain( table->libere, table->tete ); + elem = table->tete; + + for( i = 1 ; i < 64 ; i++ ) + { + elem->suivant = elem + 1; + elem++; + } + elem->suivant = NULL; + } + + elem = table->tete; + table->tete = table->tete->suivant; + + return( elem ); +} + +void liberehashelem( table, elem ) +thash *table; +hashelem *elem; +{ + elem->suivant = table->tete; + table->tete = elem; +} + +void addthashelem( nouveau, ptr, table ) +char *nouveau; +void *ptr; +thash *table; +{ + int s; + hashelem *elm; + + + if( table->nbelem == 1 << ( table->entree + HASH_DELTA ) && + table->entree < HASH_MAXI ) + resizetable( table, table->entree + 1 ); + + s = thashsignature( nouveau, table->entree ); + elm = nouvhashelem( table ); + + elm->suivant = table->table[ s ]; + table->table[ s ] = elm; + + elm->mot = nouveau; + elm->ptr = ptr; + + table->nbelem++; +} + +void* getthashelem( elem, table, status ) +char *elem; +thash *table; +int *status; +{ + int s; + hashelem *scan; + + s = thashsignature( elem, table->entree ); + + for( scan = table->table[ s ] ; scan ; scan = scan->suivant ) + { + if( scan->mot == elem || strcmp( scan->mot, elem ) == 0 ) + { + if( status != NULL ) + *status = 1; + return( scan->ptr ); + } + } + + if( status != NULL ) + *status = 0; + + return( NULL ); +} + +int thashsignature( c, l ) +char *c; +int l; +{ + int bit; + int b; + int dec; + + dec = 0; + bit = 0; + + while( *c ) + { + for( bit = 0; bit < 8 ; bit ++ ) + { + b = ( *c >> bit ) & 0x1; + + /* Polynome générateur : X^15 + X + 1 */ + dec = ( ( dec & 0x3FFE ) << 1 ) | + ( ( ( dec & 0x4000 ) >> 13 ) ^ ( ( dec & 0x1 ) << 1 ) ) | + ( ( ( dec & 0x4000 ) >> 14 ) ^ b ) ; + } + c++; + } + + return( dec % ( 1 << l ) ); +} + +void resizetable( table, elem ) +thash *table; +int elem; +{ + hashelem **new; + hashelem *nouv; + hashelem *scan; + hashelem *suiv; + int n; + int i; + int s; + + n = 1 << elem; + + new = ( hashelem** )mbkalloc( sizeof( hashelem* ) * n ); + for( i = 0 ; i < n ; i++ ) + new[ i ] = NULL; + + n = 1 << table->entree; + + for( i = 0 ; i < n ; i++ ) + { + for( scan = table->table[i] ; scan ; scan = scan->suivant ) + { + nouv = nouvhashelem( table ); + s = thashsignature( scan->mot, elem ); + + nouv->suivant = new[ s ]; + new[s] = nouv; + nouv->mot = scan->mot; + nouv->ptr = scan->ptr; + } + + for( scan = table->table[i] ; scan ; scan = suiv ) + { + suiv = scan->suivant; + liberehashelem( table, scan ); + } + } + + mbkfree( table->table ); + table->table = new; + table->entree = elem; +} diff --git a/alliance/src/mbkspice/src/spi_hash.h b/alliance/src/mbkspice/src/spi_hash.h new file mode 100644 index 00000000..76176ea8 --- /dev/null +++ b/alliance/src/mbkspice/src/spi_hash.h @@ -0,0 +1,87 @@ +/* + * 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 library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library 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. + */ + + +/******************************************************************************* +* * +* Tool : Spice parser / driver v 7.00 * +* Author(s) : Gregoire AVOT * +* Updates : March, 18th 1998 * +* * +*******************************************************************************/ + +#ifndef SPI_HASH +#define SPI_HASH + +typedef struct shashelem +{ + struct shashelem *suivant; + char *mot; + void *ptr; +} hashelem; + +typedef struct sthash +{ + int entree; /* Nombre d'entrées dans la table de hash 2^n */ + int nbelem; /* Nombre d'element dans les liste */ + hashelem **table; /* informations dans la table */ + hashelem *tete; /* Blocs libre pour allocation par tat */ + chain_list *libere; /* Pointeurs pour les libérations */ +} thash; + +thash* creatthash __P(( )); +/* + Crée une nouvelle table de hash. Le parametre d'entrée est le nombre +d'entrees de la nouvelle table +*/ + +void freethash __P(( thash *pt )); +/* + Libère une table de hash précédement allouée +*/ + +void addthashelem __P(( char *nouveau, void *ptr, thash *table )); +/* + Ajoute un élément dans la table de hash. Le premier parametre est +la chaine identifiant l'élément, le second est l'élément que l'on place dans +la table et finalement le troisième est l'élément vers la table de hash +*/ + +void* getthashelem __P(( char *elem, thash *table, int *status )); +/* + Récupère un élément dans la table de hash à partir de son identificateur +passé en premier paramètre. Le second argument est la table de hash sur laquelle +la recherche est effectuée. Si le troisième élément est différent de NULL, +la valeur 1 est plcée à cette adresse si l'élément est trouvé, 0 sinon. La +valeur renvoyée est celle de l'élément recherché. +*/ + +int thashsignature __P(( char *c, int l )); +/* + Utilisé en interne +*/ + +void resizetable __P(( thash*, int )); +hashelem* nouvhashelem __P(( thash* )); +void liberehashelem __P(( thash*, hashelem* )); +#endif diff --git a/alliance/src/mbkspice/src/spi_int.c b/alliance/src/mbkspice/src/spi_int.c new file mode 100644 index 00000000..7b4c9138 --- /dev/null +++ b/alliance/src/mbkspice/src/spi_int.c @@ -0,0 +1,245 @@ +/* + * 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 library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library 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. + */ + + +/******************************************************************************* +* * +* Tool : Spice parser / driver v 7.00 * +* Author(s) : Gregoire AVOT * +* Updates : March, 18th 1998 * +* * +*******************************************************************************/ + +#include +#include +#include +#include +#include +#include "spi_int.h" + +tableint* creattableint() +{ + tableint *new; + int i; + + new = (tableint*) mbkalloc( sizeof( tableint ) * SPI_TABLEINTMAX ); + + for( i = 0 ; i < SPI_TABLEINTMAX ; i++ ) + { + new[ i ].index = 0; + new[ i ].data = NULL; + new[ i ].down = NULL; + } + + return( new ); +} + +int settableint( table, value, data ) +tableint *table; +int value; +void *data; +{ + int p; + int niveau; + + niveau = 3; + + while( 1 ) + { + p = ( value >> ( niveau * 8 ) ) & ( SPI_TABLEINTMASK ); + + if( table[ p ].index == value ) + { + /* L'element existe déjà : on le remplace */ + table[ p ].data = data; + return( 0 ); + } + + if( table[ p ].index == 0 ) + { + /* Nouvel élément */ + table[ p ].index = value; + table[ p ].data = data; + return( 1 ); + } + + if( table[ p ].down == NULL ) + table[ p ].down = creattableint(); + + niveau--; + + table = table[p].down; + } +} + +void* tsttableint( table, value ) +tableint *table; +int value; +{ + int p; + int niveau; + + niveau = 3; + + while( 1 ) + { + p = ( value >> ( niveau * 8 ) ) & (SPI_TABLEINTMASK); + + if( table[ p ].index == value ) + return( table[ p ].data ); + + if( table[ p ].down == NULL ) + return( NULL ); + + niveau--; + + table = table[ p ].down; + } +} + +void freetableint( table ) +tableint *table; +{ + int i; + + for( i = 0 ; i < SPI_TABLEINTMAX ; i++ ) + { + if( table[ i ].down ) + freetableint( table[ i ].down ); + } + mbkfree( table ); +} + +int scanint( table, n ) +tableint *table; +int n; +{ + int i=0, l=0 ; + int n3, n2, n1, n0 ; + tableint *t=NULL, *t3, *t2, *t1, *t0 ; + + if( n == 0 ) + { + for( i = 0 ; i < SPI_TABLEINTMAX ; i++ ) + { + if( table[i].index ) + return( table[i].index ); + } + return( 0 ); + } + + n0 = n & SPI_TABLEINTMASK; + n1 = ( n >> 8 ) & SPI_TABLEINTMASK; + n2 = ( n >> 16 ) & SPI_TABLEINTMASK; + n3 = ( n >> 24 ) & SPI_TABLEINTMASK; + + /* recherche de l'element n */ + + t3 = NULL; + t2 = NULL; + t1 = NULL; + t0 = NULL; + + if( table[ n3 ].index == n ) + { + t = table; + l = n3; + t3 = t; + } + else + if( table[ n3 ].down[ n2 ].index == n ) + { + t = table[ n3 ].down ; + l = n2; + t3 = table; + t2 = t; + } + else + if( table[ n3 ].down[ n2 ].down[ n1 ].index == n) + { + t = table[ n3 ].down[ n2 ].down; + l = n1; + t3 = table; + t2 = table[ n3 ].down; + t1 = t; + } + else + if( table[ n3 ].down[ n2 ].down[ n1 ].down[ n0 ].index == n ) + { + t = table[ n3 ].down[ n2 ].down[ n1 ].down; + l = n0; + t3 = table; + t2 = table[ n3 ].down; + t1 = table[ n3 ].down[ n2 ].down; + t0 = t; + } + + /* Descent d'un niveau */ + + if( t[ l ].down ) + { + t = t[ l ].down; + + for( i = 0 ; i < SPI_TABLEINTMAX ; i++ ) + { + if( t[ i ].index ) + return( t[ i ].index ); + } + /* jamais executé */ + } + + while( 1 ) + { + /* Parcour un niveau horizontalement */ + + for( i = l + 1 ; i < SPI_TABLEINTMAX ; i++ ) + { + if( t[ i ].index ) + return( t[ i ].index ); + } + + /* Remonte les niveaux */ + + if( t == t0 ) + { + t = t1; + l = n1; + } + else + if( t == t1 ) + { + t = t2; + l = n2; + } + else + if( t == t2 ) + { + t = t3; + l = n3; + } + else + if( t == t3 ) + return( 0 ); + } + /* Cette boucle se finie en interne par un return */ +} diff --git a/alliance/src/mbkspice/src/spi_int.h b/alliance/src/mbkspice/src/spi_int.h new file mode 100644 index 00000000..59241b74 --- /dev/null +++ b/alliance/src/mbkspice/src/spi_int.h @@ -0,0 +1,68 @@ +/* + * 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 library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library 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. + */ + + +/******************************************************************************* +* * +* Tool : Spice parser / driver v 7.00 * +* Author(s) : Gregoire AVOT * +* Updates : March, 18th 1998 * +* * +*******************************************************************************/ + +#ifndef spi_int +#define spi_int + +typedef struct st_tableint +{ + int index; + void *data; + struct st_tableint *down; +} tableint; + +/* Lors qu'on ajoute quelque chose dans la liste, le pointeur DATA ne doit pas + etre NULL, cette valeur etant utilisée en interne sur ce champs */ + +#define SPI_TABLEINTMAX 256 +#define SPI_TABLEINTMASK 0x000000FF + +tableint* creattableint __P(()); +/* Crée une nouvelle table */ + +int settableint __P(( tableint *table, int value, void *data )); +/* Ajoute un élément dans la table. Renvoie 1 si l'élément est nouveau, + 0 sinon (l'élément précédent est alors remplacé) */ + +void* tsttableint __P(( tableint *table, int value )); +/* Renvoie l'élément recherché par la valeur */ + +void freetableint __P(( tableint *table )); +/* Libère la table */ + +int scanint __P(( tableint *table, int n )); +/* Parcour des éléments mémorisés dans la table. On commence par mettre + l'entier d'entrée à 0, puis pour les elements suivant on met la valeur + du noeud retourné précédement. La fin est indiqué par un retour 0 */ + + +#endif diff --git a/alliance/src/mbkspice/src/spi_msg.c b/alliance/src/mbkspice/src/spi_msg.c new file mode 100644 index 00000000..86d88a0b --- /dev/null +++ b/alliance/src/mbkspice/src/spi_msg.c @@ -0,0 +1,188 @@ +/* + * 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 library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library 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. + */ + + +/******************************************************************************* +* * +* Tool : Spice parser / driver v 7.00 * +* Author(s) : Gregoire AVOT * +* Updates : March, 18th 1998 * +* * +*******************************************************************************/ + +#include +#include +#include "spi_msg.h" + +#include + +char *spimsg[NBLANG][NBMSG] = + { +/* English */ { + /* 0 */ "*** Error in parser driver Spice", + /* 1 */ "Syntax error", + /* 2 */ "Can't use .INCLUDE inside a subckt", + /* 3 */ "Incorrect value for variable MBK_SPI_LANG : Using English", + /* 4 */ "Can't find *interf in file", + /* 5 */ "Internal error [1]", + /* 6 */ "Identical nodes on subckt", + /* 7 */ "Variable MBK_SPI_SEPAR must be a single character", + /* 8 */ "Can't read lofig with this mode", + /* 9 */ "Can't open file", + /* 10 */ "Data structure not empty when delete", + /* 11 */ "File", + /* 12 */ "Line", + /* 13 */ "Incomplete line", + /* 14 */ "Too many element on line", + /* 15 */ "Can't use subckt in another subckt", + /* 16 */ "No name for subckt", + /* 17 */ "Node for *ASIMNET must be number", + /* 18 */ "No symbol '=' after node in *ASIMNET", + /* 19 */ "No node in *ASIMNET", + /* 20 */ "No name for node in *ASIMNET", + /* 21 */ "Only one name supported in *ASIMNET", + /* 22 */ ".ENDS without .SUBCKT", + /* 23 */ "No name for subckt", + /* 24 */ "Name for .ENDS differs than name of .SUBCKT", + /* 25 */ "No name for transistor", + /* 26 */ "Transistor is already defined", + /* 27 */ "The transistor has no DRAIN node", + /* 28 */ "The transistor has no GRID node", + /* 29 */ "The transistor has no SOURCE node", + /* 30 */ "The transistor has no BULK node", + /* 31 */ "The transistor has no type", + /* 32 */ "The transistor has a bad type", + /* 33 */ "Parameter incomplete for transistor", + /* 34 */ "Bad value", + /* 35 */ "Parameter not supported", + /* 36 */ "No name for resistor", + /* 37 */ "Resistor already defined in subckt", + /* 38 */ "No name for capacitance", + /* 39 */ "Capacitance already defined in subckt", + /* 40 */ "No name for subckt", + /* 41 */ "Subckt already defined", + /* 42 */ "Unreconized element ignored", + /* 43 */ "No model found", + /* 44 */ "Number of node differs between model and instance", + /* 45 */ "Signal is both VDD and VSS", + /* 46 */ "Many signals are VSS", + /* 47 */ "Many signals are VDD", + /* 48 */ "Line too long", + /* 49 */ "Incorrect value for node", + /* 50 */ "Incorrect name for node", + /* 51 */ "The node has already a name", + /* 52 */ "Illegal signal name", + /* 53 */ "File open", + /* 54 */ "Circuit", + /* 55 */ "Instance", + /* 56 */ "Model", + /* 57 */ "Too many model of transistors", + /* 58 */ "Model name too long" + + }, +/* French */ { + /* 0 */ "*** Erreur dans le parser driver Spice", + /* 1 */ "Erreur de syntaxe", + /* 2 */ "Un .INCLUDE n'est pas utilisable dans un subckt", + /* 3 */ "Valeur incorrecte pour MBK_SPI_LANG : Utilisation du Francais", + /* 4 */ "Impossible de trouver le *interf le fichier", + /* 5 */ "Erreur interne [1] : Pas de locon correspondant au nom dans la liste de l'ordre des locons.", + /* 6 */ "Connecteur identiques sur le subckt", + /* 7 */ "La variable MBK_SPI_SEPAR doit etre un caractere seul", + /* 8 */ "Mode de lecture de la lofig non supporte", + /* 9 */ "Impossible d'acceder au fichier", + /* 10 */ "Structure de donnee non nettoyee avant liberation", + /* 11 */ "Fichier", + /* 12 */ "Ligne", + /* 13 */ "Ligne incomplete", + /* 14 */ "Trop d'elements sur la ligne", + /* 15 */ "Les subckt imbriques ne sont pas supportes", + /* 16 */ "Pas de nom pour le subckt", + /* 17 */ "Les noeuds dans les *ASIMNET doivent etre des nombres", + /* 18 */ "Caractere '=' absent apres les noeuds de '*ASIMNET'", + /* 19 */ "Noeud absent dans *ASIMNET", + /* 20 */ "Pas de nom pour les noeuds dans *ASIMNET", + /* 21 */ "Un seul nom doit etre donne dans *ASIMNET", + /* 22 */ ".ENDS rencontre sans avoir le .SUBCKT correspondant", + /* 23 */ "Le nom du subckt est absent", + /* 24 */ "Le nom specifie dans le .ENDS n'est pas le meme que pour le .SUBCKT", + /* 25 */ "Le nom du transistor n'est pas specifie", + /* 26 */ "Le transistor existe deja dans ce subckt", + /* 27 */ "Le transistor ne possede pas de DRAIN", + /* 28 */ "Le transistor ne possede pas de GRILLE", + /* 29 */ "Le transistor ne possede pas de SOURCE", + /* 30 */ "Le transistor ne possede pas de SUBSTRAT", + /* 31 */ "Type du transistor absent", + /* 32 */ "Type du transistor incorrecte", + /* 33 */ "Parametre du transistor incomplet", + /* 34 */ "Valeur incorrect", + /* 35 */ "Parametre non supporte", + /* 36 */ "Le nom de la resistance n'est pas specifie", + /* 37 */ "La resistance existe deja dans le subckt", + /* 38 */ "Le nom de la capacite n'est pas specifie", + /* 39 */ "La capacite existe deja dans le subckt", + /* 40 */ "Pas de nom pour le subckt", + /* 41 */ "Le subckt existe deja", + /* 42 */ "Element non reconnu par le parser ignore", + /* 43 */ "Modele non trouve", + /* 44 */ "Le mombre de connecteurs differe entre le modele et l'instance", + /* 45 */ "Un signal est a la fois VDD et VSS", + /* 46 */ "Plusieurs equipotentielles sont VSS", + /* 47 */ "Plusieurs equipotentielles sont VDD", + /* 48 */ "Ligne trop longue", + /* 49 */ "Valeur du noeud incorrect", + /* 50 */ "Nom du noeud incorrect", + /* 51 */ "Renommage d'un noeud qui possede un nom", + /* 52 */ "Nom de signal vecteur incorrect", + /* 53 */ "Ouverture du fichier", + /* 54 */ "Circuit", + /* 55 */ "Instance", + /* 56 */ "Model", + /* 57 */ "Trops de modeles de transistors", + /* 58 */ "Nom de modele trop long" + } + }; + +int SPI_LANG = DEFAULT_SPI_LANG; + +void spi_init_lang( void ) +{ + char *env; + + env = mbkgetenv( "MBK_SPI_LANG" ); + + if( env ) + { + if( strcmp( env, "Francais" ) == 0 ) + SPI_LANG = 1; + else + if( strcmp( env, "English" ) == 0 ) + SPI_LANG = 0; + else + { + SPI_LANG = DEFAULT_SPI_LANG; + fflush( stdout ); + fprintf( stderr,"%s.\n", SPIMSG(3) ); + } + } +} diff --git a/alliance/src/mbkspice/src/spi_msg.h b/alliance/src/mbkspice/src/spi_msg.h new file mode 100644 index 00000000..148dccd5 --- /dev/null +++ b/alliance/src/mbkspice/src/spi_msg.h @@ -0,0 +1,50 @@ +/* + * 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 library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library 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. + */ + + +/******************************************************************************* +* * +* Tool : Spice parser / driver v 7.00 * +* Author(s) : Gregoire AVOT * +* Updates : March, 18th 1998 * +* * +*******************************************************************************/ + +#ifndef SPI_MSGH +#define SPI_MSGH + +#define NBLANG 2 +/* + * 0 Anglais + * 1 Francais +*/ +#define DEFAULT_SPI_LANG 0 +#define NBMSG 59 + +extern int SPI_LANG; +extern char *spimsg[NBLANG][NBMSG]; + +#define SPIMSG(num) spimsg[SPI_LANG][num] + +void spi_init_lang(void); +#endif diff --git a/alliance/src/mbkspice/src/spi_parse.c b/alliance/src/mbkspice/src/spi_parse.c new file mode 100644 index 00000000..d445e626 --- /dev/null +++ b/alliance/src/mbkspice/src/spi_parse.c @@ -0,0 +1,3116 @@ +/* + * 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 library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library 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. + */ + +#ident "$Author: fred $ $Date: 2002/03/13 17:58:33 $ $Revision: 1.1 $" + +/******************************************************************************* +* * +* Tool : Spice parser / driver v 7.00 * +* Author(s) : Gregoire AVOT * +* Updates : March, 18th 1998 * +* * +*******************************************************************************/ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include "msl.h" +#include "spi_int.h" +#include "spi_hash.h" +#include "spi_parse.h" +#include "spi_msg.h" +#include "spi_global.h" + +/* Fonctions dynamiques */ +static int (*ext_handler)() = NULL; +static int (*cmp_handler)() = NULL; + +/* Variables globales MSL */ +lofig_list *msl_ptfig; +int msl_figloaded; +char* msl_figname; +char* msl_subckt; +int msl_line; + +char SPI_SEPAR ; +char *SPI_NETNAME ; +char SPI_ONE_NODE_NORC ; +char SPI_MERGE ; +char SPI_VERBOSE ; +char SPI_FILE ; +char SPI_CHECK_NAME ; +char SPI_AUTO_LOAD ; +char SPI_NODE_EQUI_DRIVE ; +char SPI_AFF_UNK ; + +/******************************************************************************/ + +void spiceloadlofig(ptfig, name, mode) +lofig_list *ptfig; +char *name; +char mode; +{ + char *env; + ginterf *teteinterf; + ginterf *effinterf; + ginterf *scaninterf; + chain_list *scanchain; + char *spicename; + + /* Comportement par defaut */ + + SPI_SEPAR = '.' ; + SPI_NETNAME = "NET" ; + SPI_MERGE = 1 ; + SPI_VERBOSE = 0 ; + SPI_FILE = 0 ; + SPI_ONE_NODE_NORC = 0 ; + SPI_CHECK_NAME = 0 ; + SPI_AUTO_LOAD = 0 ; + SPI_NODE_EQUI_DRIVE = 0 ; + SPI_AFF_UNK = 1 ; + + spi_init_lang(); + + env = mbkgetenv( "MBK_SPI_NETNAME" ); + + if( env ) + SPI_NETNAME = env; + + env = mbkgetenv( "MBK_SPI_SEPAR" ); + + if( env ) + { + switch( strlen( env ) ) + { + case 0: + SPI_SEPAR = 0; + SPI_MERGE = 0; + break; + case 1: + SPI_SEPAR = *env; + break; + default : + fflush( stdout ); + fprintf( stderr, "%s.\n", SPIMSG(7) ); + EXIT(1); + break; + } + } + + env = mbkgetenv( "MBK_SPI_CHECK_NAME" ); + + if( env ) + SPI_CHECK_NAME = 1; + + env = mbkgetenv( "MBK_SPI_AUTO_LOAD" ); + + if( env ) + SPI_AUTO_LOAD = 1; + + /* Variables d'environnement cachees */ + + /* MBK_SPI_MERGE. Si positionnee, on n'effectue pas + * de regroupement de locon sur les noms toto, toto.1, toto.2, toto.3... + */ + + env = mbkgetenv( "MBK_SPI_MERGE" ); + + if( env ) + SPI_MERGE = 0; + + env = mbkgetenv( "MBK_SPI_FILE" ); + + if( env ) + SPI_FILE = 1; + + env = mbkgetenv( "MBK_SPI_VERBOSE" ); + + if( env ) + SPI_VERBOSE = 1; + + env = mbkgetenv( "MBK_SPI_ONE_NODE_NORC" ); + + if( env ) + SPI_ONE_NODE_NORC = 1; + + env = mbkgetenv( "MBK_SPI_NODE_EQUI_DRIVE" ); + + if( env ) + SPI_NODE_EQUI_DRIVE = 1; + + env = mbkgetenv( "MBK_SPI_NO_AFF_UNK" ); + + if( env ) + SPI_AFF_UNK = 0; + + if( SPI_VERBOSE ) + { + printf( "Parser Spice compile le %s a %s\n", __DATE__, __TIME__ ); + printf( "Revision : %s\n", "$Revision: 1.1 $" ); + printf( "Date : %s\n", "$Date: 2002/03/13 17:58:33 $" ); + + printf( "Separateur : '%c'\n", SPI_SEPAR ); + printf( "Nom de noeud : %s\n", SPI_NETNAME ); + printf( "Regroupement : %s\n", SPI_MERGE ? "Oui" : "Non" ); + printf( "Noms : %s\n", SPI_CHECK_NAME ? "Oui" : "Non" ); + printf( + "Ne cree pas les vues RC sur les reseaux ne contenant qu'un seul noeud : %s\n", + SPI_ONE_NODE_NORC ? "Oui" : "Non" + ); + } + + if( mode != 'A' ) + { + fflush( stdout ); + fprintf( stderr, "%s\n", SPIMSG(0) ); + fprintf( stderr, "%s : '%c'\n", SPIMSG(8), mode ); + EXIT(1); + } + + spicename = (char*)mbkalloc( sizeof(char)*( strlen(name)+5 )); + sprintf( spicename, "%s.%s", name, IN_LO ); + + msl_figname = name; + msl_ptfig = NULL; + + teteinterf = NULL; + + teteinterf = spiceloading( ptfig, spicename, mode, teteinterf ); + + if( teteinterf ) + { + effinterf = NULL; + for( scaninterf = teteinterf; scaninterf ; scaninterf = scaninterf->SUIV ) + { + if( effinterf ) + { + free( effinterf->NOM ); + for( scanchain = effinterf->GINTERF ; + scanchain ; + scanchain = scanchain->NEXT ) + mbkfree( scanchain->DATA ); + freechain( effinterf->GINTERF ); + mbkfree( effinterf ); + } + effinterf = scaninterf; + } + if( effinterf ) + { + free( effinterf->NOM ); + for( scanchain = effinterf->GINTERF ; + scanchain ; + scanchain = scanchain->NEXT ) + mbkfree( scanchain->DATA ); + freechain( effinterf->GINTERF ); + mbkfree( effinterf ); + } + } + + mbkfree( spicename ); +} + +spifile* spifileopen( name ) +char *name; +{ + spifile *pt; + + if( SPI_FILE ) + { + fflush( stdout ); + fprintf( stderr, "%s : %s\n", SPIMSG(53), name ); + } + + pt = mbkalloc( sizeof( *pt ) ); + pt->df = mbkfopen( name, NULL, READ_TEXT ); + pt->decomp1 = NULL; + pt->decomp2 = NULL; + pt->filename = name; + pt->msl_line = -1; + *(pt->file_line) = '\0'; + + + if( ! pt->df ) + { + fflush( stdout ); + fprintf( stderr, "%s\n", SPIMSG(0) ); + fprintf( stderr, "%s %s.\n", SPIMSG(9), name ); + EXIT(1); + } + + return( pt ); +} + +void spifileclose( pt ) +spifile *pt; +{ + fclose( pt->df ); + + if( pt->decomp1 || pt->decomp2 ) + { + fflush( stdout ); + fprintf( stderr, "%s\n", SPIMSG(0) ); + fprintf( stderr, "%s.\n", SPIMSG(10) ); + EXIT(1); + } + + mbkfree( pt ); +} + +ginterf* spiceloading(ptfig, name, mode, teteinterf ) +lofig_list *ptfig; +char *name; +char mode; +ginterf *teteinterf; +{ + circuit *ptcir; + spifile *df; + lofig_list *newfig; + + df = spifileopen( name ); + + + while( ( ptcir = lirecircuit( df, &teteinterf ) ) ) + { + constequi( ptcir, teteinterf ); + teteinterf = constinterf( ptcir, teteinterf ); + + if( SPI_VERBOSE ) + taillevuespice( ptcir ); + + if( ptfig && strcasecmp( ptcir->NOM, ptfig->NAME ) == 0 ) + { + if( SPI_VERBOSE ) + printf( "Construction figure pere.\n" ); + + constlofig( ptcir, ptfig, teteinterf, mode ); + msl_ptfig = ptfig; + ptfig->USER = constphinterf( ptfig->USER, teteinterf ); + } + else + { + /* Si la figure est vide, on ne construit pas la lofig correspondante */ + if( ptcir->RESI || + ptcir->VALIM || + ptcir->TRANS || + ptcir->CAPA || + ptcir->INST + ) + { + if( SPI_VERBOSE ) + printf( "Construction figure fille %s.\n", ptcir->NOM ); + + /* figure fille ou n'ayant rien a voir avec ptfig */ + newfig = addlofig( ptcir->NOM ); + + constlofig( ptcir, newfig, teteinterf, mode ); + msl_ptfig = newfig; + newfig->USER = constphinterf( newfig->USER, teteinterf ); + } + else + if( SPI_VERBOSE ) + printf( "Ne construit pas la figure %s.\n", ptcir->NOM ); + } + + if( SPI_VERBOSE ) + printf( "Taille memoire occupee par le subckt %s : %ld\n", + ptcir->NOM, + ptcir->TAILLE + ); + + liberecircuit( ptcir ); + } + + spifileclose( df ); + + if( cmp_handler ) + { + msl_figloaded = FALSE; + msl_subckt = NULL; + msl_line = df->msl_line; + cmp_handler(); + } + + return( teteinterf ); +} + +/******************************************************************************/ + +ptype_list* constphinterf( pt, interface ) +ptype_list *pt; +ginterf *interface; +{ + chain_list *tete_ph_interf; + chain_list *scan; + char *nomdevec; + + tete_ph_interf=NULL; + + for( scan = interface->GINTERF ; scan ; scan = scan->NEXT ) + { + nomdevec = spi_devect( (char*)(scan->DATA) ); + tete_ph_interf = addchain( tete_ph_interf, namealloc( nomdevec ) ); + mbkfree( nomdevec ); + } + + return( addptype( pt, PH_INTERF, reverse( tete_ph_interf )) ); +} + +/******************************************************************************/ + +ginterf* constinterf( ptcir, teteinterf ) +circuit *ptcir; +ginterf *teteinterf; +{ + ginterf *ninterf; + chain_list *scaninterf; + char **tabnom; + int i; + int nb; + noeud *ptnoeud; + noeud *scannoeud; + char nom[80]; + + ninterf = (ginterf*) mbkalloc( sizeof( ginterf ) ); + ninterf->NOM = mbkstrdup( ptcir->NOM ); + + ninterf->SUIV = teteinterf; + + /* On cree pour chaque signal de l'interface une chain_list contenant tous + * les noms possibles pour un signal. Pour chaque signal, le nom retenu en + * priorite est le premier nommé sur l'interface */ + + /* Calcul du nombre d'elements */ + nb = 0; + for( scaninterf = ptcir->CINTERF ; + scaninterf ; + scaninterf = scaninterf->NEXT + ) + { + ptnoeud = (noeud*) scaninterf->DATA; + + if( ptnoeud->SIGNAL > nb ) + nb = ptnoeud->SIGNAL; + } + + /* Creation du tableau */ + tabnom = (char**) mbkalloc( sizeof(char*) * nb ); + for( i = 0 ; i < nb ; i++ ) + tabnom[ i ] = NULL; + + /* Remplissage du tableau */ + /* On regarde d'abord l'interface */ + for( scaninterf = ptcir->CINTERF ; + scaninterf ; + scaninterf = scaninterf->NEXT + ) + { + ptnoeud = (noeud*) scaninterf->DATA; + if( ptnoeud->NOM && ! tabnom[ ptnoeud->SIGNAL - 1 ] ) + { + tabnom[ ptnoeud->SIGNAL - 1 ] = ptnoeud->NOM; + } + } + /* Puis les noeuds constituant les signaux */ + + for( scaninterf = ptcir->CINTERF ; + scaninterf ; + scaninterf = scaninterf->NEXT + ) + { + ptnoeud = (noeud*) scaninterf->DATA; + if( ! tabnom[ ptnoeud->SIGNAL - 1 ] ) + { + for( scannoeud = ptcir->NOEUD ; scannoeud ; scannoeud = scannoeud->SUIV ) + { + if( scannoeud->SIGNAL == ptnoeud->SIGNAL && scannoeud->NOM ) + { + /* Il est possible que le nom de signal soit deja utilise : + * on le verifie*/ + for( i = 0 ; i < nb ; i++ ) + if( tabnom[ i ] == scannoeud->NOM ) + break; + + if( i == nb ) + { + tabnom[ ptnoeud->SIGNAL - 1 ] = scannoeud->NOM; + break; + } + } + } + } + } + + /* finallement on cree un nom de connecteurs */ + i=0; + for( scaninterf = ptcir->CINTERF ; + scaninterf ; + scaninterf = scaninterf->NEXT + ) + { + ptnoeud = (noeud*) scaninterf->DATA; + if( tabnom[ ptnoeud->SIGNAL - 1 ] == NULL ) + { + sprintf( nom, "SPICE_C_%d",i++); + tabnom[ ptnoeud->SIGNAL - 1 ] = spicenamealloc( ptcir, nom ); + } + } + + /* On cree la chainlist de interf */ + + ninterf->GINTERF = NULL; + for( scaninterf = ptcir->CINTERF ; + scaninterf ; + scaninterf = scaninterf->NEXT + ) + { + ptnoeud = (noeud*) scaninterf->DATA; + strcpy( nom, tabnom[ ptnoeud->SIGNAL -1 ] ); + + if( SPI_MERGE ) + stopchainsepar( nom ); + + ninterf->GINTERF = addchain( ninterf->GINTERF, + mbkstrdup( nom ) + ); + } + + ninterf->GINTERF = reverse( ninterf->GINTERF ); + + mbkfree( tabnom ); + + return( ninterf ); +} + +/******************************************************************************/ + +circuit* lirecircuit( df, teteinterf ) +spifile *df; +ginterf **teteinterf; +{ + char complet; + char debut; + chain_list *ligne; + chain_list *elem, *elem1, *elem2; + float valeur; + circuit *ptcir; + noeud *ptnoeud; + chain_list *sc1, *sc2, *prev; + resi *ptresi, *scanresi; + capa *ptcapa, *scancapa; + trans *pttrans, *scantrans; + inst *ptinst, *scaninst; + valim *ptvalim, *scanvalim; + int nbelem; + int status; + int i; + int traitecomment; + float com_x,com_y; + ginterf *scaninterf; + char buf[1024]; + char tt; + + debut = 0; + complet = 0; + ptcir = NULL; + + while( !complet ) + { + ligne = lireligne( df ); + traitecomment = TRUE; + + if( !ligne ) /* fin de fichier */ + break; + + com_x = 0.0; + com_y = 0.0; + + /* On récupère les paramètres non standards : $X, $Y */ + for( sc1 = ligne; sc1; sc1 = sc1->NEXT ) + { + if( strcasecmp( (char*)(sc1->DATA), "$X" ) == 0 && + sc1->NEXT && + sc1->NEXT->NEXT + ) + { + if( strcmp( (char*)(sc1->NEXT->DATA), "=" ) ) + continue; + valeur = spicefloat( (char*)(sc1->NEXT->NEXT->DATA) ,&status ); + if( status == -1 ) + continue; + com_x = valeur; + } + else + if( strcasecmp( (char*)(sc1->DATA), "$Y" ) == 0 && + sc1->NEXT && + sc1->NEXT->NEXT + ) + { + if( strcmp( (char*)(sc1->NEXT->DATA), "=" ) ) + continue; + valeur = spicefloat( (char*)(sc1->NEXT->NEXT->DATA) ,&status ); + if( status == -1 ) + continue; + com_y = valeur; + } + } + + prev = NULL; + + for( sc1 = ligne; sc1; sc1 = sc1->NEXT ) + { + if( *((char*)(sc1->DATA)) == '$' ) + break; + prev = sc1; + } + + if( sc1 ) + { + for( sc2 = sc1 ; sc2 ; sc2 = sc2->NEXT ) + mbkfree( sc2->DATA ); + + if( prev ) + prev->NEXT = NULL; + + freechain( sc1 ); + } + + if( ! prev ) + ligne = NULL; + + if( !ligne ) + { + } + else + if( strcasecmp( (char*)ligne->DATA, ".INCLUDE" ) == 0 ) + { + if( ptcir ) + spierror( 2, df->filename, df->msl_line ); + + elem = ligne->NEXT; + + if( !elem ) + spierror( 13, df->filename, df->msl_line ); + + if( elem->NEXT ) + spierror( 14, df->filename, df->msl_line ); + + *teteinterf = traiteinclude( *teteinterf, (char*)elem->DATA ); + } + else + if( strcasecmp( (char*)ligne->DATA, ".SUBCKT" ) == 0 ) + { + if( ptcir ) + spierror( 15, df->filename, df->msl_line ); + + ptcir = (circuit*)mbkalloc( sizeof( circuit ) ); + ptcir->NOEUD = NULL; + ptcir->TRANS = NULL; + ptcir->RESI = NULL; + ptcir->CAPA = NULL; + ptcir->INST = NULL; + ptcir->NOM = NULL; + ptcir->CINTERF = NULL; + ptcir->FREE = NULL; + ptcir->VALIM = NULL; + ptcir->INT_NOEUD = creattableint(); + ptcir->NOM_NOEUD = creatthash( ); + ptcir->HASHGNAME = creatthash( ); + ptcir->HASHCAPA = creatthash( ); + ptcir->HASHRESI = creatthash( ); + ptcir->HASHVALIM = creatthash( ); + ptcir->HASHINST = creatthash( ); + ptcir->HASHTRAN = creatthash( ); + ptcir->TAILLE = sizeof( circuit ); + ptcir->RESTENOM = 0; + + elem = ligne->NEXT; + + if( !elem ) + spierror( 16, df->filename, df->msl_line ); + + ptcir->NOM = (char*)spiciralloue( ptcir, + sizeof(char)*( strlen( (char*)(elem->DATA) ) + 1 ) + ); + strcpy( ptcir->NOM, (char*)( elem->DATA ) ); + + /* Pour verifier qu'on a pas plusieurs fois le meme noeud, on + * met un 1 dans le champs RCN */ + for( elem = elem->NEXT; elem; elem = elem->NEXT ) + { + ptnoeud = ajoutenoeud( ptcir, (char*)(elem->DATA), df ); + + if( ptnoeud->RCN ) + { + fflush( stdout ); + fprintf( stderr, "%s.\n", SPIMSG(0) ); + fprintf( stderr, "%s : %s - %d\n", SPIMSG(6), + ptnoeud->NOM, + ptnoeud->SPICE + ); + fprintf( stderr, "%s : %s, %s : %d\n", SPIMSG(11), df->filename, + SPIMSG(12), df->msl_line + ); + exit( 1 ); + } + ptnoeud->RCN = 1; + + ptcir->CINTERF = addchain( ptcir->CINTERF, ptnoeud ); + } + + for( sc1 = ptcir->CINTERF ; sc1 ; sc1 = sc1->NEXT ) + ((noeud*)(sc1->DATA))->SPICE = -1; + + ptcir->CINTERF = reverse( ptcir->CINTERF ); + + } + else + if( *( (char*)(ligne->DATA) ) == '*' ) + { + traitecomment = FALSE; + + elem = ligne->NEXT; + + if( ptcir && elem ) + { + + if( strcasecmp( (char*)(elem->DATA), SPI_NETNAME ) == 0 ) + { + traitecomment = TRUE; + elem = elem->NEXT; + sc1 = elem; + sc2 = NULL; + + for( ; elem && strcasecmp( (char*)(elem->DATA), "=" ) != 0; + elem = elem->NEXT ) + { + for( i=0; ((char*)(elem->DATA))[i] >= '0' && + ((char*)(elem->DATA))[i] <= '9' ; i++ ) ; + + if( ((char*)(elem->DATA))[i] != 0 ) + spierror( 17, df->filename, df->msl_line ); + + ptnoeud = ajoutenoeud( ptcir, (char*)(elem->DATA), df ); + sc2 = addchain( sc2, ptnoeud ); + } + + if( !elem ) + spierror( 18, df->filename, df->msl_line ); + + if( elem == sc1 ) + spierror( 19, df->filename, df->msl_line ); + + elem = elem->NEXT; /* on passe le = */ + + if( !elem ) + spierror( 20, df->filename, df->msl_line ); + + for( sc1 = sc2; sc1; sc1 = sc1->NEXT) + nomenoeud( ptcir, (noeud*)(sc1->DATA), (char*)(elem->DATA), df ); + freechain(sc2); + + elem = elem->NEXT; + if( elem ) + spierror( 21, df->filename, df->msl_line ); + } + } + + if( ext_handler && ! traitecomment ) + { + msl_figloaded = ( ptcir ? TRUE : FALSE ); + msl_subckt = ( ptcir ? ptcir->NOM : NULL ); + msl_line = df->msl_line; + ext_handler( df->file_line1 ); + } + } + else + if( strcasecmp( (char*)(ligne->DATA), ".ENDS" ) == 0 ) + { + if( !ptcir ) + spierror( 22, df->filename, df->msl_line ); + + if( !ligne->NEXT ) + { + /*spierror( 23, df->filename, df->msl_line );*/ + } + else + { + if( strcasecmp( (char*)(ligne->NEXT->DATA), ptcir->NOM ) != 0 ) + spierror( 24, df->filename, df->msl_line ); + + if( ligne->NEXT->NEXT ) + spierror( 14, df->filename, df->msl_line ); + } + complet = 1; + + /* Vérification de l'existance des modèles pour les instances */ + if( SPI_AUTO_LOAD ) + { + for( scaninst = ptcir->INST ; scaninst ; scaninst = scaninst->SUIV ) + { + for( scaninterf = *teteinterf ; + scaninterf ; + scaninterf = scaninterf->SUIV + ) + { + if( strcasecmp( scaninterf->NOM, scaninst->MODELE )==0 ) + break; + } + + if( !scaninterf ) + { + sprintf( buf,"%s.%s", scaninst->MODELE, IN_LO ); + *teteinterf = traiteinclude( *teteinterf, buf ); + } + } + } + } + else + if( ( *((char*)ligne->DATA)=='M' || *((char*)ligne->DATA)=='m' ) && ptcir ) + { + pttrans = (trans*) spiciralloue( ptcir, sizeof( trans ) ); + pttrans->L = 0.0; + pttrans->W = 0.0; + pttrans->AS = 0.0; + pttrans->AD = 0.0; + pttrans->PS = 0.0; + pttrans->PD = 0.0; + + if( *( (char*)( ligne->DATA ) + 1 ) == 0 ) + spierror( 25, df->filename, df->msl_line ); + + pttrans->NOM = spicenamealloc( ptcir, (char*)(ligne->DATA) + 1 ); + + scantrans = getthashelem( pttrans->NOM, ptcir->HASHTRAN, NULL ); + + if( scantrans ) + { + if( SPI_CHECK_NAME ) + spierror( 26, df->filename, df->msl_line ); + } + else + addthashelem( pttrans->NOM, pttrans, ptcir->HASHTRAN ); + + pttrans->SUIV = ptcir->TRANS; + ptcir->TRANS = pttrans; + + elem = ligne->NEXT; /* drain */ + + if( !elem ) + spierror( 27, df->filename, df->msl_line ); + + ptnoeud = ajoutenoeud( ptcir, (char*)(elem->DATA), df ); + pttrans->DRAIN = ptnoeud; + + elem = elem->NEXT; /* grille */ + + if( !elem ) + spierror( 28, df->filename, df->msl_line ); + + ptnoeud = ajoutenoeud( ptcir, (char*)(elem->DATA), df ); + pttrans->GRILLE = ptnoeud; + + elem = elem->NEXT; /* source */ + + if( !elem ) + spierror( 29, df->filename, df->msl_line ); + + ptnoeud = ajoutenoeud( ptcir, (char*)(elem->DATA), df ); + pttrans->SOURCE = ptnoeud; + + elem = elem->NEXT; /* bulk ou type du transistor */ + + if( !elem ) + spierror( 30, df->filename, df->msl_line ); + + tt = spitranstype( (char*)(elem->DATA) ); + if( tt != SPI_UNK_TRANS_TYPE ) + { + pttrans->TYPE = tt; + pttrans->SUBST = NULL; + } + else + { + ptnoeud = ajoutenoeud( ptcir, (char*)(elem->DATA), df ); + pttrans->SUBST = ptnoeud; + + elem = elem->NEXT; /* type du transistor */ + + if( !elem ) + spierror( 31, df->filename, df->msl_line ); + + tt = spitranstype( (char*)(elem->DATA) ); + if( tt != SPI_UNK_TRANS_TYPE ) + pttrans->TYPE = tt; + else + spierror( 32, df->filename, df->msl_line ); + } + + /* Le reste des parametres est de la forme xxx = yyy */ + + while( (elem = elem->NEXT ) ) + { + elem1 = elem->NEXT; + elem2 = ( elem1 ? elem1->NEXT : NULL ); + + if( !elem2 ) + spierror( 33, df->filename, df->msl_line ); + + if( strcmp( (char*)(elem1->DATA), "=" ) ) + spierror( 33, df->filename, df->msl_line ); + + valeur = spicefloat( (char*)(elem2->DATA) ,&status ); + if( status == -1 ) + spierror( 34, df->filename, df->msl_line ); + + if( strcasecmp( (char*)(elem->DATA), "L" ) == 0 ) + pttrans->L = valeur; + else + if( strcasecmp( (char*)(elem->DATA), "W" ) == 0 ) + pttrans->W = valeur; + else + if( strcasecmp( (char*)(elem->DATA), "AS" ) == 0 ) + pttrans->AS = valeur; + else + if( strcasecmp( (char*)(elem->DATA), "AD" ) == 0 ) + pttrans->AD = valeur; + else + if( strcasecmp( (char*)(elem->DATA), "PS" ) == 0 ) + pttrans->PS = valeur; + else + if( strcasecmp( (char*)(elem->DATA), "PD" ) == 0 ) + pttrans->PD = valeur; + else + { + fflush( stdout ); + fprintf( stderr, "%s.\n", SPIMSG(0) ); + fprintf( stderr, "%s. %s %s. %s %d.\n", + SPIMSG(1), + SPIMSG(11), + df->filename, + SPIMSG(12), + df->msl_line + ); + fprintf( stderr, "%s : %s.\n", SPIMSG(35), (char*)(elem->DATA) ); + EXIT(1); + } + elem = elem->NEXT->NEXT; + } + pttrans->X = com_x; + pttrans->Y = com_y; + } + else + if( ( *((char*)ligne->DATA)=='R' || *((char*)ligne->DATA)=='r' ) && ptcir ) + { + ptresi = (resi*) spiciralloue( ptcir, sizeof(resi) ); + + if( *( (char*)( ligne->DATA ) +1 ) == 0 ) + spierror( 36, df->filename, df->msl_line ); + + ptresi->NOM = spicenamealloc( ptcir, (char*)(ligne->DATA) + 1 ); + + scanresi = getthashelem( ptresi->NOM, ptcir->HASHRESI, NULL ); + + if( scanresi ) + { + if( SPI_CHECK_NAME ) + spierror( 37, df->filename, df->msl_line ); + } + else + addthashelem( ptresi->NOM, ptresi, ptcir->HASHRESI ); + + ptresi->SUIV = ptcir->RESI; + ptcir->RESI = ptresi; + + elem = ligne->NEXT; /* first node */ + + if( !elem ) + spierror( 13, df->filename, df->msl_line ); + + ptnoeud = ajoutenoeud( ptcir, (char*)(elem->DATA), df ); + ptresi->N1 = ptnoeud; + + elem = elem->NEXT; /* second node */ + + if( !elem ) + spierror( 13, df->filename, df->msl_line ); + + ptnoeud = ajoutenoeud( ptcir, (char*)(elem->DATA), df ); + ptresi->N2 = ptnoeud; + + elem = elem->NEXT; /* R value */ + if( !elem ) + spierror( 13, df->filename, df->msl_line ); + + valeur = spicefloat( (char*)(elem->DATA) ,&status ); + if( status == -1 ) + spierror( 34, df->filename, df->msl_line ); + + ptresi->RESI = valeur; + + elem = elem->NEXT; /* no more parameters */ + if( elem ) + spierror( 14, df->filename, df->msl_line ); + } + else + if( ( *((char*)ligne->DATA)=='C' || *((char*)ligne->DATA)=='c' ) && ptcir ) + { + ptcapa = (capa*) spiciralloue( ptcir, sizeof(capa) ); + + if( *( (char*)( ligne->DATA ) +1 ) == 0 ) + spierror( 38, df->filename, df->msl_line ); + + ptcapa->NOM = spicenamealloc( ptcir, (char*)(ligne->DATA) + 1 ); + + scancapa = getthashelem( ptcapa->NOM, ptcir->HASHCAPA, NULL ); + if( scancapa ) + { + if( SPI_CHECK_NAME ) + spierror( 39, df->filename, df->msl_line ); + } + else + addthashelem( ptcapa->NOM, ptcapa, ptcir->HASHCAPA); + + + ptcapa->SUIV = ptcir->CAPA; + ptcir->CAPA = ptcapa; + + elem = ligne->NEXT; /* first node */ + + if( !elem ) + spierror( 13, df->filename, df->msl_line ); + + ptnoeud = ajoutenoeud( ptcir, (char*)(elem->DATA), df ); + ptcapa->N1 = ptnoeud; + + elem = elem->NEXT; /* second node */ + + if( !elem ) + spierror( 13, df->filename, df->msl_line ); + + ptnoeud = ajoutenoeud( ptcir, (char*)(elem->DATA), df ); + ptcapa->N2 = ptnoeud; + + elem = elem->NEXT; /* C value */ + if( !elem ) + spierror( 13, df->filename, df->msl_line ); + + valeur = spicefloat( (char*)(elem->DATA) ,&status ); + + if( status == -1 ) + spierror( 34, df->filename, df->msl_line ); + + /* Les valeurs dans Alliance sont en pif */ + ptcapa->CAPA = valeur * 1e12 ; + + elem = elem->NEXT; /* no more parameters */ + + if( elem ) + spierror( 14, df->filename, df->msl_line ); + } + else + if( ( *((char*)ligne->DATA)=='V' || *((char*)ligne->DATA)=='v' ) && ptcir ) + { + ptvalim = (valim*) spiciralloue( ptcir, sizeof(valim) ); + + if( *( (char*)( ligne->DATA ) +1 ) == 0 ) + spierror( 36, df->filename, df->msl_line ); + + ptvalim->NOM = spicenamealloc( ptcir, (char*)(ligne->DATA) + 1 ); + + scanvalim = getthashelem( ptvalim->NOM, ptcir->HASHVALIM, NULL ); + + if( scanvalim ) + { + if( SPI_CHECK_NAME ) + spierror( 37, df->filename, df->msl_line ); + } + else + addthashelem( ptvalim->NOM, ptvalim, ptcir->HASHVALIM ); + + ptvalim->SUIV = ptcir->VALIM; + ptcir->VALIM = ptvalim; + + elem = ligne->NEXT; /* first node */ + + if( !elem ) + spierror( 13, df->filename, df->msl_line ); + + ptnoeud = ajoutenoeud( ptcir, (char*)(elem->DATA), df ); + ptvalim->N1 = ptnoeud; + + elem = elem->NEXT; /* second node */ + + if( !elem ) + spierror( 13, df->filename, df->msl_line ); + + ptnoeud = ajoutenoeud( ptcir, (char*)(elem->DATA), df ); + ptvalim->N2 = ptnoeud; + + elem = elem->NEXT; /* R value */ + if( !elem ) + spierror( 13, df->filename, df->msl_line ); + + valeur = spicefloat( (char*)(elem->DATA) ,&status ); + if( status == -1 ) + spierror( 34, df->filename, df->msl_line ); + + ptvalim->TENSION = valeur; + + elem = elem->NEXT; /* no more parameters */ + if( elem ) + spierror( 14, df->filename, df->msl_line ); + } + else + if( ( *(char*)(ligne->DATA) == 'X' || *(char*)(ligne->DATA) == 'x' ) && + ptcir ) + { + ptinst = (inst*)spiciralloue( ptcir, sizeof(inst) ); + ptinst->IINTERF = NULL; + + if( *( ((char*)(ligne->DATA)) + 1) == 0 ) + spierror( 40, df->filename, df->msl_line ); + + ptinst->NOM = spicenamealloc( ptcir, ((char*)(ligne->DATA)) + 1 ); + + + scaninst = getthashelem( ptinst->NOM, ptcir->HASHINST, NULL ); + if( scaninst ) + spierror( 41, df->filename, df->msl_line ); + + ptinst->SUIV = ptcir->INST; + ptcir->INST = ptinst; + addthashelem( ptinst->NOM, ptinst, ptcir->HASHINST ); + + for( nbelem=0, elem = ligne->NEXT ; elem ; elem = elem->NEXT, nbelem++ ); + + if( nbelem <= 1 ) + spierror( 13, df->filename, df->msl_line ); + + for( elem = ligne->NEXT; elem->NEXT; elem = elem->NEXT ) + { + ptnoeud = ajoutenoeud( ptcir, (char*)(elem->DATA), df ); + ptinst->IINTERF = addchain( ptinst->IINTERF, ptnoeud ); + } + ptinst->IINTERF = reverse( ptinst->IINTERF ); + + ptinst->MODELE = spicenamealloc( ptcir, (char*)elem->DATA ); + } + else + { + if( SPI_AFF_UNK ) + { + fflush( stdout ); + fprintf( stderr, "%s\n", SPIMSG(0) ); + fprintf( stderr, "%s. %s %s. %s %d :\n", + SPIMSG(42), + SPIMSG(11), + df->filename, + SPIMSG(12), + df->msl_line + ); + fprintf( stderr, "%s\n", (char*)ligne->DATA ); + } + } + + if( ligne ) + { + for( sc1 = ligne; sc1; sc1 = sc1->NEXT ) + mbkfree( sc1->DATA ); + + freechain( ligne ); + } + } + + + return( ptcir ); +} + +/******************************************************************************/ + +ginterf* traiteinclude( instance, nom ) +ginterf *instance; +char *nom; +{ + ginterf *sci; + ginterf *nouvinterf; + + for( sci = instance ; sci ; sci = sci->SUIV ) + { + if( strcasecmp( sci->NOM, nom ) == 0 ) + { + fflush( stdout ); + fprintf( stderr, "%s\n", SPIMSG(0) ); + fprintf( stderr, "%s : %s.\n", SPIMSG(41), nom ); + EXIT( 1 ); + } + } + + nouvinterf = spiceloading( NULL, nom, 'A', instance ); + + return( nouvinterf ); +} + +/******************************************************************************/ + +void loconinterf( ptfig, tete ) +lofig_list *ptfig; +chain_list *tete; +{ + chain_list *sc1; + chain_list *sc2; + char *nomdevec; + /*int sigidx; + losig_list *ptsig; + + sigidx = 0;*/ + + for( sc1 = tete ; sc1 ; sc1 = sc1->NEXT ) + { + for( sc2 = tete; sc2 != sc1 ; sc2 = sc2->NEXT ) + if( strcasecmp( sc1->DATA, sc2->DATA ) == 0 ) + break; + if( sc1 == sc2 ) + { + /* + sigidx++; + ptsig = addlosig( ptfig, sigidx, NULL, 'E' ); + */ + nomdevec = spi_devect( (char*)(sc1->DATA) ); + addlocon( ptfig, namealloc(nomdevec), /*ptsig*/ NULL, 'X' ); + mbkfree( nomdevec ); + } + } + + ptfig->LOCON = (locon_list*)reverse( (chain_list*)ptfig->LOCON ); +} + +/******************************************************************************/ + +void constequi( ptcir, instances ) +circuit *ptcir; +ginterf *instances; +{ + inst *scaninst; + chain_list *sc1, *sc2, *sc3, *sc4, *sc5 ; + ptype_list *pt, *pt2; + int idsig = 0 ; /* Warning a la compil */ + int signal; + ptype_list *headsig; + int nb; + int t; + ptype_list *spt; + noeud *scannoeud; + resi *scanresi; + valim *scanvalim; + ginterf *sci; + char *vdd; + char *vss; + int vuevss; + int vuevdd; + int cirvss; + int cirvdd; + chain_list *scanchain; + noeud *node1; + noeud *node2; + + signal = 1; + headsig = NULL; + + /* traite les instances */ + + for( scaninst = ptcir->INST; scaninst; scaninst = scaninst->SUIV ) + { + for( sci = instances; sci; sci = sci->SUIV ) + { + if( strcasecmp( sci->NOM, scaninst->MODELE ) == 0 ) + break; + } + + if( !sci ) + { + fflush( stdout ); + fprintf( stderr, "%s\n", SPIMSG(0) ); + fprintf( stderr, "%s %s.\n", SPIMSG( 43 ), scaninst->MODELE ); + EXIT(1); + } + + for( sc1 = sci->GINTERF, sc2 = scaninst->IINTERF ; + sc1 && sc2 ; + sc1 = sc1->NEXT, sc2 = sc2->NEXT ) + { + /* On verifie qu'on a une nouvelle equipotentielle */ + + for( sc3 = sci->GINTERF ; sc3 != sc1 ; sc3 = sc3->NEXT ) + if( strcasecmp( sc3->DATA, sc1->DATA ) == 0 ) + break; + if( sc3 != sc1 ) + continue; + + nb = 0; /* nombre d'equipotentielle deja existant sur l'interface */ + + for( sc3 = sc1, sc4 = sc2 ; sc3 && sc4 ; sc3 = sc3->NEXT, sc4 = sc4->NEXT) + if( strcasecmp( sc3->DATA, sc1->DATA ) == 0 && + ( (noeud*)( sc4->DATA ) )->SIGNAL != 0 ) + { + nb ++; + idsig = ( (noeud*)( sc4->DATA ) )->SIGNAL; + } + + switch( nb ) + { + case 0 : /* creation d'une nouvelle equi */ + + headsig = addptype( headsig, signal, NULL ); + + for( sc3 = sc1, sc4 = sc2 ; + sc3 && sc4 ; + sc3 = sc3->NEXT, sc4 = sc4->NEXT) + if( strcasecmp( sc3->DATA, sc1->DATA ) == 0 ) + { + ((noeud*)(sc4->DATA))->SIGNAL = signal; + headsig->DATA = addchain( headsig->DATA, sc4->DATA ); + } + + signal++; + + break; + + case 1: /* On reutilise l'equi existante */ + + pt = getptype( headsig, idsig ); + + for( sc3 = sc1, sc4 = sc2 ; + sc3 && sc4 ; + sc3 = sc3->NEXT, sc4 = sc4->NEXT) + if( strcasecmp( sc3->DATA, sc1->DATA ) == 0 ) + { + if( ! ((noeud*)(sc4->DATA))->SIGNAL ) + { + ((noeud*)( sc4->DATA ))->SIGNAL = idsig; + pt->DATA = addchain( pt->DATA, sc4->DATA ); + } + } + + break; + + default : /* Il y a plus de deux equi existante : il faut + les regrouper en une seule */ + pt = getptype( headsig, idsig ); + + for( sc3 = sc1, sc4 = sc2 ; + sc3 && sc4 ; + sc3 = sc3->NEXT, sc4 = sc4->NEXT) + if( strcasecmp( sc3->DATA, sc1->DATA ) == 0 ) + { + /* Pas de signal sur le noeud sc4 */ + if( ! ( (noeud*)( sc4->DATA ) )->SIGNAL ) + { + ((noeud*)( sc4->DATA ))->SIGNAL = idsig; + pt->DATA = addchain( pt->DATA, sc4->DATA ); + } + else + /* Si on se trouve sur un autre signal */ + if( ( (noeud*)( sc4->DATA ) )->SIGNAL != idsig ) + { + /* t : index signal source */ + t = ( (noeud*)( sc4->DATA ) )->SIGNAL; + pt2 = getptype( headsig, t ); + + /* on change ne numero de signal de tous les noeuds du signal + * source */ + for( sc5 = pt2->DATA ; sc5 ; sc5 = sc5->NEXT ) + ( (noeud*)( sc5->DATA ) )->SIGNAL = idsig; + + /* on ajoute la chain_list source a la fin de la chain_list + * destination */ + for( sc5 = (chain_list*)( pt->DATA ) ; + sc5->NEXT ; + sc5 = sc5->NEXT ); + sc5->NEXT = (chain_list*)pt2->DATA; + + /* On libere le signal source */ + headsig = delptype( headsig, t ); + + } + /* Cas où on est sur le meme signal : on ne fait rien */ + } + + break; + } + } + + if( sc1 || sc2 ) + { + fflush( stdout ); + fprintf( stderr, "%s\n", SPIMSG(0) ); + fprintf( stderr, "%s :\n%s %s. %s %s. %s %s.\n", SPIMSG( 44 ), + SPIMSG( 54 ), + ptcir->NOM, + SPIMSG( 55 ), + scaninst->NOM, + SPIMSG( 56 ), + scaninst->MODELE + ); + EXIT(1); + } + } + + /* traite les resistances : Ca peut s'ameliorer pour aller + vite */ + + for( scanresi = ptcir->RESI ; scanresi ; scanresi = scanresi->SUIV ) + { + if( scanresi->N1->SIGNAL == 0 && scanresi->N2->SIGNAL == 0 ) + { + headsig = addptype( headsig, signal, NULL ); + scanresi->N1->SIGNAL = signal; + scanresi->N2->SIGNAL = signal; + headsig->DATA = addchain( headsig->DATA, scanresi->N1 ); + headsig->DATA = addchain( headsig->DATA, scanresi->N2 ); + signal++; + } + else + if( scanresi->N1->SIGNAL != 0 && scanresi->N2->SIGNAL == 0 ) + { + pt = getptype( headsig, scanresi->N1->SIGNAL ); + pt->DATA = addchain( pt->DATA, scanresi->N2 ); + scanresi->N2->SIGNAL = pt->TYPE; + } + else + if( scanresi->N1->SIGNAL == 0 && scanresi->N2->SIGNAL != 0 ) + { + pt = getptype( headsig, scanresi->N2->SIGNAL ); + pt->DATA = addchain( pt->DATA, scanresi->N1 ); + scanresi->N1->SIGNAL = pt->TYPE; + } + else + if( scanresi->N1->SIGNAL != scanresi->N2->SIGNAL ) + { + pt = getptype( headsig, scanresi->N1->SIGNAL ); + pt2 = getptype( headsig, scanresi->N2->SIGNAL ); + + for( sc1 = pt2->DATA ; sc1 ; sc1 = sc1->NEXT ) + ((noeud*)(sc1->DATA))->SIGNAL = pt->TYPE; + for( sc1 = pt->DATA ; sc1->NEXT ; sc1 = sc1->NEXT ) ; + sc1->NEXT = pt2->DATA; + headsig = delptype( headsig, pt2->TYPE ); + } + } + + for( scanvalim = ptcir->VALIM ; scanvalim ; scanvalim = scanvalim->SUIV ) + { + if( scanvalim->N1->SIGNAL == 0 && scanvalim->N2->SIGNAL == 0 ) + { + headsig = addptype( headsig, signal, NULL ); + scanvalim->N1->SIGNAL = signal; + scanvalim->N2->SIGNAL = signal; + headsig->DATA = addchain( headsig->DATA, scanvalim->N1 ); + headsig->DATA = addchain( headsig->DATA, scanvalim->N2 ); + signal++; + } + else + if( scanvalim->N1->SIGNAL != 0 && scanvalim->N2->SIGNAL == 0 ) + { + pt = getptype( headsig, scanvalim->N1->SIGNAL ); + pt->DATA = addchain( pt->DATA, scanvalim->N2 ); + scanvalim->N2->SIGNAL = pt->TYPE; + } + else + if( scanvalim->N1->SIGNAL == 0 && scanvalim->N2->SIGNAL != 0 ) + { + pt = getptype( headsig, scanvalim->N2->SIGNAL ); + pt->DATA = addchain( pt->DATA, scanvalim->N1 ); + scanvalim->N1->SIGNAL = pt->TYPE; + } + else + if( scanvalim->N1->SIGNAL != scanvalim->N2->SIGNAL ) + { + pt = getptype( headsig, scanvalim->N1->SIGNAL ); + pt2 = getptype( headsig, scanvalim->N2->SIGNAL ); + + for( sc1 = pt2->DATA ; sc1 ; sc1 = sc1->NEXT ) + ((noeud*)(sc1->DATA))->SIGNAL = pt->TYPE; + for( sc1 = pt->DATA ; sc1->NEXT ; sc1 = sc1->NEXT ) ; + sc1->NEXT = pt2->DATA; + headsig = delptype( headsig, pt2->TYPE ); + } + } + + if( SPI_MERGE == 1 ) + { + for( sc1 = ptcir->CINTERF ; sc1 ; sc1 = sc1->NEXT ) + { + node1 = ( noeud* )( sc1->DATA ); + + for( sc2 = ptcir->CINTERF ; sc2 != sc1 ; sc2 = sc2->NEXT ) + { + node2 = ( noeud* )( sc2->DATA ); + if( nodenameisequi( node1->NOM, node2->NOM ) ) + break; + } + + if( sc1 != sc2 ) + continue; + + for( sc2 = sc1->NEXT ; sc2 ; sc2 = sc2->NEXT ) + { + node2 = ( noeud* )( sc2->DATA ); + + if( nodenameisequi( node1->NOM, node2->NOM ) ) + { + if( node1->SIGNAL == 0 && node2->SIGNAL == 0 ) + { + headsig = addptype( headsig, signal, NULL ); + node1->SIGNAL = signal; + node2->SIGNAL = signal; + headsig->DATA = addchain( headsig->DATA, node1 ); + headsig->DATA = addchain( headsig->DATA, node2 ); + signal++; + } + else + if( node1->SIGNAL != 0 && node2->SIGNAL == 0 ) + { + pt = getptype( headsig, node1->SIGNAL ); + pt->DATA = addchain( pt->DATA, node2 ); + node2->SIGNAL = node1->SIGNAL; + } + else + if( node1->SIGNAL == 0 && node2->SIGNAL != 0 ) + { + pt = getptype( headsig, node2->SIGNAL ); + pt->DATA = addchain( pt->DATA, node1 ); + node1->SIGNAL = node2->SIGNAL; + } + else + if( node1->SIGNAL != node2->SIGNAL ) + { + pt = getptype( headsig, node1->SIGNAL ); + pt2 = getptype( headsig, node2->SIGNAL ); + + for( sc3 = pt2->DATA ; sc3 ; sc3 = sc3->NEXT ) + ((noeud*)(sc3->DATA))->SIGNAL = node1->SIGNAL; + for( sc3 = pt->DATA ; sc3->NEXT ; sc3 = sc3->NEXT ) ; + sc3->NEXT = pt2->DATA; + headsig = delptype( headsig, pt2->TYPE ); + } + else + { + /* rien a faire : node1->SIGNAL == node2->SIGNAL */ + } + } + } + } + } + + /* On s'occupe des noeuds libres */ + + for( scannoeud = ptcir->NOEUD; scannoeud; scannoeud = scannoeud->SUIV ) + { + if( scannoeud->SIGNAL == 0 ) + { + headsig = addptype( headsig, signal, addchain( NULL, scannoeud ) ); + scannoeud->SIGNAL = signal++; + + } + } + + /* Remplie le champ RCN de chaque noeud */ + + for( spt = headsig ; spt ; spt = spt->NEXT ) + { + sc1 = (chain_list*)(spt->DATA); + + if( sc1->NEXT || SPI_ONE_NODE_NORC == 0 ) + { + nb = 1; + for( ; sc1 ; sc1 = sc1->NEXT ) + ((noeud*)(sc1->DATA))->RCN = nb++ ; + } + else + { + ((noeud*)(sc1->DATA))->RCN = 0; + } + } + + /* Tous les noeuds d'un signal VSS ou VDD ont le nom VSS ou VDD */ + + vss = spicenamealloc( ptcir, VSS ); + vdd = spicenamealloc( ptcir, VDD ); + cirvss = 0; + cirvdd = 0; + + for( spt = headsig ; spt ; spt = spt->NEXT ) + { + vuevss = vuevdd = 0; + + for( sc1 = spt->DATA ; sc1 ; sc1 = sc1->NEXT ) + { + if( ( ( noeud* )( sc1->DATA ) )->NOM == vss ) + vuevss = 1; + + if( ( ( noeud* )( sc1->DATA ) )->NOM == vdd ) + vuevdd = 1; + } + + if( vuevss && vuevdd ) + { + fflush( stdout ); + fprintf( stderr, "%s\n", SPIMSG(0) ); + fprintf( stderr, "%s : %s\n", SPIMSG(45), ptcir->NOM ); + EXIT( 1 ); + } + + if( vuevss && cirvss ) + { + fflush( stdout ); + fprintf( stderr, "%s\n", SPIMSG(0) ); + fprintf( stderr, "%s : %s\n", SPIMSG(46), ptcir->NOM ); + EXIT( 1 ); + } + + if( vuevss ) + { + for( sc1 = spt->DATA ; sc1 ; sc1 = sc1->NEXT ) + ( ( noeud* )( sc1->DATA ) )->NOM = vss; + cirvss = 1; + } + + if( vuevdd && cirvdd ) + { + fflush( stdout ); + fprintf( stderr, "%s\n", SPIMSG(0) ); + fprintf( stderr, "%s : %s\n", SPIMSG(47), ptcir->NOM ); + EXIT( 1 ); + } + + if( vuevdd ) + { + for( sc1 = spt->DATA ; sc1 ; sc1 = sc1->NEXT ) + ( ( noeud* )( sc1->DATA ) )->NOM = vdd; + cirvdd = 1; + } + } + + /* + if( !cirvss || !cirvdd ) + { + fflush( stdout ); + fprintf( stderr, + "*** mbkspi error *** : No vdd or vss nodes in %s\n", + ptcir->NOM + ); + EXIT( 1 ); + } + */ + + /* On renumerote les signaux en partant de 1, c'est plus propre. */ + idsig = 1; + for(spt = headsig ; spt ; spt = spt->NEXT ) + { + if( spt->DATA ) + { + for( scanchain = (chain_list*)(spt->DATA) ; + scanchain ; + scanchain = scanchain->NEXT + ) + { + scannoeud = (noeud*)(scanchain->DATA); + scannoeud->SIGNAL = idsig; + } + idsig++; + } + } + + if( SPI_NODE_EQUI_DRIVE ) + spi_dump_equi( ptcir->NOM, headsig ); + + /* libere la liste des noeuds par signal */ + + for(spt = headsig; spt; spt = spt->NEXT ) + if( spt->DATA ) + freechain( (chain_list*)(spt->DATA) ); + freeptype( headsig ); + +} + +/******************************************************************************/ +void spi_dump_equi( char *figname, ptype_list *headsig ) +{ + ptype_list *spt; + chain_list *scan; + FILE *ptf; + noeud *node; + + ptf = mbkfopen( figname, "equi", WRITE_TEXT ); + if( !ptf ) + return; + + for( spt = headsig ; spt ; spt = spt->NEXT ) + { + if( spt->DATA ) + { + scan = (chain_list*)spt->DATA ; + fprintf( ptf, "Signal %d.\n", ((noeud*)(scan->DATA))->SIGNAL ); + for( ; scan ; scan = scan->NEXT ) + { + node = ((noeud*)scan->DATA ); + fprintf( ptf, + " %5d %5d %s\n", + node->SPICE, + node->RCN, + node->NOM ? node->NOM : "-" + ); + } + } + } + fclose( ptf ); +} + +/******************************************************************************/ + +int nodenameisequi( name1, name2 ) +/* Renvoie 1 si les deux noms sont sur la meme equipotentielle */ +char *name1; +char *name2; +{ + int end1; + int end2; + int end1x; + int end2x; + + if( name1 == NULL || name2 == NULL ) + return(0); + + /*modif karim pour passer les fichier ck1 ck1.1 ck1.2*/ + /*end1 = strlen( name1 ) - 1 ;*/ + end1x = end1 = strlen( name1 ) - 1 ; + + /* on passe les chiffres */ + + while( end1 > 0 && isdigit( (int)name1[ end1 ] ) ) + end1--; + + /* on passe le '.' */ + + /*modif karim pour passer les fichier ck1 ck1.1 ck1.2*/ + if( name1[ end1 ] == SPI_SEPAR ) + end1--; + else + end1 = end1x ; + + /*modif karim pour passer les fichier ck1 ck1.1 ck1.2*/ + /*end2 = strlen( name2 ) - 1 ;*/ + end2x = end2 = strlen( name2 ) - 1 ; + + /* on passe les chiffres */ + + while( end2 > 0 && isdigit( (int)name2[ end2 ] ) ) + end2--; + + /* on passe le '.' */ + + /*modif karim pour passer les fichier ck1 ck1.1 ck1.2*/ + if( name2[ end2 ] == SPI_SEPAR ) + end2--; + else + end2 = end2x ; + + end1++; + end2++; + + if( end1 == end2 ) + if( strncmp( name1, name2, end1 ) == 0 ) + return( 1 ); + + return( 0 ); +} + +/******************************************************************************/ + +void constlofig( ptcir, ptfig, instances, mode ) +circuit *ptcir; +lofig_list *ptfig; +ginterf *instances; +char mode; +{ + noeud *scannoeud; + noeud *ptnoeud; + chain_list *sc1, *sc2, *sc3, *sc4, *sc5; + locon_list *scanlocon; + losig_list *ptsig; + int nbsig; + int i; + losig_list **tabsig; + num_list *interf; + chain_list *connec_sig; + chain_list *connec_noeud; + chain_list *connec_nom; + chain_list *connec_con; + trans *scantrans; + inst *scaninst; + char *nom; + int idxcon; + lotrs_list *pttrs; + locon_list *scancon; + capa *scancapa; + loins_list *ptinst; + resi *scanresi; + valim *scanvalim; + ginterf *sci; + lofig_list *modele; + lofig_list *tetemodele; + loctc_list *ptctc; + char *devect; + ptype_list *ptnodename; + + + tetemodele = NULL; + + /* Création du tableau des signaux */ + + nbsig = 0; + for( scannoeud = ptcir->NOEUD; scannoeud ; scannoeud = scannoeud->SUIV ) + if( scannoeud->SIGNAL > nbsig ) + nbsig = scannoeud->SIGNAL; + + tabsig = (losig_list**)mbkalloc( sizeof(losig_list*)*nbsig ); + for( i = 0 ; i < nbsig ; i++ ) + tabsig[i] = NULL; + + /* Création des signaux */ + + setsigsize( ptfig, nbsig > 1024 ? 1024 : nbsig ); + + for( scannoeud = ptcir->NOEUD; scannoeud ; scannoeud = scannoeud->SUIV ) + { + if( !(ptsig = tabsig[ scannoeud->SIGNAL - 1 ]) ) + { + ptsig = addlosig( ptfig, scannoeud->SIGNAL, NULL, INTERNAL ); + tabsig[ scannoeud->SIGNAL - 1 ] = ptsig; + } + + if( scannoeud->NOM ) + { + devect = spi_devect( scannoeud->NOM ); + + nom = namealloc( devect ); + mbkfree( devect ); + + for( sc1 = ptsig->NAMECHAIN; sc1 ; sc1 = sc1->NEXT ) + if( sc1->DATA == nom ) + break; + + if( ! sc1 ) + ptsig->NAMECHAIN = addchain( ptsig->NAMECHAIN, nom ); + } + } + + /* On construit les vues RCN et/ou CTC */ + /* + for( ptsig = ptfig->LOSIG ; ptsig ; ptsig = ptsig->NEXT ) + if( ! ptsig->PRCN ) + addlorcnet( ptsig ); + */ + + triecapa( ptcir ); + + for( scancapa = ptcir->CAPA ; scancapa ; scancapa = scancapa->SUIV ) + { + if( !tabsig[ scancapa->N1->SIGNAL -1 ]->PRCN ) + addlorcnet( tabsig[ scancapa->N1->SIGNAL -1 ] ); + + if( !tabsig[ scancapa->N2->SIGNAL -1 ]->PRCN ) + addlorcnet( tabsig[ scancapa->N2->SIGNAL -1 ] ); + + tabsig[ scancapa->N1->SIGNAL -1 ]->PRCN->CAPA += scancapa->CAPA; + tabsig[ scancapa->N2->SIGNAL -1 ]->PRCN->CAPA += scancapa->CAPA; + } + + for( scanresi = ptcir->RESI ; scanresi ; scanresi = scanresi->SUIV ) + { + if( !tabsig[ scanresi->N1->SIGNAL - 1 ]->PRCN ) + addlorcnet( tabsig[ scanresi->N1->SIGNAL - 1 ] ); + + addlowire( tabsig[ scanresi->N1->SIGNAL - 1 ], + RCN_WIRE_UNKNOW, + 0, + scanresi->RESI, + scanresi->CAPA, + 0l, + 0l, + 0l, + 0l, + scanresi->N1->RCN, + scanresi->N2->RCN + ); + } + + for( scanvalim = ptcir->VALIM ; scanvalim ; scanvalim = scanvalim->SUIV ) + { + if( !tabsig[ scanvalim->N1->SIGNAL - 1 ]->PRCN ) + addlorcnet( tabsig[ scanvalim->N1->SIGNAL - 1 ] ); + + addlowire( tabsig[ scanvalim->N1->SIGNAL - 1 ], + RCN_WIRE_UNKNOW, + 0, + 0.0, + 0.0, + 0l, + 0l, + 0l, + 0l, + scanvalim->N1->RCN, + scanvalim->N2->RCN + ); + } + + for( scancapa = ptcir->CAPA ; scancapa ; scancapa = scancapa->SUIV ) + { + if( !tabsig[ scancapa->N1->SIGNAL - 1 ]->PRCN ) + addlorcnet( tabsig[ scancapa->N1->SIGNAL - 1 ] ); + + if( !tabsig[ scancapa->N2->SIGNAL - 1 ]->PRCN ) + addlorcnet( tabsig[ scancapa->N2->SIGNAL - 1 ] ); + + if( scancapa->NOM != NULL && scancapa->N1 != scancapa->N2 ) + { + ptctc = getloctc( tabsig[ scancapa->N1->SIGNAL - 1 ], + scancapa->N1->RCN ? scancapa->N1->RCN : 1, + tabsig[ scancapa->N2->SIGNAL - 1 ], + scancapa->N2->RCN ? scancapa->N2->RCN : 1 + ); + + if( ptctc ) + ptctc->CAPA = ptctc->CAPA + scancapa->CAPA; + else + addloctc( tabsig[ scancapa->N1->SIGNAL - 1 ], + scancapa->N1->RCN ? scancapa->N1->RCN : 1, + tabsig[ scancapa->N2->SIGNAL - 1 ], + scancapa->N2->RCN ? scancapa->N2->RCN : 1, + scancapa->CAPA + ); + } + } + + /* Connecteurs de l'interface */ + + idxcon = 1; + for( sc1 = ptcir->CINTERF, sc2 = instances->GINTERF ; + sc1 && sc2 ; + sc1 = sc1->NEXT, sc2 = sc2->NEXT + ) + { + ptnoeud = (noeud*)(sc1->DATA); + + for( scanlocon = ptfig->LOCON ; scanlocon ; scanlocon = scanlocon->NEXT ) + if( scanlocon->SIG->INDEX == ptnoeud->SIGNAL ) + break; + + if( !scanlocon ) + { + ptsig = tabsig[ ptnoeud->SIGNAL - 1 ]; + ptsig->TYPE = 'E'; + + devect = spi_devect( (char*)(sc2->DATA) ); + + if( SPI_MERGE == 1 ) + stopchainsepar( devect ); + + nom = namealloc( devect ); + mbkfree( devect ); + + scanlocon = addlocon( ptfig, nom, ptsig, UNKNOWN ); + scanlocon->USER = addptype( scanlocon->USER, PNODENAME, NULL ); + } + + if( ptnoeud->RCN ) + { + if( !scanlocon->SIG->PRCN ) + addlorcnet( scanlocon->SIG ); + + setloconnode( scanlocon, ptnoeud->RCN ); + ptnodename = getptype( scanlocon->USER, PNODENAME ); + + if( ptnoeud->NOM ) + ((chain_list*)(ptnodename->DATA)) = + addchain( ((chain_list*)(ptnodename->DATA)), namealloc( ptnoeud->NOM ) ); + else + ((chain_list*)(ptnodename->DATA)) = + addchain( ((chain_list*)(ptnodename->DATA)), NULL ); + } + } + + if( sc1 || sc2 ) + { + fflush( stdout ); + fprintf( stderr,"sc1 ou sc2.\n" ); + EXIT(-1); + } + + for( scanlocon = ptfig->LOCON ; scanlocon ; scanlocon = scanlocon->NEXT ) + { + (chain_list*)scanlocon->PNODE = reverse( (chain_list*)scanlocon->PNODE ); + + ptnodename = getptype( scanlocon->USER, PNODENAME ); + for( sc1 = (chain_list*)( ptnodename->DATA ) ; sc1 ; sc1 = sc1->NEXT ) + if( sc1->DATA ) + break; + if( sc1 ) + ((chain_list*)(ptnodename->DATA)) = + reverse( ((chain_list*)(ptnodename->DATA)) ); + else + { + freechain( (chain_list*)ptnodename->DATA ); + scanlocon->USER = delptype( scanlocon->USER, PNODENAME ); + } + } + + (chain_list*)ptfig->LOCON = reverse( (chain_list*)ptfig->LOCON ); + + /* On cree les transistors */ + + for( scantrans = ptcir->TRANS; scantrans; scantrans = scantrans->SUIV ) + { + pttrs = addlotrs( + ptfig, + scantrans->TYPE, + float2long( scantrans->X ), + float2long( scantrans->Y ), + float2long( scantrans->W * SCALE_X * 1e6 ), + float2long( scantrans->L * SCALE_X * 1e6 ), + float2long( scantrans->PS * SCALE_X * 1e6 ), + float2long( scantrans->PD * SCALE_X * 1e6 ), + float2long( scantrans->AS * SCALE_X * 1e6 / scantrans->W ), + float2long( scantrans->AD * SCALE_X * 1e6 / scantrans->W ), + tabsig[ scantrans->GRILLE->SIGNAL - 1 ], + tabsig[ scantrans->SOURCE->SIGNAL - 1 ], + tabsig[ scantrans->DRAIN->SIGNAL - 1 ], + scantrans->SUBST ? + tabsig[ scantrans->SUBST->SIGNAL - 1 ] : + NULL, + scantrans->NOM + ); + + if( scantrans->DRAIN->RCN ) + { + if( !pttrs->DRAIN->SIG->PRCN ) + addlorcnet( pttrs->DRAIN->SIG ); + setloconnode(pttrs->DRAIN, scantrans->DRAIN->RCN ); + if( scantrans->DRAIN->NOM ) + pttrs->DRAIN->USER = addptype( pttrs->DRAIN->USER, + PNODENAME, + addchain( NULL, + namealloc( scantrans->DRAIN->NOM) + ) + ); + } + + if( scantrans->GRILLE->RCN ) + { + if( !pttrs->GRID->SIG->PRCN ) + addlorcnet( pttrs->GRID->SIG ); + setloconnode(pttrs->GRID, scantrans->GRILLE->RCN ); + if( scantrans->GRILLE->NOM ) + pttrs->GRID->USER = addptype( pttrs->GRID->USER, + PNODENAME, + addchain( NULL, + namealloc( scantrans->GRILLE->NOM) + ) + ); + } + + if( scantrans->SOURCE->RCN ) + { + if( !pttrs->SOURCE->SIG->PRCN ) + addlorcnet( pttrs->SOURCE->SIG ); + setloconnode(pttrs->SOURCE, scantrans->SOURCE->RCN ); + if( scantrans->SOURCE->NOM ) + pttrs->SOURCE->USER = addptype( pttrs->SOURCE->USER, + PNODENAME, + addchain( NULL, + namealloc( scantrans->SOURCE->NOM) + ) + ); + } + + if( scantrans->SUBST ) + { + if( scantrans->SUBST->RCN ) + { + if( !pttrs->BULK->SIG->PRCN ) + addlorcnet( pttrs->BULK->SIG ); + setloconnode(pttrs->BULK, scantrans->SUBST->RCN ); + if( scantrans->SUBST->NOM ) + pttrs->BULK->USER = addptype( pttrs->BULK->USER, + PNODENAME, + addchain( NULL, + namealloc( scantrans->SUBST->NOM) + ) + ); + } + } + } + + /* On cree les instances */ + + + for( scaninst = ptcir->INST ; scaninst ; scaninst = scaninst->SUIV ) + { + connec_sig = NULL; + connec_noeud = NULL; + connec_nom = NULL; + connec_con = NULL; + + for( sci = instances ; sci ; sci = sci->SUIV ) + { + if( strcasecmp( sci->NOM, scaninst->MODELE ) == 0 ) + break; + } + + if( !sci ) + { + fflush( stdout ); + fprintf( stderr, + "Internal error : can't find model %s.\n", + scaninst->MODELE + ); + EXIT( 1 ); + } + + /* Constitue la liste des signaux */ + for( sc1 = sci->GINTERF, sc2 = scaninst->IINTERF ; + sc1 && sc2 ; + sc1 = sc1->NEXT, sc2 = sc2->NEXT + ) + { + for( sc3 = sci->GINTERF ; sc3 != sc1 ; sc3 = sc3->NEXT ) + if( strcasecmp( sc3->DATA, sc1->DATA ) == 0 ) + break; + + if( sc3 == sc1 ) /* Creation d'un nouveau locon */ + { + connec_sig = addchain( connec_sig, + tabsig[ ((noeud*)(sc2->DATA))->SIGNAL - 1 ] + ); + connec_noeud = addchain( connec_noeud, + addnum( NULL, ((noeud*)(sc2->DATA))->RCN ) + ); + connec_nom = addchain( connec_nom, + addchain( NULL, + namealloc( ((noeud*)(sc2->DATA))->NOM ) + ) + ); + connec_con = addchain( connec_con, sc1->DATA ); + } + else /* On complete des noeuds d'un locon */ + { + for ( sc3 = connec_con, sc4 = connec_noeud, sc5 = connec_nom ; + strcasecmp( (char*)sc3->DATA, (char*)sc1->DATA ) != 0 ; + sc3 = sc3->NEXT, sc4 = sc4->NEXT, sc5 = sc5->NEXT + ) ; + + sc4->DATA = addnum( sc4->DATA, ((noeud*)(sc2->DATA))->RCN ); + sc5->DATA = addchain( sc5->DATA, namealloc ( + ((noeud*)(sc2->DATA))->NOM + ) + ); + } + } + + freechain( connec_con ); + connec_sig = reverse( connec_sig ); + connec_noeud = reverse( connec_noeud ); + connec_nom = reverse( connec_nom ); + + nom = namealloc( sci->NOM ); + + modele = getlomodel( tetemodele, nom ); + if( !modele ) + modele = tetemodele = recuperemodele( tetemodele, nom, sci->GINTERF ); + + ptinst = addloins( ptfig, "*", modele, connec_sig ); + ptinst->INSNAME = namealloc( scaninst->NOM ) ; + + ptinst->USER = constphinterf( ptinst->USER, sci ); + + for( scancon = ptinst->LOCON, sc1 = connec_noeud, sc2 = connec_nom ; + scancon ; + scancon = scancon->NEXT, sc1 = sc1->NEXT, sc2 = sc2->NEXT + ) + { + interf = (num_list*)sc1->DATA; + scancon->USER = addptype( scancon->USER, PNODENAME, NULL ); + ptnodename = scancon->USER; + + if( interf->DATA ) + { + if( !scancon->SIG->PRCN ) + addlorcnet( scancon->SIG ); + + for( ; interf ; interf = interf->NEXT ) + setloconnode( scancon, interf->DATA ); + + sc3 = (chain_list*)sc2->DATA; + for( ; sc3 ; sc3 = sc3->NEXT ) + ((chain_list*)(ptnodename->DATA)) = addchain( + ((chain_list*)(ptnodename->DATA)), + sc3->DATA + ); + + } + } + + freechain( connec_sig ); + for( sc1 = connec_noeud ; sc1 ; sc1 = sc1->NEXT ) + freenum( sc1->DATA ); + freechain( connec_noeud ); + for( sc1 = connec_nom ; sc1 ; sc1 = sc1->NEXT ) + freechain( sc1->DATA ); + freechain( connec_nom ); + + for( scancon = ptinst->LOCON ; scancon ; scancon = scancon->NEXT ) + { + ptnodename = getptype( scancon->USER, PNODENAME ); + for( sc1 = (chain_list*)( ptnodename->DATA ) ; sc1 ; sc1 = sc1->NEXT ) + if( sc1->DATA ) + break; + if( !sc1 ) + { + freechain( (chain_list*)ptnodename->DATA ); + scancon->USER = delptype( scancon->USER, PNODENAME ); + } + } + } + + ptfig->MODE = mode; + mbkfree( tabsig ); + freelomodel( tetemodele ); + + ptfig->LOTRS = ( lotrs_list* ) reverse( (chain_list*) ptfig->LOTRS ); + + lofigchain( ptfig ); +} + +/******************************************************************************/ + +chain_list* lireligne( df ) +spifile *df; +{ + chain_list *sc; + chain_list *eff; + + if( df->decomp2 == NULL ) + { + df->decomp1 = decompligne(df); + strcpy( df->file_line1, df->file_line ); + } + else + { + df->decomp1 = df->decomp2; + strcpy( df->file_line1, df->file_line2 ); + } + + if( df->decomp1 == NULL ) /* cas d'un fichier vide */ + return(NULL); + + while( TRUE ) + { + df->decomp2 = decompligne(df); + strcpy( df->file_line2, df->file_line ); + + if( df->decomp2 == NULL ) + break; + + /* + if( strcmp( (char*)df->decomp2->DATA, "+" ) != 0 ) + */ + if( ((char*)(df->decomp2->DATA))[0] != '+' || + ((char*)(df->decomp2->DATA))[1] != 0 ) + break; + + /* On reforme les lignes séparées par des + */ + + eff = df->decomp2; + df->decomp2 = df->decomp2->NEXT; + eff->NEXT = NULL; + mbkfree( eff->DATA ); + freechain(eff); + + for( sc = df->decomp1; sc->NEXT; sc = sc->NEXT ); + sc->NEXT = df->decomp2; + } + return( df->decomp1 ); +} + +/******************************************************************************/ + +chain_list* decompligne( df ) +spifile *df; +{ + char mot[LONG_LIGNE]; + int lg; + chain_list *decomp; + char motencours; + char *element; + int i, j=0 ; /* Warning a la compilation */ + + do + { + df->msl_line++; + decomp = NULL; + + fgets( df->file_line, LONG_LIGNE, df->df ); + + if( feof(df->df) ) + return( NULL ); + + lg = strlen(df->file_line); + + if( lg == LONG_LIGNE-1 ) + spierror( 48, df->filename, df->msl_line ); + + motencours = 0; + + /* Un cas particulier : si le premier caractere de la ligne est + * un '+'. Sur la suite de la ligne, le '+' sera considere comme un + * caractere standard. */ + + i=0; + while( df->file_line[i] == ' ' ) + i++; + + if( df->file_line[i] == '+' ) + { + element = (char*)mbkalloc( 2 * sizeof(char) ); + element[0] = df->file_line[i]; + element[1] = 0; + decomp = addchain( decomp, element ); + i++; + } + + /* On traite le reste de la ligne */ + + for( ; ifile_line[i] >= 'A' && df->file_line[i] <= 'Z' ) || + ( df->file_line[i] >= 'a' && df->file_line[i] <= 'z' ) || + ( df->file_line[i] >= '0' && df->file_line[i] <= '9' ) || + strchr( ":/$<>[]._-|+@", df->file_line[i] ) ) + { + if( !motencours ) + { + motencours = 1; + j = 0; + } + mot[j++] = df->file_line[i]; + } + else + { + if( motencours ) + { + mot[j++] = 0; + + element = (char*)mbkalloc( j * sizeof(char) ); + memcpy( element, mot, j ); + decomp = addchain( decomp, element ); + + motencours = 0; + } + + if( strchr( "=*$", df->file_line[i] ) ) + { + element = (char*)mbkalloc( 2 * sizeof(char) ); + element[0] = df->file_line[i]; + element[1] = 0; + decomp = addchain( decomp, element ); + } + } + } + } + while(!decomp); + + return(reverse(decomp)); +} + +/******************************************************************************/ + +void liberecircuit( ptcir ) +circuit *ptcir; +{ + chain_list *scanchain; + inst *scaninst; + + for( scaninst = ptcir->INST ; scaninst ; scaninst = scaninst->SUIV ) + freechain( scaninst->IINTERF ); + + for( scanchain = ptcir->FREE ; scanchain ; scanchain = scanchain->NEXT ) + mbkfree( scanchain->DATA ); + + freechain( ptcir->FREE ); + freechain( ptcir->CINTERF ); + freetableint( ptcir->INT_NOEUD ); + freethash( ptcir->HASHGNAME ); + freethash( ptcir->HASHCAPA ); + freethash( ptcir->HASHRESI ); + freethash( ptcir->HASHVALIM ); + freethash( ptcir->HASHINST ); + freethash( ptcir->HASHTRAN ); + freethash( ptcir->NOM_NOEUD ); + mbkfree( ptcir ); +} + +/******************************************************************************/ + +noeud* ajoutenoeud( ptcir, index, df ) +circuit *ptcir; +char *index; +spifile *df; +{ + int val; + char *fin; + noeud *sn; + char *nom; + + val = -1; + nom = NULL; + + val = strtol( index, &fin, 10 ); + + if( fin != index ) /* Ca commence par un nombre */ + { + if( *fin!=0 ) + { + fflush( stdout ); + fprintf( stderr, "%s\n", SPIMSG(0) ); + fprintf( stderr, "%s : %s\n", SPIMSG(49), index ); + fprintf( stderr, "%s %s. %s %d :\n", + SPIMSG(11), + df->filename, + SPIMSG(12), + df->msl_line + ); + EXIT( 1 ); + } + + sn = (noeud*) tsttableint( ptcir->INT_NOEUD, val ); + if( sn ) + return( sn ); + } + else + { + if(!(( index[0] >= 'A' && index[0] <= 'Z' ) || + ( index[0] >= 'a' && index[0] <= 'z' ) || + ( index[0] == '_' || index[0] == '@' ) ) ) + { + fflush( stdout ); + fprintf( stderr, "%s\n", SPIMSG(0) ); + fprintf( stderr, "%s : %s\n", SPIMSG(50), index ); + fprintf( stderr, "%s %s. %s %d :\n", + SPIMSG(11), + df->filename, + SPIMSG(12), + df->msl_line + ); + EXIT( 1 ); + } + + nom = spicenamealloc( ptcir, index ); + + sn = getthashelem( nom, ptcir->NOM_NOEUD, NULL ); + if( sn ) + return( sn ); + } + + sn = (noeud*)spiciralloue( ptcir, sizeof(noeud) ); + sn->SUIV = ptcir->NOEUD; + ptcir->NOEUD = sn; + + sn->NOM = nom; + sn->SIGNAL = 0; + sn->RCN = 0; + sn->SPICE = val; + + if( val != -1 ) + settableint( ptcir->INT_NOEUD, val, sn ); + if( nom ) + addthashelem( nom, sn, ptcir->NOM_NOEUD ); + + return(sn); +} + +/******************************************************************************/ + +void nomenoeud( ptcir, ptnoeud, ptnom, df ) +circuit *ptcir; +noeud *ptnoeud; +char *ptnom; +spifile *df; +{ + if( ptnoeud->NOM ) + { + fflush( stdout ); + fprintf( stderr, "%s\n", SPIMSG(0) ); + fprintf( stderr, "%s : %s\n", SPIMSG(51), ptnoeud->NOM ); + fprintf( stderr, "%s %s. %s %d :\n", + SPIMSG(11), + df->filename, + SPIMSG(12), + df->msl_line + ); + EXIT( 1 ); + } + + ptnoeud->NOM = spicenamealloc( ptcir, ptnom ); + addthashelem( ptnoeud->NOM, ptnoeud, ptcir->NOM_NOEUD ); +} + +/******************************************************************************/ + +char* spicenamealloc( ptcir, ptnom ) +circuit *ptcir; +char *ptnom; +{ + char *elem; + char tmp[LONG_LIGNE]; + int l; + + downstr( ptnom, tmp ); + /* Bug dans la fonction downstr : il ne recopie pas le 0 de fin de chaine */ + tmp[ strlen(ptnom) ] = 0; + + elem = getthashelem( tmp, ptcir->HASHGNAME, NULL ); + if( elem ) + return( elem ); + + l = sizeof(char) * (strlen( tmp ) + 1 ); + if( ptcir->RESTENOM < l ) + { + ptcir->ALLOUENOM = (char*)spiciralloue( ptcir, TAILLENOM ); + ptcir->RESTENOM = TAILLENOM; + } + + elem = strcpy( ptcir->ALLOUENOM + ( TAILLENOM - ptcir->RESTENOM ), tmp ); + ptcir->RESTENOM = ptcir->RESTENOM - l; + addthashelem( elem, elem, ptcir->HASHGNAME ); + return( elem ); +} + +/******************************************************************************/ + +void* spiciralloue( cir, taille ) +circuit *cir; +int taille; +{ + void *pt; + + if(!cir) + { + fflush( stdout ); + fprintf( stderr, "*** mbkspi internal error *** : spiciralloue()\n" ); + EXIT(1); + } + + pt = mbkalloc( taille ); + cir->FREE = addchain( cir->FREE, pt ); + cir->TAILLE = cir->TAILLE + taille ; + return( pt ); +} + +/******************************************************************************/ + +float spicefloat( nombre, status ) +char *nombre; +int *status; +{ + float valeur; + char *fin; + + /* Les caractères suivant une unité sont ignorés */ + + *status = -1 ; + + valeur = (float)strtod( nombre, &fin ); + + if( *fin == 0 ) + *status = 1; + else + if( strncasecmp( fin, "F", 1 ) == 0 ) + { + *status = 1; + valeur = valeur * 1e-15 ; + } + else + if( strncasecmp( fin, "P", 1 ) == 0 ) + { + *status = 1; + valeur = valeur * 1e-12 ; + } + else + if( strncasecmp( fin, "N", 1 ) == 0 ) + { + *status = 1; + valeur = valeur * 1e-9 ; + } + else + if( strncasecmp( fin, "U", 1 ) == 0 ) + { + *status = 1; + valeur = valeur * 1e-6 ; + } + else + if( strncasecmp( fin, "M", 1 ) == 0 ) + { + *status = 1; + valeur = valeur * 1e-3 ; + } + else + if( strncasecmp( fin, "K", 1 ) == 0 ) + { + *status = 1; + valeur = valeur * 1e+3 ; + } + else + if( strncasecmp( fin, "MEG", 3 ) == 0 ) + { + *status = 1; + valeur = valeur * 1e+6 ; + } + else + if( strncasecmp( fin, "MI", 2 ) == 0 ) + { + *status = 1; + valeur = valeur * 25.4e+6 ; + } + else + if( strncasecmp( fin, "G", 1 ) == 0 ) + { + *status = 1; + valeur = valeur * 1e+9 ; + } + else /*unit values*/ + if( strncasecmp( fin, "V", 1 ) == 0 ) + { + *status = 1; + valeur = valeur * 1e+9 ; + } + + return( valeur); +} + +/******************************************************************************/ + +void triecapa( ptcir ) +circuit *ptcir; +{ + resi *scanresi; + char *n1, *n2; + capa *c1, *c2; + noeud *tmp; + char *vss; + char *vdd; + + vdd = spicenamealloc( ptcir, VDD ); + vss = spicenamealloc( ptcir, VSS); + + for( scanresi = ptcir->RESI ; scanresi ; scanresi = scanresi->SUIV ) + { + n1 = mbkalloc( sizeof( char ) * ( strlen(scanresi->NOM) + 2 ) ); + n2 = mbkalloc( sizeof( char ) * ( strlen(scanresi->NOM) + 2 ) ); + + sprintf( n1 , "%s1", scanresi->NOM ); + sprintf( n2 , "%s2", scanresi->NOM ); + + c1 = NULL; + c2 = NULL; + + c1 = getthashelem( n1, ptcir->HASHCAPA, NULL ); + c2 = getthashelem( n2, ptcir->HASHCAPA, NULL ); + + if( !c1 || !c2 ) + { + scanresi->CAPA = 0.0; + mbkfree( n1 ); + mbkfree( n2 ); + continue; + } + + if( c1->N2->NOM == vss ) + { + tmp = c1->N2; + c1->N2 = c1->N1; + c1->N1 = tmp; + } + else + if( c1->N1->NOM != vss ) + { + scanresi->CAPA = 0.0; + mbkfree( n1 ); + mbkfree( n2 ); + continue; + } + + if( c2->N2->NOM == vss ) + { + tmp = c2->N2; + c2->N2 = c2->N1; + c2->N1 = tmp; + } + else + if( c2->N1->NOM != vss ) + { + scanresi->CAPA = 0.0; + mbkfree( n1 ); + mbkfree( n2 ); + continue; + } + + if( c1->CAPA != c2->CAPA ) + { + scanresi->CAPA = 0.0; + mbkfree( n1 ); + mbkfree( n2 ); + continue; + } + + if( ( c1->N2 == scanresi->N1 && c2->N2 == scanresi->N2 ) || + ( c2->N2 == scanresi->N1 && c1->N2 == scanresi->N1 ) ) + { + /* On ne prendra plus ces capacites en compte */ + + c1->NOM = NULL; + c2->NOM = NULL; + + scanresi->CAPA = c1->CAPA+c1->CAPA; + } + else + { + scanresi->CAPA = 0.0; + mbkfree( n1 ); + mbkfree( n2 ); + continue; + } + + mbkfree( n1 ); + mbkfree( n2 ); + + } +} + +/******************************************************************************/ + +long float2long( v ) +float v; +{ + long i; + float r; + + i = v; + r = v-i; + + if( r >= 0.5 ) + return ( i+1 ); + return(i); +} + +/******************************************************************************/ + +void taillevuespice( ptcir ) +circuit *ptcir; +{ + int nb_noeud = 0; + int nb_resi = 0; + int nb_capa = 0; + int nb_inst = 0; + int nb_alim = 0; + int nb_trans = 0; + int total; + noeud *scannoeud; + resi *scanresi; + capa *scancapa; + trans *scantrans; + inst *scaninst; + valim *scanalim; + + for( scannoeud = ptcir->NOEUD ; scannoeud ; scannoeud = scannoeud->SUIV ) + nb_noeud++; + + for( scantrans = ptcir->TRANS ; scantrans ; scantrans = scantrans->SUIV ) + nb_trans++; + + for( scanresi = ptcir->RESI ; scanresi ; scanresi = scanresi->SUIV ) + nb_resi++; + + for( scancapa = ptcir->CAPA ; scancapa ; scancapa = scancapa->SUIV ) + nb_capa++; + + for( scaninst = ptcir->INST ; scaninst ; scaninst = scaninst->SUIV ) + nb_inst++; + + for( scanalim = ptcir->VALIM ; scanalim ; scanalim = scanalim->SUIV ) + nb_alim++; + + printf( "Data size structure :\n" ); + printf( " noeud : %7dx%3d = %9d\n", + nb_noeud, + sizeof( noeud ), + nb_noeud * sizeof(noeud) + ); + printf( " trans : %7dx%3d = %9d\n", + nb_trans, + sizeof(trans), + nb_trans * sizeof(trans) + ); + printf( " resi : %7dx%3d = %9d\n", + nb_resi, + sizeof(resi), + nb_resi * sizeof(resi) + ); + printf( " capa : %7dx%3d = %9d\n", + nb_capa, + sizeof(capa), + nb_capa * sizeof(capa) + ); + printf( " inst : %7dx%3d = %9d\n", + nb_inst, + sizeof(inst), + nb_inst * sizeof(inst) + ); + printf( " alim : %7dx%3d = %9d\n", + nb_alim, + sizeof(valim), + nb_alim * sizeof(valim) + ); + + total = nb_noeud * sizeof(noeud) + + nb_trans * sizeof(trans) + + nb_resi * sizeof(resi) + + nb_capa * sizeof(capa) + + nb_inst * sizeof(inst) + + nb_alim * sizeof(valim); + + printf( "Total : %d.\n", total ); + printf( "Real size : %ld\n", ptcir->TAILLE ); + +} + +/******************************************************************************/ + +void affvuespice( ptcir ) +circuit *ptcir; +{ + chain_list *sc; + inst *scaninst; + trans *scantrans; + resi *scanresi; + capa *scancapa; + + printf("Circuit : %s\n", ptcir->NOM ); + + printf("Interface :\n"); + for( sc = ptcir->CINTERF; sc; sc = sc->NEXT ) + printf(" %8X %4d %4d %4d %s\n", + ((unsigned int)(sc->DATA)), + ((noeud*)(sc->DATA))->SPICE, + ((noeud*)(sc->DATA))->SIGNAL, + ((noeud*)(sc->DATA))->RCN, + ((noeud*)(sc->DATA))->NOM ? ((noeud*)(sc->DATA))->NOM : "" ); + + for(scantrans = ptcir->TRANS; scantrans; scantrans = scantrans->SUIV) + { + printf("Transitor : %s\n",scantrans->NOM); + printf(" DRAIN %8X %4d %4d %4d %s\n", + (unsigned int)scantrans->DRAIN, + scantrans->DRAIN->SPICE, + scantrans->DRAIN->SIGNAL, + scantrans->DRAIN->RCN, + scantrans->DRAIN->NOM ? scantrans->DRAIN->NOM : "" ); + printf(" GRILLE %8X %4d %4d %4d %s\n", + (unsigned int)scantrans->GRILLE, + scantrans->GRILLE->SPICE, + scantrans->GRILLE->SIGNAL, + scantrans->GRILLE->RCN, + scantrans->GRILLE->NOM ? scantrans->GRILLE->NOM : "" ); + printf(" SOURCE %8X %4d %4d %4d %s\n", + (unsigned int)scantrans->SOURCE, + scantrans->SOURCE->SPICE, + scantrans->SOURCE->SIGNAL, + scantrans->SOURCE->RCN, + scantrans->SOURCE->NOM ? scantrans->SOURCE->NOM : "" ); + if( scantrans->SUBST ) + { + printf(" SUBST %8X %4d %4d %4d %s\n", + (unsigned int)scantrans->SUBST, + scantrans->SUBST->SPICE, + scantrans->SUBST->SIGNAL, + scantrans->SUBST->RCN, + scantrans->SUBST->NOM ? scantrans->SUBST->NOM : "" ); + printf(" TYPE %c\n",scantrans->TYPE ); + printf(" L=%g W=%g AS=%g AD=%g PS=%g PD=%g\n",scantrans->L, + scantrans->W, + scantrans->AS, + scantrans->AD, + scantrans->PS, + scantrans->PD ); + } + } + + for(scanresi = ptcir->RESI ; scanresi; scanresi = scanresi->SUIV ) + { + printf("Resistance : %s\n",scanresi->NOM); + printf(" N1 %8X %4d %4d %4d %s\n", + (unsigned int)scanresi->N1, + scanresi->N1->SPICE, + scanresi->N1->SIGNAL, + scanresi->N1->RCN, + scanresi->N1->NOM ? scanresi->N1->NOM : "" ); + printf(" N2 %8X %4d %4d %4d %s\n", + (unsigned int)scanresi->N2, + scanresi->N2->SPICE, + scanresi->N2->SIGNAL, + scanresi->N2->RCN, + scanresi->N2->NOM ? scanresi->N2->NOM : "" ); + printf(" R=%g\n",scanresi->RESI); + } + + for(scancapa = ptcir->CAPA ; scancapa; scancapa = scancapa->SUIV ) + { + printf("Capacite : %s\n",scancapa->NOM); + printf(" N1 %8X %4d %4d %4d %s\n", + (unsigned int)scancapa->N1, + scancapa->N1->SPICE, + scancapa->N1->SIGNAL, + scancapa->N1->RCN, + scancapa->N1->NOM ? scancapa->N1->NOM : "" ); + printf(" N2 %8X %4d %4d %4d %s\n", + (unsigned int)scancapa->N2, + scancapa->N2->SPICE, + scancapa->N2->SIGNAL, + scancapa->N2->RCN, + scancapa->N2->NOM ? scancapa->N2->NOM : "" ); + printf(" C=%g\n",scancapa->CAPA); + } + + for( scaninst = ptcir->INST; scaninst; scaninst = scaninst->SUIV) + { + printf("Instance %s basee sur %s\n",scaninst->NOM, scaninst->MODELE); + for( sc = scaninst->IINTERF; sc; sc = sc->NEXT ) + printf(" %8X %4d %4d %4d %s\n", + ((unsigned int)(sc->DATA)), + ((noeud*)(sc->DATA))->SPICE, + ((noeud*)(sc->DATA))->SIGNAL, + ((noeud*)(sc->DATA))->RCN, + ((noeud*)(sc->DATA))->NOM ? ((noeud*)(sc->DATA))->NOM : "" ); + } +} + +/******************************************************************************/ + +char* retireextention( nom ) +char *nom; +{ + char *pt; + int i; + + pt = mbkstrdup( nom ); + + /* On retire l'extention du nom, c'est a dire qu'on arrete la chaine au + * dernier point rencontré */ + /* >0 : On laisse quand meme 1 caractere si le nom commence par un point */ + for( i = strlen( pt ) - 1 ; i > 0 ; i-- ) + if( pt[i] == '.' ) + { + pt[i] = 0; + break; + } + + return( pt ); +} + +/******************************************************************************/ + +lofig_list* recuperemodele( tetemodel, nom, interf ) +lofig_list *tetemodel; +char *nom; +chain_list *interf; +{ + lofig_list *ptmod; + chain_list *sc1, *sc2; + char *nomdevec; + + ptmod = addlomodel( tetemodel, nom ); + + for( sc1 = interf ; sc1 ; sc1 = sc1->NEXT ) + { + for( sc2 = interf; sc1 != sc2 ; sc2 = sc2->NEXT ) + if( strcasecmp( sc1->DATA, sc2->DATA ) == 0 ) + break; + + if( sc1 != sc2 ) + continue; + + nomdevec = spi_devect( (char*)(sc1->DATA) ); + ptmod->LOCON = addlocon( ptmod, namealloc( nomdevec ), NULL, 'X' ); + mbkfree( nomdevec ); + } + + ptmod->LOCON = (locon_list*)reverse( (chain_list*) ptmod->LOCON ); + return( ptmod ); +} + +/******************************************************************************/ + +void mslAddExtension(mslExtHandler) +int (*mslExtHandler)(); +{ + ext_handler = mslExtHandler; +} + +/******************************************************************************/ + +void mslRmvExtension() +{ + ext_handler = NULL; +} + +/******************************************************************************/ + +void mslAddCompletion(mslCmpHandler) +int (*mslCmpHandler)(); +{ + cmp_handler = mslCmpHandler; +} + +/******************************************************************************/ + +void mslRmvCompletion() +{ + cmp_handler = NULL; +} + +/******************************************************************************/ + +char* spi_devect( nom ) +char *nom; +{ + int taille; + int i; + int j; + char *nouv; + int fin; + int modif; + + taille = strlen( nom ); + if( taille == 0 ) + { + /* message */ + EXIT(1); + } + + nouv = (char*)mbkalloc( sizeof(char) * (taille+1) ); + fin = taille - 1 ; + modif = 0; + + if( nom[fin] == ']' ) + { + /* Retrouve le crochet ouvrant */ + for( i = fin-1 ; i >= 0 && isdigit( (int)nom[i] ) ; i-- ); + + if( nom[i] == '[' ) + { + if( i == 0 || i == fin - 1 ) + { + /* nom de variable bizare, de la forme [43] ou toto[] */ + fflush( stdout ); + fprintf( stderr, "%s : \"%s\"\n", SPIMSG(52), nom ); + EXIT(1); + } + else + { + /* bon vecteur : toto[32] */ + for( j = 0 ; j < fin ; j++ ) + if( i != j ) + nouv[j] = nom[j]; + else + nouv[i] = ' '; + nouv[j] = 0; + + modif = 1; + } + } + else + { + /* Nom de variable bizarre, de la forme toto32], toto] ou 32] */ + fflush( stdout ); + fprintf( stderr, "%s : \"%s\"\n", SPIMSG(52), nom ); + EXIT(1); + } + } + + if( ! modif ) + strcpy( nouv, nom ); + + return(nouv); +} + +/******************************************************************************/ + +void spierror( mesg, file, line ) +int mesg; +char *file; +int line; +{ + fflush( stdout ); + fprintf( stderr, "%s.\n", SPIMSG(0) ); + fprintf( stderr, "%s. %s %s. %s %d.\n", + SPIMSG(1), + SPIMSG(11), + file, + SPIMSG(12), + line + ); + fprintf( stderr, "%s.\n",SPIMSG(mesg)); + EXIT(1); +} + +/******************************************************************************/ + +void stopchainsepar( chaine ) +char *chaine; +{ + int i; + + /* On retire le nombre en fin de nom et le SPI_SEPAR */ + for( i = strlen( chaine ) - 1 ; i >= 0 ; i-- ) + if( ! isdigit( (int)chaine[i] ) ) + break; + + if( i > 0 ) + if( chaine[i] == SPI_SEPAR ) + chaine[i] = '\0' ; +} diff --git a/alliance/src/mbkspice/src/spi_parse.h b/alliance/src/mbkspice/src/spi_parse.h new file mode 100644 index 00000000..ce9a3632 --- /dev/null +++ b/alliance/src/mbkspice/src/spi_parse.h @@ -0,0 +1,187 @@ +/* + * 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 library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library 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. + */ + + +/******************************************************************************* +* * +* Tool : Spice parser / driver v 7.00 * +* Author(s) : Gregoire AVOT * +* Updates : March, 18th 1998 * +* * +*******************************************************************************/ + +#ifndef SPI_PARSEH +#define SPI_PARSEH + +#define SPIEQUI 1664 + +#define TAILLENOM 4096 + +typedef struct s_circuit +{ + struct s_noeud *NOEUD; + struct s_trans *TRANS; + struct s_resi *RESI; + struct s_capa *CAPA; + struct s_inst *INST; + struct s_valim *VALIM; + char *NOM; + chain_list *CINTERF; /* DATA fiels : s_noeud */ + chain_list *FREE; + tableint *INT_NOEUD; + thash *NOM_NOEUD; + thash *HASHGNAME; + thash *HASHCAPA; + thash *HASHRESI; + thash *HASHVALIM; + thash *HASHINST; + thash *HASHTRAN; + long TAILLE; + char *ALLOUENOM; + int RESTENOM; +} circuit; + +typedef struct s_noeud +{ + struct s_noeud *SUIV; + char *NOM; + int SIGNAL; + int RCN; + int SPICE; +} noeud; + +typedef struct s_trans +{ + struct s_trans *SUIV; + struct s_noeud *DRAIN; + struct s_noeud *SOURCE; + struct s_noeud *GRILLE; + struct s_noeud *SUBST; + char TYPE; + char *NOM; + float L; + float W; + float AS; + float AD; + float PS; + float PD; + float X; + float Y; +} trans; + +typedef struct s_inst +{ + struct s_inst *SUIV; + char *NOM; + char *MODELE; + chain_list *IINTERF; +} inst; + +typedef struct s_resi +{ + struct s_resi *SUIV; + float RESI; + struct s_noeud *N1; + struct s_noeud *N2; + char *NOM; + float CAPA; +} resi; + +typedef struct s_capa +{ + struct s_capa *SUIV; + float CAPA; + struct s_noeud *N1; + struct s_noeud *N2; + char *NOM; +} capa; + +typedef struct s_valim +{ + struct s_valim *SUIV; + float TENSION; + struct s_noeud *N1; + struct s_noeud *N2; + char *NOM; +} valim; + +typedef struct s_interf +{ + struct s_interf *SUIV; + char *NOM; + chain_list *GINTERF; /* DATA field : char* nom des locons */ +} ginterf; + +#define LONG_LIGNE 16384 + +typedef struct s_spifile +{ + FILE *df; + chain_list *decomp1; + chain_list *decomp2; + char file_line[LONG_LIGNE]; + char file_line1[LONG_LIGNE]; + char file_line2[LONG_LIGNE]; + int msl_line; + char *filename; +} spifile ; + +/* Fonctions d'allocation mémoire pour un circuit */ + +void* spiciralloue __P(( circuit*, int )); +void liberecircuit __P(( circuit* )); + +/* Fonctions pour parser le fichier au format Spice */ + +circuit* lirecircuit __P(( spifile*, ginterf** )); +chain_list* lireligne __P(( spifile* )); +chain_list* decompligne __P(( spifile* )); +noeud* ajoutenoeud __P(( circuit*, char*, spifile* )); +void nomenoeud __P(( circuit*, noeud*, char*, spifile* )); +char* spicenamealloc __P(( circuit*, char* )); +void affvuespice __P(( circuit* )); +float spicefloat __P(( char*, int* )); +chain_list* recupereinterf __P(( char* )); +void loconinterf __P(( lofig_list*, chain_list* )); +ginterf* traiteinclude __P(( ginterf*, char* )); +char* retireextention __P(( char *nom )); +lofig_list* recuperemodele __P(( lofig_list*, char*, chain_list* )); +ginterf* constinterf __P(( circuit*, ginterf* )); +ginterf* spiceloading __P(( lofig_list*, char*, char, ginterf* )); +spifile* spifileopen __P(( char* )); +void spierror __P(( int, char*, int )); + +/* Fonctions pour convertir la vue spice en vue Alliance */ + +void constequi __P(( circuit*, ginterf* )); +void constlofig __P(( circuit*, lofig_list*, ginterf*, char)); +void triecapa __P(( circuit* )); +long float2long __P(( float )); +ptype_list* constphinterf __P(( ptype_list*, ginterf* )); +char* spi_devect __P(( char* )); + +int nodenameisequi __P(( char*, char* )); +void stopchainsepar __P(( char* )); +void spi_dump_equi __P(( char*, ptype_list* )); +void taillevuespice __P(( circuit* )); +#endif