From 999cb88bff638e98a7c2491ef468975e410d074f Mon Sep 17 00:00:00 2001 From: Frederic Petrot Date: Thu, 14 Mar 2002 13:47:47 +0000 Subject: [PATCH] Importing MBKMG sources into the new CVS tree --- alliance/src/mbkmg/Makefile.am | 1 + alliance/src/mbkmg/configure.in | 54 +++ alliance/src/mbkmg/src/Makefile.am | 8 + alliance/src/mbkmg/src/mbk2mg.c | 506 +++++++++++++++++++++++ alliance/src/mbkmg/src/mg2mbk_l.l | 161 ++++++++ alliance/src/mbkmg/src/mg2mbk_y.y | 625 +++++++++++++++++++++++++++++ alliance/src/mbkmg/src/mmg.h | 23 ++ 7 files changed, 1378 insertions(+) create mode 100644 alliance/src/mbkmg/Makefile.am create mode 100644 alliance/src/mbkmg/configure.in create mode 100644 alliance/src/mbkmg/src/Makefile.am create mode 100644 alliance/src/mbkmg/src/mbk2mg.c create mode 100644 alliance/src/mbkmg/src/mg2mbk_l.l create mode 100644 alliance/src/mbkmg/src/mg2mbk_y.y create mode 100644 alliance/src/mbkmg/src/mmg.h diff --git a/alliance/src/mbkmg/Makefile.am b/alliance/src/mbkmg/Makefile.am new file mode 100644 index 00000000..af437a64 --- /dev/null +++ b/alliance/src/mbkmg/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = src diff --git a/alliance/src/mbkmg/configure.in b/alliance/src/mbkmg/configure.in new file mode 100644 index 00000000..2c5991f1 --- /dev/null +++ b/alliance/src/mbkmg/configure.in @@ -0,0 +1,54 @@ +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/14 13:47:47 fred Exp $ +dnl +dnl +AC_INIT(src/mbk2mg.c) +AM_INIT_AUTOMAKE(mbkmg, 1.0) +AC_PROG_INSTALL +AC_PROG_CC +AC_PROG_YACC +AM_PROG_LEX +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/mbkmg/src/Makefile.am b/alliance/src/mbkmg/src/Makefile.am new file mode 100644 index 00000000..3638e44f --- /dev/null +++ b/alliance/src/mbkmg/src/Makefile.am @@ -0,0 +1,8 @@ +lib_LIBRARIES = libMmg.a +libMmg_a_SOURCES = mbk2mg.c mg2mbk_y.y mg2mbk_l.l mmg.h +CLEANFILES = mg2mbk_y.c mg2mbk_y.h mg2mbk_l.c + +mg2mbk_y.c mg2mbk_y.h : $(srcdir)/mg2mbk_y.y + $(YACC) -d $(YFLAGS) $(srcdir)/mg2mbk_y.y && sed -e "s/yy/mgn/g" -e "s/YY/MGN/g" y.tab.c > mg2mbk_y.c && sed -e "s/yy/mgn/g" -e "s/YY/MGN/g" y.tab.h > mg2mbk_y.h +mg2mbk_l.c : $(srcdir)/mg2mbk_l.l mg2mbk_y.h + $(LEX) -t $(srcdir)/mg2mbk_l.l | sed -e "s/yy/mgn/g" -e "s/YY/MGN/g" > mg2mbk_l.c diff --git a/alliance/src/mbkmg/src/mbk2mg.c b/alliance/src/mbkmg/src/mbk2mg.c new file mode 100644 index 00000000..779bff40 --- /dev/null +++ b/alliance/src/mbkmg/src/mbk2mg.c @@ -0,0 +1,506 @@ +/* + * 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. + */ + +/******************************************************************************* +* version 1.1 : mbk2mg or how to translate symbolic leaf cells to modgen format* +* Written by Frederic Petrot, to be used on leafs cells for idps generators * +* This update uses macros for contacts and transistors as described in * +* idps.atoms * +* * +* version 1.2 : now includes instances also * +* * +* e-mail : cao-vlsi@masi.ibp.fr * +* * +* version : 1.2 * +* date : 22/01/92 * +*******************************************************************************/ + +#include +#include +#include +#include + +static float RTrans = 1.5; /* o_ps_aa : Poly overlap on Dif */ +static float MWTrans = 1.0; /* w_ps : Min transistor width */ + +static int number; + +static int Ext[LAST_LAYER + 1] = { + /* NWELL */ 0, + /* PWELL */ 0, + /* NTIE */ 1, + /* PTIE */ 1, + /* NDIF */ 1, + /* PDIF */ 1, + /* NTRANS */ 0, /* meant for N transistor grid */ + /* PTRANS */ 0, /* meant for P transistor grid */ + /* POLY */ 1, + /* ALU1 */ 1, + /* ALU2 */ 2, + /* ALU3 */ 2, + /* TPOLY */ 1, + /* TALU1 */ 1, + /* TALU2 */ 2, + /* TALU3 */ 2 }; + +/******************************************************************************* +* Macro * +*******************************************************************************/ +#define HALF(X) ((X) >> 1) + +/******************************************************************************* +* Functions declaration * +*******************************************************************************/ +static void segments(); +static void connectors(); +static void virtualconnectors(); +static void vias(); +static void instances(); +static void abutmentbox(); +static void figure(); + +/******************************************************************************* +* Layers, Vias, Orientation & Gemetrical operation translation table * +*******************************************************************************/ +static char * + busname(name) +char *name; +{ +static char buffer[255]; +char *s, *t; +char one = 1; + + if (!name || *name == '*') + return NULL; + + s = name; + t = buffer; + while (*s) { + if (*s == ' ' || (*s == '_' && !one)) + if (one) { + *t++ = '['; + s++; + one = 0; + } else { + *t++ = ']'; + *t++ = '['; + s++; + } + if ((*s == '/' || *s == '_') && !one) { + *t++ = ']'; + one = 1; + } + *t++ = *s++; + } + if (!one) + *t++ = ']'; + *t = '\0'; + return buffer; +} + +static char * +layer(mbk_layer) +char mbk_layer; +{ +static char *mg_layer[] = { + /* NWELL */ "nw", + /* PWELL */ "pw", + /* NTIE */ "xn", + /* PTIE */ "xp", + /* NDIF */ "nn", + /* PDIF */ "pp", + /* NTRANS */ "NULL", + /* PTRANS */ "NULL", + /* POLY */ "ps", + /* ALU1 */ "m1", + /* ALU2 */ "m2", + /* ALU3 */ "NULL", + /* TPOLY */ "NULL", + /* TALU1 */ "am1", + /* TALU2 */ "am2", + /* TALU3 */ "NULL" + }; + return mg_layer[(int)mbk_layer]; +} + +static char * + via(mbk_via) +char mbk_via; +{ +static char *mg_via[] = { + /* CONT_POLY */ "cops", + /* CONT_VIA */ "pvia", + /* CONT_DIFN */ "con", + /* CONT_DIFP */ "cop", + /* CONT_BODY_N */ "conw", + /* CONT_BODY_P */ "copw", + /* C_X_N */ "cxn", + /* C_X_P */ "cxp", + /* CONT_VIA2 */ "NULL" + }; + return mg_via[(int)mbk_via]; +} + +static char * + orient(face) +char face; +{ + switch (face) { + case NORTH : + return "top"; + case SOUTH : + return "bottom"; + case EAST : + return "right"; + case WEST : + return "left"; + default : + return "allside"; + } +} + +static char * + geop(trsf, s) +char trsf; +char **s; +{ + + switch (trsf) { + case NOSYM : + *s = "ll"; + return NULL; + case SYM_X : + *s = "lr"; + return "my"; + case SYM_Y : + *s = "ul"; + return "mx"; + case SYMXY : + *s = "ur"; + return "mx my"; + case ROT_P : + *s = "ul"; + return "r 90"; + case ROT_M : + *s = "lr"; + return "r 270"; + case SY_RP : + *s = "ll"; + return "mx r 90"; + case SY_RM : + *s = "ur"; + return "mx r 270"; + default : + fflush(stdout); + fprintf(stderr, "Unknown geometrical operation\n"); + exit(1); + } +} + +void + mgnsavephfig(Cell) +phfig_list *Cell; +{ +chain_list *Model; +char *CellName; +int i; +FILE *file; +static int notfirst; + + if (!notfirst) { + for (i = 0; i < LAST_LAYER + 1; i++) + Ext[i] = HALF(Ext[i] * SCALE_X); + notfirst++; + } + + CellName = Cell->NAME; + if ((file = mbkfopen(CellName, "mg", WRITE_TEXT)) == NULL) { + fflush(stdout); + fprintf(stderr, "Can't open %s.%s for writing\n", CellName, "mg"); + exit(1); + } + Model = Cell->MODELCHAIN; + + fputs("/", file); + for (i = 1; i < 80; i++) + fputs("*", file); + fputs("\n", file); + i = fprintf(file, "* file %s.mg has been generated by mbk2mg translator", + CellName); + for (; i < 79; i++) + fputs(" ", file); + fputs("*\n", file); + i = fprintf(file, + "* for cao-vlsi generators in order to fit IDPS standard modgen"); + for (; i < 79; i++) + fputs(" ", file); + fputs("*\n", file); + for (i = 0; i < 79; i++) + fputs("*", file); + fputs("/\n", file); + fprintf(file, "#ifndef BULLATOMS\n"); + fprintf(file, "#define BULLATOMS\n"); + fprintf(file, "#include \"%s/tech/bull.atoms\"\n", mbkgetenv("MODGEN")); + fprintf(file, "#endif\n"); + + while (Model) { + fprintf(file, "#include \"%s\"\n", + filepath((char *)Model->DATA, "mg")); + Model = Model->NEXT; + } + /* last figure : + this is the real one, boys. */ + figure(file, Cell); +} + +static void + rect(file, mg_layer, x0, y0, x1, y1) +FILE *file; +char *mg_layer; +long x0, y0, x1, y1; +{ + + if (!strcmp(mg_layer, "NULL")) + return; + fprintf(file, "\tra(%s, %.2f, %.2f, %.2f, %.2f);\n", + mg_layer, (float)x0 / SCALE_X, (float)x1 / SCALE_X, + (float)y0 / SCALE_X, (float)y1 / SCALE_X); +} + +static void + figure(file, Cell) +FILE *file; +phfig_list *Cell; +{ + fprintf(file, "\ncell %s\n{\n", Cell->NAME); + abutmentbox(file, Cell); + connectors(file, Cell->PHCON); + virtualconnectors(file, Cell->PHREF); + instances(file, Cell->PHINS); + segments(file, Cell->PHSEG); + vias(file, Cell->PHVIA); + fputs("}\n", file); +} + +static void + abutmentbox(file, Cell) +FILE *file; +phfig_list *Cell; +{ + rect(file, "zd", Cell->XAB1, Cell->YAB1, Cell->XAB2, Cell->YAB2); + fprintf(file, "\tterminal ll (WIDTH = 1.00) left zd at (%.2f, %.2f);\n", + (float)Cell->XAB1/SCALE_X, (float)Cell->YAB1/SCALE_X); + fprintf(file, "\tterminal lr (WIDTH = 1.00) right zd at (%.2f, %.2f);\n", + (float)Cell->XAB2/SCALE_X, (float)Cell->YAB1/SCALE_X); + fprintf(file, "\tterminal ul (WIDTH = 1.00) left zd at (%.2f, %.2f);\n", + (float)Cell->XAB1/SCALE_X, (float)Cell->YAB2/SCALE_X); + fprintf(file, "\tterminal ur (WIDTH = 1.00) right zd at (%.2f, %.2f);\n", + (float)Cell->XAB2/SCALE_X, (float)Cell->YAB2/SCALE_X); +} + +static void + segments(file, HeadOfList) +FILE *file; +phseg_list *HeadOfList; +{ +register phseg_list *Ptr; +register long Xbl, Ybl, Xtr, Ytr; /* bl : bottom left, tr : top right */ +register long Twidth, Tlenght; +register long Xcenter, Ycenter; + + for (Ptr = HeadOfList; Ptr; Ptr = Ptr->NEXT) { + if (Ptr->TYPE == LEFT || Ptr->TYPE == RIGHT) { + switch (Ptr->LAYER) { + case NTRANS : + case PTRANS : + Xbl = Ptr->X1; + Ybl = Ptr->Y1; + Xtr = Ptr->X2; + Twidth = Xtr - Xbl - 2 * (int)((RTrans) * SCALE_X); + Tlenght = MWTrans * Ptr->WIDTH; + Xcenter = Xbl + HALF(Xtr - Xbl); + Ycenter = Ybl; + + (void)fprintf(file,"\tplace x%x$ = ", number++); + (void)fprintf(file,"%s(%.2f, %.2f) ", + Ptr->LAYER == NTRANS ? "ntr" : "ptr", + (float)Twidth / SCALE_X, + (float)Tlenght / SCALE_X); + (void)fprintf(file,"at (%.2f,%.2f);\n", + (float)Xcenter / SCALE_X, + (float)Ycenter / SCALE_X); + break; + case TPOLY : + case TALU3 : + case ALU3 : + break; + default : + (void)fprintf(file, + "\tstretch(%s, %.2f, %s, %.2f, %.2f, %.2f, %.2f);\n", + layer(Ptr->LAYER), + (float)Ptr->WIDTH / SCALE_X, "hor", + (float)(Ptr->X1 - Ext[(int)Ptr->LAYER]) / SCALE_X, + (float)Ptr->Y1 / SCALE_X, + (float)(Ptr->X2 + Ext[(int)Ptr->LAYER]) / SCALE_X, + (float)Ptr->Y2 / SCALE_X); + } + } else { + switch (Ptr->LAYER) { + case NTRANS : + case PTRANS : + Xbl = Ptr->X1; + Ybl = Ptr->Y1; + Ytr = Ptr->Y2; + Twidth = Ytr - Ybl - 2 * (int)((RTrans) * SCALE_X); + Tlenght = MWTrans * Ptr->WIDTH; + Xcenter = Xbl; + Ycenter = Ybl + HALF(Ytr - Ybl); + + (void)fprintf(file,"\tplace x%x$ = ", number++); + (void)fprintf(file,"%s(%.2f, %.2f) r 90 ", + Ptr->LAYER == NTRANS ? "ntr" : "ptr", + (float)Twidth / SCALE_X, + (float)Tlenght / SCALE_X); + (void)fprintf(file,"at (%.2f,%.2f);\n", + (float)Xcenter / SCALE_X, + (float)Ycenter / SCALE_X); + break; + case TPOLY : + case TALU3 : + case ALU3 : + break; + default : + (void)fprintf(file, + "\tstretch(%s, %.2f, %s, %.2f, %.2f, %.2f, %.2f);\n", + layer(Ptr->LAYER), (float)Ptr->WIDTH/SCALE_X, "ver", + (float)Ptr->X1 / SCALE_X, + (float)(Ptr->Y1 - Ext[(int)Ptr->LAYER]) / SCALE_X, + (float)Ptr->X2 / SCALE_X, + (float)(Ptr->Y2 + Ext[(int)Ptr->LAYER]) / SCALE_X); + } + } + } +} + +static void + connectors(file, HeadOfList) +FILE *file; +phcon_list *HeadOfList; +{ +register phcon_list *pt; + + for (pt = HeadOfList; pt; pt = pt->NEXT) { + char *l = layer(pt->LAYER); + if (!strcmp("NULL", l)) + continue; + /* text because we don't know how to print anything */ + fprintf(file, "\ttext %s \"%s\" ", l, busname(pt->NAME)); + fprintf(file, "at (%.2f, %.2f);\n", + (float)pt->XCON/SCALE_X, (float)pt->YCON/SCALE_X); + fprintf(file, "\tterminal %s[%ld] ", busname(pt->NAME), pt->INDEX); + fprintf(file, "(WIDTH = %.2f) %s %s ", + (float)pt->WIDTH/SCALE_X, orient(pt->ORIENT), l); + fprintf(file, "at (%.2f, %.2f);\n", + (float)pt->XCON/SCALE_X, (float)pt->YCON/SCALE_X); + } +} + +static void +virtualconnectors(file, HeadOfList) +FILE *file; +phref_list *HeadOfList; +{ +register phref_list *pt; +static refindex; + + for (pt = HeadOfList; pt; pt = pt->NEXT) { + /* text because we don't know how to print anything */ + (void)fprintf(file, "\ttext zd \"%s\" ", busname(pt->NAME)); + (void)fprintf(file, "at (%.2f, %.2f);\n", + (float)pt->XREF / SCALE_X, + (float)pt->YREF / SCALE_X); + /* object itself */ + (void)fprintf(file,"\tplace %s[%d] = ", busname(pt->NAME), refindex++); + (void)fprintf(file,"%s at (%.2f,%.2f);\n", pt->FIGNAME, + (float)pt->XREF / SCALE_X, + (float)pt->YREF / SCALE_X); + } +} + +static void + vias(file, HeadOfViasList) +FILE *file; +phvia_list *HeadOfViasList; +{ +#define SIZE_C_X (5 * SCALE_X) +register phvia_list *ViaPtr; + + for (ViaPtr = HeadOfViasList; ViaPtr; ViaPtr = ViaPtr->NEXT) { + switch (ViaPtr->TYPE) { +#ifdef NOTLABOTEC + case C_X_N : + rect(file, layer(POLY), + ViaPtr->XVIA - HALF(SCALE_X), ViaPtr->YVIA - HALF(SCALE_X), + ViaPtr->XVIA + HALF(SCALE_X), ViaPtr->YVIA + HALF(SCALE_X)); + rect(file, layer(NDIF), + ViaPtr->XVIA - HALF(SIZE_C_X), ViaPtr->YVIA - HALF(SIZE_C_X), + ViaPtr->XVIA + HALF(SIZE_C_X), ViaPtr->YVIA + HALF(SIZE_C_X)); + continue; + case C_X_P : + rect(file, layer(POLY), + ViaPtr->XVIA - HALF(SCALE_X), ViaPtr->YVIA - HALF(SCALE_X), + ViaPtr->XVIA + HALF(SCALE_X), ViaPtr->YVIA + HALF(SCALE_X)); + rect(file, layer(PDIF), + ViaPtr->XVIA - HALF(SIZE_C_X), ViaPtr->YVIA - HALF(SIZE_C_X), + ViaPtr->XVIA + HALF(SIZE_C_X), ViaPtr->YVIA + HALF(SIZE_C_X)); + continue; +#endif + default : + (void)fprintf(file,"\tplace %s%d = ", via(ViaPtr->TYPE), number++); + (void)fprintf(file,"%s at (%.2f,%.2f);\n", via(ViaPtr->TYPE), + (float)ViaPtr->XVIA / SCALE_X, + (float)ViaPtr->YVIA / SCALE_X); + } + } +} + +static void + instances(file, List) +FILE *file; +phins_list *List; +{ +register phins_list *insPtr; +char *trsf, *corner; + + for (insPtr = List; insPtr; insPtr = insPtr->NEXT) { + trsf = geop(insPtr->TRANSF, &corner); + (void)fprintf(file,"\tplace %s.%s = ", insPtr->INSNAME, corner); + if (trsf) + (void)fprintf(file,"%s %s ", insPtr->FIGNAME, trsf); + else + (void)fprintf(file,"%s ", insPtr->FIGNAME); + (void)fprintf(file,"at (%.2f,%.2f);\n", + (float)insPtr->XINS / SCALE_X, + (float)insPtr->YINS / SCALE_X); + } +} diff --git a/alliance/src/mbkmg/src/mg2mbk_l.l b/alliance/src/mbkmg/src/mg2mbk_l.l new file mode 100644 index 00000000..d1be2758 --- /dev/null +++ b/alliance/src/mbkmg/src/mg2mbk_l.l @@ -0,0 +1,161 @@ +%{ +/* + * 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. + */ + /* + * Parsing Philips modgen format, done during the IDPS project. + * Author: Frédéric Pétrot + */ + +#include +#include +#include +#include "mg2mbk_y.h" +static void zweep(); +extern char *filenameforlex(); +/* change lex input routine to a non case sensitive one */ +#ifdef FLEX_SCANNER +#ifdef YY_INPUT +#undef YY_INPUT +#endif +#define YY_INPUT(buf,result,max_size) \ + do { \ + int c = getc(yyin); \ + result = (c == EOF) ? YY_NULL \ + : (buf[0] = isupper(c) ? tolower(c) : c, 1); \ + } while(0) + +int yylineno; +#else /* using lex, for sure */ +#ifdef input +#undef input +#endif +#define input() (((yytchar = yysptr > yysbuf ? U(*--yysptr) \ + : getc(yyin)) == 10 ?(yylineno++,yytchar) \ + : yytchar) == EOF ? 0 \ + : isupper(yytchar) ? tolower(yytchar) \ + : yytchar) +#endif +%} + +cset [a-zA-Z_/] +digit [0-9] +sign [-+] +blank [ \t]* +ident {cset}({cset}|{digit}|\[{digit}+\]|\.|$)* +fp {sign}?{digit}*\.?{digit}+ + +%% +{blank} {} +\n { +#ifdef FLEX_SCANNER + yylineno++; +#endif + } +\/\* {zweep('/');} +\# {zweep('\n');} +property {zweep('}');} +node {zweep('}');} +text {zweep(';');} +constraint {zweep(';');} +cell {return CELL;} +place {return PLACE;} +terminal {return TERMINAL;} +ra {return RA;} +stretch {return STRETCH;} +wire {return WIRE;} +width {return MWIDTH;} +hor {return HORIZ;} +ver {return VERTI;} +left {return MLEFT;} +right {return MRIGHT;} +top {return MTOP;} +bottom {return MBOTTOM;} +at {return AT;} +mx {return MX;} +my {return MY;} +r {return R;} +ntr {return NTR;} +ptr {return PTR;} +cop {return COP;} +con {return CON;} +cops {return COPS;} +copw {return COPW;} +conw {return CONW;} +pvia {return PVIA;} +cxn {return CXN;} +cxp {return CXP;} +"=" {return '=';} +"{" {return '{';} +"}" {return '}';} +"(" {return '(';} +")" {return ')';} +"," {return ',';} +";" {return ';';} +{ident} { yylval.s = mbkstrdup(yytext); + return STRING;} +{fp} {float f; + sscanf(yytext, "%f", &f); + yylval.n = (long)(f * SCALE_X); +#ifdef GRIDDED + yylval.n *= 2; +#endif + return NUM;} +%% + +int yywrap() +{ + return 1; +} + +static void zweep(find_it) +char find_it; +{ +char c; + + while (1) { + if ((c = input()) == 0) { + (void)fprintf(stderr, "reached EOF before expected end line %d\n", + yylineno); + exit(12); + } + /* special case for comments */ + if (c == '*') + if (find_it == '/') + if ((c = input()) == 0) { + (void)fprintf(stderr, + "reached EOF before expected end of comment\n"); + exit(12); + } + if (c == find_it) + return; + } +} + +int yyerror(s) +char *s; +{ + fflush(stdout); + fprintf(stderr, "modgen parser : syntax error line %d on %s file %s\n", + yylineno, yytext, filenameforlex()); + exit(13); +} diff --git a/alliance/src/mbkmg/src/mg2mbk_y.y b/alliance/src/mbkmg/src/mg2mbk_y.y new file mode 100644 index 00000000..65115e11 --- /dev/null +++ b/alliance/src/mbkmg/src/mg2mbk_y.y @@ -0,0 +1,625 @@ +/* + * 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. + */ + +/****************************************************************************** +* small modgen parser for absolute placement only * +* no control flow statement allowed, nor fancy stuff. * +* Written By Frederic Petrot, petrot@masi.ibp.fr for Masi/cao-vlsi team * +* Done for the IDPS project * +******************************************************************************/ +%{ +#include +#include +#include +#include +#define MAXLAYER (LAST_LAYER + 1) + +static phfig_list *mgleaf; /* modgen leaf cell parsed */ +static char mbk_layer(); +static char *checkinsname(); +static char *checkconname(); +static char *checkrefname(); +static chain_list *pl; +static int Extension[MAXLAYER] = { + /* NWELL */ 0, + /* PWELL */ 0, + /* NTIE */ 1, + /* PTIE */ 1, + /* NDIF */ 1, + /* PDIF */ 1, + /* NTRANS */ 0, /* meant for N transistor grid */ + /* PTRANS */ 0, /* meant for P transistor grid */ + /* POLY */ 1, + /* ALU1 */ 1, + /* ALU2 */ 2, + /* ALU3 */ 2, + /* TPOLY */ 1, + /* TALU1 */ 1, + /* TALU2 */ 2, + /* TALU3 */ 2 }; + +#define O_PS_AA 1.5 +#define O_AA_PS 2 + +#ifdef GRIDDED +#define TWO 2 +#else +#define TWO 1 +#endif + +/* note : + All STRINGs are allocated using mbkstrdup since the pointer to yytext + will change when more than a STRING is used in the grammar. + So all STRINGs are freed once used. */ + +%} + +%union { + char *s; + long n; + struct pxy { + long x; + long y; + } *p; +} + +%token CELL +%token PLACE +%token TERMINAL +%token RA +%token STRETCH +%token WIRE +%token MWIDTH +%token HORIZ +%token VERTI +%token MLEFT +%token MRIGHT +%token MTOP +%token MBOTTOM +%token AT +%token MX +%token MY +%token R +%token NTR +%token PTR +%token COP +%token CON +%token COPS +%token COPW +%token CONW +%token PVIA +%token CXN +%token CXP +%token STRING +%token NUM + +%type

