1 /*
2 * DBtcontact.c --
3 *
4 * Management of contacts.
5 * This file makes a distinction between the following two terms:
6 *
7 * Layer -- Logical type as specified in "types" section of .tech
8 * file. A layer may consist of many TileTypes, as is the
9 * case when it is a contact.
10 * Type -- TileType stored in a tile
11 *
12 * *********************************************************************
13 * * Copyright (C) 1985, 1990 Regents of the University of California. *
14 * * Permission to use, copy, modify, and distribute this *
15 * * software and its documentation for any purpose and without *
16 * * fee is hereby granted, provided that the above copyright *
17 * * notice appear in all copies. The University of California *
18 * * makes no representations about the suitability of this *
19 * * software for any purpose. It is provided "as is" without *
20 * * express or implied warranty. Export of this software outside *
21 * * of the United States of America may require an export license. *
22 * *********************************************************************
23 */
24
25 #ifndef lint
26 static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/database/DBtcontact.c,v 1.3 2008/09/05 13:56:25 tim Exp $";
27 #endif /* not lint */
28
29 #include <stdio.h>
30 #include <string.h>
31 #include <ctype.h>
32
33 #include "utils/magic.h"
34 #include "utils/geometry.h"
35 #include "utils/utils.h"
36 #include "utils/malloc.h"
37 #include "tiles/tile.h"
38 #include "utils/hash.h"
39 #include "database/database.h"
40 #include "database/databaseInt.h"
41 #include "utils/tech.h"
42 #include "textio/textio.h"
43
44 /* type-to-bitmask conversion (1 bit per entry) */
45 TileTypeBitMask DBLayerTypeMaskTbl[NT];
46
47 /* Filled in after contact types have been generated */
48 TileTypeBitMask DBPlaneTypes[PL_MAXTYPES];
49 TileTypeBitMask DBHomePlaneTypes[PL_MAXTYPES];
50 PlaneMask DBTypePlaneMaskTbl[NT];
51
52 /* --------------------- Data local to this file ---------------------- */
53
54 /* Table of the properties of all layers */
55 LayerInfo dbLayerInfo[NT];
56
57 /* Array of pointers to the entries in above table for contacts only */
58 LayerInfo *dbContactInfo[NT];
59 int dbNumContacts;
60
61 /* Forward declaration */
62 void dbTechMatchResidues();
63 void dbTechAddStackedContacts();
64 int dbTechAddOneStackedContact();
65
66
67 /*
68 * ----------------------------------------------------------------------------
69 *
70 * DBTechInitContact --
71 *
72 * Mark all types as being non-contacts initially.
73 *
74 * Results:
75 * None.
76 *
77 * Side effects:
78 * Initializes dbLayerInfo.
79 *
80 * ----------------------------------------------------------------------------
81 */
82
83 void
DBTechInitContact()84 DBTechInitContact()
85 {
86 TileType t;
87 LayerInfo *lp;
88
89 for (t = 0; t < TT_MAXTYPES; t++)
90 {
91 lp = &dbLayerInfo[t];
92 lp->l_type = t;
93 lp->l_isContact = FALSE;
94 lp->l_pmask = 0;
95 TTMaskZero(&lp->l_residues);
96 TTMaskSetOnlyType(&DBLayerTypeMaskTbl[t], t);
97 }
98
99 dbNumContacts = 0;
100 }
101
102 /*
103 * ----------------------------------------------------------------------------
104 *
105 * DBTechAddContact --
106 *
107 * Add the definition of a new contact type.
108 * The syntax of each line in the "contact" section is:
109 *
110 * contactType res1 res2 [res3...]
111 *
112 * where res1, res2, res3, etc. are the residue types on the planes
113 * connected by the contact. The home plane of the contact (the
114 * plane specified in the "types" section for the type contactType)
115 * must be the lowest-numbered plane in the list of residues. Each
116 * listed residue must be on a different plane. There are no other
117 * restrictions on contacts.
118 *
119 * Magic-7.3 additional syntax:
120 *
121 * stackable type1 [type2 [alias12] [type3 [alias13] ...]]
122 *
123 * where type1 and type2 are contact types, allows type1 and type2
124 * to be drawn on top of one other by generating an extra contact
125 * type to represent the union of type1 and type2 on the shared
126 * plane. If more than two types are specified, then type1 will be
127 * set to be stackable with each of the indicated types. If only
128 * type1 is specified, then type1 will be made stackable with all
129 * other (existing) contact types. Wherever a layer name exists
130 * after a known type that is not a known layer name, it is
131 * considered to be an alias name for the stacked type. e.g.,
132 * "stackable pc via pm12contact" is valid if "pc" and "via" are
133 * defined types. Thie provides compatibility with layout files
134 * created with technology files that explicitly define stacked
135 * contact types, especially those from magic-7.2 and earlier
136 * versions.
137 *
138 * stackable
139 *
140 * allows all contact types to stack, where applicable. This
141 * statement overrides any other "stackable" statement.
142 *
143 * Notes:
144 * All indicated types must have been declared in the "contact"
145 * section prior to use of the "stackable" keyword. The 1- and
146 * 2-argument variants will create stacking types with all
147 * previously-declared contact types.
148 *
149 * Expanded syntax:
150 * Now allows the section "image" with statements "contact" and
151 * "device". Statements beginning with the layer name are
152 * backwardly-compatible with the original syntax. "contact"
153 * statements are equivalent to the original syntax after skipping
154 * the keyword "contact". "device" statements have the same
155 * syntax as the "contact" statement but describe a composite
156 * image such as a transistor or capacitor formed by layers on
157 * different planes.
158 *
159 * Results:
160 * FALSE on error, TRUE if successful.
161 *
162 * Side effects:
163 * Adds the definition of a new contact type.
164 *
165 * ----------------------------------------------------------------------------
166 */
167
168 bool
DBTechAddContact(sectionName,argc,argv)169 DBTechAddContact(sectionName, argc, argv)
170 char *sectionName;
171 int argc;
172 char *argv[];
173 {
174 TileType contactType;
175 int nresidues;
176
177 if ((contactType = DBTechNameType(*argv)) < 0)
178 {
179 if (!strcmp(*argv, "contact") || !strcmp(*argv, "device"))
180 {
181 argc--;
182 argv++;
183 if ((contactType = DBTechNameType(*argv)) < 0)
184 {
185 DBTechNoisyNameType(*argv);
186 return FALSE;
187 }
188 }
189 else if (!strcmp(*argv, "stackable"))
190 {
191 TileType stackType, newType = -1;
192 LayerInfo *lim, *lin;
193
194 if (argc == 1)
195 dbTechAddStackedContacts();
196 else
197 {
198 contactType = DBTechNoisyNameType(*++argv);
199 if (contactType < 0)
200 return FALSE;
201 else if (argc == 2)
202 {
203 int n, result;
204
205 lim = &dbLayerInfo[contactType];
206
207 for (n = 0; n < dbNumContacts; n++)
208 {
209 lin = dbContactInfo[n];
210 if (lim == lin) continue;
211 result = dbTechAddOneStackedContact(lim->l_type, lin->l_type);
212 if (result == -3)
213 return FALSE; /* overran tiletype maximum number */
214 }
215 }
216 else
217 {
218 TileType lastType = TT_SPACE;
219 char *primary;
220
221 while (--argc > 1)
222 {
223 stackType = DBTechNameType(*++argv);
224 if (stackType >= 0)
225 {
226 newType = dbTechAddOneStackedContact(contactType,
227 stackType);
228 if (newType == -1)
229 TechError("Contact types %s and %s do not stack\n",
230 DBTypeLongNameTbl[contactType],
231 DBTypeLongNameTbl[stackType]);
232 lastType = stackType;
233 }
234 else if (lastType >= TT_SPACE)
235 {
236 /* (*argv) becomes an alias name for layer newType */
237 if (newType < 0)
238 TechError("Contact type %s unknown or contact "
239 "missing in stackable statement\n", *argv);
240 else
241 DBTechAddNameToType(*argv, newType, FALSE);
242 lastType = TT_SPACE;
243 }
244 else
245 {
246 DBTechNoisyNameType(*argv);
247 lastType = TT_SPACE;
248 }
249 }
250 }
251 }
252 return TRUE;
253 }
254 else
255 {
256 DBTechNoisyNameType(*argv);
257 return FALSE;
258 }
259 }
260
261 /* Read the contact residues and check them for validity */
262 nresidues = dbTechContactResidues(--argc, ++argv, contactType);
263 if (nresidues < 0)
264 return FALSE;
265
266 /* Remember this as a paintable contact */
267 dbContactInfo[dbNumContacts++] = &dbLayerInfo[contactType];
268
269 return TRUE;
270 }
271
272 /*
273 * ----------------------------------------------------------------------------
274 * dbTechAddStackedContacts --
275 *
276 * Generate new contact types where existing contact types share a
277 * residue. These contact types will exist only on the planes
278 * shared between the two contact types. This method allows contacts
279 * to be stacked without requiring a declaration of every combination
280 * in the techfile.
281 *
282 * When searching for contact types with shared planes, we want to
283 * make sure that no existing contact exactly matches the stacked
284 * type, in case stacked contacts are explicitly called out in the
285 * tech file (e.g., pm12contact).
286 *
287 * Results:
288 * None.
289 *
290 * Side effects:
291 * Adds to the tiletype database.
292 *
293 * ----------------------------------------------------------------------------
294 */
295
296 void
dbTechAddStackedContacts()297 dbTechAddStackedContacts()
298 {
299 int m, n;
300 LayerInfo *lim, *lin;
301 int dbNumUserContacts = dbNumContacts;
302 int result;
303
304 for (m = 0; m < dbNumUserContacts; m++)
305 {
306 lim = dbContactInfo[m];
307 for (n = m + 1; n < dbNumUserContacts; n++)
308 {
309 lin = dbContactInfo[n];
310 result = dbTechAddOneStackedContact(lim->l_type, lin->l_type);
311 if (result == -3)
312 return; /* overran tiletype maximum number */
313 }
314 }
315
316 /* Diagnostic */
317 /* fprintf(stderr, "DBNumUserLayers = %d, DBNumTypes = %d\n",
318 DBNumUserLayers, DBNumTypes);
319 fflush(stderr); */
320 }
321
322 /*
323 * ----------------------------------------------------------------------------
324 * dbTechAddOneStackedContact --
325 *
326 * Generate one new stacked contact type representing the union of
327 * types "type1" and "type2" on their shared plane(s) (normally
328 * one, but not necessarily).
329 *
330 * Results:
331 * tile type of new stacked contact if successful, -1 if stacking
332 * not allowed, -2 if a contact type already exists which stacks
333 * type1 and type2, or -3 on overrun of the total number of layers.
334 * ----------------------------------------------------------------------------
335 */
336
337 int
dbTechAddOneStackedContact(type1,type2)338 dbTechAddOneStackedContact(type1, type2)
339 TileType type1, type2;
340 {
341 LayerInfo *lim, *lin, *lp;
342 TileTypeBitMask ttshared, ttall, mmask;
343 TileType stackedType, sres;
344
345 lim = &dbLayerInfo[type1];
346 lin = &dbLayerInfo[type2];
347
348 /* Both types must be contacts */
349 if (!lim->l_isContact || !lin->l_isContact) return -1;
350
351 /* Contacts do not stack if they share more than one plane */
352 /* if (lim->l_pmask == lin->l_pmask) return -1; */
353 if (((lim->l_pmask & lin->l_pmask) & ((lim->l_pmask & lin->l_pmask) - 1))
354 != 0)
355 return -1;
356
357 TTMaskAndMask3(&ttshared, &lim->l_residues, &lin->l_residues);
358
359 if (!TTMaskEqual(&ttshared, &DBZeroTypeBits))
360 {
361 /* Find if there exists an image with the same residue */
362 /* mask as the combination of these two contact types. */
363
364 TTMaskZero(&ttall);
365 TTMaskSetMask3(&ttall, &lim->l_residues, &lin->l_residues);
366
367 dbTechMatchResidues(&ttall, &mmask, TRUE);
368
369 if (!TTMaskEqual(&mmask, &DBZeroTypeBits))
370 return -2; /* Contact type exists, so don't create one. */
371
372 /* Also check if there is a stacking type made of these contact */
373 /* images. If we already have one, don't re-make it. */
374
375 else if (DBTechFindStacking(type1, type2) != -1)
376 return -2; /* Stacking type exists, so don't create one. */
377
378 /* All clear to set the residue bitmask for this contact type */
379
380 /* Diagnostic */
381 /* fprintf(stderr, "Stackable %s and %s\n",
382 DBTypeLongName(lim->l_type),
383 DBTypeLongName(lin->l_type));
384 fflush(stderr); */
385
386 stackedType = dbTechNewStackedType(lim->l_type, lin->l_type);
387
388 /* Error condition (usually, reached max. no. tile types) */
389 if (stackedType < 0) return -3;
390
391 /* fill in layer info */
392
393 lp = &dbLayerInfo[stackedType];
394 lp->l_isContact = TRUE;
395
396 /* The residue of a stacked contact is the two contacts */
397 /* which make it up. Residues which are contact types */
398 /* are unique to stacking types. */
399
400 TTMaskZero(&lp->l_residues);
401 TTMaskSetType(&lp->l_residues, lim->l_type);
402 TTMaskSetType(&lp->l_residues, lin->l_type);
403 lp->l_pmask = lin->l_pmask | lim->l_pmask;
404
405 /* The home plane of the contact is the plane of the */
406 /* first shared residue found. */
407
408 for (sres = TT_TECHDEPBASE; sres < DBNumUserLayers; sres++)
409 if (TTMaskHasType(&ttshared, sres))
410 {
411 DBPlane(stackedType) = DBPlane(sres);
412 break;
413 }
414
415 /* Remember this as a paintable contact */
416 dbContactInfo[dbNumContacts++] = &dbLayerInfo[stackedType];
417
418 return (int)stackedType; /* success */
419 }
420 return -1;
421 }
422
423 /*
424 * ----------------------------------------------------------------------------
425 *
426 * DBPlaneToResidue --
427 *
428 * For the given tile type and plane, return the residue of that type on the
429 * plane.
430 *
431 * Results:
432 * A tile type.
433 *
434 * Side effects:
435 * None.
436 *
437 * ----------------------------------------------------------------------------
438 */
439
440 TileType
DBPlaneToResidue(type,plane)441 DBPlaneToResidue(type, plane)
442 TileType type;
443 int plane;
444 {
445 TileType rt, rt2;
446 LayerInfo *lp = &dbLayerInfo[type], *lr;
447
448 for (rt = TT_TECHDEPBASE; rt < DBNumUserLayers; rt++)
449 if (TTMaskHasType(&lp->l_residues, rt))
450 {
451 if (type >= DBNumUserLayers) /* Stacked type */
452 {
453 lr = &dbLayerInfo[rt];
454 for (rt2 = TT_TECHDEPBASE; rt2 < DBNumUserLayers; rt2++)
455 if (TTMaskHasType(&lr->l_residues, rt2))
456 if (DBPlane(rt2) == plane)
457 return rt2;
458 }
459 else if (DBPlane(rt) == plane) /* Normal type */
460 return rt;
461 }
462
463 return TT_SPACE; /* no residue on plane */
464 }
465
466 /*
467 * ----------------------------------------------------------------------------
468 *
469 * DBMaskAddStacking ---
470 *
471 * A general-purpose routine to add stacked types containing types that are
472 * already in the mask.
473 *
474 * ----------------------------------------------------------------------------
475 */
476
477 void
DBMaskAddStacking(mask)478 DBMaskAddStacking(mask)
479 TileTypeBitMask *mask;
480 {
481 TileType ttype;
482 TileTypeBitMask *rMask;
483
484 for (ttype = DBNumUserLayers; ttype < DBNumTypes; ttype++)
485 {
486 rMask = DBResidueMask(ttype);
487 if (TTMaskIntersect(rMask, mask))
488 TTMaskSetType(mask, ttype);
489 }
490 }
491
492
493 /*
494 * ----------------------------------------------------------------------------
495 *
496 * dbTechContactResidues --
497 *
498 * Process an argc/argv vector of contact residue type names, creating
499 * image types for each, and ensuring that:
500 * No residue is itself a contact
501 * One of the residues is on the home plane of contactType.
502 *
503 * Results:
504 * Returns the number of residues in the contact,
505 * or -1 in the event of an error.
506 *
507 * Side effects:
508 * Adds to database of layer types.
509 *
510 * ----------------------------------------------------------------------------
511 */
512
513 int
dbTechContactResidues(argc,argv,contactType)514 dbTechContactResidues(argc, argv, contactType)
515 int argc;
516 char **argv;
517 TileType contactType;
518 {
519 int homePlane, residuePlane, nresidues;
520 PlaneMask pMask;
521 TileType residueType, imageType;
522 bool residueOnHome;
523 LayerInfo *lp;
524 TileTypeBitMask rmask, mmask;
525
526 nresidues = 0;
527 pMask = 0;
528 residueOnHome = FALSE;
529
530 TTMaskZero(&rmask);
531 homePlane = DBPlane(contactType);
532 for ( ; argc > 0; argc--, argv++)
533 {
534 if ((residueType = DBTechNoisyNameType(*argv)) < 0)
535 return -1;
536
537 if (IsContact(residueType))
538 {
539 TechError("Residue type %s is a contact itself\n",
540 DBTypeLongName(residueType));
541 return -1;
542 }
543
544 /*
545 * Make sure the residue is on the same or an adjacent plane
546 * to the contact's home type.
547 */
548 residuePlane = DBPlane(residueType);
549 if (residuePlane < 0)
550 {
551 TechError("Residue type %s doesn't have a home plane\n",
552 DBTypeLongName(residueType));
553 return -1;
554 }
555
556 /* Enforce a single residue per plane */
557 if (PlaneMaskHasPlane(pMask, residuePlane))
558 {
559 TechError("Contact residues (%s) must be on different planes\n",
560 DBTypeLongName(residueType));
561 return -1;
562 }
563 pMask |= PlaneNumToMaskBit(residuePlane);
564 if (homePlane == residuePlane)
565 residueOnHome = TRUE;
566
567 TTMaskSetType(&rmask, residueType);
568 }
569
570 if (!residueOnHome)
571 {
572 TechError("Contact type %s missing a residue on its home plane\n",
573 DBTypeLongName(contactType));
574 return -1;
575 }
576
577 /*
578 * See if there are any other contact types with identical residues;
579 * if so, disallow contactType.
580 *
581 * Can this restriction be lifted? ---Tim 07/24/03
582 * This restriction is partially lifted, as one can create a non-stacked
583 * type such as "pad" having the same residues as one stacked type,
584 * such as "m123c". Due to the way magic handles stacked types, these
585 * will not be confused. ---Tim 05/11/04
586 *
587 * Restriction entirely lifted 6/18/04. Error message left as a warning
588 * until it is clear that there are no unwanted side effects of having
589 * two contact types with identical residues.
590 */
591
592 /* Find if there exists an image with the same residue mask */
593
594 dbTechMatchResidues(&rmask, &mmask, TRUE);
595
596 /* Ignore self */
597
598 TTMaskClearType(&mmask, contactType);
599
600 if (!TTMaskEqual(&mmask, &DBZeroTypeBits))
601 {
602 TxPrintf("Contact residues for %s identical to those for ",
603 DBTypeLongName(contactType));
604
605 for (imageType = TT_TECHDEPBASE; imageType < DBNumTypes; imageType++)
606 if (TTMaskHasType(&mmask, imageType))
607 TxPrintf("%s ", DBTypeLongName(imageType));
608
609 TxPrintf("\n");
610 }
611
612 /* All clear to set the residue bitmask for this contact type */
613
614 lp = &dbLayerInfo[contactType];
615
616 lp->l_isContact = TRUE;
617 TTMaskSetMask(&lp->l_residues, &rmask);
618 lp->l_pmask = pMask;
619
620 return nresidues;
621 }
622
623 /*
624 * ----------------------------------------------------------------------------
625 *
626 * dbTechMatchResidues --
627 *
628 * Find the types whose residues match those of the supplied inMask.
629 *
630 * All this masking about is rather subtle, so pay attention: Each TYPE
631 * has a RESIDUAL, which for a contact is (generally) the type which surrounds
632 * each contact image on its plane (remember, there is one contact image per
633 * plane contacted). So when creating the paint/erase tables, we want to
634 * knock out planes from the residual mask of a contact and see if what's
635 * left is another kind of contact. So from the original contact TYPE, we
636 * make a mask of RESIDUALS, then this routine compares that to the mask
637 * of residuals for all other (contact) types, then create another mask of
638 * all the types which had matching residual masks, and return it. Grok
639 * that?
640 *
641 * Note that the stacked contact mechanism returns the stacked type where
642 * residues of two types match. This is required when composing paint
643 * rules for contacts on contacts.
644 *
645 * Results:
646 * None.
647 *
648 * Side effects:
649 * Yet another TileType bitmask pointer, outMask, is filled in with
650 * the matching types.
651 *
652 * ----------------------------------------------------------------------------
653 */
654
655 void
dbTechMatchResidues(inMask,outMask,contactsOnly)656 dbTechMatchResidues(inMask, outMask, contactsOnly)
657 TileTypeBitMask *inMask, *outMask;
658 bool contactsOnly;
659 {
660 TileType type;
661 LayerInfo *li;
662
663 TTMaskZero(outMask);
664 for (type = TT_TECHDEPBASE; type < DBNumUserLayers; type++)
665 {
666 li = &dbLayerInfo[type];
667 if (!li->l_isContact && contactsOnly)
668 continue;
669
670 if (TTMaskEqual(inMask, &li->l_residues))
671 TTMaskSetType(outMask, type);
672 }
673 }
674
675
676 /*
677 * ----------------------------------------------------------------------------
678 * DBTechFindStacking --
679 *
680 * Find a stacking tile type which connects the two indicated types.
681 * Stacking types have the l_residues field of the LayerInfo entry filled
682 * with the mask of the two types which make up the stacked contact type.
683 *
684 * Results:
685 * The stacking tile type, if it exists, or -1 if there's no stacking
686 * type connecting type1 and type2.
687 *
688 * Side effects:
689 * None.
690 * ----------------------------------------------------------------------------
691 */
692
693 TileType
DBTechFindStacking(type1,type2)694 DBTechFindStacking(type1, type2)
695 TileType type1, type2;
696 {
697 TileType rtype, rtype1, rtype2, stackType;
698 LayerInfo *li;
699
700 for (stackType = DBNumUserLayers; stackType < DBNumTypes; stackType++)
701 {
702 rtype1 = rtype2 = -1;
703 li = &dbLayerInfo[stackType];
704 for (rtype = TT_TECHDEPBASE; rtype < DBNumUserLayers; rtype++)
705 if (TTMaskHasType(&li->l_residues, rtype))
706 {
707 rtype1 = rtype;
708 break;
709 }
710 for (++rtype; rtype < DBNumUserLayers; rtype++)
711 if (TTMaskHasType(&li->l_residues, rtype))
712 {
713 rtype2 = rtype;
714 break;
715 }
716
717 if (((rtype1 == type1) && (rtype2 == type2)) ||
718 ((rtype1 == type2) && (rtype2 == type1)))
719 return stackType;
720
721 }
722 return -1;
723 }
724
725 /*
726 * ----------------------------------------------------------------------------
727 *
728 * DBTechFinalContact --
729 *
730 * Conclude reading the "contact" section of a technology file.
731 * At this point, all tile types are known so we can call dbTechInitPaint()
732 * to fill in the default paint/erase tables, and dbTechInitMasks() to fill
733 * in the various exported TileTypeBitMasks.
734 *
735 * Results:
736 * None.
737 *
738 * Side effects:
739 * Fills in the dbLayerInfo table for non-contacts.
740 * Sets DBLayerTypeMaskTbl to its final value.
741 * Initializes DBTypePlaneMaskTbl[] and DBPlaneTypes[].
742 *
743 * ----------------------------------------------------------------------------
744 */
745
746 void
DBTechFinalContact()747 DBTechFinalContact()
748 {
749 TileType primaryType;
750 LayerInfo *lp;
751 int pNum;
752
753 /* Fill in plane and residue info for non-contact types */
754
755 for (primaryType = 0; primaryType < DBNumTypes; primaryType++)
756 {
757 lp = &dbLayerInfo[primaryType];
758 pNum = DBPlane(primaryType);
759 if (!lp->l_isContact && (pNum > 0))
760 {
761 lp->l_pmask = PlaneNumToMaskBit(pNum);
762 TTMaskSetOnlyType(&lp->l_residues, primaryType);
763 }
764 }
765
766 /*
767 * Initialize the masks of planes on which each type appears.
768 * It will contain all planes (except router) for space,
769 * the home plane for each type up to DBNumTypes, and no
770 * planes for undefined types. Also update the mask of
771 * types visible on each plane.
772 */
773
774 DBTypePlaneMaskTbl[TT_SPACE] = ~(PlaneNumToMaskBit(PL_ROUTER));
775 for (primaryType = 0; primaryType < DBNumTypes; primaryType++)
776 {
777 pNum = DBPlane(primaryType);
778 if (pNum > 0)
779 {
780 DBTypePlaneMaskTbl[primaryType] = PlaneNumToMaskBit(pNum);
781 if (!IsContact(primaryType))
782 TTMaskSetType(&DBPlaneTypes[pNum], primaryType);
783 else
784 {
785 lp = &dbLayerInfo[primaryType];
786
787 /* if (primaryType < DBNumUserLayers) */
788 DBTypePlaneMaskTbl[primaryType] |= lp->l_pmask;
789
790 for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
791 if (PlaneMaskHasPlane(lp->l_pmask, pNum))
792 TTMaskSetType(&DBPlaneTypes[pNum], primaryType);
793 }
794 }
795 }
796
797 /* Create a mask for which each type only appears on one plane. */
798 /* This is useful for non-redundant searches. */
799
800 for (pNum = 0; pNum < PL_MAXTYPES; pNum++)
801 TTMaskZero(&DBHomePlaneTypes[pNum]);
802
803 for (primaryType = TT_SPACE + 1; primaryType < DBNumTypes; primaryType++)
804 TTMaskSetType(&DBHomePlaneTypes[DBPlane(primaryType)], primaryType);
805 }
806
807 /*
808 * ----------------------------------------------------------------------------
809 * DBTechTypesOnPlane --
810 *
811 * Given a tile type bitmask and a plane index, check if all types in the
812 * bitmask have an image on the indicated plane.
813 *
814 * Results:
815 * TRUE if all types in "src" have at least one image on plane.
816 * FALSE if any type in "src" does not contain any image in plane.
817 *
818 * Side effects:
819 * None.
820 * ----------------------------------------------------------------------------
821 */
822
823 bool
DBTechTypesOnPlane(src,plane)824 DBTechTypesOnPlane(src, plane)
825 TileTypeBitMask *src;
826 int plane;
827 {
828 int i;
829 PlaneMask pmask;
830
831 for (i = 0; i < DBNumTypes; i++)
832 if (TTMaskHasType(src, i))
833 if (!PlaneMaskHasPlane(DBTypePlaneMaskTbl[i], plane))
834 return FALSE;
835
836 return TRUE;
837 }
838
839 /*
840 * ----------------------------------------------------------------------------
841 *
842 * DBTechGetContact --
843 *
844 * Given two tile types, determine the corresponding contact type.
845 * (Or rather, for two types, get the first contact type connecting
846 * the two planes on which those types lie. . . not quite the same
847 * thing.)
848 *
849 * Results:
850 * Returns a contact type.
851 *
852 * Side effects:
853 * Prints stuff if it can't find a contact type.
854 *
855 * ----------------------------------------------------------------------------
856 */
857
858 TileType
DBTechGetContact(type1,type2)859 DBTechGetContact(type1, type2)
860 TileType type1, type2;
861 {
862 int pmask;
863 LayerInfo *lp;
864 TileType t;
865
866 pmask = DBTypePlaneMaskTbl[type1] | DBTypePlaneMaskTbl[type2];
867 for (t = TT_TECHDEPBASE; t < DBNumTypes; t++)
868 {
869 lp = &dbLayerInfo[t];
870 if (lp->l_isContact)
871 if (lp->l_pmask == pmask)
872 return t;
873 }
874
875 TxPrintf("No contact type for %d %d\n", type1, type2);
876 return (TileType) -1;
877 }
878
879 /*
880 * ----------------------------------------------------------------------------
881 *
882 * DBIsContact --
883 *
884 * Like IsContact(), except as a subroutine, not a macro. For export
885 * to other routines.
886 *
887 * ----------------------------------------------------------------------------
888 */
889
890 bool
DBIsContact(type)891 DBIsContact(type)
892 TileType type;
893 {
894 if (IsContact(type)) return TRUE;
895 return FALSE;
896 }
897
898 /*
899 * ----------------------------------------------------------------------------
900 *
901 * DBResidueMask --
902 *
903 * Get the residue mask of the specified type. For export to other
904 * routines.
905 * ----------------------------------------------------------------------------
906 */
907
908 TileTypeBitMask *
DBResidueMask(type)909 DBResidueMask(type)
910 TileType type;
911 {
912 LayerInfo *li = &dbLayerInfo[type];
913 return (&li->l_residues);
914 }
915
916 /*
917 * ----------------------------------------------------------------------------
918 *
919 * DBFullResidueMask --
920 *
921 * Get the residue mask of the specified type. For stacking contacts,
922 * decompose the contact residues into their component residue layers.
923 *
924 * Results:
925 * None.
926 *
927 * Side Effects:
928 * "rmask" is a pointer to a TileTypeBitMask. The result is placed
929 * in this location.
930 * ----------------------------------------------------------------------------
931 */
932
933 void
DBFullResidueMask(type,rmask)934 DBFullResidueMask(type, rmask)
935 TileType type;
936 TileTypeBitMask *rmask;
937 {
938 TileType t;
939 TileTypeBitMask *lmask;
940 LayerInfo *li, *lr;
941
942 li = &dbLayerInfo[type];
943 lmask = &li->l_residues;
944 TTMaskZero(rmask);
945
946 if (type < DBNumUserLayers)
947 {
948 TTMaskSetMask(rmask, &li->l_residues);
949 }
950 else
951 {
952 for (t = TT_TECHDEPBASE; t < DBNumUserLayers; t++)
953 if (TTMaskHasType(lmask, t))
954 {
955 lr = &dbLayerInfo[t];
956 TTMaskSetMask(rmask, &lr->l_residues);
957 }
958 }
959 }
960
961 /*
962 * ----------------------------------------------------------------------------
963 *
964 * dbTechPrintContacts --
965 *
966 * DEBUGGING.
967 * Print a list of the contact types to which each possible contact image
968 * belongs.
969 *
970 * Results:
971 * None.
972 *
973 * Side effects:
974 * Prints stuff.
975 *
976 * ----------------------------------------------------------------------------
977 */
978
979 void
dbTechPrintContacts()980 dbTechPrintContacts()
981 {
982 LayerInfo *lpImage;
983 TileType t;
984 int m, pNum;
985
986 for (m = 0; m < dbNumContacts; m++)
987 {
988 lpImage = dbContactInfo[m];
989 TxPrintf("Contact %s (on %s) ",
990 DBTypeLongName(lpImage->l_type),
991 DBPlaneLongName(DBPlane(lpImage->l_type)));
992
993 TxPrintf(" connects:");
994 for (t = TT_TECHDEPBASE; t < DBNumTypes; t++)
995 if ( TTMaskHasType(&DBConnectTbl[lpImage->l_type], t) )
996 TxPrintf(" %s", DBTypeLongName(t));
997
998 TxPrintf(" planes:");
999 for ( pNum = PL_TECHDEPBASE; pNum < PL_MAXTYPES; pNum++ )
1000 if ( PlaneNumToMaskBit(pNum) & DBConnPlanes[lpImage->l_type] )
1001 TxPrintf(" %s", DBPlaneLongName(pNum));
1002
1003 TxPrintf(" residues:");
1004 for ( t = TT_TECHDEPBASE; t < DBNumTypes; t++ )
1005 if (TTMaskHasType(&lpImage->l_residues, t))
1006 TxPrintf(" %s on plane %s\n",
1007 DBTypeLongName(t),
1008 DBPlaneLongName(DBPlane(t)));
1009
1010 TxPrintf("\n");
1011 }
1012 }
1013
1014