forked from RTimothyEdwards/magic
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgrouteCrss.c
795 lines (731 loc) · 24.4 KB
/
grouteCrss.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
/*
* grouteCross.c -
*
* Global signal router. Code to do crossing placement.
*
* *********************************************************************
* * Copyright (C) 1985, 1990 Regents of the University of California. *
* * Permission to use, copy, modify, and distribute this *
* * software and its documentation for any purpose and without *
* * fee is hereby granted, provided that the above copyright *
* * notice appear in all copies. The University of California *
* * makes no representations about the suitability of this *
* * software for any purpose. It is provided "as is" without *
* * express or implied warranty. Export of this software outside *
* * of the United States of America may require an export license. *
* *********************************************************************
* Lawrence Livermore National Laboratory
*/
#ifndef lint
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/grouter/grouteCrss.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
#endif /* not lint */
#include <stdio.h>
#include <string.h>
#include "utils/magic.h"
#include "utils/geometry.h"
#include "utils/geofast.h"
#include "utils/hash.h"
#include "utils/heap.h"
#include "utils/malloc.h"
#include "debug/debug.h"
#include "tiles/tile.h"
#include "database/database.h"
#include "gcr/gcr.h"
#include "windows/windows.h"
#include "utils/main.h"
#include "dbwind/dbwind.h"
#include "utils/signals.h"
#include "router/router.h"
#include "grouter/grouter.h"
#include "utils/netlist.h"
#include "textio/textio.h"
#include "utils/styles.h"
/* Passed to glCrossChoose() */
GlPoint *glCrossLookAhead;
/* The following penalties get scaled by RtrGridSpacing */
int glJogPenalty = 5;
int glObsPenalty1 = 5, glObsPenalty2 = 3;
int glNbrPenalty1 = 2, glNbrPenalty2 = 5;
int glOrphanPenalty = 3;
int glChanPenalty = 1;
bool glPenaltiesScaled = FALSE;
/* Forward declarations */
GlPoint *glCrossAdjust();
int glCrossChoose();
void glCrossTakePin();
/*
* ----------------------------------------------------------------------------
*
* glCrossMark --
*
* Mark all the pins crossed by the linked list of GlPoints pointed to
* by 'path' as taken. This list is linked along the gl_path pointers.
* The starting entry 'path' indicates a pin reserved for a NLTermLoc;
* the last entry is one of the pins on the previous starting-point list.
*
* Results:
* None.
*
* Side effects:
* Marks the pins along the path as taken by 'net'.
* Assigns a segment identifier to each pin that is different
* for each pair of GlPoints in the path.
* Increments pNetId->netid_seg once for each new segment identifier
* created.
* Updates the density information in each channel as the pins are
* marked as taken.
*
* ----------------------------------------------------------------------------
*/
void
glCrossMark(rootUse, path, pNetId)
CellUse *rootUse; /* For error feedback if non-NULL */
GlPoint *path; /* Path linked via gl_path pointers */
NetId *pNetId; /* Net and segment identifier; netid_seg is updated */
{
GCRPin *srcPin, *dstPin;
GlPoint *rp;
bool srcTaken;
NetId markNetId;
/*
* Walk from path back along gl_path pointers down the list.
* At each step, process the segment between srcPin and
* dstPin in the channel srcPin->gcr_ch.
*/
for (rp = path; rp->gl_path; rp = rp->gl_path)
{
/*
* Increment the segment id once for each channel the net passes
* through. The intent is to make this net appear different to
* the channel router for each global segment processed.
*/
pNetId->netid_seg++;
glCrossingsUsed++;
/*
* Figure out which segment number to use:
* If srcPin has already been assigned a net, use its segment id
* to mark dstPin and don't do anything to srcPin; otherwise,
* use pNetId->netid_seg as the segment identifier and mark
* both pins as taken.
*/
markNetId = *pNetId;
srcPin = rp->gl_path->gl_pin;
srcTaken = srcPin->gcr_pId && srcPin->gcr_pSeg != GCR_STEMSEGID;
if (srcTaken)
markNetId.netid_seg = srcPin->gcr_pSeg;
/* Pick the dest pin in the same channel as srcPin */
dstPin = rp->gl_pin;
if (dstPin->gcr_ch != srcPin->gcr_ch) dstPin = dstPin->gcr_linked;
ASSERT(dstPin&&dstPin->gcr_ch == srcPin->gcr_ch, "glCrossMark");
/* Adjust the density -- must happen before pins are marked! */
if (glDensAdjust(((GlobChan *) srcPin->gcr_ch->gcr_client)->gc_postDens,
srcPin, dstPin, markNetId))
glChanBlockDens(srcPin->gcr_ch);
/* Mark pins as taken */
if (!srcTaken)
glCrossTakePin(rootUse, srcPin, markNetId);
glCrossTakePin(rootUse, dstPin, markNetId);
}
}
/*
* ----------------------------------------------------------------------------
*
* glCrossTakePin --
*
* Reserve a channel's pin for the given net.
* Make a number of sanity checks.
*
* Results:
* None.
*
* Side effects:
* Marks the pin as being taken by the net, by setting
* gcr_pId and gcr_pSeg.
*
* ----------------------------------------------------------------------------
*/
void
glCrossTakePin(rootUse, pin, netid)
CellUse *rootUse; /* For error feedback if non-NULL */
GCRPin *pin; /* Pin to take */
NetId netid; /* Identifier to assign */
{
char c[2048+64], name1[1024], name2[1024];
Rect r;
if (DebugIsSet(glDebugID, glDebGreedy))
return;
if (DebugIsSet(glDebugID, glDebCross))
{
glShowCross(pin, netid, CROSS_PERM);
TxMore("-- crossing --");
}
r.r_ll = r.r_ur = pin->gcr_point; r.r_xtop++; r.r_ytop++;
ASSERT(netid.netid_net != (NLNet *) NULL, "glCrossTakePin");
if (pin->gcr_pId == (GCRNet *) NULL
|| (pin->gcr_pId == (GCRNet *) netid.netid_net
&& pin->gcr_pSeg == GCR_STEMSEGID))
{
pin->gcr_pId = (GCRNet *) netid.netid_net;
pin->gcr_pSeg = netid.netid_seg;
/* Unlink from list along channel side */
if (pin->gcr_pPrev && (pin->gcr_pPrev->gcr_pNext = pin->gcr_pNext))
pin->gcr_pNext->gcr_pPrev = pin->gcr_pPrev;
}
else if (pin->gcr_pId == (GCRNet *) netid.netid_net
&& pin->gcr_pSeg == netid.netid_seg)
{
(void) sprintf(c, "Warning: crossing reassigned to same net/seg");
if (rootUse)
DBWFeedbackAdd(&r, c, rootUse->cu_def, 1, STYLE_PALEHIGHLIGHTS);
else TxError("%s\n", c);
}
else
{
/* Shouldn't happen: indicates a bug elsewhere */
(void) strcpy(name1, NLNetName(pin->gcr_pId));
(void) strcpy(name2, NLNetName(netid.netid_net));
(void) sprintf(c, "Crossing multiply used, nets %s/%d, %s/%d",
name1, pin->gcr_pSeg, name2, netid.netid_seg);
if (rootUse)
DBWFeedbackAdd(&r, c, rootUse->cu_def, 1, STYLE_PALEHIGHLIGHTS);
else TxError("%s\n", c);
}
}
/*
* ----------------------------------------------------------------------------
*
* glCrossUnreserve --
*
* Visit all of the pins used by the stems of the NLNet 'net' and reset
* the gcr_pId and gcr_pSeg fields to show a NULL net and no segment id.
* This procedure is called only just prior to the global routing for each
* net; it keeps the crossings that might be used by this net reserved up
* until the last possible minute, but makes sure that they don't stay
* reserved once we actually know the routing for this net (since otherwise
* the channel router would try to connect them up!).
*
* Results:
* None.
*
* Side effects:
* See above.
*
* ----------------------------------------------------------------------------
*/
void
glCrossUnreserve(net)
NLNet *net;
{
NLTermLoc *loc;
NLTerm *term;
GCRPin *pin;
/* De-reserve the pins taken by each terminal location in this net */
for (term = net->nnet_terms; term; term = term->nterm_next)
for (loc = term->nterm_locs; loc; loc = loc->nloc_next)
{
pin = loc->nloc_pin;
ASSERT(pin->gcr_pSeg == GCR_STEMSEGID, "glCrossUnreserve");
pin->gcr_pId = (GCRNet *) NULL;
pin->gcr_pSeg = 0;
}
}
/*
* ----------------------------------------------------------------------------
*
* glCrossEnum --
*
* Enumerate the crossing points between the tile inPt->gl_tile
* and 'tp'. The two tiles should overlap different channels.
*
* For each available crossing (i.e., a pin that is yet unassigned
* and has a linked pin), call the procedure (*func)(), which should
* be of the following form:
*
* int
* (*func)(inPt, tp, pin, cdata)
* GlPoint *inPt; /# Same as inPt passed to glCrossEnum #/
* Tile *tp; /# Same as tp passed to glCrossEnum #/
* GCRPin *pin; /# A free pin in 'tp' #/
* ClientData cdata; /# Same as cdata passed to glCrossEnum #/
* {
* }
*
* If (*func)() returns 1, glCrossEnum() immediately stops visiting
* further crossing points and returns 1 itself; otherwise, we keep
* going until we run out of crossing points to visit.
*
* Results:
* Returns 1 if (*func)() returned 1; otherwise, returns 0.
*
* Side effects:
* Whatever (*func)() does.
*
* ----------------------------------------------------------------------------
*/
int
glCrossEnum(inPt, tp, func, cdata)
GlPoint *inPt; /* Top of heap point being expanded */
Tile *tp; /* Tile adjacent to inPt->gl_tile */
int (*func)(); /* Called for each crossing */
ClientData cdata; /* Passed to (*func)() */
{
int outSide, origin, lo, hi, max, start, n, nhi;
GCRChannel *ch = inPt->gl_pin->gcr_ch;
Tile *inTile = inPt->gl_tile;
GCRPin *pins, *pin;
/* Sanity checks: callers should ensure that these are true */
ASSERT(tp->ti_client != (ClientData) CLIENTDEFAULT, "glCrossEnum");
ASSERT((GCRChannel *) tp->ti_client != ch, "glCrossEnum");
/*
* Find out the direction from inTile to tp.
* We assume that the two tiles share a side, so this
* is pretty straightforward.
*/
if (LEFT(inTile) == RIGHT(tp)) outSide = GEO_WEST;
else if (RIGHT(inTile) == LEFT(tp)) outSide = GEO_EAST;
else if (TOP(inTile) == BOTTOM(tp)) outSide = GEO_NORTH;
else if (BOTTOM(inTile) == TOP(tp)) outSide = GEO_SOUTH;
/*
* Find the range of points shared between the two tiles.
* Note that we look at the TILES, not the CHANNELS, since
* there can be many tiles for a single channel.
*/
if (outSide == GEO_NORTH || outSide == GEO_SOUTH)
{
lo = MAX(LEFT(inTile), LEFT(tp));
hi = MIN(RIGHT(inTile), RIGHT(tp));
origin = ch->gcr_origin.p_x;
max = ch->gcr_length;
}
else
{
lo = MAX(BOTTOM(inTile), BOTTOM(tp));
hi = MIN(TOP(inTile), TOP(tp));
origin = ch->gcr_origin.p_y;
max = ch->gcr_width;
}
/*
* Now find the range of pins shared between the two tiles.
* We're careful about which pins are actually shared: we
* round the lower coordinate up unless it's grid-aligned,
* but round the higher coordinate down even if it is
* grid-aligned. I.e.,
*
* lo' = pin with least coordinate >= lo
* hi' = pin with greatest coordinate < hi
*
* The range of pins shared should be non-NULL; if it's not,
* something is wrong (most likely the channel is too small).
* The pins range from lo to hi, inclusive, and should not
* include pin[0] or pin[length+1] or pin[width+1] (the latter
* respectively for vertical or horizontal edges between tiles).
*/
lo = (lo + RtrGridSpacing - 1 - origin) / RtrGridSpacing;
hi = (hi - origin - 1) / RtrGridSpacing;
ASSERT(lo >= 1 && lo <= max, "glCrossEnum");
if (lo > hi)
return 0;
switch (outSide)
{
case GEO_NORTH: pins = ch->gcr_tPins; break;
case GEO_SOUTH: pins = ch->gcr_bPins; break;
case GEO_EAST: pins = ch->gcr_rPins; break;
case GEO_WEST: pins = ch->gcr_lPins; break;
}
/*
* Now comes the fun part: enumerating pins in the range
* from lo .. hi inclusive in such a way that we visit
* the CLOSEST pin to inPt FIRST. Choose start so that
* it's the index of the closest pin on the exit side to
* inPt, and then worry about whether or not it's in the
* range of pins shared with the next tile.
*/
start = (outSide == GEO_NORTH || outSide == GEO_SOUTH)
? inPt->gl_pin->gcr_x
: inPt->gl_pin->gcr_y;
/* CASE 1: visit from bottom to top (or left to right) */
if (start <= lo)
{
for (n = lo; n <= hi; n++, glCrossingsSeen++)
{
pin = &pins[n];
if (PINOK(pin) && PINOK(pin->gcr_linked)
&& (*func)(inPt, tp, pin->gcr_linked, cdata))
return 1;
}
return 0;
}
/* CASE 1: visit from top to bottom (or right to left) */
if (start >= hi)
{
for (n = hi; n >= lo; n--, glCrossingsSeen++)
{
pin = &pins[n];
if (PINOK(pin) && PINOK(pin->gcr_linked)
&& (*func)(inPt, tp, pin->gcr_linked, cdata))
return 1;
}
return 0;
}
/*
* CASE 3:
* Have to consider candidates alternating from
* left to right (or top to bottom) to find the
* closest available pin. Start at the center.
*/
for (n = start, nhi = start+1; n >= lo || nhi <= hi; n--, nhi++)
{
if (n >= lo)
{
glCrossingsSeen++;
pin = &pins[n];
if (PINOK(pin) && PINOK(pin->gcr_linked)
&& (*func)(inPt, tp, pin->gcr_linked, cdata))
return 1;
}
if (nhi <= hi)
{
glCrossingsSeen++;
pin = &pins[nhi];
if (PINOK(pin) && PINOK(pin->gcr_linked)
&& (*func)(inPt, tp, pin->gcr_linked, cdata))
return 1;
}
}
return 0;
}
/*
* ----------------------------------------------------------------------------
*
* glCrossAdjust --
*
* Given a path of crossing points, wiggle them around in each channel
* to try to reduce the total penalty on the path. Construct a new
* path of crossing points that uses the points we select in this way,
* and whose cost fields (gl_cost) include both distance and the
* penalties. Be careful when wiggling crossings through a river
* routing channel: they all have to wiggle at the same time.
*
* Algorithm:
* Two crossing points in the input path are already fixed:
* path itself, and the crossing point at the very end (the
* one for which gl_path is NULL). Starting from the crossing
* point at the end and working back toward 'path', assign
* crossings to all points in the middle. The procedure to
* do this is recursive, considering at each stage three
* crossing points: one that has already been assigned
* (which is either the last point in the path, or the result
* of the previous recursive call), one that is to be assigned
* (the current point along the path), and a "lookahead" point
* (the one that will be next assigned, so we can consider
* it as well when positining the current point.
*
* Results:
* Returns a pointer to the final point in a new path of crossings,
* linked via their gl_path pointers.
*
* Side effects:
* See above.
*
* ----------------------------------------------------------------------------
*/
GlPoint *
glCrossAdjust(lookAhead, path)
GlPoint *lookAhead; /* Normally, lookAhead->gl_path == path, except on the
* initial call, in which case lookAhead == NULL.
*/
GlPoint *path; /* Adjust crossings along this path */
{
GlPoint *newPath, *newRest;
GCRPin *linkedPin, *pin;
GCRChannel *ch;
/*
* The location of the last crossing along the path is fixed,
* since it's the "starting point". Simply return when we
* reach this point, since there's no penalty to be computed
* yet.
*/
ASSERT(path != (GlPoint *) NULL, "glCrossAdjust");
if (path->gl_path == (GlPoint *) NULL)
return path;
/*
* Basic recursive step: assign crossings to everything
* in the remainder of the path, then cons a new GlPoint
* to the front of the path and adjust its position
* below. The initial cost of newPath will be that
* to the pin it initially occupies, before being
* wiggled by glCrossChoose() later. This gives
* us an upper bound on an acceptable cost.
*/
newRest = glCrossAdjust(path, path->gl_path);
newPath = glPathNew(path->gl_pin, 0, newRest);
newPath->gl_cost = newRest->gl_cost + glCrossCost(lookAhead, path, newRest);
newPath->gl_tile = path->gl_tile;
/*
* If this was the first crossing in the path, it's also
* immutable and so we just cons it to the path and return.
* We still use a new GlPoint, though, since the cost of
* this point has to include the penalties along the path.
*/
if (lookAhead == (GlPoint *) NULL)
return newPath;
if (TiGetType(newRest->gl_tile) != CHAN_NORMAL)
{
/*
* If newRest was through a river-routing channel, it fixes
* the pin on the exit side.
*/
pin = newRest->gl_pin;
ch = pin->gcr_ch;
switch (pin->gcr_side)
{
case GEO_NORTH: linkedPin = &ch->gcr_bPins[pin->gcr_x]; break;
case GEO_EAST: linkedPin = &ch->gcr_lPins[pin->gcr_y]; break;
case GEO_SOUTH: linkedPin = &ch->gcr_tPins[pin->gcr_x]; break;
case GEO_WEST: linkedPin = &ch->gcr_rPins[pin->gcr_y]; break;
}
ASSERT(PINOK(linkedPin), "glCrossAdjust");
newPath->gl_pin = linkedPin->gcr_linked;
newPath->gl_cost = newRest->gl_cost;
newPath->gl_cost += glCrossCost(lookAhead, newPath, newRest);
}
else
{
/*
* Time to choose a crossing for 'path'.
* It has to lie somewhere along the boundary between path->gl_tile
* and newRest->gl_tile. (These two tiles will be different unless
* path is the destination point, but we checked for that above when
* we looked for lookAhead being NULL). Enumerate the crossings
* along this boundary looking for the best one.
*/
glCrossLookAhead = lookAhead;
(void) glCrossEnum(newRest, path->gl_tile, glCrossChoose,
(ClientData) newPath);
}
return newPath;
}
/*
* ----------------------------------------------------------------------------
*
* glCrossChoose --
*
* Called by glCrossEnum() on behalf of glCrossAdjust() above.
* Evaluate 'pin' as a possible crossing by computing the penalty of
* a segment from newRest through newPath (setting newPath->gl_pin to
* pin), and on through to glCrossLookAhead (if it's non-NULL).
*
* Results:
* Returns 0 normally, or 1 to tell glCrossEnum() that it
* can stop looking at further crossings.
*
* Side effects:
* May modify newPath->gl_cost and newPath->gl_pin.
*
* ----------------------------------------------------------------------------
*/
/*ARGSUSED*/
int
glCrossChoose(newRest, tp, pin, newPath)
GlPoint *newRest; /* Portion of path already assigned */
Tile *tp; /* UNUSED */
GCRPin *pin; /* Pin on boundary of tp being considered */
GlPoint *newPath; /* Update newPath->gl_pin, newPath->gl_cost */
{
GCRPin *savePin;
int cost;
/*
* We've been visiting crossings in order of increasing distance
* from newRest. If the distance to 'pin' plus newRest->gl_cost
* already exceeds the best cost we've been able to find for
* newPath, then we can't gain any more improvement by considering
* any more crossing point, so we stop.
*/
cost = ABSDIFF(pin->gcr_point.p_x, newRest->gl_pin->gcr_point.p_x)
+ ABSDIFF(pin->gcr_point.p_y, newRest->gl_pin->gcr_point.p_y)
+ newRest->gl_cost;
if (cost >= newPath->gl_cost)
return 1;
/*
* Evaluate the cost of using 'pin' as the crossing point.
* If it's a better choice than what's currently stored in newPath,
* then use it and update the cost in newPath.
*/
savePin = newPath->gl_pin;
newPath->gl_pin = pin;
cost = newRest->gl_cost + glCrossCost(glCrossLookAhead, newPath, newRest);
if (cost < newPath->gl_cost)
newPath->gl_cost = cost;
else
newPath->gl_pin = savePin;
/* Keep looking at more crossing points */
return 0;
}
/*
* ----------------------------------------------------------------------------
*
* glCrossCost --
*
* Evaluate the cost of the segment from 'entryPt' to 'exitPt' (and on through
* 'lookAhead' if it is non-NULL).
*
* Results:
* Returns the sum of the distance from rest to path and the
* penalties associated with this segment.
*
* Side effects:
* None.
*
* ----------------------------------------------------------------------------
*/
int
glCrossCost(lookAhead, exitPt, entryPt)
GlPoint *lookAhead;
GlPoint *exitPt;
GlPoint *entryPt;
{
GCRPin *entryPin, *exitPin, *otherPin;
GCRPin *opposite;
int count, cost;
/*
* Make sure that both entryPin and exitPin are in the same
* channel, and otherPin is in the next channel.
*/
entryPin = entryPt->gl_pin;
exitPin = exitPt->gl_pin;
if (exitPin->gcr_ch != entryPin->gcr_ch)
exitPin = exitPin->gcr_linked;
otherPin = exitPin->gcr_linked;
ASSERT(exitPin != NULL, "glCrossCost");
/* Distance cost */
cost = ABSDIFF(entryPin->gcr_point.p_x, exitPin->gcr_point.p_x)
+ ABSDIFF(entryPin->gcr_point.p_y, exitPin->gcr_point.p_y);
/*
* If exitPt is in a river-routing tile, and we have to continue
* across the channel (lookAhead is non-NULL), then make sure the pin
* on the opposite side is free; otherwise, exitPt has "infinite"
* penalty since it's unusable.
*/
if (lookAhead && TiGetType(exitPt->gl_tile) != CHAN_NORMAL)
{
switch (otherPin->gcr_side)
{
case GEO_NORTH:
opposite = &otherPin->gcr_ch->gcr_bPins[otherPin->gcr_x];
break;
case GEO_SOUTH:
opposite = &otherPin->gcr_ch->gcr_tPins[otherPin->gcr_x];
break;
case GEO_EAST:
opposite = &otherPin->gcr_ch->gcr_lPins[otherPin->gcr_y];
break;
case GEO_WEST:
opposite = &otherPin->gcr_ch->gcr_rPins[otherPin->gcr_y];
break;
}
if (!PINOK(opposite))
return INFINITY;
}
/* Penalty for using lots of channels */
cost += glChanPenalty;
/* Penalize if the net doesn't run straight across the channel */
if (entryPin->gcr_x != exitPin->gcr_x && entryPin->gcr_y != exitPin->gcr_y)
cost += glJogPenalty;
/*
* If there is an obstacle or hazard over a crossing, or an
* obstacle somewhere along the track or column of the pin,
* then assess a penalty. Look on both sides of the crossing
* to get this penalty.
*/
#define BADCROSSFLAGS (GCROBST|GCRHAZRD|GCRTCC)
if (otherPin && otherPin->gcr_ch->gcr_type == CHAN_NORMAL)
{
if ((otherPin->gcr_pFlags & BADCROSSFLAGS) || otherPin->gcr_pSize != 0)
{
ASSERT(otherPin->gcr_pSize >= 0, "glCrossPenalty");
cost += glObsPenalty1;
if (otherPin->gcr_pFlags & GCROBST)
cost += glObsPenalty2 * otherPin->gcr_pSize;
else if (otherPin->gcr_pFlags & GCRHAZRD)
cost += MAX(glObsPenalty2*otherPin->gcr_pSize
- otherPin->gcr_pDist, 0);
}
}
/*
* Done if this channel is used for river-routing (in which
* case the subsequent penalty computation is not needed).
*/
if (entryPin->gcr_ch->gcr_type != CHAN_NORMAL)
return cost;
if ((exitPin->gcr_pFlags & BADCROSSFLAGS) || exitPin->gcr_pSize != 0)
{
ASSERT(exitPin->gcr_pSize >= 0, "glCrossPenalty");
cost += glObsPenalty1;
if (exitPin->gcr_pFlags & GCROBST)
cost += glObsPenalty2 * exitPin->gcr_pSize;
else if (exitPin->gcr_pFlags & GCRHAZRD)
cost += MAX(glObsPenalty2 * exitPin->gcr_pSize
- exitPin->gcr_pDist, 0);
}
/* Penalty for "congestion" (neighboring pins in use) */
count = 0;
if ((exitPin + 1)->gcr_pId) count++;
if ((exitPin - 1)->gcr_pId) count++;
if (count == 2) cost += glNbrPenalty2;
else if (count == 1) cost += glNbrPenalty1;
/*
* If the path turns in the channel and the exit crossing
* isn't a paired orphan, assess a penalty.
*/
if (exitPin->gcr_side != GeoOppositePos[entryPin->gcr_side])
{
switch (exitPin->gcr_side)
{
case GEO_NORTH:
otherPin = &entryPin->gcr_ch->gcr_bPins[exitPin->gcr_x];
break;
case GEO_SOUTH:
otherPin = &entryPin->gcr_ch->gcr_tPins[exitPin->gcr_x];
break;
case GEO_EAST:
otherPin = &entryPin->gcr_ch->gcr_lPins[exitPin->gcr_y];
break;
case GEO_WEST:
otherPin = &entryPin->gcr_ch->gcr_rPins[exitPin->gcr_y];
break;
}
if (otherPin->gcr_pId == (GCRNet *) NULL)
cost += glOrphanPenalty;
}
return cost;
}
/*
* ----------------------------------------------------------------------------
*
* glCrossScalePenalties --
*
* Scale the penalties used in the global router cost function so they
* reflect the actual grid size used during routing.
*
* Results:
* None.
*
* Side effects:
* See above.
*
* ----------------------------------------------------------------------------
*/
void
glCrossScalePenalties()
{
if (glPenaltiesScaled)
return;
glPenaltiesScaled = TRUE;
glJogPenalty *= RtrGridSpacing;
glObsPenalty1 *= RtrGridSpacing;
glObsPenalty2 *= RtrGridSpacing;
glNbrPenalty1 *= RtrGridSpacing;
glNbrPenalty2 *= RtrGridSpacing;
glOrphanPenalty *= RtrGridSpacing;
glChanPenalty *= RtrGridSpacing;
}