1 ///////////////////////////////////////////////////////////////////////////////
2 // BSD 3-Clause License
3 //
4 // Copyright (c) 2019, Nefelus Inc
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions are met:
9 //
10 // * Redistributions of source code must retain the above copyright notice, this
11 // list of conditions and the following disclaimer.
12 //
13 // * Redistributions in binary form must reproduce the above copyright notice,
14 // this list of conditions and the following disclaimer in the documentation
15 // and/or other materials provided with the distribution.
16 //
17 // * Neither the name of the copyright holder nor the names of its
18 // contributors may be used to endorse or promote products derived from
19 // this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 // POSSIBILITY OF SUCH DAMAGE.
32 #include <dbRtTree.h>
33
34 #include "dbUtil.h"
35 #include "rcx/extRCap.h"
36 #include "utl/Logger.h"
37
38 #ifdef HI_ACC_1
39 #define FRINGE_UP_DOWN
40 #endif
41 //#define CHECK_SAME_NET
42 //#define DEBUG_NET 208091
43 //#define MIN_FOR_LOOPS
44
45 namespace rcx {
46
47 using utl::RCX;
48
49 using odb::dbBlock;
50 using odb::dbBox;
51 using odb::dbBTerm;
52 using odb::dbCapNode;
53 using odb::dbCCSeg;
54 using odb::dbChip;
55 using odb::dbDatabase;
56 using odb::dbNet;
57 using odb::dbRSeg;
58 using odb::dbRtTree;
59 using odb::dbSet;
60 using odb::dbShape;
61 using odb::dbSigType;
62 using odb::dbTech;
63 using odb::dbTechLayer;
64 using odb::dbTechLayerDir;
65 using odb::dbTechLayerType;
66 using odb::dbWire;
67 using odb::dbWirePath;
68 using odb::dbWirePathItr;
69 using odb::dbWirePathShape;
70 using odb::gs;
71 using odb::Rect;
72 using odb::SEQ;
73
computeResDist(SEQ * s,uint trackMin,uint trackMax,uint targetMet,Ath__array1D<SEQ * > * diagTable)74 int extMeasure::computeResDist(SEQ* s, uint trackMin, uint trackMax,
75 uint targetMet, Ath__array1D<SEQ*>* diagTable) {
76 int trackDist = 4;
77 int loTrack;
78 int hiTrack;
79 int planeIndex =
80 getDgPlaneAndTrackIndex(targetMet, trackDist, loTrack, hiTrack);
81 if (planeIndex < 0)
82 return 0;
83
84 uint len = 0;
85
86 Ath__array1D<SEQ*> tmpTable(16);
87 copySeqUsingPool(s, &tmpTable);
88
89 Ath__array1D<SEQ*> residueTable(16);
90
91 int trackTable[200];
92 uint cnt = 0;
93 for (int kk = (int)trackMin; kk <= (int)trackMax;
94 kk++) // skip overlapping track
95 {
96 /* TEST 0322
97 if (!kk)
98 continue; */
99 /*
100 #ifdef HI_ACC_1
101 if (kk <= _dgContextHiTrack[planeIndex])
102 #else
103 if (kk < _dgContextHiTrack[planeIndex])
104 #endif
105 trackTable[cnt++] = *_dgContextTracks / 2 + kk;
106 */
107 if (-kk >= _dgContextLowTrack[planeIndex])
108 trackTable[cnt++] = *_dgContextTracks / 2 - kk;
109 }
110
111 for (uint ii = 0; ii < cnt; ii++) {
112 int trackn = trackTable[ii];
113
114 #ifdef HI_ACC_1
115 if (_dgContextArray[planeIndex][trackn]->getCnt() <= 1)
116 continue;
117 #endif
118 // Check for same track: 032021 DF
119 bool same_track = false;
120 Ath__array1D<SEQ*>* dTable = _dgContextArray[planeIndex][trackn];
121 int cnt = (int)dTable->getCnt();
122 for (uint idx = 1; idx < (int)cnt; idx++) {
123 SEQ* tseq = dTable->get(idx);
124 if (tseq->type == _rsegSrcId) {
125 same_track = true;
126 break;
127 }
128 }
129 if (same_track)
130 continue;
131
132 bool add_all_diag = false;
133 if (!add_all_diag) {
134 for (uint jj = 0; jj < tmpTable.getCnt(); jj++)
135 len += computeRes(tmpTable.get(jj), targetMet, _dir, planeIndex, trackn,
136 &residueTable);
137 } else {
138 len += computeRes(s, targetMet, _dir, planeIndex, trackn, &residueTable);
139 }
140
141 seq_release(&tmpTable);
142 tableCopyP(&residueTable, &tmpTable);
143 residueTable.resetCnt();
144 }
145 // seq_release(&tmpTable);
146 if (diagTable != NULL)
147 tableCopyP(&tmpTable, diagTable);
148 else
149 seq_release(&tmpTable);
150 return len;
151 }
computeRes(SEQ * s,uint targetMet,uint dir,uint planeIndex,uint trackn,Ath__array1D<SEQ * > * residueSeq)152 uint extMeasure::computeRes(SEQ* s, uint targetMet, uint dir, uint planeIndex,
153 uint trackn, Ath__array1D<SEQ*>* residueSeq) {
154 Ath__array1D<SEQ*>* dgContext = _dgContextArray[planeIndex][trackn];
155 if (dgContext->getCnt() <= 1)
156 return 0;
157
158 Ath__array1D<SEQ*> overlapSeq(16);
159 getDgOverlap_res(s, _dir, dgContext, &overlapSeq, residueSeq);
160
161 uint len = 0;
162 for (uint jj = 0; jj < overlapSeq.getCnt(); jj++) {
163 SEQ* tgt = overlapSeq.get(jj);
164 uint diagDist = calcDist(tgt->_ll, tgt->_ur);
165 uint tgWidth = tgt->_ur[_dir] - tgt->_ll[_dir];
166 uint len1 = getLength(tgt, !_dir);
167
168 DebugDiagCoords(_met, targetMet, len1, diagDist, tgt->_ll, tgt->_ur);
169 int d2 = _dist > 0 ? diagDist - _dist - (_ur[_dir] - _ll[_dir]) : diagDist;
170 int w2 = tgt->_ur[_dir] - tgt->_ll[_dir];
171 const char* x = _dir ? "x" : "y";
172 const char* y = _dir ? "y" : "x";
173 // fprintf(stdout, " %s %7d %7d %s=%d W%d L%d D%d d2=%d\n",
174 // x, tgt->_ll[!_dir], tgt->_ur[!_dir], y, tgt->_ll[_dir], w2, len1,
175 // diagDist, d2);
176 len += len1;
177 calcRes(_rsegSrcId, len1, _dist, diagDist, _met);
178 }
179 seq_release(&overlapSeq);
180 return len;
181 }
getMaxDist(int tgtMet,uint modelIndex)182 int extMeasure::getMaxDist(int tgtMet, uint modelIndex) {
183 uint modelCnt = _metRCTable.getCnt();
184 if (modelCnt == 0)
185 return -1;
186
187 extMetRCTable* rcModel = _metRCTable.get(modelIndex);
188 if (rcModel->_resOver[tgtMet] == NULL)
189 return -1;
190
191 extDistRCTable* distTable =
192 rcModel->_resOver[tgtMet]->getRuleTable(0, _width);
193
194 int maxDist = distTable->getComputeRC_maxDist();
195 return maxDist;
196 }
getComputeRC_maxDist()197 int extDistRCTable::getComputeRC_maxDist() { return _maxDist; }
calcRes(int rsegId1,uint len,int dist1,int dist2,int tgtMet)198 void extMeasure::calcRes(int rsegId1, uint len, int dist1, int dist2,
199 int tgtMet) {
200 if (dist1 == -1)
201 dist1 = 0;
202 if (dist2 == -1)
203 dist1 = 0;
204 int min_dist = 0;
205 if (dist1 > dist2) {
206 min_dist = dist1;
207 dist1 = dist2;
208 dist2 = min_dist;
209 }
210 uint modelCnt = _metRCTable.getCnt();
211 for (uint ii = 0; ii < modelCnt; ii++) {
212 extMetRCTable* rcModel = _metRCTable.get(ii);
213 if (rcModel->_resOver[tgtMet] == NULL)
214 continue;
215
216 extDistRC* rc = rcModel->_resOver[tgtMet]->getRes(0, _width, dist1, dist2);
217 if (rc != NULL) {
218 double R1 = rc->_diag > 0 ? rc->_diag : rc->_res;
219 double R = len * R1;
220 _rc[ii]->_res += R;
221 }
222 }
223 }
calcRes0(double * deltaRes,uint tgtMet,uint len,int dist1,int dist2)224 void extMeasure::calcRes0(double* deltaRes, uint tgtMet, uint len, int dist1,
225 int dist2) {
226 uint modelCnt = _metRCTable.getCnt();
227 for (uint ii = 0; ii < modelCnt; ii++) {
228 extMetRCTable* rcModel = _metRCTable.get(ii);
229 if (rcModel->_resOver[tgtMet] == NULL)
230 continue;
231
232 extDistRC* rc = rcModel->_resOver[tgtMet]->getRes(0, _width, dist1, dist2);
233 double R = len * rc->_res;
234 deltaRes[ii] = R;
235 }
236 }
calcRes0(double * deltaRes,uint tgtMet,uint width,uint len,int dist1,int dist2)237 void extMain::calcRes0(double* deltaRes, uint tgtMet, uint width, uint len,
238 int dist1, int dist2) {
239 for (uint jj = 0; jj < _modelMap.getCnt(); jj++) {
240 uint modelIndex = _modelMap.get(jj);
241 extMetRCTable* rcModel = _currentModel->getMetRCTable(modelIndex);
242
243 if (rcModel->_resOver[tgtMet] == NULL)
244 continue;
245
246 extDistRC* rc = rcModel->_resOver[tgtMet]->getRes(0, width, dist1, dist2);
247 if (rc == NULL)
248 continue;
249 double R = len * rc->_res;
250 deltaRes[jj] = R;
251 }
252 }
findRes(int dist1,int dist2,bool compute)253 extDistRC* extDistRCTable::findRes(int dist1, int dist2, bool compute) {
254 Ath__array1D<extDistRC*>* table = _computeTable;
255 if (!compute)
256 table = _measureTable;
257
258 if (table->getCnt() == 0)
259 return NULL;
260
261 int target_dist_index = -1;
262 extDistRC* rc = NULL;
263 uint ii = 0;
264 for (; ii < table->getCnt(); ii++) {
265 rc = table->get(ii);
266 if (dist1 == rc->_coupling) {
267 target_dist_index = ii;
268 break;
269 }
270 if (dist1 < rc->_coupling) {
271 target_dist_index = ii;
272 break;
273 }
274 }
275 if (target_dist_index < 0) {
276 rc = table->get(0); // assume first rec is 0,0
277 return rc;
278 }
279 extDistRC* last_rc = NULL;
280 for (uint ii = target_dist_index; ii < table->getCnt(); ii++) {
281 extDistRC* rc1 = table->get(ii);
282 if (rc->_coupling != rc1->_coupling) {
283 return last_rc;
284 }
285 if (dist2 == rc1->_sep) {
286 return rc1;
287 }
288 if (dist2 < rc1->_sep) {
289 if (last_rc != NULL)
290 return last_rc;
291 return rc1;
292 }
293 last_rc = rc1;
294 }
295 if (table->getCnt() > 0) {
296 rc = table->get(0); // assume first rec is 0,0
297 return rc;
298 }
299 return NULL;
300 }
getComputeRC_res(uint dist1,uint dist2)301 extDistRC* extDistRCTable::getComputeRC_res(uint dist1, uint dist2) {
302 int min_dist = 0;
303 if (dist1 > dist2) {
304 min_dist = dist1;
305 dist1 = dist2;
306 dist2 = min_dist;
307 }
308 if (_measureTable == NULL)
309 return NULL;
310
311 if (_measureTable->getCnt() <= 0)
312 return NULL;
313
314 extDistRC* rc1 = _measureTableR[0]->geti(0);
315 rc1->_diag = 0.0;
316 if (rc1 == NULL)
317 return NULL;
318
319 if (dist1 + dist2 == 0) { // ASSUMPTION: 0 dist exists as first
320 return rc1;
321 }
322 if (dist1 >= _maxDist && dist2 >= _maxDist) {
323 return NULL;
324 }
325 if (dist2 > _maxDist) {
326 dist2 = dist1;
327 dist1 = 0;
328 }
329
330 uint index_dist = 0;
331 bool found = false;
332 extDistRC* rc2 = rc2 = _measureTableR[1]->geti(0);
333 if (rc2 == NULL)
334 return rc1; // TO TEST
335
336 if (dist1 <= rc1->_sep) {
337 index_dist = 0;
338 found = true;
339 } else if (dist1 < rc2->_sep) {
340 index_dist = 0;
341 found = true;
342 } else if (dist1 == rc2->_sep) {
343 index_dist = 1;
344 found = true;
345 } else {
346 index_dist = 2;
347 }
348 extDistRC* rc = NULL;
349 if (!found) {
350 // find first dist
351
352 uint ii;
353 for (ii = index_dist; ii < _distCnt; ii++) {
354 rc = _measureTableR[ii]->geti(0);
355 if (dist1 == rc->_sep) {
356 found = true;
357 index_dist = ii;
358 break;
359 }
360 if (dist1 < rc->_sep) {
361 found = true;
362 index_dist = ii;
363 break;
364 }
365 }
366 if (!found && ii == _distCnt) {
367 index_dist = ii - 1;
368 found = true;
369 }
370 }
371 if (found) {
372 _measureTable = _measureTableR[index_dist];
373 _computeTable = _computeTableR[index_dist];
374 extDistRC* res = findIndexed_res(dist1, dist2);
375 res->_diag = 0;
376 if (rc != NULL && dist1 < rc->_sep) {
377 _measureTable = _measureTableR[index_dist - 1];
378 _computeTable = _computeTableR[index_dist - 1];
379 extDistRC* res1 = findIndexed_res(dist1, dist2);
380 double R = (res->_res + res1->_res) / 2;
381 double R1 = res->interpolate_res(dist1, res1);
382 res1->_diag = R1;
383 return res1;
384 }
385 return res;
386 }
387 return NULL;
388 }
findIndexed_res(uint dist1,uint dist2)389 extDistRC* extDistRCTable::findIndexed_res(uint dist1, uint dist2) {
390 extDistRC* firstRC = _measureTable->get(0);
391 uint firstDist = firstRC->_sep;
392 if (dist2 <= firstDist) {
393 return firstRC;
394 }
395 if (_measureTable->getCnt() == 1) {
396 return firstRC;
397 }
398 extDistRC* resLast = _measureTable->getLast();
399 if (dist2 >= resLast->_sep)
400 return resLast;
401
402 uint n = dist2 / _unit;
403 extDistRC* res = _computeTable->geti(n);
404 return res;
405 }
406
getRes(uint mou,uint w,int dist1,int dist2)407 extDistRC* extDistWidthRCTable::getRes(uint mou, uint w, int dist1, int dist2) {
408 int wIndex = getWidthIndex(w);
409 if (wIndex < 0)
410 return NULL;
411
412 // extDistRC *rc= _rcDistTable[mou][wIndex]->findRes(dist1, dist2, false);
413 extDistRC* rc = _rcDistTable[mou][wIndex]->getComputeRC_res(dist1, dist2);
414
415 return rc;
416 }
getRuleTable(uint mou,uint w)417 extDistRCTable* extDistWidthRCTable::getRuleTable(uint mou, uint w) {
418 int wIndex = getWidthIndex(w);
419 if (wIndex < 0)
420 return NULL;
421
422 return _rcDistTable[mou][wIndex];
423 }
424
getDgOverlap_res(SEQ * sseq,uint dir,Ath__array1D<SEQ * > * dgContext,Ath__array1D<SEQ * > * overlapSeq,Ath__array1D<SEQ * > * residueSeq)425 void extMeasure::getDgOverlap_res(SEQ* sseq, uint dir,
426 Ath__array1D<SEQ*>* dgContext,
427 Ath__array1D<SEQ*>* overlapSeq,
428 Ath__array1D<SEQ*>* residueSeq) {
429 int idx = 1;
430 uint lp = dir ? 0 : 1; // x : y
431 uint wp = dir ? 1 : 0; // y : x
432 SEQ* rseq;
433 SEQ* tseq;
434 SEQ* wseq;
435 int covered = sseq->_ll[lp];
436
437 #ifdef HI_ACC_1
438 if (idx == dgContext->getCnt()) {
439 rseq = _seqPool->alloc();
440 rseq->_ll[wp] = sseq->_ll[wp];
441 rseq->_ur[wp] = sseq->_ur[wp];
442 rseq->_ll[lp] = sseq->_ll[lp];
443 rseq->_ur[lp] = sseq->_ur[lp];
444 residueSeq->add(rseq);
445 return;
446 }
447 #endif
448
449 dbRSeg* srseg = NULL;
450 if (_rsegSrcId > 0)
451 srseg = dbRSeg::getRSeg(_block, _rsegSrcId);
452 for (; idx < (int)dgContext->getCnt(); idx++) {
453 tseq = dgContext->get(idx);
454 if (tseq->_ur[lp] <= covered)
455 continue;
456
457 if (tseq->_ll[lp] >= sseq->_ur[lp]) {
458 rseq = _seqPool->alloc();
459 rseq->_ll[wp] = sseq->_ll[wp];
460 rseq->_ur[wp] = sseq->_ur[wp];
461 rseq->_ll[lp] = covered;
462 rseq->_ur[lp] = sseq->_ur[lp];
463 assert(rseq->_ur[lp] >= rseq->_ll[lp]);
464 residueSeq->add(rseq);
465 break;
466 }
467 #ifdef CHECK_SAME_NET
468 dbRSeg* trseg = NULL;
469 if (tseq->type > 0)
470 trseg = dbRSeg::getRSeg(_block, tseq->type);
471 if ((trseg != NULL) && (srseg != NULL) &&
472 (trseg->getNet() == srseg->getNet())) {
473 if ((tseq->_ur[lp] >= sseq->_ur[lp]) ||
474 (idx == (int)dgContext->getCnt() - 1)) {
475 rseq = _seqPool->alloc();
476 rseq->_ll[wp] = sseq->_ll[wp];
477 rseq->_ur[wp] = sseq->_ur[wp];
478 rseq->_ll[lp] = covered;
479 rseq->_ur[lp] = sseq->_ur[lp];
480 assert(rseq->_ur[lp] >= rseq->_ll[lp]);
481 residueSeq->add(rseq);
482 break;
483 } else
484 continue;
485 }
486 #endif
487 wseq = _seqPool->alloc();
488 wseq->type = tseq->type;
489 wseq->_ll[wp] = tseq->_ll[wp];
490 wseq->_ur[wp] = tseq->_ur[wp];
491 if (tseq->_ur[lp] <= sseq->_ur[lp])
492 wseq->_ur[lp] = tseq->_ur[lp];
493 else
494 wseq->_ur[lp] = sseq->_ur[lp];
495 if (tseq->_ll[lp] <= covered)
496 wseq->_ll[lp] = covered;
497 else {
498 wseq->_ll[lp] = tseq->_ll[lp];
499 rseq = _seqPool->alloc();
500 rseq->_ll[wp] = sseq->_ll[wp];
501 rseq->_ur[wp] = sseq->_ur[wp];
502 rseq->_ll[lp] = covered;
503 rseq->_ur[lp] = tseq->_ll[lp];
504 assert(rseq->_ur[lp] >= rseq->_ll[lp]);
505 residueSeq->add(rseq);
506 }
507 assert(wseq->_ur[lp] >= wseq->_ll[lp]);
508 overlapSeq->add(wseq);
509 covered = wseq->_ur[lp];
510 if (tseq->_ur[lp] >= sseq->_ur[lp])
511 break;
512 if (idx == (int)dgContext->getCnt() - 1 && covered < sseq->_ur[lp]) {
513 rseq = _seqPool->alloc();
514 rseq->_ll[wp] = sseq->_ll[wp];
515 rseq->_ur[wp] = sseq->_ur[wp];
516 rseq->_ll[lp] = covered;
517 rseq->_ur[lp] = sseq->_ur[lp];
518 assert(rseq->_ur[lp] >= rseq->_ll[lp]);
519 residueSeq->add(rseq);
520 }
521 }
522 dgContext->get(0)->_ll[0] = idx;
523 if (idx == dgContext->getCnt() && residueSeq->getCnt() == 0) {
524 rseq = _seqPool->alloc();
525 rseq->_ll[wp] = sseq->_ll[wp];
526 rseq->_ur[wp] = sseq->_ur[wp];
527 rseq->_ll[lp] = sseq->_ll[lp];
528 rseq->_ur[lp] = sseq->_ur[lp];
529 residueSeq->add(rseq);
530 }
531 }
532
533 } // namespace rcx
534