1 /*
2 * DBtechpaint.c --
3 *
4 * Management of composition rules and the paint/erase tables.
5 *
6 * *********************************************************************
7 * * Copyright (C) 1985, 1990 Regents of the University of California. *
8 * * Permission to use, copy, modify, and distribute this *
9 * * software and its documentation for any purpose and without *
10 * * fee is hereby granted, provided that the above copyright *
11 * * notice appear in all copies. The University of California *
12 * * makes no representations about the suitability of this *
13 * * software for any purpose. It is provided "as is" without *
14 * * express or implied warranty. Export of this software outside *
15 * * of the United States of America may require an export license. *
16 * *********************************************************************
17 */
18
19 #ifndef lint
20 static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/database/DBtpaint.c,v 1.2 2010/06/08 19:16:42 tim Exp $";
21 #endif /* not lint */
22
23 #include <stdio.h>
24 #include <ctype.h>
25 #include <string.h> /* for memset(), memcpy() */
26
27 #include "utils/magic.h"
28 #include "utils/geometry.h"
29 #include "utils/utils.h"
30 #include "tiles/tile.h"
31 #include "utils/hash.h"
32 #include "database/database.h"
33 #include "database/databaseInt.h"
34 #include "utils/tech.h"
35 #include "textio/textio.h"
36
37 /* Painting and erasing tables */
38 PaintResultType DBPaintResultTbl[NP][NT][NT];
39 PaintResultType DBEraseResultTbl[NP][NT][NT];
40 PaintResultType DBWriteResultTbl[NT][NT];
41 PaintResultType DBSpecialResultTbl[NT];
42
43 PlaneMask DBTypePaintPlanesTbl[NT];
44 PlaneMask DBTypeErasePlanesTbl[NT];
45
46 /* ----------------- Data local to tech file processing --------------- */
47
48 /*
49 * Tables telling which rules are default, and which have come
50 * from user-specified rules. The bit is CLEAR if the type is
51 * a default type.
52 */
53 TileTypeBitMask dbNotDefaultEraseTbl[NT];
54 TileTypeBitMask dbNotDefaultPaintTbl[NT];
55
56 /* --------------------- Data local to this file ---------------------- */
57
58 int dbNumSavedRules = 0;
59 Rule dbSavedRules[NT];
60
61 /* Forward declarations */
62
63 extern void dbTechBitTypeInit();
64
65 bool dbTechAddPaintErase();
66 bool dbTechSaveCompose();
67
68 /*
69 * ----------------------------------------------------------------------------
70 *
71 * DBTechInitCompose --
72 *
73 * Initialize the painting and erasing rules prior to processing
74 * the "compose" section. The rules for builtin types are computed
75 * here, as well as the default rules for all other types. This
76 * procedure must be called after the "types" and "contacts" sections
77 * have been read, since we need to know about all existing tile types.
78 *
79 * Results:
80 * None.
81 *
82 * Side effects:
83 * Modifies the paint and erase tables.
84 *
85 * ----------------------------------------------------------------------------
86 */
87
88 void
DBTechInitCompose()89 DBTechInitCompose()
90 {
91 TileType q, s, t, r;
92 int ps;
93 PaintResultType *stype, *dtype;
94 TileTypeBitMask *ttype;
95
96 /* Default painting rules for error types */
97
98 static TileType errorBitToType[] =
99 {
100 TT_SPACE, /* 0 */ TT_ERROR_P, /* 1 */
101 TT_ERROR_S, /* 2 */ TT_ERROR_PS, /* 3 */
102 };
103
104 /* Painting and erasing are no-ops for undefined tile types */
105
106 /* The following code is the FAST version using memcpy(). */
107 /* See below for the actual slow loops. */
108
109 stype = dtype = &(DBEraseResultTbl[0][0][0]);
110 for (ps = 0; ps < TT_MAXTYPES; ps++)
111 *dtype++ = (PaintResultType)ps;
112 for (ps = 1; ps < PL_MAXTYPES * TT_MAXTYPES; ps++)
113 {
114 memcpy((void *)dtype, (void *)stype, (size_t)TT_MAXTYPES
115 * sizeof(PaintResultType));
116 dtype += TT_MAXTYPES;
117 }
118
119 /* Fast copy the entire erase table to the paint table memory */
120 dtype = &(DBPaintResultTbl[0][0][0]);
121 memcpy((void *)dtype, (void *)stype, (size_t)(TT_MAXTYPES
122 * TT_MAXTYPES * PL_MAXTYPES * sizeof(PaintResultType)));
123
124 /* The following code is dreadfully slow, but I'm leaving it */
125 /* in as a comment because it's easier to read. The code */
126 /* above uses memory copying tricks to speed up the process. */
127 /*
128
129 for (pNum = 0; pNum < PL_MAXTYPES; pNum++)
130 {
131 for (s = 0; s < TT_MAXTYPES; s++)
132 {
133 for (t = 0; t < TT_MAXTYPES; t++)
134 {
135 /- Paint and erase are no-ops -/
136 dbSetEraseEntry(s, t, pNum, s);
137 dbSetPaintEntry(s, t, pNum, s);
138 }
139 }
140 }
141
142 for (s = 0; s < TT_MAXTYPES; s++)
143 {
144 for (t = 0; t < TT_MAXTYPES; t++)
145 {
146 /- Write overwrites existing contents -/
147 dbSetWriteEntry(s, t, t);
148 }
149 }
150 */
151
152 #if TT_MAXTYPES <= 256
153 /* For single-byte values, memset() is fastest. */
154
155 dtype = &(DBWriteResultTbl[0][0]);
156 for (q = 0; q < TT_MAXTYPES; q++)
157 {
158 memset((void *)dtype, (int)q, (size_t)TT_MAXTYPES);
159 dtype += TT_MAXTYPES;
160 }
161
162 #else
163 /* This is the slow loop, but it still faster than using */
164 /* macro dbSetWriteEntry(). */
165
166 dtype = &(DBWriteResultTbl[0][0]);
167 for (t = 0; t < TT_MAXTYPES; t++)
168 for (s = 0; s < TT_MAXTYPES; s++)
169 *dtype++ = t;
170
171 #endif
172
173 /* All painting and erasing rules are default initially */
174
175 /* This is also faster than the loop below. */
176
177 ttype = &(dbNotDefaultEraseTbl[0]);
178 for (s = 0; s < DBNumTypes; s++) *ttype++ = DBZeroTypeBits;
179 ttype = &(dbNotDefaultPaintTbl[0]);
180 for (s = 0; s < DBNumTypes; s++) *ttype++ = DBZeroTypeBits;
181
182 /*
183 for (s = 0; s < DBNumTypes; s++)
184 {
185 dbNotDefaultEraseTbl[s] = DBZeroTypeBits;
186 dbNotDefaultPaintTbl[s] = DBZeroTypeBits;
187 }
188 */
189
190 /*
191 * For each type t:
192 * erase(t, t, plane(t)) -> SPACE
193 *
194 * For each type s, t:
195 * paint(s, t, plane(t)) -> t
196 * paint(s, t, ~plane(t)) -> s
197 */
198
199 for (s = 0; s < DBNumTypes; s++)
200 {
201 if ((ps = DBPlane(s)) > 0)
202 {
203 for (t = 0; t < DBNumTypes; t++)
204 {
205 if (DBPlane(t) > 0)
206 {
207 r = (ps == DBPlane(t)) ? t : s;
208 dbSetEraseEntry(s, t, ps, s);
209 dbSetPaintEntry(s, t, ps, r);
210 }
211 }
212
213 /* Everything can be erased to space on its home plane */
214 dbSetEraseEntry(s, s, ps, TT_SPACE);
215
216 /* Everything paints over space on its home plane */
217 dbSetPaintEntry(TT_SPACE, s, ps, s);
218 }
219 }
220
221 /*
222 * Special handling for check tile and error tile combinations.
223 */
224 #define PCHK PL_DRC_CHECK
225 #define PERR PL_DRC_ERROR
226 #define tblsize(t) ( (sizeof (t)) / (sizeof (t[0])) )
227 dbTechBitTypeInit(errorBitToType, tblsize(errorBitToType), PERR, FALSE);
228 #undef tblsize
229
230 /*
231 * Paint results are funny for check plane because
232 * CHECKPAINT+CHECKSUBCELL = CHECKPAINT
233 */
234 dbSetPaintEntry(TT_SPACE, TT_CHECKPAINT, PCHK, TT_CHECKPAINT);
235 dbSetPaintEntry(TT_SPACE, TT_CHECKSUBCELL, PCHK, TT_CHECKSUBCELL);
236 dbSetPaintEntry(TT_CHECKPAINT, TT_CHECKSUBCELL, PCHK, TT_CHECKPAINT);
237 dbSetPaintEntry(TT_CHECKSUBCELL, TT_CHECKPAINT, PCHK, TT_CHECKPAINT);
238 #undef PCHK
239 #undef PERR
240
241 /* Added 5/27/10: Special table used for painting non-Manhattan */
242 /* tiles. Uses TT_CHECKSUBCELL because that type does not exist on */
243 /* any paintable plane, and the checkpaint plane does not use non- */
244 /* manhattan tiles. */
245
246 for (s = 0; s < DBNumTypes; s++) DBSpecialResultTbl[s] = TT_CHECKSUBCELL;
247 }
248
249 /*
250 * ----------------------------------------------------------------------------
251 *
252 * dbTechBitTypeInit --
253 *
254 * Handle initialization of the paint and erase result tables for a
255 * set of ln2(n) primary types with n distinct mutual overlap types.
256 * The table bitToType points to a table containing n TileTypes
257 * (the overlap types) with the property that
258 *
259 * bitToType[i] and bitToType[j] combine to yield bitToType[i | j]
260 *
261 * Also (unless composeFlag is set) erasing bitToType[j] from bitToType[i]
262 * gives bitToType[i & (~j)],
263 * i.e., it clears all of the j-type material out of the i-type material.
264 * The bitToType[k] for which k's binary representation has only a single
265 * bit set in it are the "primary" types.
266 *
267 * If composeFlag is set, the above is modified slightly to be analagous
268 * to compose rules, specifically, erase rules for nonprimary types are
269 * the default rules, i.e. they only erase precisely themselves. This
270 * makes ":erase *-primary" work in the expected way.
271 *
272 * Results:
273 * None.
274 *
275 * Side effects:
276 * See above.
277 *
278 * ----------------------------------------------------------------------------
279 */
280
281 void
dbTechBitTypeInit(bitToType,n,pNum,composeFlag)282 dbTechBitTypeInit(bitToType, n, pNum, composeFlag)
283 TileType *bitToType;
284 int n, pNum;
285 bool composeFlag;
286 {
287 int i, j;
288 TileType have, type;
289
290 for (i = 0; i < n; i++)
291 {
292 have = bitToType[i];
293 for (j = 0; j < n; j++)
294 {
295 type = bitToType[j];
296 dbSetPaintEntry(have, type, pNum, bitToType[i | j]);
297 if(!composeFlag || dbIsPrimary(j))
298 {
299 dbSetEraseEntry(have, type, pNum, bitToType[i & (~j)]);
300 }
301 }
302 }
303 }
304
305 /* Returns nonzero if exactly one bit set */
306
307 int
dbIsPrimary(n)308 dbIsPrimary(n)
309 int n;
310 {
311 int bitCount;
312
313 for(bitCount=0; n>0; n=n>>1)
314 {
315 if(n&1)
316 {
317 bitCount++;
318 }
319 }
320
321 return (bitCount==1);
322 }
323
324
325 /*
326 * ----------------------------------------------------------------------------
327 *
328 * DBTechAddCompose --
329 *
330 * Process a single compose/erase rule. If the type being described is
331 * a contact, save the rule and defer processing it until the end of this
332 * section, because we need to know the behavior of all non-contact types
333 * that might be residues before processing a contact composition rule.
334 * Rules for non-contact types are processed here.
335 *
336 * Results:
337 * TRUE if successful, FALSE on error.
338 *
339 * Side effects:
340 * Modifies the paint/erase tables if the type being described
341 * is not a contact; otherwise, appends a rule to the list of
342 * contact erase/compose rules for later processing. Marks the
343 * paint/erase table entries affected to show that they contain
344 * user-specified rules instead of the default ones, so we don't
345 * override them later.
346 *
347 * ----------------------------------------------------------------------------
348 */
349
350 /*ARGSUSED*/
351 bool
DBTechAddCompose(sectionName,argc,argv)352 DBTechAddCompose(sectionName, argc, argv)
353 char *sectionName;
354 int argc;
355 char *argv[];
356 {
357 TileType type, r, s;
358 int pNum, ruleType, i;
359 static char *ruleNames[] =
360 { "compose", "decompose", "paint", "erase", 0 };
361 static int ruleTypes[] =
362 { RULE_COMPOSE, RULE_DECOMPOSE, RULE_PAINT, RULE_ERASE };
363
364 if (argc < 4)
365 {
366 TechError("Line must contain at least ruletype, result + pair\n");
367 return FALSE;
368 }
369
370 /* Look up and skip over type of rule */
371 i = Lookup(*argv, ruleNames);
372 if (i < 0)
373 {
374 TechError("%s rule type %s. Must be one of:\n\t",
375 i == -1 ? "Ambiguous" : "Unknown", *argv);
376 for (i = 0; ruleNames[i]; i++)
377 TxError("\"%s\" ", ruleNames[i]);
378 TxError("\n");
379 return FALSE;
380 }
381 ruleType = ruleTypes[i];
382 argv++, argc--;
383
384 /* Paint or erase rules are processed specially */
385 switch (ruleType)
386 {
387 case RULE_PAINT:
388 case RULE_ERASE:
389 return (dbTechAddPaintErase(ruleType, sectionName, argc, argv));
390 }
391
392 /* Compose or decompose rule: find result type and then skip over it */
393 if ((type = DBTechNoisyNameType(*argv)) < 0)
394 return FALSE;
395 argv++, argc--;
396 if (argc & 01)
397 {
398 TechError("Types on RHS of rule must be in pairs\n");
399 return FALSE;
400 }
401
402 /* Compose/decompose rules for contacts are saved away */
403 if (IsContact(type))
404 return dbTechSaveCompose(ruleType, type, argc, argv);
405
406 /* Rules for non-contacts are processed here */
407 for ( ; argc > 0; argc -= 2, argv += 2)
408 {
409 if ((r = DBTechNoisyNameType(argv[0])) < 0
410 || (s = DBTechNoisyNameType(argv[1])) < 0)
411 return FALSE;
412
413 if (IsContact(r) || IsContact(s))
414 {
415 TechError("Can't have contact layers on RHS of non-contact rule\n");
416 return FALSE;
417 }
418
419 pNum = DBPlane(r);
420 switch (ruleType)
421 {
422 case RULE_COMPOSE:
423 dbSetPaintEntry(r, s, pNum, type);
424 dbSetPaintEntry(s, r, pNum, type);
425 TTMaskSetType(&dbNotDefaultPaintTbl[r], s);
426 TTMaskSetType(&dbNotDefaultPaintTbl[s], r);
427 /* Fall through to */
428 case RULE_DECOMPOSE:
429 dbSetPaintEntry(type, r, pNum, type);
430 dbSetPaintEntry(type, s, pNum, type);
431 dbSetEraseEntry(type, r, pNum, s);
432 dbSetEraseEntry(type, s, pNum, r);
433 TTMaskSetType(&dbNotDefaultPaintTbl[type], r);
434 TTMaskSetType(&dbNotDefaultPaintTbl[type], s);
435 TTMaskSetType(&dbNotDefaultEraseTbl[type], r);
436 TTMaskSetType(&dbNotDefaultEraseTbl[type], s);
437 break;
438 }
439 }
440
441 return TRUE;
442 }
443
444 /*
445 * ----------------------------------------------------------------------------
446 *
447 * dbTechSaveCompose --
448 *
449 * Save a compose rule for a contact 't' in the table dbSavedRules.
450 * Check to make sure the rule is legal.
451 *
452 * Results:
453 * Returns TRUE if successful, FALSE on error.
454 *
455 * Side effects:
456 * Updates dbSavedRules[] and increments dbNumSavedRules.
457 *
458 * ----------------------------------------------------------------------------
459 */
460
461 bool
dbTechSaveCompose(ruleType,t,argc,argv)462 dbTechSaveCompose(ruleType, t, argc, argv)
463 int ruleType;
464 TileType t;
465 int argc;
466 char *argv[];
467 {
468 TileType r, s;
469 Rule *rp;
470
471 rp = &dbSavedRules[dbNumSavedRules++];
472 rp->r_ruleType = ruleType;
473 rp->r_result = t;
474 rp->r_npairs = 0;
475 for ( ; argc > 0; argc -= 2, argv += 2)
476 {
477 r = DBTechNoisyNameType(argv[0]);
478 s = DBTechNoisyNameType(argv[1]);
479 if (r < 0 || s < 0)
480 return FALSE;
481
482 /* At most one of r and s may be a contact */
483 if (IsContact(r) && IsContact(s))
484 {
485 TechError("Only one type in each pair may be a contact\n");
486 return FALSE;
487 }
488
489 /*
490 * The planes comprising 't' must be a superset of the
491 * planes comprising 'r' and the planes comprising 's'.
492 */
493 if (((LayerPlaneMask(r) | LayerPlaneMask(s)) & ~LayerPlaneMask(t)) != 0)
494 {
495 TechError("Component planes are a superset of result planes\n");
496 return FALSE;
497 }
498
499 if (ruleType == RULE_COMPOSE)
500 {
501 /* Types r and s can't appear on planes outside of t's */
502 if ((LayerPlaneMask(r) | LayerPlaneMask(s)) != LayerPlaneMask(t))
503 {
504 TechError("Union of pair planes must = result planes\n");
505 return FALSE;
506 }
507
508 /* The following restriction has been lifted due to */
509 /* the recursive plane painting method added to */
510 /* routine DBPaint(). (Tim, 5/11/04) */
511
512 // if (!dbTechCheckImages(t, r, s) || !dbTechCheckImages(t, s, r))
513 // return FALSE;
514 }
515
516 rp->r_pairs[rp->r_npairs].rp_a = r;
517 rp->r_pairs[rp->r_npairs].rp_b = s;
518 rp->r_npairs++;
519 }
520
521 return TRUE;
522 }
523
524
525 #if 0 /* deprecated function (5/11/04) */
526 /*
527 * ----------------------------------------------------------------------------
528 *
529 * dbTechCheckImages --
530 *
531 * When processing a compose rule for 't' with RHS components
532 * 'r' and 's', check to be sure that the images of 't' on
533 * those planes present in 'r' but not in 's' are identical to
534 * the images of 'r' on those planes. This is necessary in order
535 * that the result on these planes not depend on types present on
536 * other planes.
537 *
538 * Results:
539 * Returns TRUE if successful, FALSE on error.
540 *
541 * Side effects:
542 * None.
543 *
544 * ----------------------------------------------------------------------------
545 */
546
547 bool
548 dbTechCheckImages(t, r, s)
549 TileType t; /* Type that is composed */
550 TileType r; /* First constituent */
551 TileType s; /* Second constituent */
552 {
553 int pNum;
554 PlaneMask pMask;
555
556 if (pMask = (LayerPlaneMask(r) & ~LayerPlaneMask(s)))
557 {
558 for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
559 if (PlaneMaskHasPlane(pMask, pNum) && (t != r))
560 {
561 TechError("Result image on plane %s must be the same "
562 "as image of %s on plane %s\n",
563 DBPlaneLongName(pNum),
564 DBTypeLongName(r),
565 DBPlaneLongName(pNum));
566 return FALSE;
567 }
568 }
569
570 return TRUE;
571 }
572 #endif /* 0 */
573
574
575 /*
576 * ----------------------------------------------------------------------------
577 *
578 * dbTechAddPaintErase --
579 *
580 * Add a new entry to the paint or erase table.
581 * The semantics is that painting a tile of type1 with paint type2
582 * yields a tile of typeres.
583 *
584 * Results:
585 * Returns TRUE if successful, FALSE on error.
586 *
587 * Side effects:
588 * Updates the database technology variables.
589 *
590 * ----------------------------------------------------------------------------
591 */
592
593 bool
dbTechAddPaintErase(type,sectionName,argc,argv)594 dbTechAddPaintErase(type, sectionName, argc, argv)
595 int type;
596 char *sectionName;
597 int argc;
598 char *argv[];
599 {
600 int pNum;
601 PlaneMask pMask, rMask;
602 TileType t1, t2, tres;
603 TileTypeBitMask tMask;
604
605 if (argc < 3)
606 {
607 TechError("Line must contain at least 3 types\n");
608 return FALSE;
609 }
610
611 if ((t1 = DBTechNoisyNameType(argv[0])) < 0) return FALSE;
612 if ((t2 = DBTechNoisyNameType(argv[1])) < 0) return FALSE;
613
614 /* Modified 9/22/2020 to allow multiple types to paint, for example */
615 /* to replace a contact type with types on both residue planes. */
616
617 rMask = DBTechNoisyNameMask(argv[2], &tMask);
618 if (TTMaskIsZero(&tMask)) return FALSE;
619
620 if (argc == 3)
621 {
622 if (t1 == TT_SPACE)
623 {
624 TechError("<%s, %s, %s>:\n"
625 "Must specify plane in paint table for "
626 "painting space\n",
627 argv[0], argv[1], argv[2]);
628 return FALSE;
629 }
630 else
631 pMask = LayerPlaneMask(t1);
632 }
633 else
634 {
635 if ((pNum = DBTechNoisyNamePlane(argv[3])) < 0) return FALSE;
636 else
637 pMask = PlaneNumToMaskBit(pNum);
638 }
639
640 pMask &= ~rMask;
641
642 /* 10/30/2020: Changed from DBNumTypes to DBNumUserLayers, */
643 /* because DBTechNoisyNameMask() was modified to add stacking */
644 /* contact types, and it is not correct for tMask to have more */
645 /* than one type in the mask that share the same plane. */
646 /* NOTE: Paint rules for stacked contacts probably have to be */
647 /* handled too, but in a separate way. */
648
649 for (tres = 0; tres < DBNumUserLayers; tres++)
650 {
651 if (TTMaskHasType(&tMask, tres))
652 {
653 if (type == RULE_PAINT)
654 {
655 /* Apply to all planes of rMask. */
656
657 for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
658 if (PlaneMaskHasPlane(rMask, pNum))
659 if (DBTypeOnPlane(tres, pNum))
660 dbSetPaintEntry(t1, t2, pNum, tres);
661 }
662 else /* (type == RULE_ERASE) */
663 {
664 /* Apply to all planes of rMask. */
665
666 for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
667 if (PlaneMaskHasPlane(rMask, pNum))
668 if (DBTypeOnPlane(tres, pNum))
669 dbSetEraseEntry(t1, t2, pNum, tres);
670 }
671 }
672 }
673
674 if (type == RULE_PAINT)
675 {
676 /* For all planes of pMask which are not in rMask, result is space */
677
678 for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
679 if (PlaneMaskHasPlane(pMask, pNum))
680 dbSetPaintEntry(t1, t2, pNum, TT_SPACE);
681 }
682 else /* (type == RULE_ERASE) */
683 {
684 /* For all planes of pMask which are not in rMask, result is space */
685
686 for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
687 if (PlaneMaskHasPlane(pMask, pNum))
688 dbSetEraseEntry(t1, t2, pNum, TT_SPACE);
689 }
690 TTMaskSetType(&dbNotDefaultPaintTbl[t1], t2);
691 return TRUE;
692 }
693
694
695 /*
696 * ----------------------------------------------------------------------------
697 *
698 * dbTechCheckPaint --
699 *
700 * DEBUGGING.
701 * Check painting and erasing rules to make sure that the result
702 * type is legal for the plane being affected.
703 *
704 * Results:
705 * None.
706 *
707 * Side effects:
708 * Prints stuff in the event of an error.
709 *
710 * ----------------------------------------------------------------------------
711 */
712
713 void
dbTechCheckPaint(where)714 dbTechCheckPaint(where)
715 char *where; /* If non-null, print this as header */
716 {
717 TileType have, t, result;
718 bool printedHeader = FALSE;
719
720 for (have = TT_TECHDEPBASE; have < DBNumTypes; have++)
721 {
722 for (t = TT_TECHDEPBASE; t < DBNumTypes; t++)
723 {
724 result = DBStdPaintEntry(have, t, DBPlane(have));
725 if (result != TT_SPACE && DBPlane(result) != DBPlane(have))
726 {
727 if (!printedHeader && where)
728 TxPrintf("\n%s:\n", where), printedHeader = TRUE;
729 TxPrintf("%s + %s -> %s\n",
730 DBTypeShortName(have), DBTypeShortName(t),
731 DBTypeShortName(result));
732 }
733 result = DBStdEraseEntry(have, t, DBPlane(have));
734 if (result != TT_SPACE && DBPlane(result) != DBPlane(have))
735 {
736 if (!printedHeader && where)
737 TxPrintf("\n%s:\n", where), printedHeader = TRUE;
738 TxPrintf("%s - %s -> %s\n",
739 DBTypeShortName(have), DBTypeShortName(t),
740 DBTypeShortName(result));
741 }
742 }
743 }
744 }
745
746 /*
747 * ----------------------------------------------------------------------------
748 *
749 * dbTechPrintPaint --
750 *
751 * DEBUGGING.
752 * Print painting and erasing rules. If contactsOnly is TRUe, only
753 * print those rules involving pairs of contact types. The argument
754 * "where" is printed as a header if it is non-NULL. If doPaint is
755 * TRUE, we print the paint rules, else we print the erase rules.
756 *
757 * Results:
758 * None.
759 *
760 * Side effects:
761 * Prints stuff.
762 *
763 * ----------------------------------------------------------------------------
764 */
765
766 void
dbTechPrintPaint(where,doPaint,contactsOnly)767 dbTechPrintPaint(where, doPaint, contactsOnly)
768 char *where; /* If non-null, print this as header */
769 bool doPaint; /* TRUE -> print paint tables, FALSE -> print erase */
770 bool contactsOnly;
771 {
772 TileType have, paint, erase, result;
773 int plane;
774 LayerInfo *lp;
775
776 if (where)
777 TxPrintf("\n%s:\n\n", where);
778
779 if (doPaint)
780 {
781 TxPrintf("PAINTING RULES:\n");
782 for (have = TT_TECHDEPBASE; have < DBNumTypes; have++)
783 {
784 if (contactsOnly && !IsContact(have)) continue;
785 for (paint = TT_TECHDEPBASE; paint < DBNumTypes; paint++)
786 {
787 if (contactsOnly && !IsContact(paint)) continue;
788 for (plane = PL_TECHDEPBASE; plane < DBNumPlanes; plane++)
789 {
790 lp = &dbLayerInfo[have];
791 if (!PlaneMaskHasPlane(lp->l_pmask, plane))
792 continue;
793
794 result = DBStdPaintEntry(have, paint, plane);
795 if (result != have)
796 {
797 TxPrintf("%s ",
798 DBTypeShortName(have));
799 if (IsContact(have))
800 TxPrintf("(on %s) ",
801 DBPlaneLongName(plane));
802 TxPrintf(" + %s -> %s\n",
803 DBTypeShortName(paint),
804 DBTypeShortName(result));
805 }
806 }
807 }
808 }
809 }
810 else
811 {
812 TxPrintf("ERASING RULES:\n");
813 for (have = TT_TECHDEPBASE; have < DBNumTypes; have++)
814 {
815 if (contactsOnly && !IsContact(have)) continue;
816 for (erase = TT_TECHDEPBASE; erase < DBNumTypes; erase++)
817 {
818 if (contactsOnly && !IsContact(erase)) continue;
819 for (plane = PL_TECHDEPBASE; plane < DBNumPlanes; plane++)
820 {
821 lp = &dbLayerInfo[have];
822 if (!PlaneMaskHasPlane(lp->l_pmask, plane))
823 continue;
824
825 result = DBStdEraseEntry(have, erase, plane);
826 if (result != have)
827 {
828 TxPrintf("%s ",
829 DBTypeShortName(have));
830 if (IsContact(have))
831 TxPrintf("(on %s) ",
832 DBPlaneLongName(plane));
833 TxPrintf(" - %s -> %s\n",
834 DBTypeShortName(erase),
835 DBTypeShortName(result));
836 }
837 }
838 }
839 }
840 }
841 }
842