Files
magic/resis/ResBasic.c
T
Darryl L. Miles 606f37cc80 Ti[GS]etClient() usage enforcement
All naked access to `ti_client` now uses the function-like-macro
to encapsulate this action.  This macro existed before this just
makes all sites utilize it.

Added additional INT and PTR variants to remove the programmer
load on thinking about casing and casts polluting the point
of use.  So the use now looks cleaner.

Equivalent prototypes:

 void TiSetClient(Tile*, ClientData)
 void TiSetClientINT(Tile*, intptr_t) /* pointertype */
 void TiSetClientPTR(Tile*, void*)

 ClientData TiGetClient(Tile*)
 intptr_t TiGetClientINT(Tile*) /* pointertype */
 void *TiGetClientPTR(Tile*)
2025-04-09 14:55:58 -04:00

479 lines
12 KiB
C

#ifndef lint
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 $";
#endif /* not lint */
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include "utils/magic.h"
#include "utils/geometry.h"
#include "utils/geofast.h"
#include "tiles/tile.h"
#include "utils/hash.h"
#include "database/database.h"
#include "utils/malloc.h"
#include "textio/textio.h"
#include "extract/extract.h"
#include "extract/extractInt.h"
#include "windows/windows.h"
#include "dbwind/dbwind.h"
#include "utils/tech.h"
#include "textio/txcommands.h"
#include "resis/resis.h"
/*
*--------------------------------------------------------------------------
*
* resNodeIsPort --
*
* If the given position is inside any port declared on the tile,
* change the node name to the port name. Remove the port
* declaration if it was used.
*
*--------------------------------------------------------------------------
*/
void
resNodeIsPort(node, x, y, tile)
resNode *node;
int x;
int y;
Tile *tile;
{
Rect *rect;
Point p;
resPort *pl, *lp;
tileJunk *junk = (tileJunk *)TiGetClientPTR(tile);
p.p_x = x;
p.p_y = y;
for (pl = junk->portList; pl; pl = pl->rp_nextPort)
{
rect = &(pl->rp_bbox);
if (GEO_ENCLOSE(&p, rect))
{
node->rn_name = pl->rp_nodename;
if (junk->portList == pl)
junk->portList = pl->rp_nextPort;
else
{
for (lp = junk->portList; lp && (lp->rp_nextPort != pl);
lp = lp->rp_nextPort);
lp->rp_nextPort = pl->rp_nextPort;
}
freeMagic(pl);
break;
}
}
}
/*
*--------------------------------------------------------------------------
*
* resAllPortNodes --
*
* Generate new nodes and breakpoints for every unused port declared
* on a tile.
*
*--------------------------------------------------------------------------
*/
void
resAllPortNodes(tile, list)
Tile *tile;
resNode **list;
{
int x, y;
resNode *resptr;
resPort *pl;
tileJunk *junk = (tileJunk *)TiGetClientPTR(tile);
for (pl = junk->portList; pl; pl = pl->rp_nextPort)
{
x = pl->rp_loc.p_x;
y = pl->rp_loc.p_y;
resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode)));
InitializeNode(resptr, x, y, RES_NODE_ORIGIN);
resptr->rn_status = TRUE;
resptr->rn_noderes = 0;
resptr->rn_name = pl->rp_nodename;
ResAddToQueue(resptr, list);
NEWBREAK(resptr, tile, x, y, NULL);
freeMagic(pl);
}
}
/*
*--------------------------------------------------------------------------
*
* ResMultiPlaneFunc---
*
* If device is found overlapping one of its source/drain types, then
* generate a new device at the center of the tile and add to ResNodeQueue.
*
* Results:
* Always 0 to keep the search going.
*
* Side effects:
* Adds to ResNodeQueue
*
*--------------------------------------------------------------------------
*/
int
ResMultiPlaneFunc(tile, tpptr)
Tile *tile, **tpptr;
{
Tile *tp = *tpptr;
int xj, yj;
xj = (LEFT(tile) + RIGHT(tile)) / 2;
yj = (TOP(tile) + BOTTOM(tile)) / 2;
ResNewSDDevice(tp, tile, xj, yj, OTHERPLANE, &ResNodeQueue);
return 0;
}
/*
*--------------------------------------------------------------------------
*
* ResSubstrateFunc---
*
* If device is found overlapping its substrate type, then generate a new
* device at the center of the tile and add to ResNodeQueue.
*
* Results:
* Always 0 to keep the search going.
*
* Side effects:
* Adds to ResNodeQueue
*
*--------------------------------------------------------------------------
*/
int
ResSubstrateFunc(tile, tpptr)
Tile *tile, **tpptr;
{
Tile *tp = *tpptr;
int xj, yj;
xj = (LEFT(tile) + RIGHT(tile)) / 2;
yj = (TOP(tile) + BOTTOM(tile)) / 2;
ResNewSubDevice(tp, tile, xj, yj, OTHERPLANE, &ResNodeQueue);
return 0;
}
/*
*--------------------------------------------------------------------------
*
* ResEachTile--for each tile, make a list of all possible current sources/
* sinks including contacts, devices, and junctions. Once this
* list is made, calculate the resistor network for the tile.
*
* Results: returns TRUE or FALSE depending on whether a node was
* involved in a merge.
*
* Side Effects: creates Nodes, devices, junctions, and breakpoints.
*
*
*--------------------------------------------------------------------------
*/
bool
ResEachTile(tile, startpoint)
Tile *tile;
Point *startpoint;
{
Tile *tp;
resNode *resptr;
cElement *ce;
TileType t1, t2;
int xj, yj, i;
bool merged;
tElement *tcell;
tileJunk *tstructs= (tileJunk *)TiGetClientPTR(tile);
ExtDevice *devptr;
ResTileCount++;
/* Process startpoint, if any. */
if (IsSplit(tile))
{
t1 = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
}
else
t1 = TiGetTypeExact(tile);
if (startpoint != (Point *) NULL)
{
int x = startpoint->p_x;
int y = startpoint->p_y;
resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode)));
InitializeNode(resptr, x, y, RES_NODE_ORIGIN);
resptr->rn_status = TRUE;
resptr->rn_noderes = 0;
ResAddToQueue(resptr, &ResNodeQueue);
NEWBREAK(resptr, tile, x, y, NULL);
resCurrentNode = resptr;
resNodeIsPort(resptr, x, y, tile);
}
if TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t1)
{
/*
* The device is put in the center of the tile. This is fine
* for single tile device, but not as good for multiple ones.
*/
if (tstructs->tj_status & RES_TILE_DEV)
{
if (tstructs->deviceList->rd_fet_gate == NULL)
{
int x = (LEFT(tile) + RIGHT(tile)) >> 1;
int y = (TOP(tile) + BOTTOM(tile)) >> 1;
resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode)));
tstructs->deviceList->rd_fet_gate = resptr;
tcell = (tElement *) mallocMagic((unsigned)(sizeof(tElement)));
tcell->te_thist = tstructs->deviceList;
tcell->te_nextt = NULL;
InitializeNode(resptr, x, y, RES_NODE_JUNCTION);
resptr->rn_te = tcell;
ResAddToQueue(resptr, &ResNodeQueue);
resNodeIsPort(resptr, x, y, tile);
NEWBREAK(resptr, tile, resptr->rn_loc.p_x,
resptr->rn_loc.p_y, NULL);
}
}
}
/* Process all the contact points */
ce = tstructs->contactList;
while (ce != (cElement *) NULL)
{
ResContactPoint *cp = ce->ce_thisc;
cElement *oldce;
if (cp->cp_cnode[0] == (resNode *) NULL)
{
ResDoContacts(cp, &ResNodeQueue, &ResResList);
}
oldce = ce;
ce = ce->ce_nextc;
freeMagic((char *)oldce);
}
tstructs->contactList = NULL;
/*
* Walk the four sides of the tile looking for adjoining connecting
* materials.
*/
/* left */
for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp=RT(tp))
{
t2 = TiGetRightType(tp);
if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t2))
{
for (devptr = ExtCurStyle->exts_device[t2]; devptr;
devptr = devptr->exts_next)
{
for (i = 0; i < devptr->exts_deviceSDCount; i++)
{
if (TTMaskHasType(&(devptr->exts_deviceSDTypes[i]), t1))
{
/* found device */
xj = LEFT(tile);
yj = (TOP(tp) + BOTTOM(tp)) >> 1;
ResNewSDDevice(tile, tp, xj, yj, RIGHTEDGE, &ResNodeQueue);
break;
}
}
if (i < devptr->exts_deviceSDCount) break;
}
}
if TTMaskHasType(&(ExtCurStyle->exts_nodeConn[t1]), t2)
{
/* tile is junction */
xj = LEFT(tile);
yj = (MAX(BOTTOM(tile), BOTTOM(tp)) + MIN(TOP(tile), TOP(tp))) >> 1;
(void) ResProcessJunction(tile, tp, xj, yj, &ResNodeQueue);
}
}
/* right */
for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp=LB(tp))
{
t2 = TiGetLeftType(tp);
if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t2))
{
for (devptr = ExtCurStyle->exts_device[t2]; devptr;
devptr = devptr->exts_next)
{
for (i = 0; i < devptr->exts_deviceSDCount; i++)
{
if (TTMaskHasType(&(devptr->exts_deviceSDTypes[i]), t1))
{
/* found device */
xj = RIGHT(tile);
yj = (TOP(tp) + BOTTOM(tp)) >> 1;
ResNewSDDevice(tile, tp, xj, yj, LEFTEDGE, &ResNodeQueue);
break;
}
}
if (i < devptr->exts_deviceSDCount) break;
}
}
if TTMaskHasType(&ExtCurStyle->exts_nodeConn[t1], t2)
{
/* tile is junction */
xj = RIGHT(tile);
yj = (MAX(BOTTOM(tile),BOTTOM(tp)) + MIN(TOP(tile), TOP(tp))) >> 1;
(void)ResProcessJunction(tile, tp, xj, yj, &ResNodeQueue);
}
}
/* top */
for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp))
{
t2 = TiGetBottomType(tp);
if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t2))
{
for (devptr = ExtCurStyle->exts_device[t2]; devptr;
devptr = devptr->exts_next)
{
for (i = 0; i < devptr->exts_deviceSDCount; i++)
{
if (TTMaskHasType(&(devptr->exts_deviceSDTypes[i]), t1))
{
/* found device */
yj = TOP(tile);
xj = (LEFT(tp) + RIGHT(tp)) >> 1;
ResNewSDDevice(tile, tp, xj, yj, BOTTOMEDGE, &ResNodeQueue);
break;
}
}
if (i < devptr->exts_deviceSDCount) break;
}
}
if TTMaskHasType(&ExtCurStyle->exts_nodeConn[t1], t2)
{
/* tile is junction */
yj = TOP(tile);
xj = (MAX(LEFT(tile),LEFT(tp)) + MIN(RIGHT(tile),RIGHT(tp))) >> 1;
ResProcessJunction(tile, tp, xj, yj, &ResNodeQueue);
}
}
/* bottom */
for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp=TR(tp))
{
t2 = TiGetTopType(tp);
if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t2))
{
for (devptr = ExtCurStyle->exts_device[t2]; devptr;
devptr = devptr->exts_next)
{
for (i = 0; i < devptr->exts_deviceSDCount; i++)
{
if (TTMaskHasType(&(devptr->exts_deviceSDTypes[i]), t1))
{
/* found device */
yj = BOTTOM(tile);
xj = (LEFT(tp) + RIGHT(tp)) >> 1;
ResNewSDDevice(tile, tp, xj, yj, TOPEDGE, &ResNodeQueue);
break;
}
}
if (i < devptr->exts_deviceSDCount) break;
}
}
if TTMaskHasType(&(ExtCurStyle->exts_nodeConn[t1]), t2)
{
/* tile is junction */
yj = BOTTOM(tile);
xj = (MAX(LEFT(tile),LEFT(tp)) + MIN(RIGHT(tile),RIGHT(tp))) >> 1;
ResProcessJunction(tile, tp, xj, yj, &ResNodeQueue);
}
}
/* Check for source/drain on other planes (e.g., capacitors, bipolars, ...) */
if (TTMaskHasType(&ResSDTypesBitMask, t1))
{
Rect r;
int pNum;
TileTypeBitMask devMask;
TiToRect(tile, &r);
for (pNum = 0; pNum < DBNumPlanes; pNum++)
{
if (DBTypeOnPlane(t1, pNum)) continue;
/* NOTE: This is ridiculously inefficient and should be done
* in a different way.
*/
TTMaskZero(&devMask);
for (t2 = TT_TECHDEPBASE; t2 < DBNumUserLayers; t2++)
for (devptr = ExtCurStyle->exts_device[t2]; devptr;
devptr = devptr->exts_next)
for (i = 0; !TTMaskIsZero(&devptr->exts_deviceSDTypes[i]); i++)
if (TTMaskHasType(&devptr->exts_deviceSDTypes[i], t1))
TTMaskSetType(&devMask, t2);
DBSrPaintArea((Tile *)NULL, ResUse->cu_def->cd_planes[pNum],
&r, &devMask, ResMultiPlaneFunc, (ClientData)&tile);
}
}
/* Check for substrate under device */
if (TTMaskHasType(&ResSubTypesBitMask, t1))
{
Rect r;
int pNum;
TileTypeBitMask devMask;
TiToRect(tile, &r);
for (pNum = 0; pNum < DBNumPlanes; pNum++)
{
if (DBTypeOnPlane(t1, pNum)) continue;
/* NOTE: This is ridiculously inefficient and should be done
* in a different way.
*/
TTMaskZero(&devMask);
for (t2 = TT_TECHDEPBASE; t2 < DBNumUserLayers; t2++)
for (devptr = ExtCurStyle->exts_device[t2]; devptr;
devptr = devptr->exts_next)
if (TTMaskHasType(&devptr->exts_deviceSubstrateTypes, t1))
TTMaskSetType(&devMask, t2);
DBSrPaintArea((Tile *)NULL, ResUse->cu_def->cd_planes[pNum],
&r, &devMask, ResSubstrateFunc, (ClientData)&tile);
}
}
tstructs->tj_status |= RES_TILE_DONE;
resAllPortNodes(tile, &ResNodeQueue);
merged = ResCalcTileResistance(tile, tstructs, &ResNodeQueue,
&ResNodeList);
return(merged);
}