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