magic/resis/ResMakeRes.c

970 lines
25 KiB
C

#ifndef lint
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/resis/ResMakeRes.c,v 1.3 2010/06/24 12:37:56 tim Exp $";
#endif /* not lint */
#include <stdio.h>
#include <stdlib.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"
#include "cif/CIFint.h"
/* C99 compat */
#include "cif/cif.h"
/* Forward declarations */
bool ResCalcNearDevice();
bool ResCalcNorthSouth();
bool ResCalcEastWest();
/*
*--------------------------------------------------------------------------
*
* ResCalcTileResistance-- Given a set of partitions for a tile, the tile can
* be converted into resistors. To do this, nodes are sorted in the
* direction of current flow. Resistors are created by counting squares
* between successive breakpoints. Breakpoints with the same coordinate
* are combined.
*
* Results: returns TRUE if the startnode was involved in a merge.
*
* Side Effects: Resistor structures are produced. Some nodes may be
* eliminated.
*--------------------------------------------------------------------------
*/
bool
ResCalcTileResistance(tile, junk, pendingList, doneList)
Tile *tile;
tileJunk *junk;
resNode **pendingList, **doneList;
{
int MaxX = MINFINITY, MinX = INFINITY;
int MaxY = MINFINITY, MinY = INFINITY;
int device;
bool merged;
Breakpoint *p1;
merged = FALSE;
device = FALSE;
if ((p1 = junk->breakList) == NULL) return FALSE;
for (; p1; p1 = p1->br_next)
{
int x = p1->br_loc.p_x;
int y = p1->br_loc.p_y;
if (x > MaxX) MaxX = x;
if (x < MinX) MinX = x;
if (y > MaxY) MaxY = y;
if (y < MinY) MinY = y;
if (p1->br_this->rn_why == RES_NODE_DEVICE)
{
device = TRUE;
}
}
/* Finally, produce resistors for partition. Keep track of */
/* whether or not the node was involved in a merge. */
if (device)
{
merged |= ResCalcNearDevice(tile, pendingList, doneList, &ResResList);
}
else if (MaxY-MinY > MaxX-MinX)
{
merged |= ResCalcNorthSouth(tile, pendingList, doneList, &ResResList);
}
else
{
merged |= ResCalcEastWest(tile, pendingList, doneList, &ResResList);
}
/*
* For all the new resistors, propagate the resistance from the origin
* to the new nodes.
*/
return(merged);
}
/*
*-------------------------------------------------------------------------
*
* ResCalcEastWest-- Makes resistors from an EastWest partition.
*
* Results: Returns TRUE if the sacredNode was involved in a merge.
*
* Side Effects: Makes resistors. Frees breakpoints.
*
*-------------------------------------------------------------------------
*/
bool
ResCalcEastWest(tile, pendingList, doneList, resList)
Tile *tile;
resNode **pendingList, **doneList;
resResistor **resList;
{
int height;
bool merged;
Breakpoint *p1, *p2, *p3;
resResistor *resistor;
resElement *element;
resNode *currNode;
float rArea;
tileJunk *junk = (tileJunk *)tile->ti_client;
merged = FALSE;
height = TOP(tile) - BOTTOM(tile);
/*
* One Breakpoint? No resistors need to be made. Free up the first
* breakpoint, then return.
*/
p1 = junk->breakList;
if (p1->br_next == NULL)
{
p1->br_this->rn_float.rn_area += height * (LEFT(tile) - RIGHT(tile));
freeMagic((char *)p1);
junk->breakList = NULL;
return(merged);
}
/* Re-sort nodes left to right. */
ResSortBreaks(&junk->breakList, TRUE);
/*
* Eliminate breakpoints with the same X coordinate and merge
* their nodes.
*/
p2= junk->breakList;
/* Add extra left area to leftmost node */
p2->br_this->rn_float.rn_area += height * (p2->br_loc.p_x - LEFT(tile));
while (p2->br_next != NULL)
{
p1 = p2;
p2 = p2->br_next;
if (p2->br_loc.p_x == p1->br_loc.p_x)
{
if (p2->br_this == p1->br_this)
{
currNode = NULL;
p1->br_next = p2->br_next;
freeMagic((char *)p2);
p2 = p1;
}
else if (p2->br_this == resCurrentNode)
{
currNode = p1->br_this;
ResMergeNodes(p2->br_this, p1->br_this, pendingList, doneList);
merged = TRUE;
freeMagic((char *)p1);
}
else if (p1->br_this == resCurrentNode)
{
currNode = p2->br_this;
p1->br_next = p2->br_next;
ResMergeNodes(p1->br_this, p2->br_this, pendingList, doneList);
merged = TRUE;
freeMagic((char *)p2);
p2 = p1;
}
else
{
currNode = p1->br_this;
ResMergeNodes(p2->br_this, p1->br_this, pendingList, doneList);
freeMagic((char *)p1);
}
/*
* Was the node used in another junk or breakpoint?
* If so, replace the old node with the new one.
*/
p3 = p2->br_next;
while (p3 != NULL)
{
if (p3->br_this == currNode)
p3->br_this = p2->br_this;
p3 = p3->br_next;
}
}
/*
* If the X coordinates don't match, make a resistor between
* the breakpoints.
*/
else
{
resistor = (resResistor *)mallocMagic((unsigned)sizeof(resResistor));
resistor->rr_nextResistor = (*resList);
resistor->rr_lastResistor = NULL;
if ((*resList) != NULL) (*resList)->rr_lastResistor = resistor;
(*resList) = resistor;
resistor->rr_connection1 = p1->br_this;
resistor->rr_connection2 = p2->br_this;
element = (resElement *)mallocMagic((unsigned)sizeof(resElement));
element->re_nextEl = p1->br_this->rn_re;
element->re_thisEl = resistor;
p1->br_this->rn_re = element;
element = (resElement *)mallocMagic((unsigned)sizeof(resElement));
element->re_nextEl = p2->br_this->rn_re;
element->re_thisEl = resistor;
p2->br_this->rn_re = element;
resistor->rr_cl = (TOP(tile) + BOTTOM(tile)) >> 1;
resistor->rr_width = height;
if (IsSplit(tile))
{
resistor->rr_tt = (SplitSide(tile)) ? SplitRightType(tile)
: SplitLeftType(tile);
resistor->rr_status = RES_DIAGONAL;
resistor->rr_status |= (SplitDirection(tile)) ? RES_NS
: RES_EW;
}
else
{
resistor->rr_status = RES_EW;
resistor->rr_tt = TiGetTypeExact(tile);
}
#ifdef ARIEL
resistor->rr_csArea = height *
ExtCurStyle->exts_thick[resistor->rr_tt];
#endif
resistor->rr_value =
(float)ExtCurStyle->exts_sheetResist[resistor->rr_tt]
* (float)(p2->br_loc.p_x - p1->br_loc.p_x)
/ (float)height;
rArea = ((p2->br_loc.p_x - p1->br_loc.p_x) * height) / 2;
resistor->rr_connection1->rn_float.rn_area += rArea;
resistor->rr_connection2->rn_float.rn_area += rArea;
resistor->rr_float.rr_area = 0;
freeMagic((char *)p1);
}
}
p2->br_this->rn_float.rn_area += height * (RIGHT(tile) - p2->br_loc.p_x);
freeMagic((char *)p2);
junk->breakList = NULL;
return merged;
}
/*
*-------------------------------------------------------------------------
*
* ResCalcNorthSouth-- Makes resistors from a NorthSouth partition
*
* Results: Returns TRUE if the resCurrentNode was involved in a merge.
*
* Side Effects: Makes resistors. Frees breakpoints
*
*-------------------------------------------------------------------------
*/
bool
ResCalcNorthSouth(tile, pendingList, doneList, resList)
Tile *tile;
resNode **pendingList, **doneList;
resResistor **resList;
{
int width;
bool merged;
Breakpoint *p1, *p2, *p3;
resResistor *resistor;
resElement *element;
resNode *currNode;
float rArea;
tileJunk *junk = (tileJunk *)tile->ti_client;
merged = FALSE;
width = RIGHT(tile) - LEFT(tile);
/*
* One Breakpoint? No resistors need to be made. Free up the first
* breakpoint, then return.
*/
p1 = junk->breakList;
if (p1->br_next == NULL)
{
p1->br_this->rn_float.rn_area += width * (TOP(tile) - BOTTOM(tile));
freeMagic((char *)p1);
junk->breakList = NULL;
return(merged);
}
/* Re-sort nodes south to north. */
ResSortBreaks(&junk->breakList, FALSE);
/*
* Eliminate breakpoints with the same Y coordinate and merge
* their nodes.
*/
p2 = junk->breakList;
/* Add extra left area to leftmost node */
p2->br_this->rn_float.rn_area += width * (p2->br_loc.p_y - BOTTOM(tile));
while (p2->br_next != NULL)
{
p1 = p2;
p2 = p2->br_next;
if (p1->br_loc.p_y == p2->br_loc.p_y)
{
if (p2->br_this == p1->br_this)
{
currNode = NULL;
p1->br_next = p2->br_next;
freeMagic((char *)p2);
p2 = p1;
}
else if (p2->br_this == resCurrentNode)
{
currNode = p1->br_this;
ResMergeNodes(p2->br_this, p1->br_this, pendingList, doneList);
freeMagic((char *)p1);
merged = TRUE;
}
else if (p1->br_this == resCurrentNode)
{
currNode = p2->br_this;
p1->br_next = p2->br_next;
ResMergeNodes(p1->br_this, p2->br_this, pendingList, doneList);
merged = TRUE;
freeMagic((char *)p2);
p2 = p1;
}
else
{
currNode = p1->br_this;
ResMergeNodes(p2->br_this, p1->br_this, pendingList, doneList);
freeMagic((char *)p1);
}
/*
* Was the node used in another junk or breakpoint?
* If so, replace the old node with the new one.
*/
p3 = p2->br_next;
while (p3 != NULL)
{
if (p3->br_this == currNode)
p3->br_this = p2->br_this;
p3 = p3->br_next;
}
}
/*
* If the Y coordinates don't match, make a resistor between
* the breakpoints.
*/
else
{
resistor = (resResistor *) mallocMagic((unsigned) (sizeof(resResistor)));
resistor->rr_nextResistor = (*resList);
resistor->rr_lastResistor = NULL;
if ((*resList) != NULL) (*resList)->rr_lastResistor = resistor;
(*resList) = resistor;
resistor->rr_connection1 = p1->br_this;
resistor->rr_connection2 = p2->br_this;
element = (resElement *) mallocMagic((unsigned) (sizeof(resElement)));
element->re_nextEl = p1->br_this->rn_re;
element->re_thisEl = resistor;
p1->br_this->rn_re = element;
element = (resElement *) mallocMagic((unsigned) (sizeof(resElement)));
element->re_nextEl = p2->br_this->rn_re;
element->re_thisEl = resistor;
p2->br_this->rn_re = element;
resistor->rr_cl = (LEFT(tile) + RIGHT(tile)) >> 1;
resistor->rr_width = width;
if (IsSplit(tile))
{
resistor->rr_tt = (SplitSide(tile)) ? SplitRightType(tile)
: SplitLeftType(tile);
resistor->rr_status = RES_DIAGONAL;
resistor->rr_status |= (SplitDirection(tile)) ? RES_NS
: RES_EW;
}
else
{
resistor->rr_status = RES_NS;
resistor->rr_tt = TiGetTypeExact(tile);
}
#ifdef ARIEL
resistor->rr_csArea = width
* ExtCurStyle->exts_thick[resistor->rr_tt];
#endif
resistor->rr_value =
(float)ExtCurStyle->exts_sheetResist[resistor->rr_tt]
* (float)(p2->br_loc.p_y - p1->br_loc.p_y)
/ (float)width;
rArea = ((p2->br_loc.p_y - p1->br_loc.p_y) * width) / 2;
resistor->rr_connection1->rn_float.rn_area += rArea;
resistor->rr_connection2->rn_float.rn_area += rArea;
resistor->rr_float.rr_area = 0;
freeMagic((char *)p1);
}
}
p2->br_this->rn_float.rn_area += width * (TOP(tile) - p2->br_loc.p_y);
freeMagic((char *)p2);
junk->breakList = NULL;
return(merged);
}
/*
*-------------------------------------------------------------------------
*
* ResCalcNearDevice-- Calculating the direction of current flow near
* devices is tricky because there are two adjoining regions with
* vastly different sheet resistances. ResCalcNearDevice is called
* whenever a diffusion tile adjoining a real tile is found. It makes
* a guess at the correct direction of current flow, removes extra
* breakpoints, and call either ResCalcEastWest or ResCalcNorthSouth
*
* Results:
* TRUE if merging occurred, FALSE if not.
*
* Side Effects: Makes resistors. Frees breakpoints
*
*-------------------------------------------------------------------------
*/
bool
ResCalcNearDevice(tile, pendingList, doneList, resList)
Tile *tile;
resNode **pendingList, **doneList;
resResistor **resList;
{
bool merged;
int devcount, devedge, deltax, deltay;
Breakpoint *p1, *p2, *p3;
tileJunk *junk = (tileJunk *)tile->ti_client;
merged = FALSE;
/*
* One Breakpoint? No resistors need to be made. Free up the first
* breakpoint, then return.
*/
if (junk->breakList->br_next == NULL)
{
freeMagic((char *)junk->breakList);
junk->breakList = NULL;
return(merged);
}
/* Count the number of device breakpoints */
/* Mark which edge they connect to */
devcount = 0;
devedge = 0;
for (p1 = junk->breakList; p1 != NULL; p1 = p1->br_next)
{
if (p1->br_this->rn_why == RES_NODE_DEVICE)
{
devcount++;
if (p1->br_loc.p_x == LEFT(tile)) devedge |= LEFTEDGE;
else if (p1->br_loc.p_x == RIGHT(tile)) devedge |= RIGHTEDGE;
else if (p1->br_loc.p_y == TOP(tile)) devedge |= TOPEDGE;
else if (p1->br_loc.p_y == BOTTOM(tile)) devedge |= BOTTOMEDGE;
}
}
/* Use distance from device to next breakpoint as determinant */
/* If there is only one device or if all the devices are along */
/* the same edge. */
if (devcount == 1 ||
(devedge & LEFTEDGE) == devedge ||
(devedge & RIGHTEDGE) == devedge ||
(devedge & TOPEDGE) == devedge ||
(devedge & BOTTOMEDGE) == devedge)
{
ResSortBreaks(&junk->breakList,TRUE);
p2 = NULL;
for (p1 = junk->breakList; p1 != NULL; p1 = p1->br_next)
{
if (p1->br_this->rn_why == RES_NODE_DEVICE)
break;
if (p1->br_next != NULL &&
(p1->br_loc.p_x != p1->br_next->br_loc.p_x ||
p1->br_loc.p_y != p1->br_next->br_loc.p_y))
p2 = p1;
}
deltax = INFINITY;
for (p3 = p1->br_next; p3 != NULL &&
p3->br_loc.p_x == p1->br_loc.p_x &&
p3->br_loc.p_y == p1->br_loc.p_y; p3 = p3->br_next);
if (p3 != NULL)
{
if (p3->br_crect)
{
if (p3->br_crect->r_ll.p_x > p1->br_loc.p_x)
{
deltax = p3->br_crect->r_ll.p_x - p1->br_loc.p_x;
}
else if (p3->br_crect->r_ur.p_x < p1->br_loc.p_x)
{
deltax = p1->br_loc.p_x - p3->br_crect->r_ur.p_x;
}
else
{
deltax = 0;
}
}
else
{
deltax = abs(p1->br_loc.p_x - p3->br_loc.p_x);
}
}
if (p2 != NULL)
{
if (p2->br_crect)
{
if (p2->br_crect->r_ll.p_x > p1->br_loc.p_x)
{
deltax = MIN(deltax, p2->br_crect->r_ll.p_x - p1->br_loc.p_x);
}
else if (p2->br_crect->r_ur.p_x < p1->br_loc.p_x)
{
deltax = MIN(deltax, p1->br_loc.p_x - p2->br_crect->r_ur.p_x);
}
else
{
deltax = 0;
}
}
else
{
deltax = MIN(deltax, abs(p1->br_loc.p_x - p2->br_loc.p_x));
}
}
/* Re-sort nodes south to north. */
ResSortBreaks(&junk->breakList, FALSE);
p2 = NULL;
for (p1 = junk->breakList; p1 != NULL; p1 = p1->br_next)
{
if (p1->br_this->rn_why == RES_NODE_DEVICE)
{
break;
}
if (p1->br_next != NULL &&
(p1->br_loc.p_x != p1->br_next->br_loc.p_x ||
p1->br_loc.p_y != p1->br_next->br_loc.p_y))
{
p2 = p1;
}
}
deltay = INFINITY;
for (p3 = p1->br_next; p3 != NULL &&
p3->br_loc.p_x == p1->br_loc.p_x &&
p3->br_loc.p_y == p1->br_loc.p_y; p3 = p3->br_next);
if (p3 != NULL)
{
if (p3->br_crect)
{
if (p3->br_crect->r_ll.p_y > p1->br_loc.p_y)
{
deltay = p3->br_crect->r_ll.p_y - p1->br_loc.p_y;
}
else if (p3->br_crect->r_ur.p_y < p1->br_loc.p_y)
{
deltay = p1->br_loc.p_y - p3->br_crect->r_ur.p_y;
}
else
{
deltay=0;
}
}
else
{
deltay = abs(p1->br_loc.p_y - p3->br_loc.p_y);
}
}
if (p2 != NULL)
{
if (p2->br_crect)
{
if (p2->br_crect->r_ll.p_y > p1->br_loc.p_y)
{
deltay = MIN(deltay,p2->br_crect->r_ll.p_y - p1->br_loc.p_y);
}
else if (p2->br_crect->r_ur.p_y < p1->br_loc.p_y)
{
deltay = MIN(deltay,p1->br_loc.p_y - p2->br_crect->r_ur.p_y);
}
else
{
deltay=0;
}
}
else
{
deltay = MIN(deltay, abs(p1->br_loc.p_y - p2->br_loc.p_y));
}
}
if (deltay > deltax)
{
return ResCalcNorthSouth(tile, pendingList, doneList, resList);
}
else
{
return ResCalcEastWest(tile, pendingList, doneList, resList);
}
}
/* Multiple devices connected to the partition */
else
{
if (devedge == 0)
{
TxError("Error in device current direction routine\n");
return(merged);
}
/* Check to see if the current flow is north-south */
/* Possible north-south conditions: */
/* 1. There are devices along the top and bottom edges */
/* but not along the left or right */
/* 2. There are devices along two sides at right angles, */
/* and the tile is wider than it is tall. */
if ((devedge & TOPEDGE) && (devedge & BOTTOMEDGE) &&
!(devedge & LEFTEDGE) && !(devedge & RIGHTEDGE) ||
(devedge & TOPEDGE || devedge & BOTTOMEDGE) &&
(devedge & LEFTEDGE || devedge & RIGHTEDGE) &&
(RIGHT(tile) - LEFT(tile)) > (TOP(tile) - BOTTOM(tile)))
{
/* re-sort nodes south to north. */
ResSortBreaks(&junk->breakList, FALSE);
/* eliminate duplicate S/D pointers */
for (p1 = junk->breakList; p1 != NULL; p1 = p1->br_next)
{
if (p1->br_this->rn_why == RES_NODE_DEVICE &&
(p1->br_loc.p_y == BOTTOM(tile) ||
p1->br_loc.p_y == TOP(tile)))
{
p3 = NULL;
p2 = junk->breakList;
while (p2 != NULL)
{
if (p2->br_this == p1->br_this && p2 != p1 &&
p2->br_loc.p_y != BOTTOM(tile) &&
p2->br_loc.p_y != TOP(tile))
{
if (p3 == NULL)
{
junk->breakList = p2->br_next;
freeMagic((char *) p2);
p2 = junk->breakList;
}
else
{
p3->br_next = p2->br_next;
freeMagic((char *) p2);
p2 = p3->br_next;
}
}
else
{
p3 = p2;
p2 = p2->br_next;
}
}
}
}
return ResCalcNorthSouth(tile, pendingList, doneList, resList);
}
else
{
/* Eliminate duplicate S/D pointers */
for (p1 = junk->breakList; p1 != NULL; p1 = p1->br_next)
{
if (p1->br_this->rn_why == RES_NODE_DEVICE &&
(p1->br_loc.p_x == LEFT(tile) ||
p1->br_loc.p_x == RIGHT(tile)))
{
p3 = NULL;
p2 = junk->breakList;
while (p2 != NULL)
{
if (p2->br_this == p1->br_this && p2 != p1 &&
p2->br_loc.p_x != LEFT(tile) &&
p2->br_loc.p_x != RIGHT(tile))
{
if (p3 == NULL)
{
junk->breakList = p2->br_next;
freeMagic((char *) p2);
p2 = junk->breakList;
}
else
{
p3->br_next = p2->br_next;
freeMagic((char *) p2);
p2 = p3->br_next;
}
}
else
{
p3 = p2;
p2 = p2->br_next;
}
}
}
}
return ResCalcEastWest(tile, pendingList, doneList, resList);
}
}
}
/*
*-------------------------------------------------------------------------
*
* ResDoContacts-- Add node (or nodes) for a contact. If there are contact
* resistances, also add a resistor.
*
* Results:
* None.
*
* Side Effects: Creates nodes and resistors
*
*-------------------------------------------------------------------------
*/
void
ResDoContacts(contact, nodes, resList)
ResContactPoint *contact;
resNode **nodes;
resResistor **resList;
{
resNode *resptr;
cElement *ccell;
int tilenum, squaresx, squaresy, viawidth;
int minside, spacing, border, cscale;
float squaresf;
resResistor *resistor;
resElement *element;
static int too_small = 1;
minside = CIFGetContactSize(contact->cp_type, &viawidth, &spacing, &border);
cscale = CIFCurStyle->cs_scaleFactor;
if ((ExtCurStyle->exts_viaResist[contact->cp_type] == 0) || (viawidth == 0))
{
int x = contact->cp_center.p_x;
int y = contact->cp_center.p_y;
resptr = (resNode *) mallocMagic((unsigned) (sizeof(resNode)));
InitializeNode(resptr, x, y, RES_NODE_CONTACT);
ResAddToQueue(resptr, nodes);
ccell = (cElement *) mallocMagic((unsigned) (sizeof(cElement)));
ccell->ce_nextc = resptr->rn_ce;
resptr->rn_ce = ccell;
ccell->ce_thisc = contact;
/* Add 1 celement for each layer of contact */
for (tilenum = 0; tilenum < contact->cp_currentcontact; tilenum++)
{
Tile *tile = contact->cp_tile[tilenum];
contact->cp_cnode[tilenum] = resptr;
NEWBREAK(resptr, tile, contact->cp_center.p_x,
contact->cp_center.p_y, &contact->cp_rect);
}
}
else
{
if (((contact->cp_width * cscale) < minside) ||
((contact->cp_height * cscale) < minside))
{
if (too_small)
{
TxError("Warning: %s at %d %d smaller than extract section allows\n",
DBTypeLongNameTbl[contact->cp_type],
contact->cp_center.p_x, contact->cp_center.p_y);
too_small = 0;
}
squaresx = squaresy = 1;
}
else
{
viawidth += spacing;
squaresf = (float)((contact->cp_width * cscale) - minside);
squaresf /= (float)viawidth;
squaresx = (int)squaresf;
squaresx++;
squaresf = (float)((contact->cp_height * cscale) - minside);
squaresf /= (float)viawidth;
squaresy = (int)squaresf;
squaresy++;
}
for (tilenum = 0; tilenum < contact->cp_currentcontact; tilenum++)
{
int x = contact->cp_center.p_x;
int y = contact->cp_center.p_y;
Tile *tile = contact->cp_tile[tilenum];
resptr = (resNode *) mallocMagic((unsigned) (sizeof(resNode)));
InitializeNode(resptr, x, y, RES_NODE_CONTACT);
ResAddToQueue(resptr, nodes);
/* Add contact pointer to node */
ccell = (cElement *) mallocMagic((unsigned) (sizeof(cElement)));
ccell->ce_nextc = resptr->rn_ce;
resptr->rn_ce = ccell;
ccell->ce_thisc = contact;
contact->cp_cnode[tilenum] = resptr;
NEWBREAK(resptr, tile, contact->cp_center.p_x,
contact->cp_center.p_y, &contact->cp_rect);
/* Add resistors here */
if (tilenum > 0)
{
resistor = (resResistor *) mallocMagic((unsigned) (sizeof(resResistor)));
resistor->rr_nextResistor = (*resList);
resistor->rr_lastResistor = NULL;
if ((*resList) != NULL) (*resList)->rr_lastResistor = resistor;
(*resList) = resistor;
resistor->rr_connection1 = contact->cp_cnode[tilenum - 1];
resistor->rr_connection2 = contact->cp_cnode[tilenum];
element = (resElement *) mallocMagic((unsigned) (sizeof(resElement)));
element->re_nextEl = contact->cp_cnode[tilenum - 1]->rn_re;
element->re_thisEl = resistor;
contact->cp_cnode[tilenum - 1]->rn_re = element;
element = (resElement *) mallocMagic((unsigned)(sizeof(resElement)));
element->re_nextEl = contact->cp_cnode[tilenum]->rn_re;
element->re_thisEl = resistor;
contact->cp_cnode[tilenum]->rn_re = element;
/* Need to figure out how to handle the multiple nodes */
/* and multiple resistors necessary to determine the */
/* correct geometry for the geometry extractor. For */
/* now, extract as one big glob. */
/* rr_cl doesn't need to represent centerline; use for */
/* # squares in y direction instead; use rr_width for */
/* # squares in x direction. */
resistor->rr_cl = squaresy;
resistor->rr_width = squaresx;
resistor->rr_value =
(float)ExtCurStyle->exts_viaResist[contact->cp_type] /
(float)(squaresx * squaresy);
#ifdef ARIEL
resistor->rr_csArea =
(float)ExtCurStyle->exts_thick[contact->cp_type] /
(float)(squaresx * squaresy);
#endif
resistor->rr_tt = contact->cp_type;
resistor->rr_float.rr_area = 0;
resistor->rr_status = 0;
}
}
}
}
/*
*-------------------------------------------------------------------------
*
* ResSortBreaks --
*
* Results:
* None
*
*-------------------------------------------------------------------------
*/
void
ResSortBreaks(masterlist, xsort)
Breakpoint **masterlist;
int xsort;
{
Breakpoint *p1, *p2, *p3, *p4;
bool changed;
changed = TRUE;
while (changed == TRUE)
{
changed = FALSE;
p1 = NULL;
p2 = *masterlist;
p3 = p2->br_next;
while (p3 != NULL)
{
if (xsort == TRUE && p2->br_loc.p_x > p3->br_loc.p_x ||
xsort == FALSE && p2->br_loc.p_y > p3->br_loc.p_y)
{
changed = TRUE;
if (p1 == NULL)
{
*masterlist = p3;
}
else
{
p1->br_next = p3;
}
p2->br_next = p3->br_next;
p3->br_next = p2;
p4 = p2;
p2 = p3;
p3 = p4;
}
else
{
p1 = p2;
p2 = p3;
p3 = p3->br_next;
}
}
}
}