2017-04-25 14:41:48 +02:00
|
|
|
|
|
|
|
|
#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"
|
2019-10-14 23:17:08 +02:00
|
|
|
#include "cif/CIFint.h"
|
2017-04-25 14:41:48 +02:00
|
|
|
|
2022-10-10 11:50:15 +02:00
|
|
|
/* C99 compat */
|
|
|
|
|
#include "cif/cif.h"
|
|
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/* Forward declarations */
|
2019-10-17 22:21:56 +02:00
|
|
|
bool ResCalcNearDevice();
|
2017-04-25 14:41:48 +02:00
|
|
|
bool ResCalcNorthSouth();
|
|
|
|
|
bool ResCalcEastWest();
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
*--------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* ResCalcTileResistance-- Given a set of partitions for a tile, the tile can
|
2020-05-23 23:13:14 +02:00
|
|
|
* be converted into resistors. To do this, nodes are sorted in the
|
2017-04-25 14:41:48 +02:00
|
|
|
* 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.
|
|
|
|
|
*--------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
bool
|
2017-04-25 14:41:48 +02:00
|
|
|
ResCalcTileResistance(tile, junk, pendingList, doneList)
|
|
|
|
|
Tile *tile;
|
|
|
|
|
tileJunk *junk;
|
|
|
|
|
resNode **pendingList, **doneList;
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
int MaxX = MINFINITY, MinX = INFINITY;
|
|
|
|
|
int MaxY = MINFINITY, MinY = INFINITY;
|
2019-10-17 22:21:56 +02:00
|
|
|
int device;
|
2017-04-25 14:41:48 +02:00
|
|
|
bool merged;
|
|
|
|
|
Breakpoint *p1;
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
merged = FALSE;
|
2019-10-17 22:21:56 +02:00
|
|
|
device = FALSE;
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
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;
|
2019-10-17 22:21:56 +02:00
|
|
|
if (p1->br_this->rn_why == RES_NODE_DEVICE)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
2019-10-17 22:21:56 +02:00
|
|
|
device = TRUE;
|
2017-04-25 14:41:48 +02:00
|
|
|
}
|
|
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/* Finally, produce resistors for partition. Keep track of */
|
|
|
|
|
/* whether or not the node was involved in a merge. */
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2019-10-17 22:21:56 +02:00
|
|
|
if (device)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
2019-10-17 22:21:56 +02:00
|
|
|
merged |= ResCalcNearDevice(tile, pendingList, doneList, &ResResList);
|
2017-04-25 14:41:48 +02:00
|
|
|
}
|
|
|
|
|
else if (MaxY-MinY > MaxX-MinX)
|
|
|
|
|
{
|
|
|
|
|
merged |= ResCalcNorthSouth(tile, pendingList, doneList, &ResResList);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
merged |= ResCalcEastWest(tile, pendingList, doneList, &ResResList);
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
/*
|
2017-04-25 14:41:48 +02:00
|
|
|
* For all the new resistors, propagate the resistance from the origin
|
|
|
|
|
* to the new nodes.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
return(merged);
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* 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;
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
merged = FALSE;
|
|
|
|
|
height = TOP(tile) - BOTTOM(tile);
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
/*
|
2021-09-08 22:41:36 +02:00
|
|
|
* One Breakpoint? No resistors need to be made. Free up the first
|
2017-04-25 14:41:48 +02:00
|
|
|
* breakpoint, then return.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
p1 = junk->breakList;
|
2020-05-23 23:13:14 +02:00
|
|
|
if (p1->br_next == NULL)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
p1->br_this->rn_float.rn_area += height * (LEFT(tile) - RIGHT(tile));
|
|
|
|
|
freeMagic((char *)p1);
|
|
|
|
|
junk->breakList = NULL;
|
|
|
|
|
return(merged);
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-08 22:41:36 +02:00
|
|
|
/* Re-sort nodes left to right. */
|
2017-04-25 14:41:48 +02:00
|
|
|
|
|
|
|
|
ResSortBreaks(&junk->breakList, TRUE);
|
2020-05-23 23:13:14 +02:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Eliminate breakpoints with the same X coordinate and merge
|
2017-04-25 14:41:48 +02:00
|
|
|
* their nodes.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
p2= junk->breakList;
|
|
|
|
|
|
2021-09-08 22:41:36 +02:00
|
|
|
/* Add extra left area to leftmost node */
|
2017-04-25 14:41:48 +02:00
|
|
|
|
2021-09-08 22:41:36 +02:00
|
|
|
p2->br_this->rn_float.rn_area += height * (p2->br_loc.p_x - LEFT(tile));
|
2017-04-25 14:41:48 +02:00
|
|
|
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;
|
2021-09-08 22:41:36 +02:00
|
|
|
ResMergeNodes(p2->br_this, p1->br_this, pendingList, doneList);
|
2017-04-25 14:41:48 +02:00
|
|
|
merged = TRUE;
|
|
|
|
|
freeMagic((char *)p1);
|
|
|
|
|
}
|
|
|
|
|
else if (p1->br_this == resCurrentNode)
|
|
|
|
|
{
|
|
|
|
|
currNode = p2->br_this;
|
|
|
|
|
p1->br_next = p2->br_next;
|
2021-09-08 22:41:36 +02:00
|
|
|
ResMergeNodes(p1->br_this, p2->br_this, pendingList, doneList);
|
2017-04-25 14:41:48 +02:00
|
|
|
merged = TRUE;
|
|
|
|
|
freeMagic((char *)p2);
|
|
|
|
|
p2 = p1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
currNode = p1->br_this;
|
2021-09-08 22:41:36 +02:00
|
|
|
ResMergeNodes(p2->br_this, p1->br_this, pendingList, doneList);
|
2017-04-25 14:41:48 +02:00
|
|
|
freeMagic((char *)p1);
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
/*
|
2017-04-25 14:41:48 +02:00
|
|
|
* Was the node used in another junk or breakpoint?
|
|
|
|
|
* If so, replace the old node with the new one.
|
|
|
|
|
*/
|
2021-09-08 22:41:36 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
p3 = p2->br_next;
|
|
|
|
|
while (p3 != NULL)
|
|
|
|
|
{
|
|
|
|
|
if (p3->br_this == currNode)
|
|
|
|
|
p3->br_this = p2->br_this;
|
2021-09-08 22:41:36 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
p3 = p3->br_next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
/*
|
2017-04-25 14:41:48 +02:00
|
|
|
* If the X coordinates don't match, make a resistor between
|
|
|
|
|
* the breakpoints.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
else
|
|
|
|
|
{
|
2021-09-08 22:41:36 +02:00
|
|
|
resistor = (resResistor *)mallocMagic((unsigned)sizeof(resResistor));
|
2017-04-25 14:41:48 +02:00
|
|
|
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;
|
2021-09-08 22:41:36 +02:00
|
|
|
element = (resElement *)mallocMagic((unsigned)sizeof(resElement));
|
2017-04-25 14:41:48 +02:00
|
|
|
element->re_nextEl = p1->br_this->rn_re;
|
|
|
|
|
element->re_thisEl = resistor;
|
|
|
|
|
p1->br_this->rn_re = element;
|
2021-09-08 22:41:36 +02:00
|
|
|
element = (resElement *)mallocMagic((unsigned)sizeof(resElement));
|
2017-04-25 14:41:48 +02:00
|
|
|
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 =
|
2023-03-25 16:01:52 +01:00
|
|
|
(float)ExtCurStyle->exts_sheetResist[resistor->rr_tt]
|
|
|
|
|
* (float)(p2->br_loc.p_x - p1->br_loc.p_x)
|
|
|
|
|
/ (float)height;
|
2021-09-12 23:20:22 +02:00
|
|
|
rArea = ((p2->br_loc.p_x - p1->br_loc.p_x) * height) / 2;
|
2017-04-25 14:41:48 +02:00
|
|
|
resistor->rr_connection1->rn_float.rn_area += rArea;
|
|
|
|
|
resistor->rr_connection2->rn_float.rn_area += rArea;
|
|
|
|
|
resistor->rr_float.rr_area = 0;
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
freeMagic((char *)p1);
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-09-08 22:41:36 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
p2->br_this->rn_float.rn_area += height * (RIGHT(tile) - p2->br_loc.p_x);
|
|
|
|
|
freeMagic((char *)p2);
|
|
|
|
|
junk->breakList = NULL;
|
2021-09-08 22:41:36 +02:00
|
|
|
return merged;
|
2017-04-25 14:41:48 +02:00
|
|
|
}
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* 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;
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
merged = FALSE;
|
2021-09-08 22:41:36 +02:00
|
|
|
width = RIGHT(tile) - LEFT(tile);
|
2017-04-25 14:41:48 +02:00
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
/*
|
2017-04-25 14:41:48 +02:00
|
|
|
* One Breakpoint? No resistors need to be made. Free up the first
|
|
|
|
|
* breakpoint, then return.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
p1 = junk->breakList;
|
2021-05-27 04:34:36 +02:00
|
|
|
if (p1->br_next == NULL)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
p1->br_this->rn_float.rn_area += width * (TOP(tile) - BOTTOM(tile));
|
|
|
|
|
freeMagic((char *)p1);
|
|
|
|
|
junk->breakList = NULL;
|
|
|
|
|
return(merged);
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-08 22:41:36 +02:00
|
|
|
/* Re-sort nodes south to north. */
|
2017-04-25 14:41:48 +02:00
|
|
|
ResSortBreaks(&junk->breakList, FALSE);
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
/*
|
|
|
|
|
* Eliminate breakpoints with the same Y coordinate and merge
|
2017-04-25 14:41:48 +02:00
|
|
|
* their nodes.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
p2 = junk->breakList;
|
|
|
|
|
|
2021-09-08 22:41:36 +02:00
|
|
|
/* Add extra left area to leftmost node */
|
2017-04-25 14:41:48 +02:00
|
|
|
|
|
|
|
|
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;
|
2021-09-08 22:41:36 +02:00
|
|
|
ResMergeNodes(p2->br_this, p1->br_this, pendingList, doneList);
|
2017-04-25 14:41:48 +02:00
|
|
|
freeMagic((char *)p1);
|
|
|
|
|
merged = TRUE;
|
|
|
|
|
}
|
|
|
|
|
else if (p1->br_this == resCurrentNode)
|
|
|
|
|
{
|
|
|
|
|
currNode = p2->br_this;
|
|
|
|
|
p1->br_next = p2->br_next;
|
2021-09-08 22:41:36 +02:00
|
|
|
ResMergeNodes(p1->br_this, p2->br_this, pendingList, doneList);
|
2017-04-25 14:41:48 +02:00
|
|
|
merged = TRUE;
|
|
|
|
|
freeMagic((char *)p2);
|
|
|
|
|
p2 = p1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
currNode = p1->br_this;
|
2021-09-08 22:41:36 +02:00
|
|
|
ResMergeNodes(p2->br_this, p1->br_this, pendingList, doneList);
|
2017-04-25 14:41:48 +02:00
|
|
|
freeMagic((char *)p1);
|
|
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
|
|
|
|
|
/*
|
2017-04-25 14:41:48 +02:00
|
|
|
* Was the node used in another junk or breakpoint?
|
|
|
|
|
* If so, replace the old node with the new one.
|
|
|
|
|
*/
|
2021-09-08 22:41:36 +02:00
|
|
|
p3 = p2->br_next;
|
2017-04-25 14:41:48 +02:00
|
|
|
while (p3 != NULL)
|
|
|
|
|
{
|
|
|
|
|
if (p3->br_this == currNode)
|
|
|
|
|
p3->br_this = p2->br_this;
|
2021-09-08 22:41:36 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
p3 = p3->br_next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
/*
|
2017-04-25 14:41:48 +02:00
|
|
|
* 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 =
|
2023-03-25 16:01:52 +01:00
|
|
|
(float)ExtCurStyle->exts_sheetResist[resistor->rr_tt]
|
|
|
|
|
* (float)(p2->br_loc.p_y - p1->br_loc.p_y)
|
|
|
|
|
/ (float)width;
|
2021-09-12 23:20:22 +02:00
|
|
|
rArea = ((p2->br_loc.p_y - p1->br_loc.p_y) * width) / 2;
|
2017-04-25 14:41:48 +02:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
|
*
|
2019-10-17 22:21:56 +02:00
|
|
|
* 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
|
2017-04-25 14:41:48 +02:00
|
|
|
* whenever a diffusion tile adjoining a real tile is found. It makes
|
2020-05-23 23:13:14 +02:00
|
|
|
* a guess at the correct direction of current flow, removes extra
|
2017-04-25 14:41:48 +02:00
|
|
|
* breakpoints, and call either ResCalcEastWest or ResCalcNorthSouth
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* TRUE if merging occurred, FALSE if not.
|
|
|
|
|
*
|
|
|
|
|
* Side Effects: Makes resistors. Frees breakpoints
|
|
|
|
|
*
|
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
bool
|
2019-10-17 22:21:56 +02:00
|
|
|
ResCalcNearDevice(tile, pendingList, doneList, resList)
|
2017-04-25 14:41:48 +02:00
|
|
|
Tile *tile;
|
|
|
|
|
resNode **pendingList, **doneList;
|
|
|
|
|
resResistor **resList;
|
|
|
|
|
|
|
|
|
|
{
|
2021-09-08 22:41:36 +02:00
|
|
|
bool merged;
|
|
|
|
|
int devcount, devedge, deltax, deltay;
|
|
|
|
|
Breakpoint *p1, *p2, *p3;
|
|
|
|
|
tileJunk *junk = (tileJunk *)tile->ti_client;
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2021-09-08 22:41:36 +02:00
|
|
|
merged = FALSE;
|
2017-04-25 14:41:48 +02:00
|
|
|
|
2021-09-08 22:41:36 +02:00
|
|
|
/*
|
|
|
|
|
* One Breakpoint? No resistors need to be made. Free up the first
|
|
|
|
|
* breakpoint, then return.
|
2017-04-25 14:41:48 +02:00
|
|
|
*/
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2021-09-08 22:41:36 +02:00
|
|
|
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 ||
|
2019-10-17 22:21:56 +02:00
|
|
|
(devedge & LEFTEDGE) == devedge ||
|
2021-09-08 22:41:36 +02:00
|
|
|
(devedge & RIGHTEDGE) == devedge ||
|
2019-10-17 22:21:56 +02:00
|
|
|
(devedge & TOPEDGE) == devedge ||
|
|
|
|
|
(devedge & BOTTOMEDGE) == devedge)
|
2021-09-08 22:41:36 +02:00
|
|
|
{
|
|
|
|
|
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 &&
|
2017-04-25 14:41:48 +02:00
|
|
|
(p1->br_loc.p_x != p1->br_next->br_loc.p_x ||
|
|
|
|
|
p1->br_loc.p_y != p1->br_next->br_loc.p_y))
|
2021-09-08 22:41:36 +02:00
|
|
|
p2 = p1;
|
|
|
|
|
}
|
|
|
|
|
deltax = INFINITY;
|
|
|
|
|
for (p3 = p1->br_next; p3 != NULL &&
|
2020-05-23 23:13:14 +02:00
|
|
|
p3->br_loc.p_x == p1->br_loc.p_x &&
|
2017-04-25 14:41:48 +02:00
|
|
|
p3->br_loc.p_y == p1->br_loc.p_y; p3 = p3->br_next);
|
2021-09-08 22:41:36 +02:00
|
|
|
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 &&
|
2017-04-25 14:41:48 +02:00
|
|
|
(p1->br_loc.p_x != p1->br_next->br_loc.p_x ||
|
|
|
|
|
p1->br_loc.p_y != p1->br_next->br_loc.p_y))
|
2021-09-08 22:41:36 +02:00
|
|
|
{
|
|
|
|
|
p2 = p1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
deltay = INFINITY;
|
|
|
|
|
for (p3 = p1->br_next; p3 != NULL &&
|
2020-05-23 23:13:14 +02:00
|
|
|
p3->br_loc.p_x == p1->br_loc.p_x &&
|
2017-04-25 14:41:48 +02:00
|
|
|
p3->br_loc.p_y == p1->br_loc.p_y; p3 = p3->br_next);
|
2021-09-08 22:41:36 +02:00
|
|
|
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) ||
|
2019-10-17 22:21:56 +02:00
|
|
|
(devedge & TOPEDGE || devedge & BOTTOMEDGE) &&
|
|
|
|
|
(devedge & LEFTEDGE || devedge & RIGHTEDGE) &&
|
2021-09-08 22:41:36 +02:00
|
|
|
(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 &&
|
2017-04-25 14:41:48 +02:00
|
|
|
(p1->br_loc.p_y == BOTTOM(tile) ||
|
|
|
|
|
p1->br_loc.p_y == TOP(tile)))
|
2021-09-08 22:41:36 +02:00
|
|
|
{
|
|
|
|
|
p3 = NULL;
|
|
|
|
|
p2 = junk->breakList;
|
|
|
|
|
while (p2 != NULL)
|
|
|
|
|
{
|
|
|
|
|
if (p2->br_this == p1->br_this && p2 != p1 &&
|
2017-04-25 14:41:48 +02:00
|
|
|
p2->br_loc.p_y != BOTTOM(tile) &&
|
|
|
|
|
p2->br_loc.p_y != TOP(tile))
|
2021-09-08 22:41:36 +02:00
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
}
|
2017-04-25 14:41:48 +02:00
|
|
|
}
|
2021-09-08 22:41:36 +02:00
|
|
|
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 &&
|
2017-04-25 14:41:48 +02:00
|
|
|
(p1->br_loc.p_x == LEFT(tile) ||
|
|
|
|
|
p1->br_loc.p_x == RIGHT(tile)))
|
2021-09-08 22:41:36 +02:00
|
|
|
{
|
|
|
|
|
p3 = NULL;
|
|
|
|
|
p2 = junk->breakList;
|
|
|
|
|
while (p2 != NULL)
|
|
|
|
|
{
|
|
|
|
|
if (p2->br_this == p1->br_this && p2 != p1 &&
|
2017-04-25 14:41:48 +02:00
|
|
|
p2->br_loc.p_x != LEFT(tile) &&
|
|
|
|
|
p2->br_loc.p_x != RIGHT(tile))
|
2021-09-08 22:41:36 +02:00
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
}
|
2017-04-25 14:41:48 +02:00
|
|
|
}
|
2021-09-08 22:41:36 +02:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
p3 = p2;
|
|
|
|
|
p2 = p2->br_next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return ResCalcEastWest(tile, pendingList, doneList, resList);
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-04-25 14:41:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* ResDoContacts-- Add node (or nodes) for a contact. If there are contact
|
|
|
|
|
* resistances, also add a resistor.
|
|
|
|
|
*
|
2020-05-23 23:13:14 +02:00
|
|
|
* Results:
|
2017-04-25 14:41:48 +02:00
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side Effects: Creates nodes and resistors
|
|
|
|
|
*
|
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ResDoContacts(contact, nodes, resList)
|
|
|
|
|
ResContactPoint *contact;
|
|
|
|
|
resNode **nodes;
|
2021-09-08 22:41:36 +02:00
|
|
|
resResistor **resList;
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
resNode *resptr;
|
|
|
|
|
cElement *ccell;
|
|
|
|
|
int tilenum, squaresx, squaresy, viawidth;
|
2019-10-14 23:17:08 +02:00
|
|
|
int minside, spacing, border, cscale;
|
2017-04-25 14:41:48 +02:00
|
|
|
float squaresf;
|
|
|
|
|
resResistor *resistor;
|
|
|
|
|
resElement *element;
|
|
|
|
|
static int too_small = 1;
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
minside = CIFGetContactSize(contact->cp_type, &viawidth, &spacing, &border);
|
2019-10-14 23:17:08 +02:00
|
|
|
cscale = CIFCurStyle->cs_scaleFactor;
|
2017-04-25 14:41:48 +02:00
|
|
|
|
|
|
|
|
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)));
|
2021-09-08 22:41:36 +02:00
|
|
|
InitializeNode(resptr, x, y, RES_NODE_CONTACT);
|
|
|
|
|
ResAddToQueue(resptr, nodes);
|
2017-04-25 14:41:48 +02:00
|
|
|
|
|
|
|
|
ccell = (cElement *) mallocMagic((unsigned) (sizeof(cElement)));
|
|
|
|
|
ccell->ce_nextc = resptr->rn_ce;
|
|
|
|
|
resptr->rn_ce = ccell;
|
|
|
|
|
ccell->ce_thisc = contact;
|
|
|
|
|
|
2021-09-08 22:41:36 +02:00
|
|
|
/* Add 1 celement for each layer of contact */
|
2017-04-25 14:41:48 +02:00
|
|
|
|
2021-09-08 22:41:36 +02:00
|
|
|
for (tilenum = 0; tilenum < contact->cp_currentcontact; tilenum++)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
2021-09-08 22:41:36 +02:00
|
|
|
Tile *tile = contact->cp_tile[tilenum];
|
2017-04-25 14:41:48 +02:00
|
|
|
|
|
|
|
|
contact->cp_cnode[tilenum] = resptr;
|
|
|
|
|
NEWBREAK(resptr, tile, contact->cp_center.p_x,
|
|
|
|
|
contact->cp_center.p_y, &contact->cp_rect);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2019-10-14 23:17:08 +02:00
|
|
|
if (((contact->cp_width * cscale) < minside) ||
|
|
|
|
|
((contact->cp_height * cscale) < minside))
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
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;
|
2023-09-28 18:38:08 +02:00
|
|
|
squaresf = (float)((contact->cp_width * cscale) - minside);
|
2017-04-25 14:41:48 +02:00
|
|
|
squaresf /= (float)viawidth;
|
|
|
|
|
squaresx = (int)squaresf;
|
|
|
|
|
squaresx++;
|
|
|
|
|
|
2023-09-28 18:38:08 +02:00
|
|
|
squaresf = (float)((contact->cp_height * cscale) - minside);
|
2017-04-25 14:41:48 +02:00
|
|
|
squaresf /= (float)viawidth;
|
|
|
|
|
squaresy = (int)squaresf;
|
|
|
|
|
squaresy++;
|
|
|
|
|
}
|
2021-09-08 22:41:36 +02:00
|
|
|
for (tilenum = 0; tilenum < contact->cp_currentcontact; tilenum++)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
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)));
|
2021-09-08 22:41:36 +02:00
|
|
|
InitializeNode(resptr, x, y, RES_NODE_CONTACT);
|
|
|
|
|
ResAddToQueue(resptr, nodes);
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2021-09-08 22:41:36 +02:00
|
|
|
/* Add contact pointer to node */
|
2017-04-25 14:41:48 +02:00
|
|
|
|
|
|
|
|
ccell = (cElement *) mallocMagic((unsigned) (sizeof(cElement)));
|
|
|
|
|
ccell->ce_nextc = resptr->rn_ce;
|
|
|
|
|
resptr->rn_ce = ccell;
|
|
|
|
|
ccell->ce_thisc = contact;
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
contact->cp_cnode[tilenum] = resptr;
|
|
|
|
|
NEWBREAK(resptr, tile, contact->cp_center.p_x,
|
|
|
|
|
contact->cp_center.p_y, &contact->cp_rect);
|
|
|
|
|
|
2021-09-08 22:41:36 +02:00
|
|
|
/* Add resistors here */
|
2017-04-25 14:41:48 +02:00
|
|
|
|
|
|
|
|
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;
|
2021-09-08 22:41:36 +02:00
|
|
|
resistor->rr_connection1 = contact->cp_cnode[tilenum - 1];
|
2017-04-25 14:41:48 +02:00
|
|
|
resistor->rr_connection2 = contact->cp_cnode[tilenum];
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
element = (resElement *) mallocMagic((unsigned) (sizeof(resElement)));
|
2021-09-08 22:41:36 +02:00
|
|
|
element->re_nextEl = contact->cp_cnode[tilenum - 1]->rn_re;
|
2017-04-25 14:41:48 +02:00
|
|
|
element->re_thisEl = resistor;
|
2021-09-08 22:41:36 +02:00
|
|
|
contact->cp_cnode[tilenum - 1]->rn_re = element;
|
2017-04-25 14:41:48 +02:00
|
|
|
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;
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
/* Need to figure out how to handle the multiple nodes */
|
2017-04-25 14:41:48 +02:00
|
|
|
/* and multiple resistors necessary to determine the */
|
|
|
|
|
/* correct geometry for the geometry extractor. For */
|
|
|
|
|
/* now, extract as one big glob. */
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/* 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;
|
2023-09-29 16:48:05 +02:00
|
|
|
|
2023-09-29 18:41:54 +02:00
|
|
|
resistor->rr_value =
|
2023-03-25 16:01:52 +01:00
|
|
|
(float)ExtCurStyle->exts_viaResist[contact->cp_type] /
|
|
|
|
|
(float)(squaresx * squaresy);
|
2017-04-25 14:41:48 +02:00
|
|
|
#ifdef ARIEL
|
|
|
|
|
resistor->rr_csArea =
|
2023-03-25 16:01:52 +01:00
|
|
|
(float)ExtCurStyle->exts_thick[contact->cp_type] /
|
|
|
|
|
(float)(squaresx * squaresy);
|
2017-04-25 14:41:48 +02:00
|
|
|
#endif
|
|
|
|
|
resistor->rr_tt = contact->cp_type;
|
2021-09-08 22:41:36 +02:00
|
|
|
resistor->rr_float.rr_area = 0;
|
2017-04-25 14:41:48 +02:00
|
|
|
resistor->rr_status = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
|
*
|
2021-09-08 22:41:36 +02:00
|
|
|
* ResSortBreaks --
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None
|
|
|
|
|
*
|
2017-04-25 14:41:48 +02:00
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ResSortBreaks(masterlist, xsort)
|
|
|
|
|
Breakpoint **masterlist;
|
|
|
|
|
int xsort;
|
|
|
|
|
{
|
|
|
|
|
Breakpoint *p1, *p2, *p3, *p4;
|
2021-09-08 22:41:36 +02:00
|
|
|
bool changed;
|
2017-04-25 14:41:48 +02:00
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
|