point +%type STRING +%type NUM +%type face +%type dir +%type op + +%start design + +%% +design : cells + ; + +cells : leafcell + | cells leafcell + ; + +leafcell : CELL STRING '{' lines '}' + { + mbkfree($2); + } + ; + +lines : line + | line lines + ; + +line : PLACE STRING '=' elm ';' + { + mbkfree($2); + } + | PLACE STRING '=' STRING op AT '(' point ')' ';' + { + if (!strcmp($4, "ref_ref") || !strcmp($4, "ref_con")) + addphref(mgleaf, $4, checkrefname($2), $8->x, $8->y); + else /* unknown internally! */ + addphins(mgleaf, $4, checkinsname($2), $5, $8->x, $8->y); + mbkfree($2); + mbkfree($4); + mbkfree($8); + } + | elm ';' + ; + +elm : RA '(' STRING ',' point ',' point ')' + { + if (strncmp($3, "zd", 2)) { + fprintf(stderr, "modgen parser warning : ra not for ab box\n"); + /* exit(18); */ + } else + defab(mgleaf, $5->x, $7->x, $5->y, $7->y); + mbkfree($3); + mbkfree($5); + mbkfree($7); + } + | TERMINAL STRING '(' MWIDTH '=' NUM ')' face STRING AT '(' point ')' + { + if (strcmp($2, "ul") && strcmp($2, "ur") + && strcmp($2, "lr") && strcmp($2, "ll")) + addphcon(mgleaf, (char)$8, checkconname($2), + $12->x, $12->y, mbk_layer($9), $6); + mbkfree($2); + mbkfree($9); + mbkfree($12); + } + | STRETCH '(' STRING ',' NUM ',' dir ',' point ',' point ')' + { + char layer = mbk_layer($3); + int x1 = $9->x, y1 = $9->y, x2 = $11->x, y2 = $11->y; + + mbkfree($3); + mbkfree($9); + mbkfree($11); + if ($7 == VERTI) { + if (y2 > y1) { + y2 -= Extension[(int)layer] * SCALE_X * TWO / 2; + y1 += Extension[(int)layer] * SCALE_X * TWO / 2; + } else { + y2 += Extension[(int)layer] * SCALE_X * TWO / 2; + y1 -= Extension[(int)layer] * SCALE_X * TWO / 2; + } + } else { + if (x2 > x1) { + x2 -= Extension[(int)layer] * SCALE_X * TWO / 2; + x1 += Extension[(int)layer] * SCALE_X * TWO / 2; + } else { + x2 += Extension[(int)layer] * SCALE_X * TWO / 2; + x1 -= Extension[(int)layer] * SCALE_X * TWO / 2; + } + } + addphseg(mgleaf, layer, $5, x1, y1, x2, y2, NULL); + } + | WIRE {pl = NULL;} '(' STRING ',' NUM ',' point_list ')' + { + chain_list *l; + int x1, y1, x2, y2; + char layer = mbk_layer($4); + + mbkfree($4); + /* points in inverted order, but doesn't matter, same algo */ + for (l = pl; l->NEXT; l = l->NEXT) { + x1 = (int)((struct pxy *)(l->DATA))->x; + y1 = (int)((struct pxy *)(l->DATA))->y; + x2 = (int)((struct pxy *)(l->NEXT->DATA))->x; + y2 = (int)((struct pxy *)(l->NEXT->DATA))->y; + if (l == pl) { /* last point */ + if (x1 == x2) { + if (y2 > y1) { + y1 += Extension[(int)layer] * SCALE_X * TWO / 2; + } else { + y1 -= Extension[(int)layer] * SCALE_X * TWO / 2; + } + } else { + if (x2 > x1) { + x1 += Extension[(int)layer] * SCALE_X * TWO / 2; + } else { + x1 -= Extension[(int)layer] * SCALE_X * TWO / 2; + } + } + } + if (!l->NEXT->NEXT) { /* first point */ + if (x1 == x2) { + if (y2 > y1) { + y2 -= Extension[(int)layer] * SCALE_X * TWO / 2; + } else { + y2 += Extension[(int)layer] * SCALE_X * TWO / 2; + } + } else { + if (x2 > x1) { + x2 -= Extension[(int)layer] * SCALE_X * TWO / 2; + } else { + x2 += Extension[(int)layer] * SCALE_X * TWO / 2; + } + } + } + addphseg(mgleaf, layer, $6, x1, y1, x2, y2, NULL); + } + } + | NTR '(' NUM ',' NUM ')' op AT '(' point ')' + { /* bounding box of transistors is knows for idps technology */ + float tx; /* used to compute transistor bbox */ + int x1, y1, x2, y2; + + /* +-----------+ when not placed yet */ + tx = ((float)$3 / 2 + (float)O_PS_AA * SCALE_X * TWO); + + switch ((char)$7) { + case NOSYM: + case SYM_X: + case SYM_Y: + case SYMXY: + y2 = y1 = $10->y; + x1 = $10->x + tx; + x2 = $10->x - tx; + addphseg(mgleaf, NTRANS, $5, x1, y1, x2, y2, NULL); + break; + case ROT_P: + case ROT_M: + case SY_RP: + case SY_RM: + x2 = x1 = $10->x; + y1 = $10->y + tx; + y2 = $10->y - tx; + addphseg(mgleaf, NTRANS, $5, x1, y1, x2, y2, NULL); + break; + } + mbkfree($10); + } + | PTR '(' NUM ',' NUM ')' op AT '(' point ')' + { /* bounding box of transistors is knows for idps technology */ + float tx; /* used to compute transistor bbox */ + int x1, y1, x2, y2; + + /* +-----------+ when not placed yet */ + tx = ((float)$3 / 2 + (float)O_PS_AA * SCALE_X * TWO); + + switch ((char)$7) { + case NOSYM: + case SYM_X: + case SYM_Y: + case SYMXY: + y2 = y1 = $10->y; + x1 = $10->x + tx; + x2 = $10->x - tx; + addphseg(mgleaf, PTRANS, $5, x1, y1, x2, y2, NULL); + break; + case ROT_P: + case ROT_M: + case SY_RP: + case SY_RM: + x2 = x1 = $10->x; + y1 = $10->y + tx; + y2 = $10->y - tx; + addphseg(mgleaf, PTRANS, $5, x1, y1, x2, y2, NULL); + break; + } + mbkfree($10); + } + | COP AT '(' point ')' + { + addphvia(mgleaf, CONT_DIF_P, $4->x, $4->y, 0, 0,NULL); + mbkfree($4); + } + | CON AT '(' point ')' + { + addphvia(mgleaf, CONT_DIF_N, $4->x, $4->y, 0, 0,NULL); + mbkfree($4); + } + | COPS AT '(' point ')' + { + addphvia(mgleaf, CONT_POLY, $4->x, $4->y, 0, 0,NULL); + mbkfree($4); + } + | COPW AT '(' point ')' + { + addphvia(mgleaf, CONT_BODY_P, $4->x, $4->y, 0, 0,NULL); + mbkfree($4); + } + | CONW AT '(' point ')' + { + addphvia(mgleaf, CONT_BODY_N, $4->x, $4->y, 0, 0,NULL); + mbkfree($4); + } + | PVIA AT '(' point ')' + { + addphvia(mgleaf, CONT_VIA, $4->x, $4->y, 0, 0,NULL); + mbkfree($4); + } + | CXN AT '(' point ')' + { + addphvia(mgleaf, C_X_N, $4->x, $4->y, 0, 0,NULL); + mbkfree($4); + } + | CXP AT '(' point ')' + { + addphvia(mgleaf, C_X_P, $4->x, $4->y, 0, 0,NULL); + mbkfree($4); + } + ; + +point : NUM ',' NUM + { + struct pxy *pp; + + pp = (struct pxy *)mbkalloc(sizeof(struct pxy)); + pp->x = $1; + pp->y = $3; + $$ = pp; + } + ; + +point_list : point + { + pl = addchain(pl, (void *)$1); + } + | point ',' point_list + { + pl = addchain(pl, (void *)$1); + } + ; + +dir : HORIZ {$$ = (long)HORIZ;} + | VERTI {$$ = (long)VERTI;} + ; + +face : MLEFT {$$ = (long)WEST;} + | MRIGHT {$$ = (long)EAST;} + | MBOTTOM {$$ = (long)SOUTH;} + | MTOP {$$ = (long)NORTH;} + ; + +op : {$$ = (long)NOSYM;} + | MX + {$$ = (long)SYM_Y;} + | MY + {$$ = (long)SYM_X;} + | MX MY + {$$ = (long)SYMXY;} + | R NUM + { + if ($2 / SCALE_X / TWO == 90) + $$ = (long)ROT_P; + if ($2 / SCALE_X / TWO == 270) + $$ = (long)ROT_M; + } + | MX R NUM + { + if ($3 / SCALE_X / TWO == 90) + $$ = (long)SY_RM; + if ($3 / SCALE_X / TWO == 270) + $$ = (long)SY_RP; + } + | MY R NUM + { + if ($3 / SCALE_X / TWO == 90) + $$ = (long)SY_RP; + if ($3 / SCALE_X / TWO == 270) + $$ = (long)SY_RM; + } + ; + +%% +char * + filenameforlex() +{ + return mgleaf->NAME; +} + +void + mgnloadphfig(fig, name, mode) +phfig_list *fig; +char *name; +char mode; +{ +extern FILE *yyin; /* declared in the lex.yy.c by default */ +extern int yylineno; +chain_list *c; + + mgleaf = fig; + if ((yyin = mbkfopen(name, IN_PH, READ_TEXT)) == NULL) { + fflush(stdout); + fprintf(stderr, + "*** mbk error *** modgen parser failed opening file %s.%s\n", + name, IN_PH); + EXIT(1); + } + yylineno = 0; + if (yyparse()) { + fflush(stdout); + fprintf(stderr, + "*** mbk error *** modgen parser failed while reading file %s\n", + filepath(name, IN_PH)); + EXIT(1); + } + (void)fclose(yyin); + /* free : + temporary space for point list must be freed. */ + for (c = pl; c; c = c->NEXT) + mbkfree(c->DATA); + freechain(pl); + /* not so nice : + It would be nice if I'd parse only the necessary stuff when reading + the file, but it's a little painful, and would need some checks + I can't afford right now. */ + if (mode == 'P') { + void **ppobj; + void *next; + + /* delete instances */ + for (ppobj = (void**)&HEAD_PHFIG->PHINS; *ppobj != NULL;) { + next = (void *)((phins_list *)*ppobj)->NEXT; + mbkfree((phins_list *)*ppobj); + *ppobj = next; + } + + /* delete vias */ + for (ppobj = (void**)&HEAD_PHFIG->PHVIA; *ppobj != NULL;) { + next = (void *)((phvia_list *)*ppobj)->NEXT; + mbkfree((phvia_list *)*ppobj); + *ppobj = next; + } + + /* delete segments */ + for (ppobj = (void**)&HEAD_PHFIG->PHSEG; *ppobj != NULL;) { + if (((phseg_list *)*ppobj)->LAYER != TPOLY + && ((phseg_list *)*ppobj)->LAYER != TALU1 + && ((phseg_list *)*ppobj)->LAYER != TALU2 + && ((phseg_list *)*ppobj)->LAYER != TALU3) { + next = (void *)((phseg_list *)*ppobj)->NEXT; + mbkfree((phseg_list *)*ppobj); + *ppobj = next; + } else + ppobj = (void **)&((phseg_list *)*ppobj)->NEXT; + } + } + /* mbk strategy : + only one cell per modgen file. */ + fig = HEAD_PHFIG; +} + +static char + mbk_layer(mg_layer) +char *mg_layer; +{ + if (!strcmp(mg_layer, "nw")) + return NWELL; + if (!strcmp(mg_layer, "pw")) + return PWELL; + if (!strcmp(mg_layer, "xn")) + return NTIE; + if (!strcmp(mg_layer, "xp")) + return PTIE; + if (!strcmp(mg_layer, "nn")) + return NDIF; + if (!strcmp(mg_layer, "pp")) + return PDIF; + if (!strcmp(mg_layer, "ps")) + return POLY; + if (!strcmp(mg_layer, "m1")) + return ALU1; + if (!strcmp(mg_layer, "m2")) + return ALU2; + if (!strcmp(mg_layer, "m3")) + return ALU3; + if (!strcmp(mg_layer, "am1")) + return TALU1; + if (!strcmp(mg_layer, "am2")) + return TALU2; + if (!strcmp(mg_layer, "am3")) + return TALU3; +} + +/* decode a reference name : + xxx[?] -> xxx + xxx[?][??] -> xxx ?, + xxx[?][??][???] -> xxx ?_??. + I always have added an index since here also two instances can't have + the same name. */ + +static char + *checkrefname(name) +char *name; +{ +char *s, *t, *u = NULL; +char one = 0; + + s = t = name; + + while (*t) { + if (*t == '[') + if (!one) { + *t = ' '; + u = s; + one = 1; + } else if (one == 1) { + *t = '_'; + u = s; + one++; + } else { + *t = ' '; + u = s; + } + else if (*t == ']') + if (*(++t) == '\0') /* ok, it's finished */ + goto end; + else if (*t == '[') /* multiple array */ + continue; + *s++ = *t++; + } +end: + *s = '\0'; + /* last vectorized value : + it shall be skipped since I introduced it while driving the file. */ + if (u) + *u = '\0'; + return name; +} + +/* decode a connector name : + in modgen, 'cause we haven't the same conventions, a by me driven + connector has the forms : + xxx[?] -> xxx, where ? is a number, because I suffix all connectors that + way. + xxx[??][?] -> xxx[??], because this was previously a vector. */ + +static char + *checkconname(name) +char *name; +{ +char *s, *t, *u = NULL; + + s = t = name; + while (*t) { + if (*t == '[') { + *t = ' '; + u = s; /* last vector at that time */ + } else if (*t == ']') { + if (*(++t) == '\0') /* ok, it's finished */ + goto end; + else if (*t == '[') /* multiple array */ + continue; + } + *s++ = *t++; + } +end: + *s = '\0'; + /* last vectorized value : + it shall be skipped since I introduced it while driving the file. */ + if (u) + *u = '\0'; + return name; +} + +/* decode an instance name : + in modgen, 'cause we haven't the same conventions, a by me driven + instance has the forms : + xxx.corner + since I arranged to put the corner in such a place that it makes it + automatically good for mbk, I just forgot about the corner. */ + +static char + *checkinsname(name) +char *name; +{ +char *s = name; + + s = strrchr(name, '.'); + *s = '\0'; + return name; +} diff --git a/alliance/src/mbkmg/src/mmg.h b/alliance/src/mbkmg/src/mmg.h new file mode 100644 index 00000000..5ff5bfef --- /dev/null +++ b/alliance/src/mbkmg/src/mmg.h @@ -0,0 +1,23 @@ +/* + * 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. + */ +