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