1 /*
2 * This file is part of the Alliance CAD System
3 * Copyright (C) Laboratoire LIP6 - D�partement ASIM
4 * Universite Pierre et Marie Curie
5 *
6 * Home page : http://www-asim.lip6.fr/alliance/
7 * E-mail : mailto:alliance-users@asim.lip6.fr
8 *
9 * This library is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Library General Public License as published
11 * by the Free Software Foundation; either version 2 of the License, or (at
12 * your option) any later version.
13 *
14 * Alliance VLSI CAD System is distributed in the hope that it will be
15 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17 * Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with the GNU C Library; see the file COPYING. If not, write to the Free
21 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 */
23
24 /*******************************************************************************
25 * version 1.1 : mbk2mg or how to translate symbolic leaf cells to modgen format*
26 * Written by Frederic Petrot, to be used on leafs cells for idps generators *
27 * This update uses macros for contacts and transistors as described in *
28 * idps.atoms *
29 * *
30 * version 1.2 : now includes instances also *
31 * *
32 * e-mail : cao-vlsi@masi.ibp.fr *
33 * *
34 * version : 1.2 *
35 * date : 22/01/92 *
36 *******************************************************************************/
37
38 #include <string.h>
39 #include <stdlib.h>
40 #include <mut.h>
41 #include <mph.h>
42
43 static float RTrans = 1.5; /* o_ps_aa : Poly overlap on Dif */
44 static float MWTrans = 1.0; /* w_ps : Min transistor width */
45
46 static int number;
47
48 static int Ext[LAST_LAYER + 1] = {
49 /* NWELL */ 0,
50 /* PWELL */ 0,
51 /* NTIE */ 1,
52 /* PTIE */ 1,
53 /* NDIF */ 1,
54 /* PDIF */ 1,
55 /* NTRANS */ 0, /* meant for N transistor grid */
56 /* PTRANS */ 0, /* meant for P transistor grid */
57 /* POLY */ 1,
58 /* ALU1 */ 1,
59 /* ALU2 */ 2,
60 /* ALU3 */ 2,
61 /* TPOLY */ 1,
62 /* TALU1 */ 1,
63 /* TALU2 */ 2,
64 /* TALU3 */ 2 };
65
66 /*******************************************************************************
67 * Macro *
68 *******************************************************************************/
69 #define HALF(X) ((X) >> 1)
70
71 /*******************************************************************************
72 * Functions declaration *
73 *******************************************************************************/
74 static void segments();
75 static void connectors();
76 static void virtualconnectors();
77 static void vias();
78 static void instances();
79 static void abutmentbox();
80 static void figure();
81
82 /*******************************************************************************
83 * Layers, Vias, Orientation & Gemetrical operation translation table *
84 *******************************************************************************/
85 static char *
busname(name)86 busname(name)
87 char *name;
88 {
89 static char buffer[255];
90 char *s, *t;
91 char one = 1;
92
93 if (!name || *name == '*')
94 return NULL;
95
96 s = name;
97 t = buffer;
98 while (*s) {
99 if (*s == ' ' || (*s == '_' && !one)) {
100 if (one) {
101 *t++ = '[';
102 s++;
103 one = 0;
104 } else {
105 *t++ = ']';
106 *t++ = '[';
107 s++;
108 }
109 }
110 if ((*s == '/' || *s == '_') && !one) {
111 *t++ = ']';
112 one = 1;
113 }
114 *t++ = *s++;
115 }
116 if (!one)
117 *t++ = ']';
118 *t = '\0';
119 return buffer;
120 }
121
122 static char *
layer(mbk_layer)123 layer(mbk_layer)
124 char mbk_layer;
125 {
126 static char *mg_layer[] = {
127 /* NWELL */ "nw",
128 /* PWELL */ "pw",
129 /* NTIE */ "xn",
130 /* PTIE */ "xp",
131 /* NDIF */ "nn",
132 /* PDIF */ "pp",
133 /* NTRANS */ "NULL",
134 /* PTRANS */ "NULL",
135 /* POLY */ "ps",
136 /* ALU1 */ "m1",
137 /* ALU2 */ "m2",
138 /* ALU3 */ "NULL",
139 /* TPOLY */ "NULL",
140 /* TALU1 */ "am1",
141 /* TALU2 */ "am2",
142 /* TALU3 */ "NULL"
143 };
144 return mg_layer[(int)mbk_layer];
145 }
146
147 static char *
via(mbk_via)148 via(mbk_via)
149 char mbk_via;
150 {
151 static char *mg_via[] = {
152 /* CONT_POLY */ "cops",
153 /* CONT_VIA */ "pvia",
154 /* CONT_DIFN */ "con",
155 /* CONT_DIFP */ "cop",
156 /* CONT_BODY_N */ "conw",
157 /* CONT_BODY_P */ "copw",
158 /* C_X_N */ "cxn",
159 /* C_X_P */ "cxp",
160 /* CONT_VIA2 */ "NULL"
161 };
162 return mg_via[(int)mbk_via];
163 }
164
165 static char *
orient(face)166 orient(face)
167 char face;
168 {
169 switch (face) {
170 case NORTH :
171 return "top";
172 case SOUTH :
173 return "bottom";
174 case EAST :
175 return "right";
176 case WEST :
177 return "left";
178 default :
179 return "allside";
180 }
181 }
182
183 static char *
geop(trsf,s)184 geop(trsf, s)
185 char trsf;
186 char **s;
187 {
188
189 switch (trsf) {
190 case NOSYM :
191 *s = "ll";
192 return NULL;
193 case SYM_X :
194 *s = "lr";
195 return "my";
196 case SYM_Y :
197 *s = "ul";
198 return "mx";
199 case SYMXY :
200 *s = "ur";
201 return "mx my";
202 case ROT_P :
203 *s = "ul";
204 return "r 90";
205 case ROT_M :
206 *s = "lr";
207 return "r 270";
208 case SY_RP :
209 *s = "ll";
210 return "mx r 90";
211 case SY_RM :
212 *s = "ur";
213 return "mx r 270";
214 default :
215 fflush(stdout);
216 fprintf(stderr, "Unknown geometrical operation\n");
217 exit(1);
218 }
219 }
220
221 void
mgnsavephfig(Cell)222 mgnsavephfig(Cell)
223 phfig_list *Cell;
224 {
225 chain_list *Model;
226 char *CellName;
227 int i;
228 FILE *file;
229 static int notfirst;
230
231 if (!notfirst) {
232 for (i = 0; i < LAST_LAYER + 1; i++)
233 Ext[i] = HALF(Ext[i] * SCALE_X);
234 notfirst++;
235 }
236
237 CellName = Cell->NAME;
238 if ((file = mbkfopen(CellName, "mg", WRITE_TEXT)) == NULL) {
239 fflush(stdout);
240 fprintf(stderr, "Can't open %s.%s for writing\n", CellName, "mg");
241 exit(1);
242 }
243 Model = Cell->MODELCHAIN;
244
245 fputs("/", file);
246 for (i = 1; i < 80; i++)
247 fputs("*", file);
248 fputs("\n", file);
249 i = fprintf(file, "* file %s.mg has been generated by mbk2mg translator",
250 CellName);
251 for (; i < 79; i++)
252 fputs(" ", file);
253 fputs("*\n", file);
254 i = fprintf(file,
255 "* for cao-vlsi generators in order to fit IDPS standard modgen");
256 for (; i < 79; i++)
257 fputs(" ", file);
258 fputs("*\n", file);
259 for (i = 0; i < 79; i++)
260 fputs("*", file);
261 fputs("/\n", file);
262 fprintf(file, "#ifndef BULLATOMS\n");
263 fprintf(file, "#define BULLATOMS\n");
264 fprintf(file, "#include \"%s/tech/bull.atoms\"\n", mbkgetenv("MODGEN"));
265 fprintf(file, "#endif\n");
266
267 while (Model) {
268 fprintf(file, "#include \"%s\"\n",
269 filepath((char *)Model->DATA, "mg"));
270 Model = Model->NEXT;
271 }
272 /* last figure :
273 this is the real one, boys. */
274 figure(file, Cell);
275 }
276
277 static void
rect(file,mg_layer,x0,y0,x1,y1)278 rect(file, mg_layer, x0, y0, x1, y1)
279 FILE *file;
280 char *mg_layer;
281 long x0, y0, x1, y1;
282 {
283
284 if (!strcmp(mg_layer, "NULL"))
285 return;
286 fprintf(file, "\tra(%s, %.2f, %.2f, %.2f, %.2f);\n",
287 mg_layer, (float)x0 / SCALE_X, (float)x1 / SCALE_X,
288 (float)y0 / SCALE_X, (float)y1 / SCALE_X);
289 }
290
291 static void
figure(file,Cell)292 figure(file, Cell)
293 FILE *file;
294 phfig_list *Cell;
295 {
296 fprintf(file, "\ncell %s\n{\n", Cell->NAME);
297 abutmentbox(file, Cell);
298 connectors(file, Cell->PHCON);
299 virtualconnectors(file, Cell->PHREF);
300 instances(file, Cell->PHINS);
301 segments(file, Cell->PHSEG);
302 vias(file, Cell->PHVIA);
303 fputs("}\n", file);
304 }
305
306 static void
abutmentbox(file,Cell)307 abutmentbox(file, Cell)
308 FILE *file;
309 phfig_list *Cell;
310 {
311 rect(file, "zd", Cell->XAB1, Cell->YAB1, Cell->XAB2, Cell->YAB2);
312 fprintf(file, "\tterminal ll (WIDTH = 1.00) left zd at (%.2f, %.2f);\n",
313 (float)Cell->XAB1/SCALE_X, (float)Cell->YAB1/SCALE_X);
314 fprintf(file, "\tterminal lr (WIDTH = 1.00) right zd at (%.2f, %.2f);\n",
315 (float)Cell->XAB2/SCALE_X, (float)Cell->YAB1/SCALE_X);
316 fprintf(file, "\tterminal ul (WIDTH = 1.00) left zd at (%.2f, %.2f);\n",
317 (float)Cell->XAB1/SCALE_X, (float)Cell->YAB2/SCALE_X);
318 fprintf(file, "\tterminal ur (WIDTH = 1.00) right zd at (%.2f, %.2f);\n",
319 (float)Cell->XAB2/SCALE_X, (float)Cell->YAB2/SCALE_X);
320 }
321
322 static void
segments(file,HeadOfList)323 segments(file, HeadOfList)
324 FILE *file;
325 phseg_list *HeadOfList;
326 {
327 register phseg_list *Ptr;
328 register long Xbl, Ybl, Xtr, Ytr; /* bl : bottom left, tr : top right */
329 register long Twidth, Tlenght;
330 register long Xcenter, Ycenter;
331
332 for (Ptr = HeadOfList; Ptr; Ptr = Ptr->NEXT) {
333 if (Ptr->TYPE == LEFT || Ptr->TYPE == RIGHT) {
334 switch (Ptr->LAYER) {
335 case NTRANS :
336 case PTRANS :
337 Xbl = Ptr->X1;
338 Ybl = Ptr->Y1;
339 Xtr = Ptr->X2;
340 Twidth = Xtr - Xbl - 2 * (int)((RTrans) * SCALE_X);
341 Tlenght = MWTrans * Ptr->WIDTH;
342 Xcenter = Xbl + HALF(Xtr - Xbl);
343 Ycenter = Ybl;
344
345 (void)fprintf(file,"\tplace x%x$ = ", number++);
346 (void)fprintf(file,"%s(%.2f, %.2f) ",
347 Ptr->LAYER == NTRANS ? "ntr" : "ptr",
348 (float)Twidth / SCALE_X,
349 (float)Tlenght / SCALE_X);
350 (void)fprintf(file,"at (%.2f,%.2f);\n",
351 (float)Xcenter / SCALE_X,
352 (float)Ycenter / SCALE_X);
353 break;
354 case TPOLY :
355 case TALU3 :
356 case ALU3 :
357 break;
358 default :
359 (void)fprintf(file,
360 "\tstretch(%s, %.2f, %s, %.2f, %.2f, %.2f, %.2f);\n",
361 layer(Ptr->LAYER),
362 (float)Ptr->WIDTH / SCALE_X, "hor",
363 (float)(Ptr->X1 - Ext[(int)Ptr->LAYER]) / SCALE_X,
364 (float)Ptr->Y1 / SCALE_X,
365 (float)(Ptr->X2 + Ext[(int)Ptr->LAYER]) / SCALE_X,
366 (float)Ptr->Y2 / SCALE_X);
367 }
368 } else {
369 switch (Ptr->LAYER) {
370 case NTRANS :
371 case PTRANS :
372 Xbl = Ptr->X1;
373 Ybl = Ptr->Y1;
374 Ytr = Ptr->Y2;
375 Twidth = Ytr - Ybl - 2 * (int)((RTrans) * SCALE_X);
376 Tlenght = MWTrans * Ptr->WIDTH;
377 Xcenter = Xbl;
378 Ycenter = Ybl + HALF(Ytr - Ybl);
379
380 (void)fprintf(file,"\tplace x%x$ = ", number++);
381 (void)fprintf(file,"%s(%.2f, %.2f) r 90 ",
382 Ptr->LAYER == NTRANS ? "ntr" : "ptr",
383 (float)Twidth / SCALE_X,
384 (float)Tlenght / SCALE_X);
385 (void)fprintf(file,"at (%.2f,%.2f);\n",
386 (float)Xcenter / SCALE_X,
387 (float)Ycenter / SCALE_X);
388 break;
389 case TPOLY :
390 case TALU3 :
391 case ALU3 :
392 break;
393 default :
394 (void)fprintf(file,
395 "\tstretch(%s, %.2f, %s, %.2f, %.2f, %.2f, %.2f);\n",
396 layer(Ptr->LAYER), (float)Ptr->WIDTH/SCALE_X, "ver",
397 (float)Ptr->X1 / SCALE_X,
398 (float)(Ptr->Y1 - Ext[(int)Ptr->LAYER]) / SCALE_X,
399 (float)Ptr->X2 / SCALE_X,
400 (float)(Ptr->Y2 + Ext[(int)Ptr->LAYER]) / SCALE_X);
401 }
402 }
403 }
404 }
405
406 static void
connectors(file,HeadOfList)407 connectors(file, HeadOfList)
408 FILE *file;
409 phcon_list *HeadOfList;
410 {
411 register phcon_list *pt;
412
413 for (pt = HeadOfList; pt; pt = pt->NEXT) {
414 char *l = layer(pt->LAYER);
415 if (!strcmp("NULL", l))
416 continue;
417 /* text because we don't know how to print anything */
418 fprintf(file, "\ttext %s \"%s\" ", l, busname(pt->NAME));
419 fprintf(file, "at (%.2f, %.2f);\n",
420 (float)pt->XCON/SCALE_X, (float)pt->YCON/SCALE_X);
421 fprintf(file, "\tterminal %s[%ld] ", busname(pt->NAME), pt->INDEX);
422 fprintf(file, "(WIDTH = %.2f) %s %s ",
423 (float)pt->WIDTH/SCALE_X, orient(pt->ORIENT), l);
424 fprintf(file, "at (%.2f, %.2f);\n",
425 (float)pt->XCON/SCALE_X, (float)pt->YCON/SCALE_X);
426 }
427 }
428
429 static void
virtualconnectors(file,HeadOfList)430 virtualconnectors(file, HeadOfList)
431 FILE *file;
432 phref_list *HeadOfList;
433 {
434 register phref_list *pt;
435 static int refindex;
436
437 for (pt = HeadOfList; pt; pt = pt->NEXT) {
438 /* text because we don't know how to print anything */
439 (void)fprintf(file, "\ttext zd \"%s\" ", busname(pt->NAME));
440 (void)fprintf(file, "at (%.2f, %.2f);\n",
441 (float)pt->XREF / SCALE_X,
442 (float)pt->YREF / SCALE_X);
443 /* object itself */
444 (void)fprintf(file,"\tplace %s[%d] = ", busname(pt->NAME), refindex++);
445 (void)fprintf(file,"%s at (%.2f,%.2f);\n", pt->FIGNAME,
446 (float)pt->XREF / SCALE_X,
447 (float)pt->YREF / SCALE_X);
448 }
449 }
450
451 static void
vias(file,HeadOfViasList)452 vias(file, HeadOfViasList)
453 FILE *file;
454 phvia_list *HeadOfViasList;
455 {
456 #define SIZE_C_X (5 * SCALE_X)
457 register phvia_list *ViaPtr;
458
459 for (ViaPtr = HeadOfViasList; ViaPtr; ViaPtr = ViaPtr->NEXT) {
460 switch (ViaPtr->TYPE) {
461 #ifdef NOTLABOTEC
462 case C_X_N :
463 rect(file, layer(POLY),
464 ViaPtr->XVIA - HALF(SCALE_X), ViaPtr->YVIA - HALF(SCALE_X),
465 ViaPtr->XVIA + HALF(SCALE_X), ViaPtr->YVIA + HALF(SCALE_X));
466 rect(file, layer(NDIF),
467 ViaPtr->XVIA - HALF(SIZE_C_X), ViaPtr->YVIA - HALF(SIZE_C_X),
468 ViaPtr->XVIA + HALF(SIZE_C_X), ViaPtr->YVIA + HALF(SIZE_C_X));
469 continue;
470 case C_X_P :
471 rect(file, layer(POLY),
472 ViaPtr->XVIA - HALF(SCALE_X), ViaPtr->YVIA - HALF(SCALE_X),
473 ViaPtr->XVIA + HALF(SCALE_X), ViaPtr->YVIA + HALF(SCALE_X));
474 rect(file, layer(PDIF),
475 ViaPtr->XVIA - HALF(SIZE_C_X), ViaPtr->YVIA - HALF(SIZE_C_X),
476 ViaPtr->XVIA + HALF(SIZE_C_X), ViaPtr->YVIA + HALF(SIZE_C_X));
477 continue;
478 #endif
479 default :
480 (void)fprintf(file,"\tplace %s%d = ", via(ViaPtr->TYPE), number++);
481 (void)fprintf(file,"%s at (%.2f,%.2f);\n", via(ViaPtr->TYPE),
482 (float)ViaPtr->XVIA / SCALE_X,
483 (float)ViaPtr->YVIA / SCALE_X);
484 }
485 }
486 }
487
488 static void
instances(file,List)489 instances(file, List)
490 FILE *file;
491 phins_list *List;
492 {
493 register phins_list *insPtr;
494 char *trsf, *corner;
495
496 for (insPtr = List; insPtr; insPtr = insPtr->NEXT) {
497 trsf = geop(insPtr->TRANSF, &corner);
498 (void)fprintf(file,"\tplace %s.%s = ", insPtr->INSNAME, corner);
499 if (trsf)
500 (void)fprintf(file,"%s %s ", insPtr->FIGNAME, trsf);
501 else
502 (void)fprintf(file,"%s ", insPtr->FIGNAME);
503 (void)fprintf(file,"at (%.2f,%.2f);\n",
504 (float)insPtr->XINS / SCALE_X,
505 (float)insPtr->YINS / SCALE_X);
506 }
507 }
508