Files
magic/resis/ResMakeRes.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

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 *)TiGetClientPTR(tile);
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 *)TiGetClientPTR(tile);
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 *)TiGetClientPTR(tile);
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;
}
}
}
}