392 lines
10 KiB
C
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;
|
||
}
|