mirror of
https://github.com/RTimothyEdwards/magic.git
synced 2026-09-05 08:51:53 +02:00
and not being used. Corrected one other obscure error in which reading the .ext file picks up the wrong device type because it is possible to have multiple types map to the same device name. This is easy to detect and fix in place.
235 lines
6.7 KiB
C
235 lines
6.7 KiB
C
|
|
#ifndef lint
|
|
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/resis/ResJunct.c,v 1.1.1.1 2008/02/03 20:43:50 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 "database/databaseInt.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/stack.h"
|
|
#include "utils/tech.h"
|
|
#include "textio/txcommands.h"
|
|
#include "resis/resis.h"
|
|
|
|
/*
|
|
*-------------------------------------------------------------------------
|
|
*
|
|
* ResNewTermDevice --
|
|
*
|
|
* Called when a device is reached via a type in the device's
|
|
* terminal type list (e.g., diffusion, for MOSFETs). Note that
|
|
* devices reached by the device type (e.g., poly, for MOSFETs)
|
|
* are handled by ResEachTile.
|
|
*
|
|
* Results:
|
|
* None
|
|
*
|
|
* Side Effects:
|
|
* Determines to which terminal (source or drain) node is connected.
|
|
* Makes new node if node hasn't already been created. Allocates
|
|
* breakpoint in current tile for device.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
ResNewTermDevice(tile, tp, n, xj, yj, direction, PendingList)
|
|
Tile *tile, *tp;
|
|
int n; /* Terminal index */
|
|
int xj, yj; /* Location of connection */
|
|
int direction; /* Direction of current */
|
|
resNode **PendingList;
|
|
{
|
|
resNode *resptr = NULL;
|
|
resDevice *resDev;
|
|
tElement *tcell;
|
|
int newnode;
|
|
resInfo *ri;
|
|
|
|
newnode = FALSE;
|
|
|
|
/* Watch for invalid client data. If found, a "Bad Device" error will
|
|
* be generated which means "more debugging needed"; however, it will
|
|
* not cause a segmentation violation.
|
|
*/
|
|
if (TiGetClient(tp) == CLIENTDEFAULT) return;
|
|
|
|
ri = (resInfo *) TiGetClientPTR(tp);
|
|
resDev = ri->deviceList;
|
|
if (resDev == NULL) return; /* Shouldn't happen? */
|
|
|
|
/* Set the terminal indicated (source or drain). If the terminal
|
|
* indicated is already set, then create a new breakpoint on the
|
|
* terminal. However, to handle cases where a device may have
|
|
* source and drain tied to the same net, if there is an existing
|
|
* entry and the edge direction is opposite of "direction", then
|
|
* create a new terminal on the other side (i.e., permute source
|
|
* and drain).
|
|
*/
|
|
|
|
if (resDev->rd_terminals[2 + n] == (resNode *)NULL)
|
|
{
|
|
resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode)));
|
|
newnode = TRUE;
|
|
resDev->rd_terminals[2 + n] = resptr;
|
|
}
|
|
else if (((ri->sourceEdge & direction) != 0) || (resDev->rd_nterms < 4))
|
|
{
|
|
resptr = resDev->rd_terminals[2 + n];
|
|
}
|
|
else if ((n == 0) && (resDev->rd_terminals[3] == (resNode *)NULL))
|
|
{
|
|
resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode)));
|
|
newnode = TRUE;
|
|
resDev->rd_terminals[3] = resptr;
|
|
}
|
|
else if ((n == 1) && (resDev->rd_terminals[2] == (resNode *)NULL))
|
|
{
|
|
resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode)));
|
|
newnode = TRUE;
|
|
resDev->rd_terminals[2] = resptr;
|
|
}
|
|
|
|
if (newnode)
|
|
{
|
|
tcell = (tElement *) mallocMagic((unsigned)(sizeof(tElement)));
|
|
tcell->te_nextt = NULL;
|
|
tcell->te_thist = ri->deviceList;
|
|
InitializeResNode(resptr, xj, yj, RES_NODE_DEVICE);
|
|
resptr->rn_te = tcell;
|
|
ResAddToQueue(resptr, PendingList);
|
|
}
|
|
if (resptr != NULL)
|
|
ResNewBreak(resptr, tile, xj, yj, NULL);
|
|
}
|
|
|
|
/*
|
|
*-------------------------------------------------------------------------
|
|
*
|
|
* ResNewSubDevice -- called when a device is reached via a substrate.
|
|
*
|
|
* Results:none
|
|
*
|
|
* Side Effects: Makes new node if node hasn't already been created.
|
|
* Allocates breakpoint in current tile for device.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
ResNewSubDevice(tile, tp, xj, yj, direction, PendingList)
|
|
Tile *tile, *tp;
|
|
int xj, yj, direction;
|
|
resNode **PendingList;
|
|
{
|
|
resNode *resptr;
|
|
resDevice *resDev;
|
|
tElement *tcell;
|
|
int newnode;
|
|
resInfo *ri;
|
|
|
|
newnode = FALSE;
|
|
ri = (resInfo *) TiGetClientPTR(tp);
|
|
resDev = ri->deviceList;
|
|
|
|
if (resDev == NULL) return; /* Should not happen? */
|
|
|
|
if (resDev->rd_fet_subs == (resNode *)NULL)
|
|
{
|
|
resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode)));
|
|
newnode = TRUE;
|
|
resDev->rd_fet_subs = resptr;
|
|
}
|
|
else
|
|
resptr = resDev->rd_fet_subs;
|
|
|
|
if (newnode)
|
|
{
|
|
tcell = (tElement *) mallocMagic((unsigned)(sizeof(tElement)));
|
|
tcell->te_nextt = NULL;
|
|
tcell->te_thist = ri->deviceList;
|
|
InitializeResNode(resptr, xj, yj, RES_NODE_DEVICE);
|
|
resptr->rn_te = tcell;
|
|
ResAddToQueue(resptr, PendingList);
|
|
}
|
|
ResNewBreak(resptr, tile, xj, yj, NULL);
|
|
}
|
|
|
|
/*
|
|
*-------------------------------------------------------------------------
|
|
*
|
|
* ResProcessJunction-- Called whenever a tile connecting to the tile being
|
|
* worked on is found. If a junction is already present, its address is
|
|
* returned. Otherwise, a new junction is made.
|
|
*
|
|
* Results: None.
|
|
*
|
|
* Side Effects: Junctions may be created.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
ResProcessJunction(tile, tp, xj, yj, NodeList)
|
|
Tile *tile, *tp;
|
|
int xj, yj;
|
|
resNode **NodeList;
|
|
{
|
|
ResJunction *junction;
|
|
resNode *resptr;
|
|
jElement *jcell;
|
|
resInfo *ri0 = (resInfo *)TiGetClientPTR(tile);
|
|
resInfo *ri2 = (resInfo *)TiGetClientPTR(tp);
|
|
|
|
#ifdef PARANOID
|
|
if (tile == tp)
|
|
{
|
|
TxError("Junction being made between tile and itself \n");
|
|
return;
|
|
}
|
|
#endif
|
|
if (ri2->ri_status & RES_TILE_DONE) return;
|
|
resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode)));
|
|
resptr->rn_te = (tElement *) NULL;
|
|
junction = (ResJunction *) mallocMagic((unsigned)(sizeof(ResJunction)));
|
|
jcell = (jElement *) mallocMagic((unsigned)(sizeof(jElement)));
|
|
InitializeResNode(resptr, xj, yj, RES_NODE_JUNCTION);
|
|
resptr->rn_je = jcell;
|
|
ResAddToQueue(resptr, NodeList);
|
|
|
|
jcell->je_thisj = junction;
|
|
jcell->je_nextj = NULL;
|
|
junction->rj_status = FALSE;
|
|
junction->rj_jnode = resptr;
|
|
junction->rj_Tile[0] = tile;
|
|
junction->rj_Tile[1] = tp;
|
|
junction->rj_loc.p_x =xj;
|
|
junction->rj_loc.p_y =yj;
|
|
junction->rj_nextjunction[0] = ri0->junctionList;
|
|
ri0->junctionList = junction;
|
|
junction->rj_nextjunction[1] = ri2->junctionList;
|
|
ri2->junctionList = junction;
|
|
|
|
ResNewBreak(junction->rj_jnode, tile, junction->rj_loc.p_x,
|
|
junction->rj_loc.p_y, NULL);
|
|
|
|
ResNewBreak(junction->rj_jnode, tp, junction->rj_loc.p_x,
|
|
junction->rj_loc.p_y, NULL);
|
|
|
|
}
|