Files
magic/resis/ResBasic.c
T
Tim Edwards b493334c73 Preliminary changes to support extraction devices other than the original
simple FET device in extresist.  Also:  Extended the bloat-all CIF operator
again, allowing the trigger layer for the bloat operation to include both
CIF layers and magic layers (previously only magic layers were supported).
This extension is possible due to the previous extension allowing the
trigger layer and bloating layers to be on separate planes.  This operator
extension is useful for tagging geometry that is in the proximity of, but
not overlapping, geometry on another plane.
2019-10-17 16:21:56 -04:00

392 lines
10 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"
int resSubDevFunc();
/*
*--------------------------------------------------------------------------
*
* 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 *)(tile->ti_client);
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 *)(tile->ti_client);
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);
}
}
/*
*--------------------------------------------------------------------------
*
* 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 nextwork 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 *)(tile->ti_client);
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);
}
}
}
#ifdef ARIEL
if (i = ExtCurStyle->exts_plugSignalNum[t1])
{
tcell = (tElement *) mallocMagic((unsigned)(sizeof(tElement)));
tcell->te_thist= ResImageAddPlug(tile, i, resCurrentNode);
tcell->te_nextt = resCurrentNode->rn_te;
resCurrentNode->rn_te = tcell;
}
if (TTMaskHasType(&ResSubsTypeBitMask,t1) &&
(ResOptionsFlags & ResOpt_DoSubstrate))
{
int pNum;
Rect tileArea;
TileTypeBitMask *mask = &ExtCurStyle->exts_subsTransistorTypes[t1];
TiToRect(tile,&tileArea);
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
{
if (TTMaskIntersect(&DBPlaneTypes[pNum], mask))
{
(void)DBSrPaintArea((Tile *) NULL,
ResUse->cu_def->cd_planes[pNum],
&tileArea, mask, resSubDevFunc, (ClientData) tile);
}
}
}
#endif
/* 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);
devptr = ExtCurStyle->exts_device[t2];
if(TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t2) &&
TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), t1))
/* found device */
{
xj = LEFT(tile);
yj = (TOP(tp) + BOTTOM(tp)) >> 1;
ResNewSDDevice(tile, tp, xj, yj, RIGHTEDGE, &ResNodeQueue);
}
if TTMaskHasType(&(ExtCurStyle->exts_nodeConn[t1]), t2)
/* tile is junction */
{
/*junction rn_loc */
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);
devptr = ExtCurStyle->exts_device[t2];
if(TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t2) &&
TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), t1))
/* found device */
{
xj = RIGHT(tile);
yj = (TOP(tp)+BOTTOM(tp))>>1;
ResNewSDDevice(tile, tp, xj, yj, LEFTEDGE, &ResNodeQueue);
}
if TTMaskHasType(&ExtCurStyle->exts_nodeConn[t1], t2)
/* tile is junction */
{
/*junction rn_loc */
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);
devptr = ExtCurStyle->exts_device[t2];
if(TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t2) &&
TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t1))
/* found device */
{
yj = TOP(tile);
xj = (LEFT(tp)+RIGHT(tp))>>1;
ResNewSDDevice(tile,tp,xj,yj,BOTTOMEDGE, &ResNodeQueue);
}
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);
devptr = ExtCurStyle->exts_device[t2];
if(TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t2) &&
TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), t1))
/* found device */
{
yj = BOTTOM(tile);
xj = (LEFT(tp) + RIGHT(tp)) >> 1;
ResNewSDDevice(tile, tp, xj, yj, TOPEDGE, &ResNodeQueue);
}
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);
}
}
tstructs->tj_status |= RES_TILE_DONE;
resAllPortNodes(tile, &ResNodeQueue);
merged = ResCalcTileResistance(tile, tstructs, &ResNodeQueue,
&ResNodeList);
return(merged);
}
/*
*-------------------------------------------------------------------------
*
* resSubDevFunc -- called when DBSrPaintArea finds a device within
* a substrate area.
*
* Results: always returns 0 to keep search going.
*
* Side Effects: allocates substrate node.
*
*-------------------------------------------------------------------------
*/
int
resSubDevFunc(tile,tp)
Tile *tile,*tp;
{
tileJunk *junk = (tileJunk *)(tile->ti_client);
resNode *resptr;
tElement *tcell;
int x,y;
if (junk->deviceList->rd_fet_subs == NULL)
{
resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode)));
junk->deviceList->rd_fet_subs = resptr;
junk->tj_status |= RES_TILE_DEV;
tcell = (tElement *) mallocMagic((unsigned)(sizeof(tElement)));
tcell->te_thist = junk->deviceList;
tcell->te_nextt = NULL;
x = (LEFT(tile)+RIGHT(tile))>>1;
y = (TOP(tile)+BOTTOM(tile))>>1;
InitializeNode(resptr,x,y,RES_NODE_JUNCTION);
resptr->rn_te = tcell;
ResAddToQueue(resptr,&ResNodeQueue);
NEWBREAK(resptr,tp,x,y,NULL);
}
return 0;
}