1 /*
2 * DBtechname.c --
3 *
4 * Mapping between tile types and their names.
5 * WARNING: with the exception of DB*TechName{Type,Plane}() and
6 * DB*ShortName(), * the procedures in this file MUST be called
7 * after DBTechFinalType() has been called.
8 *
9 * *********************************************************************
10 * * Copyright (C) 1985, 1990 Regents of the University of California. *
11 * * Permission to use, copy, modify, and distribute this *
12 * * software and its documentation for any purpose and without *
13 * * fee is hereby granted, provided that the above copyright *
14 * * notice appear in all copies. The University of California *
15 * * makes no representations about the suitability of this *
16 * * software for any purpose. It is provided "as is" without *
17 * * express or implied warranty. Export of this software outside *
18 * * of the United States of America may require an export license. *
19 * *********************************************************************
20 */
21
22 #ifndef lint
23 static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/database/DBtechname.c,v 1.3 2008/06/01 18:37:39 tim Exp $";
24 #endif /* not lint */
25
26 #include <stdio.h>
27 #include <string.h>
28 #include <ctype.h>
29
30 #include "tcltk/tclmagic.h"
31 #include "utils/magic.h"
32 #include "utils/geometry.h"
33 #include "utils/utils.h"
34 #include "tiles/tile.h"
35 #include "utils/hash.h"
36 #include "database/database.h"
37 #include "database/databaseInt.h"
38 #include "utils/tech.h"
39 #include "textio/textio.h"
40 #include "utils/malloc.h"
41
42
43 /*
44 * ----------------------------------------------------------------------------
45 *
46 * DBTechNameType --
47 *
48 * Map from a type name into a type number. If the type name has
49 * the form "<type>/<plane>" and <type> is a contact, then the
50 * type returned is the image of the contact on <plane>. Of
51 * course, in this case, <type> must have an image on <plane>.
52 *
53 * Results:
54 * Type number. A value of -2 indicates that the type name was
55 * unknown; -1 indicates that it was ambiguous.
56 *
57 * Side effects:
58 * None.
59 *
60 * ----------------------------------------------------------------------------
61 */
62
63 TileType
DBTechNameType(typename)64 DBTechNameType(typename)
65 char *typename; /* The name of the type */
66 {
67 char *slash;
68 TileType type;
69 int plane;
70 LayerInfo *lp;
71
72 slash = strchr(typename, '/');
73 if (slash != NULL) *slash = 0;
74 type = (TileType)(spointertype) dbTechNameLookup(typename, &dbTypeNameLists);
75 if (type < 0)
76 {
77 /* Check against the alias table. However, any specified alias */
78 /* must point to a SINGLE tile type, or we treat it as */
79 /* ambiguous. */
80
81 HashEntry *he;
82 TileTypeBitMask *bitmask;
83 TileType ttest;
84
85 he = HashLookOnly(&DBTypeAliasTable, typename);
86 if (he)
87 {
88 bitmask = (TileTypeBitMask *)HashGetValue(he);
89 for (type = TT_TECHDEPBASE; type < DBNumUserLayers; type++)
90 if (TTMaskHasType(bitmask, type))
91 {
92 for (ttest = type + 1; ttest < DBNumUserLayers; ttest++)
93 if (TTMaskHasType(bitmask, ttest))
94 {
95 type = -1;
96 break;
97 }
98 break;
99 }
100
101 if (type == DBNumUserLayers)
102 type = -2;
103 }
104 }
105
106 if (slash == NULL) return type;
107 *slash = '/';
108 if (type < 0) return type;
109
110 /* There's a plane qualification. Make sure the type exists */
111 /* on the indicated plane. If not, return an error. */
112
113 plane = (spointertype) dbTechNameLookup(slash + 1, &dbPlaneNameLists);
114 if (plane < 0) return -2;
115
116 lp = &dbLayerInfo[type];
117 if (PlaneMaskHasPlane(lp->l_pmask, plane))
118 return type;
119
120 return -2;
121 }
122
123 TileType
DBTechNameTypeExact(typename)124 DBTechNameTypeExact(typename)
125 char *typename; /* The name of the type */
126 {
127 char *slash;
128 ClientData result;
129
130 slash = strchr(typename, '/');
131 if (slash != NULL) return (TileType)(-1);
132
133 result = dbTechNameLookupExact(typename, &dbTypeNameLists);
134 return (TileType)((spointertype)result);
135 }
136
137 /*
138 *-------------------------------------------------------------------------
139 *
140 * The following returns a bitmask with the appropriate types set for the
141 * typename supplied.
142 *
143 * Results: returns the first type found
144 *
145 * Side Effects: sets bitmask with the appropriate types.
146 *
147 *-------------------------------------------------------------------------
148 */
149
150 TileType
DBTechNameTypes(typename,bitmask)151 DBTechNameTypes(typename, bitmask)
152 char *typename; /* The name of the type */
153 TileTypeBitMask *bitmask;
154 {
155 char *slash;
156 TileType type;
157 int plane;
158 LayerInfo *lp;
159
160 TTMaskZero(bitmask);
161 slash = strchr(typename, '/');
162 if (slash != NULL) *slash = 0;
163 type = (TileType)(spointertype) dbTechNameLookup(typename, &dbTypeNameLists);
164 if (type < 0)
165 {
166 HashEntry *he;
167
168 /* Check against the alias table */
169 he = HashLookOnly(&DBTypeAliasTable, typename);
170 if (he)
171 {
172 TTMaskSetMask(bitmask, (TileTypeBitMask *)HashGetValue(he));
173 for (type = TT_TECHDEPBASE; type < DBNumUserLayers; type++)
174 if (TTMaskHasType(bitmask, type))
175 break;
176
177 if (type == DBNumUserLayers)
178 type = -2;
179 }
180 }
181 else
182 TTMaskSetType(bitmask, type);
183
184 if (slash == NULL)
185 return type;
186 else
187 *slash = '/';
188
189 /* There's a plane qualification. Locate the image. */
190
191 plane = (spointertype) dbTechNameLookup(slash + 1, &dbPlaneNameLists);
192 if (plane < 0) return -2;
193
194 TTMaskAndMask(bitmask, &DBPlaneTypes[plane]);
195
196 /* If the type is no longer in the bitmask, return the first type that is. */
197
198 if (!TTMaskHasType(bitmask, type))
199 for (type = TT_TECHDEPBASE; type < DBNumUserLayers; type++)
200 if (TTMaskHasType(bitmask, type))
201 break;
202
203 return (type < DBNumUserLayers) ? type : -2;
204 }
205
206
207 /*
208 * ----------------------------------------------------------------------------
209 *
210 * DBTechNoisyNameType --
211 *
212 * Map from a type name into a type number, complaining if the type
213 * is unknown.
214 *
215 * Results:
216 * Type number. A value of -2 indicates that the type name was
217 * unknown; -1 indicates that it was ambiguous.
218 *
219 * Side effects:
220 * Prints a diagnostic message if the type name is unknown.
221 *
222 * ----------------------------------------------------------------------------
223 */
224
225 TileType
DBTechNoisyNameType(typename)226 DBTechNoisyNameType(typename)
227 char *typename; /* The name of the type */
228 {
229 TileType type;
230
231 switch (type = DBTechNameType(typename))
232 {
233 case -1:
234 TechError("Ambiguous layer (type) name \"%s\"\n", typename);
235 break;
236 case -2:
237 TechError("Unrecognized layer (type) name \"%s\"\n", typename);
238 break;
239 default:
240 if (type < 0)
241 TechError("Funny type \"%s\" returned %d\n", typename, type);
242 break;
243 }
244
245 return (type);
246 }
247 /*
248 * ----------------------------------------------------------------------------
249 *
250 * DBTechNamePlane --
251 *
252 * Map from a plane name into a plane number.
253 *
254 * Results:
255 * Plane number. A value of -2 indicates that the plane name was
256 * unknown; -1 indicates that it was ambiguous.
257 *
258 * Side effects:
259 * None.
260 *
261 * ----------------------------------------------------------------------------
262 */
263
264 int
DBTechNamePlane(planename)265 DBTechNamePlane(planename)
266 char *planename; /* The name of the plane */
267 {
268 return ((spointertype) dbTechNameLookup(planename, &dbPlaneNameLists));
269 }
270
271 /*
272 * ----------------------------------------------------------------------------
273 *
274 * DBTechNoisyNamePlane --
275 *
276 * Map from a plane name into a plane number, complaining if the plane
277 * is unknown.
278 *
279 * Results:
280 * Plane number. A value of -2 indicates that the plane name was
281 * unknown; -1 indicates that it was ambiguous.
282 *
283 * Side effects:
284 * Prints a diagnostic message if the type name is unknown.
285 *
286 * ----------------------------------------------------------------------------
287 */
288
289 int
DBTechNoisyNamePlane(planename)290 DBTechNoisyNamePlane(planename)
291 char *planename; /* The name of the plane */
292 {
293 int pNum;
294
295 switch (pNum = DBTechNamePlane(planename))
296 {
297 case -1:
298 TechError("Ambiguous plane name \"%s\"\n", planename);
299 break;
300 case -2:
301 TechError("Unrecognized plane name \"%s\"\n", planename);
302 break;
303 }
304
305 return (pNum);
306 }
307
308 /*
309 * ----------------------------------------------------------------------------
310 *
311 * DBTypeShortName --
312 * DBPlaneShortName --
313 *
314 * Return the short name for a type or plane.
315 * The short name is the "official abbreviation" for the type or plane,
316 * identified by a leading '*' in the list of names in the technology
317 * file.
318 *
319 * Results:
320 * Pointer to the primary short name for the given type or plane.
321 * If the type or plane has no official abbreviation, returns
322 * a pointer to the string "???".
323 *
324 * Side effects:
325 * None.
326 *
327 * ----------------------------------------------------------------------------
328 */
329
330 char *
DBTypeShortName(type)331 DBTypeShortName(type)
332 TileType type;
333 {
334 NameList *tbl;
335
336 for (tbl = dbTypeNameLists.sn_next;
337 tbl != &dbTypeNameLists;
338 tbl = tbl->sn_next)
339 {
340 if (tbl->sn_value == (ClientData)(pointertype) type && tbl->sn_primary)
341 return (tbl->sn_name);
342 }
343
344 if (type < 0) return ("ERROR");
345 else if (DBTypeLongNameTbl[type])
346 return (DBTypeLongNameTbl[type]);
347 return ("???");
348 }
349
350 char *
DBPlaneShortName(pNum)351 DBPlaneShortName(pNum)
352 int pNum;
353 {
354 NameList *tbl;
355
356 for (tbl = dbPlaneNameLists.sn_next;
357 tbl != &dbPlaneNameLists;
358 tbl = tbl->sn_next)
359 {
360 if (tbl->sn_value == (ClientData)(pointertype) pNum && tbl->sn_primary)
361 return (tbl->sn_name);
362 }
363
364 if (DBPlaneLongNameTbl[pNum])
365 return (DBPlaneLongNameTbl[pNum]);
366 return ("???");
367 }
368
369 /*
370 * ----------------------------------------------------------------------------
371 *
372 * DBTechTypesToPlanes --
373 *
374 * Convert a TileTypeBitMask into a mask of the planes which may
375 * contain tiles of that type.
376 *
377 * Results:
378 * A mask with bits set for those planes in which tiles of
379 * the types specified by the mask may reside. The mask
380 * is guaranteed only to contain bits corresponding to
381 * paint tile planes.
382 *
383 * Side effects:
384 * None.
385 *
386 * ----------------------------------------------------------------------------
387 */
388
389 PlaneMask
DBTechTypesToPlanes(mask)390 DBTechTypesToPlanes(mask)
391 TileTypeBitMask *mask;
392 {
393 TileType t;
394 PlaneMask planeMask, noCellMask, retMask;
395
396 /* Space tiles are present in all planes but the router plane */
397 noCellMask = ~(PlaneNumToMaskBit(PL_ROUTER));
398 if (TTMaskHasType(mask, TT_SPACE)) {
399 retMask = PlaneNumToMaskBit(DBNumPlanes) - 1;
400 retMask &= noCellMask;
401 return retMask;
402 }
403
404 planeMask = 0;
405 for (t = 0; t < DBNumTypes; t++)
406 if (TTMaskHasType(mask, t))
407 planeMask |= DBTypePlaneMaskTbl[t];
408
409 retMask = planeMask & noCellMask;
410 return retMask;
411 }
412
413
414 /*
415 * ----------------------------------------------------------------------------
416 *
417 * DBTechPrintTypes --
418 *
419 * This routine prints out all the layer names for types defined
420 * in the current technology. If "typename" is non-NULL, then
421 * the "canonical" name of typename is printed.
422 *
423 * Results:
424 * None. In the Tcl version, the layer names are returned as a Tcl list.
425 *
426 * Side effects:
427 * Stuff is printed.
428 *
429 * ----------------------------------------------------------------------------
430 */
431
432 void
DBTechPrintTypes(mask,dolist)433 DBTechPrintTypes(mask, dolist)
434 TileTypeBitMask *mask; /* Print layers defined by this mask. */
435 bool dolist; /* return as a list and don't print aliases */
436 {
437 TileType i;
438 NameList *p;
439 bool firstline = TRUE;
440 bool firstname;
441 DefaultType *dtp;
442 char *keepname;
443
444 if (!dolist) TxPrintf("Layer names are:\n");
445
446 /* List technology-dependent types */
447 for (i = TT_TECHDEPBASE; i < DBNumUserLayers; i++)
448 {
449 if (!TTMaskHasType(mask, i)) continue;
450 firstname = TRUE;
451 for (p = dbTypeNameLists.sn_next; p != &dbTypeNameLists;
452 p = p->sn_next)
453 {
454 /* Ignore aliases */
455 if (p->sn_alias) continue;
456
457 if (((TileType)(spointertype) p->sn_value) == i)
458 {
459 if (dolist)
460 {
461 if (firstname) keepname = p->sn_name;
462 else if (strlen(p->sn_name) > strlen(keepname))
463 keepname = p->sn_name;
464 }
465 else
466 {
467 if (firstname) TxPrintf(" %s", p->sn_name);
468 else TxPrintf(" or %s", p->sn_name);
469 }
470 firstname = FALSE;
471 }
472 }
473
474 if (!firstline)
475 {
476 if (dolist)
477 {
478 #ifdef MAGIC_WRAPPER
479 Tcl_AppendResult(magicinterp, " ", (char *)NULL);
480 #else
481 TxPrintf(" ", keepname);
482 #endif
483 }
484 }
485
486 if (dolist)
487 {
488 #ifdef MAGIC_WRAPPER
489 Tcl_AppendResult(magicinterp, keepname, (char *)NULL);
490 #else
491 TxPrintf("%s", keepname);
492 #endif
493 }
494 else TxPrintf("\n");
495
496 firstline = FALSE;
497 }
498
499 /* List built-in types that are normally painted by name */
500 for (dtp = dbTechDefaultTypes; dtp->dt_names; dtp++)
501 {
502 if (!TTMaskHasType(mask, dtp->dt_type)) continue;
503 if (dtp->dt_print)
504 {
505 firstname = TRUE;
506 for (p = dbTypeNameLists.sn_next; p != &dbTypeNameLists;
507 p = p->sn_next)
508 {
509 if (((TileType)(spointertype) p->sn_value) == dtp->dt_type)
510 {
511 if (dolist)
512 {
513 if (firstname) keepname = p->sn_name;
514 else if (strlen(p->sn_name) > strlen(keepname))
515 keepname = p->sn_name;
516 }
517 else
518 {
519 if (firstname) TxPrintf(" %s", p->sn_name);
520 else TxPrintf(" or %s", p->sn_name);
521 }
522 firstname = FALSE;
523 }
524 }
525
526 if (!firstline)
527 {
528 if (dolist)
529 {
530 #ifdef MAGIC_WRAPPER
531 Tcl_AppendResult(magicinterp, " ", (char *)NULL);
532 #else
533 TxPrintf(" ", keepname);
534 #endif
535 }
536 }
537
538 if (dolist)
539 {
540 #ifdef MAGIC_WRAPPER
541 Tcl_AppendResult(magicinterp, keepname, (char *)NULL);
542 #else
543 TxPrintf("%s", keepname);
544 #endif
545 }
546 else TxPrintf("\n");
547
548 firstline = FALSE;
549 }
550 }
551 }
552
553
554 /*
555 * ----------------------------------------------------------------------------
556 *
557 * DBTechNoisyNameMask --
558 *
559 * Parses an argument string that selects a group of layers.
560 * The string may contain one or more layer names separated
561 * by commas. The special layer name of "0" specifies no layer,
562 * it is used as a place holder, e.g., to specify a null
563 * layer list for the CornerTypes field in a drc edge-rule.
564 * In addition, a tilde may be used to indicate
565 * "all layers but", and parentheses may be used for grouping.
566 * Thus ~x means "all layers but x", and ~(x,y),z means "z plus
567 * everything except x and y)". When contacts are specified,
568 * ALL images of the contact are automatically included, unless
569 * a specific plane is indicated in the layer specification
570 * using "/". For example, x/foo refers to the image of contact
571 * "x" on plane "foo". The layer specification may also follow
572 * a parenthesized group. For example, ~(x,y)/foo refers to
573 * all layers on plane "foo" except "x" and "y".
574 *
575 * Magic version 7.3 defines *x to mean "x and all
576 * contact layers containing x as a residue". Thus, for example,
577 * *metal1 expands to m1,pc,ndc,pdc,nsc,psc,m2c,... Because many
578 * connect, cif, extract, and drc rules list all these layers,
579 * the asterisk notation makes the techfile shorter and more
580 * readable.
581 *
582 * Magic version 7.3 also defines a hash table "DBTypeAliasTable"
583 * that allows macros to be embedded in the technology file.
584 * Macros are expanded first, prior to applying the parsing
585 * described above.
586 *
587 * Results:
588 * Returns a plane mask of all the planes specified.
589 *
590 * Side effects:
591 * Error messages are output if layers aren't understood.
592 * Sets the TileTypeBitMask 'mask' to all the layer names indicated.
593 *
594 * ----------------------------------------------------------------------------
595 */
596
597 PlaneMask
DBTechNameMask0(layers,mask,noisy)598 DBTechNameMask0(layers, mask, noisy)
599 char *layers; /* String to be parsed. */
600 TileTypeBitMask *mask; /* Where to store the layer mask. */
601 bool noisy; /* Whether or not to output errors */
602 {
603 char *p, *p2, c;
604 TileTypeBitMask m2; /* Each time around the loop, we will
605 * form the mask for one section of
606 * the layer string.
607 */
608 char save;
609 bool allBut;
610 PlaneMask planemask = 0;
611 TileTypeBitMask *rMask;
612
613 TTMaskZero(mask);
614 p = layers;
615 while (TRUE)
616 {
617 TTMaskZero(&m2);
618
619 c = *p;
620 if (c == 0) break;
621
622 /* Check for a tilde, and remember it in order to do negation. */
623
624 if (c == '~')
625 {
626 allBut = TRUE;
627 p += 1;
628 c = *p;
629 }
630 else allBut = FALSE;
631
632 /* Check for parentheses. If there's an open parenthesis,
633 * find the matching close parenthesis and recursively parse
634 * the string in-between.
635 */
636
637 if (c == '(')
638 {
639 int nesting = 0;
640
641 p += 1;
642 for (p2 = p; ; p2 += 1)
643 {
644 if (*p2 == '(') nesting += 1;
645 else if (*p2 == ')')
646 {
647 nesting -= 1;
648 if (nesting < 0) break;
649 }
650 else if (*p2 == 0)
651 {
652 TechError("Unmatched parenthesis in layer name \"%s\".\n",
653 layers);
654 break;
655 }
656 }
657 save = *p2;
658 *p2 = 0;
659 planemask |= DBTechNameMask0(p, &m2, noisy);
660 *p2 = save;
661 if (save == ')') p = p2 + 1;
662 else p = p2;
663 }
664 else
665 {
666 TileType t, rtype;
667 bool allResidues = FALSE;
668
669 /* No parenthesis, so just parse off a single name. Layer
670 * name "0" corresponds to no layers at all.
671 */
672
673 for (p2 = p; ; p2++)
674 {
675 c = *p2;
676 if ((c == '/') || (c == ',') || (c == 0)) break;
677 }
678 if (p2 == p)
679 {
680 TechError("Missing layer name in \"%s\".\n", layers);
681 }
682 else if (strcmp(p, "0") != 0)
683 {
684 HashEntry *he;
685
686 save = *p2;
687 *p2 = '\0';
688
689 /* Check the alias table for macro definitions */
690 he = HashLookOnly(&DBTypeAliasTable, p);
691 if (he)
692 {
693 TileTypeBitMask *amask;
694 amask = (TileTypeBitMask *)HashGetValue(he);
695 TTMaskSetMask(&m2, amask);
696 }
697 else
698 {
699 /* Check for asterisk notation, meaning to include */
700 /* all types which have this type as a residue. */
701 if (*p == '*')
702 {
703 allResidues = TRUE;
704 p++;
705 }
706
707 if (noisy)
708 t = DBTechNoisyNameType(p);
709 else
710 t = DBTechNameType(p);
711 if (t >= 0)
712 m2 = DBLayerTypeMaskTbl[t];
713
714 /* Include all types which have t as a residue */
715
716 if (allResidues)
717 for (rtype = TT_TECHDEPBASE; rtype < DBNumUserLayers; rtype++)
718 {
719 rMask = DBResidueMask(rtype);
720 if (TTMaskHasType(rMask, t))
721 TTMaskSetType(&m2, rtype);
722 }
723
724 /* Include all stacking types which have t as a residue */
725 /* (this is done regardless of the presence of "*") */
726
727 for (rtype = DBNumUserLayers; rtype < DBNumTypes; rtype++)
728 {
729 rMask = DBResidueMask(rtype);
730 if (TTMaskIntersect(rMask, &m2))
731 TTMaskSetType(&m2, rtype);
732 }
733 }
734 *p2 = save;
735 }
736 p = p2;
737 }
738
739 /* Now negate the layers, if that is called for. */
740
741 if (allBut) TTMaskCom(&m2);
742
743 /* Restrict to a single plane, if that is called for. */
744
745 if (*p == '/')
746 {
747 int plane;
748
749 p2 = p+1;
750 while ((*p2 != 0) && (*p2 != ',')) p2 += 1;
751 save = *p2;
752 *p2 = 0;
753 if (noisy)
754 plane = DBTechNoisyNamePlane(p+1);
755 else
756 plane = DBTechNamePlane(p+1);
757 *p2 = save;
758 p = p2;
759 if (plane > 0)
760 {
761 TTMaskAndMask(&m2, &DBPlaneTypes[plane]);
762 planemask = PlaneNumToMaskBit(plane);
763 }
764 }
765 else
766 {
767 TileType t;
768
769 for (t = TT_TECHDEPBASE; t < DBNumUserLayers; t++)
770 if (TTMaskHasType(&m2, t))
771 planemask |= DBTypePlaneMaskTbl[t];
772 }
773
774 TTMaskSetMask(mask, &m2);
775 while (*p == ',') p++;
776 }
777
778 /* If there are no types, or if "space" is the only type, then */
779 /* return a full planemask */
780
781 if ((TTMaskIsZero(mask) || TTMaskEqual(mask, &DBSpaceBits)) &&
782 (planemask == (PlaneMask)0))
783 planemask = DBTypePlaneMaskTbl[TT_SPACE];
784
785 return planemask;
786 }
787
788 /* Wrappers for DBTechNameMask0() */
789
790 PlaneMask
DBTechNoisyNameMask(layers,mask)791 DBTechNoisyNameMask(layers, mask)
792 char *layers; /* String to be parsed. */
793 TileTypeBitMask *mask; /* Where to store the layer mask. */
794 {
795 return DBTechNameMask0(layers, mask, TRUE);
796 }
797
798 PlaneMask
DBTechNameMask(layers,mask)799 DBTechNameMask(layers, mask)
800 char *layers; /* String to be parsed. */
801 TileTypeBitMask *mask; /* Where to store the layer mask. */
802 {
803 return DBTechNameMask0(layers, mask, FALSE);
804 }
805