1
2 #ifndef lint
3 static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/resis/ResBasic.c,v 1.3 2010/06/24 12:37:56 tim Exp $";
4 #endif /* not lint */
5
6 #include <stdio.h>
7 #include <string.h>
8 #include <ctype.h>
9 #include <math.h>
10
11 #include "utils/magic.h"
12 #include "utils/geometry.h"
13 #include "utils/geofast.h"
14 #include "tiles/tile.h"
15 #include "utils/hash.h"
16 #include "database/database.h"
17 #include "utils/malloc.h"
18 #include "textio/textio.h"
19 #include "extract/extract.h"
20 #include "extract/extractInt.h"
21 #include "windows/windows.h"
22 #include "dbwind/dbwind.h"
23 #include "utils/tech.h"
24 #include "textio/txcommands.h"
25 #include "resis/resis.h"
26
27 int resSubDevFunc();
28
29 /*
30 *--------------------------------------------------------------------------
31 *
32 * resNodeIsPort --
33 *
34 * If the given position is inside any port declared on the tile,
35 * change the node name to the port name. Remove the port
36 * declaration if it was used.
37 *
38 *--------------------------------------------------------------------------
39 */
40
41 void
resNodeIsPort(node,x,y,tile)42 resNodeIsPort(node, x, y, tile)
43 resNode *node;
44 int x;
45 int y;
46 Tile *tile;
47 {
48 Rect *rect;
49 Point p;
50 resPort *pl, *lp;
51 tileJunk *junk = (tileJunk *)(tile->ti_client);
52
53 p.p_x = x;
54 p.p_y = y;
55
56 for (pl = junk->portList; pl; pl = pl->rp_nextPort)
57 {
58 rect = &(pl->rp_bbox);
59 if (GEO_ENCLOSE(&p, rect))
60 {
61 node->rn_name = pl->rp_nodename;
62 if (junk->portList == pl)
63 junk->portList = pl->rp_nextPort;
64 else
65 {
66 for (lp = junk->portList; lp && (lp->rp_nextPort != pl);
67 lp = lp->rp_nextPort);
68 lp->rp_nextPort = pl->rp_nextPort;
69 }
70 freeMagic(pl);
71 break;
72 }
73 }
74 }
75
76 /*
77 *--------------------------------------------------------------------------
78 *
79 * resAllPortNodes --
80 *
81 * Generate new nodes and breakpoints for every unused port declared
82 * on a tile.
83 *
84 *--------------------------------------------------------------------------
85 */
86
87 void
resAllPortNodes(tile,list)88 resAllPortNodes(tile, list)
89 Tile *tile;
90 resNode **list;
91 {
92 int x, y;
93 resNode *resptr;
94 resPort *pl;
95 tileJunk *junk = (tileJunk *)(tile->ti_client);
96
97 for (pl = junk->portList; pl; pl = pl->rp_nextPort)
98 {
99 x = pl->rp_loc.p_x;
100 y = pl->rp_loc.p_y;
101 resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode)));
102 InitializeNode(resptr, x, y, RES_NODE_ORIGIN);
103 resptr->rn_status = TRUE;
104 resptr->rn_noderes = 0;
105 resptr->rn_name = pl->rp_nodename;
106 ResAddToQueue(resptr, list);
107 NEWBREAK(resptr, tile, x, y, NULL);
108 freeMagic(pl);
109 }
110 }
111
112 /*
113 *--------------------------------------------------------------------------
114 *
115 * ResMultiPlaneFunc---
116 *
117 * If device is found overlapping one of its source/drain types, then
118 * generate a new device at the center of the tile and add to ResNodeQueue.
119 *
120 * Results:
121 * Always 0 to keep the search going.
122 *
123 * Side effects:
124 * Adds to ResNodeQueue
125 *
126 *--------------------------------------------------------------------------
127 */
128
129 int
ResMultiPlaneFunc(tile,tpptr)130 ResMultiPlaneFunc(tile, tpptr)
131 Tile *tile, **tpptr;
132 {
133 Tile *tp = *tpptr;
134 int xj, yj;
135
136 xj = (LEFT(tile) + RIGHT(tile)) / 2;
137 yj = (TOP(tile) + BOTTOM(tile)) / 2;
138 ResNewSDDevice(tp, tile, xj, yj, OTHERPLANE, &ResNodeQueue);
139
140 return 0;
141 }
142
143 /*
144 *--------------------------------------------------------------------------
145 *
146 * ResSubstrateFunc---
147 *
148 * If device is found overlapping its substrate type, then generate a new
149 * device at the center of the tile and add to ResNodeQueue.
150 *
151 * Results:
152 * Always 0 to keep the search going.
153 *
154 * Side effects:
155 * Adds to ResNodeQueue
156 *
157 *--------------------------------------------------------------------------
158 */
159
160 int
ResSubstrateFunc(tile,tpptr)161 ResSubstrateFunc(tile, tpptr)
162 Tile *tile, **tpptr;
163 {
164 Tile *tp = *tpptr;
165 int xj, yj;
166
167 xj = (LEFT(tile) + RIGHT(tile)) / 2;
168 yj = (TOP(tile) + BOTTOM(tile)) / 2;
169 ResNewSubDevice(tp, tile, xj, yj, OTHERPLANE, &ResNodeQueue);
170
171 return 0;
172 }
173
174 /*
175 *--------------------------------------------------------------------------
176 *
177 * ResEachTile--for each tile, make a list of all possible current sources/
178 * sinks including contacts, devices, and junctions. Once this
179 * list is made, calculate the resistor network for the tile.
180 *
181 * Results: returns TRUE or FALSE depending on whether a node was
182 * involved in a merge.
183 *
184 * Side Effects: creates Nodes, devices, junctions, and breakpoints.
185 *
186 *
187 *--------------------------------------------------------------------------
188 */
189
190 bool
ResEachTile(tile,startpoint)191 ResEachTile(tile, startpoint)
192 Tile *tile;
193 Point *startpoint;
194
195 {
196 Tile *tp;
197 resNode *resptr;
198 cElement *ce;
199 TileType t1, t2;
200 int xj, yj, i;
201 bool merged;
202 tElement *tcell;
203 tileJunk *tstructs= (tileJunk *)(tile->ti_client);
204 ExtDevice *devptr;
205
206 ResTileCount++;
207
208 /* Process startpoint, if any. */
209
210 if (IsSplit(tile))
211 {
212 t1 = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
213 }
214 else
215 t1 = TiGetTypeExact(tile);
216
217 if (startpoint != (Point *) NULL)
218 {
219 int x = startpoint->p_x;
220 int y = startpoint->p_y;
221 resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode)));
222 InitializeNode(resptr, x, y, RES_NODE_ORIGIN);
223 resptr->rn_status = TRUE;
224 resptr->rn_noderes = 0;
225 ResAddToQueue(resptr, &ResNodeQueue);
226 NEWBREAK(resptr, tile, x, y, NULL);
227 resCurrentNode = resptr;
228 resNodeIsPort(resptr, x, y, tile);
229 }
230
231 if TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t1)
232 {
233 /*
234 * The device is put in the center of the tile. This is fine
235 * for single tile device, but not as good for multiple ones.
236 */
237
238 if (tstructs->tj_status & RES_TILE_DEV)
239 {
240 if (tstructs->deviceList->rd_fet_gate == NULL)
241 {
242 int x = (LEFT(tile) + RIGHT(tile)) >> 1;
243 int y = (TOP(tile) + BOTTOM(tile)) >> 1;
244
245 resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode)));
246 tstructs->deviceList->rd_fet_gate = resptr;
247 tcell = (tElement *) mallocMagic((unsigned)(sizeof(tElement)));
248 tcell->te_thist = tstructs->deviceList;
249 tcell->te_nextt = NULL;
250
251 InitializeNode(resptr, x, y, RES_NODE_JUNCTION);
252 resptr->rn_te = tcell;
253 ResAddToQueue(resptr, &ResNodeQueue);
254 resNodeIsPort(resptr, x, y, tile);
255
256 NEWBREAK(resptr, tile, resptr->rn_loc.p_x,
257 resptr->rn_loc.p_y, NULL);
258 }
259 }
260 }
261
262 /* Process all the contact points */
263 ce = tstructs->contactList;
264 while (ce != (cElement *) NULL)
265 {
266 ResContactPoint *cp = ce->ce_thisc;
267 cElement *oldce;
268 if (cp->cp_cnode[0] == (resNode *) NULL)
269 {
270 ResDoContacts(cp, &ResNodeQueue, &ResResList);
271 }
272 oldce = ce;
273 ce = ce->ce_nextc;
274 freeMagic((char *)oldce);
275 }
276 tstructs->contactList = NULL;
277
278 /*
279 * Walk the four sides of the tile looking for adjoining connecting
280 * materials.
281 */
282
283 /* left */
284 for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp=RT(tp))
285 {
286 t2 = TiGetRightType(tp);
287 devptr = ExtCurStyle->exts_device[t2];
288 if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t2) &&
289 TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), t1))
290 /* found device */
291 {
292 xj = LEFT(tile);
293 yj = (TOP(tp) + BOTTOM(tp)) >> 1;
294 ResNewSDDevice(tile, tp, xj, yj, RIGHTEDGE, &ResNodeQueue);
295 }
296 if TTMaskHasType(&(ExtCurStyle->exts_nodeConn[t1]), t2)
297 /* tile is junction */
298 {
299 /*junction rn_loc */
300 xj = LEFT(tile);
301 yj = (MAX(BOTTOM(tile), BOTTOM(tp)) + MIN(TOP(tile), TOP(tp))) >> 1;
302 (void) ResProcessJunction(tile, tp, xj, yj, &ResNodeQueue);
303 }
304 }
305
306 /* right */
307 for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp=LB(tp))
308 {
309 t2 = TiGetLeftType(tp);
310 devptr = ExtCurStyle->exts_device[t2];
311 if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t2) &&
312 TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), t1))
313 /* found device */
314 {
315 xj = RIGHT(tile);
316 yj = (TOP(tp)+BOTTOM(tp))>>1;
317 ResNewSDDevice(tile, tp, xj, yj, LEFTEDGE, &ResNodeQueue);
318 }
319 if TTMaskHasType(&ExtCurStyle->exts_nodeConn[t1], t2)
320 /* tile is junction */
321 {
322 /*junction rn_loc */
323 xj = RIGHT(tile);
324 yj = (MAX(BOTTOM(tile),BOTTOM(tp)) + MIN(TOP(tile), TOP(tp))) >> 1;
325 (void)ResProcessJunction(tile, tp, xj, yj, &ResNodeQueue);
326 }
327 }
328
329 /* top */
330 for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp=BL(tp))
331 {
332 t2 = TiGetBottomType(tp);
333 devptr = ExtCurStyle->exts_device[t2];
334 if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t2) &&
335 TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), t1))
336 /* found device */
337 {
338 yj = TOP(tile);
339 xj = (LEFT(tp)+RIGHT(tp))>>1;
340 ResNewSDDevice(tile, tp, xj, yj, BOTTOMEDGE, &ResNodeQueue);
341 }
342 if TTMaskHasType(&ExtCurStyle->exts_nodeConn[t1],t2)
343 /* tile is junction */
344 {
345 yj = TOP(tile);
346 xj = (MAX(LEFT(tile),LEFT(tp)) + MIN(RIGHT(tile),RIGHT(tp))) >> 1;
347 ResProcessJunction(tile, tp, xj, yj, &ResNodeQueue);
348 }
349 }
350
351 /* bottom */
352 for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp=TR(tp))
353 {
354 t2 = TiGetTopType(tp);
355 devptr = ExtCurStyle->exts_device[t2];
356 if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t2) &&
357 TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), t1))
358 /* found device */
359 {
360 yj = BOTTOM(tile);
361 xj = (LEFT(tp) + RIGHT(tp)) >> 1;
362 ResNewSDDevice(tile, tp, xj, yj, TOPEDGE, &ResNodeQueue);
363 }
364 if TTMaskHasType(&(ExtCurStyle->exts_nodeConn[t1]), t2)
365 /* tile is junction */
366 {
367 yj = BOTTOM(tile);
368 xj = (MAX(LEFT(tile),LEFT(tp)) + MIN(RIGHT(tile),RIGHT(tp))) >> 1;
369 ResProcessJunction(tile, tp, xj, yj, &ResNodeQueue);
370 }
371 }
372
373 /* Check for source/drain on other planes (e.g., capacitors, bipolars, ...) */
374
375 if (TTMaskHasType(&ResSDTypesBitMask, t1))
376 {
377 Rect r;
378 int pNum;
379 TileTypeBitMask devMask;
380
381 TiToRect(tile, &r);
382
383 for (pNum = 0; pNum < DBNumPlanes; pNum++)
384 {
385 if (DBTypeOnPlane(t1, pNum)) continue;
386
387 /* NOTE: This is ridiculously inefficient and should be done
388 * in a different way.
389 */
390
391 TTMaskZero(&devMask);
392 for (t2 = TT_TECHDEPBASE; t2 < DBNumUserLayers; t2++)
393 for (devptr = ExtCurStyle->exts_device[t2]; devptr;
394 devptr = devptr->exts_next)
395 for (i = 0; !TTMaskIsZero(&devptr->exts_deviceSDTypes[i]); i++)
396 if (TTMaskHasType(&devptr->exts_deviceSDTypes[i], t1))
397 TTMaskSetType(&devMask, t2);
398
399 DBSrPaintArea((Tile *)NULL, ResUse->cu_def->cd_planes[pNum],
400 &r, &devMask, ResMultiPlaneFunc, (ClientData)&tile);
401 }
402 }
403
404 /* Check for substrate under device */
405
406 if (TTMaskHasType(&ResSubTypesBitMask, t1))
407 {
408 Rect r;
409 int pNum;
410 TileTypeBitMask devMask;
411
412 TiToRect(tile, &r);
413
414 for (pNum = 0; pNum < DBNumPlanes; pNum++)
415 {
416 if (DBTypeOnPlane(t1, pNum)) continue;
417
418 /* NOTE: This is ridiculously inefficient and should be done
419 * in a different way.
420 */
421
422 TTMaskZero(&devMask);
423 for (t2 = TT_TECHDEPBASE; t2 < DBNumUserLayers; t2++)
424 for (devptr = ExtCurStyle->exts_device[t2]; devptr;
425 devptr = devptr->exts_next)
426 if (TTMaskHasType(&devptr->exts_deviceSubstrateTypes, t1))
427 TTMaskSetType(&devMask, t2);
428
429 DBSrPaintArea((Tile *)NULL, ResUse->cu_def->cd_planes[pNum],
430 &r, &devMask, ResSubstrateFunc, (ClientData)&tile);
431 }
432 }
433
434 tstructs->tj_status |= RES_TILE_DONE;
435
436 resAllPortNodes(tile, &ResNodeQueue);
437
438 merged = ResCalcTileResistance(tile, tstructs, &ResNodeQueue,
439 &ResNodeList);
440
441 return(merged);
442 }
443
444 /*
445 *-------------------------------------------------------------------------
446 *
447 * resSubDevFunc -- called when DBSrPaintArea finds a device within
448 * a substrate area.
449 *
450 * Results: always returns 0 to keep search going.
451 *
452 * Side Effects: allocates substrate node.
453 *
454 *-------------------------------------------------------------------------
455 */
456
457 int
resSubDevFunc(tile,tp)458 resSubDevFunc(tile, tp)
459 Tile *tile, *tp;
460 {
461 tileJunk *junk = (tileJunk *)(tile->ti_client);
462 resNode *resptr;
463 tElement *tcell;
464 int x, y;
465
466 if (junk->deviceList->rd_fet_subs == NULL)
467 {
468 resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode)));
469 junk->deviceList->rd_fet_subs = resptr;
470 junk->tj_status |= RES_TILE_DEV;
471 tcell = (tElement *) mallocMagic((unsigned)(sizeof(tElement)));
472 tcell->te_thist = junk->deviceList;
473 tcell->te_nextt = NULL;
474 x = (LEFT(tile) + RIGHT(tile)) >> 1;
475 y = (TOP(tile) + BOTTOM(tile)) >> 1;
476
477 InitializeNode(resptr, x, y, RES_NODE_JUNCTION);
478 resptr->rn_te = tcell;
479 ResAddToQueue(resptr, &ResNodeQueue);
480
481 NEWBREAK(resptr, tp, x, y, NULL);
482 }
483 return 0;
484 }
485