834 lines
20 KiB
C
834 lines
20 KiB
C
/*
|
|
* SimExtract.c
|
|
*
|
|
* This file provides routines to extract a single node name from the
|
|
* Magic circuit. Some of this code is based on the Magic extract
|
|
* module.
|
|
*
|
|
* *********************************************************************
|
|
* * Copyright (C) 1985, 1990 Regents of the University of California. *
|
|
* * Permission to use, copy, modify, and distribute this *
|
|
* * software and its documentation for any purpose and without *
|
|
* * fee is hereby granted, provided that the above copyright *
|
|
* * notice appear in all copies. The University of California *
|
|
* * makes no representations about the suitability of this *
|
|
* * software for any purpose. It is provided "as is" without *
|
|
* * express or implied warranty. Export of this software outside *
|
|
* * of the United States of America may require an export license. *
|
|
* *********************************************************************
|
|
* of California.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
|
|
#include "tcltk/tclmagic.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 "debug/debug.h"
|
|
#include "extract/extract.h"
|
|
#include "extract/extractInt.h"
|
|
#include "utils/signals.h"
|
|
#include "windows/windows.h"
|
|
#include "dbwind/dbwind.h"
|
|
#include "utils/styles.h"
|
|
#include "utils/stack.h"
|
|
#include "sim/sim.h"
|
|
|
|
/* C99 compat */
|
|
#include "extract/extract.h"
|
|
|
|
|
|
/* When performing node name extraction, we mark all tiles of a node
|
|
* as we walk through the database. Since nodes can span multiple cells,
|
|
* we need to keep a list off all cell definitions which we marked during
|
|
* the search so we can erase these marks when we are finished.
|
|
*/
|
|
typedef struct def_list_elt
|
|
{
|
|
CellDef *dl_def;
|
|
struct def_list_elt *dl_next;
|
|
} DefListElt;
|
|
|
|
/* When the node name is extracted, all the labels associated with the
|
|
* name are contained in a NodeRegion data structure. We save all the
|
|
* node regions created during the name search, freeing them when we are
|
|
* finished.
|
|
*/
|
|
|
|
|
|
static DefListElt *DefList = (DefListElt *) NULL;
|
|
/* list of cell defs used in the node name search */
|
|
|
|
static NodeRegion *NodeRegList = (NodeRegion *) NULL;
|
|
/* list of the nodes found in the current selection */
|
|
|
|
extern Stack *extNodeStack;
|
|
/* stack used to process node tiles */
|
|
|
|
static ExtStyle *simExtStyle = NULL;
|
|
|
|
/*
|
|
* Mask with a bit set for every type of transistor.
|
|
*/
|
|
TileTypeBitMask SimTransMask;
|
|
/*
|
|
* Mask indicating which tile types may form a transistor
|
|
* terminal (source/drain).
|
|
*/
|
|
TileTypeBitMask SimSDMask;
|
|
/*
|
|
* A mask indicating which tile types may be the active part
|
|
* of a transistor. if type 't' is a possible transistor terminal,
|
|
* then SimFetMask[t] indicates which tile types to search for the
|
|
* 'gate' part.
|
|
*/
|
|
TileTypeBitMask SimFetMask[TT_MAXTYPES];
|
|
/*
|
|
* Mask of planes for which SimFetMask is non-zero.
|
|
*/
|
|
PlaneMask SimFetPlanes;
|
|
|
|
|
|
/*
|
|
*----------------------------------------------------------------
|
|
* SimAddDefList --
|
|
*
|
|
* This procedure adds a cell definition to the DefList. A cell
|
|
* definition is added only if is not already in the list.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* The cell may be added to the list.
|
|
*
|
|
*----------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
SimAddDefList(
|
|
CellDef *newdef)
|
|
{
|
|
DefListElt *d;
|
|
|
|
/* check to see if the cell def is already in our list */
|
|
|
|
for (d = DefList; d != (DefListElt *) NULL; d = d->dl_next) {
|
|
if (d->dl_def == newdef) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* add the cell def to the list */
|
|
|
|
if (DefList == (DefListElt *) NULL) {
|
|
DefList = (DefListElt *) mallocMagic((unsigned) (sizeof(DefListElt)));
|
|
DefList->dl_def = newdef;
|
|
DefList->dl_next = (DefListElt *) NULL;
|
|
return;
|
|
}
|
|
else {
|
|
d = (DefListElt *) mallocMagic((unsigned) (sizeof(DefListElt)));
|
|
d->dl_next = DefList;
|
|
d->dl_def = newdef;
|
|
DefList= d;
|
|
}
|
|
}
|
|
|
|
/*
|
|
*----------------------------------------------------------------
|
|
* SimInitDefList
|
|
*
|
|
* This procedure initializes the cell definition list. Any cell
|
|
* definitions in the list have their tiles erased of the marks
|
|
* we left during the node name search, and the space in the list
|
|
* is freed.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* The cell definitions' tiles' marks we left are erased and the
|
|
* list is set to NULL.
|
|
*
|
|
*----------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
SimInitDefList(void)
|
|
{
|
|
DefListElt *p, *q;
|
|
|
|
p = q = DefList;
|
|
while (p != (DefListElt *) NULL) {
|
|
q = p;
|
|
p = p->dl_next;
|
|
ExtResetTiles(q->dl_def, extUnInit);
|
|
freeMagic(q);
|
|
}
|
|
DefList = (DefListElt *) NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
*----------------------------------------------------------------
|
|
* SimAddNodeList
|
|
*
|
|
* This procedure prepends a node region to the node region list.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* The region next pointer is updated.
|
|
*
|
|
*----------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
SimAddNodeList(
|
|
NodeRegion *newnode)
|
|
{
|
|
if( NodeRegList != (NodeRegion *) NULL )
|
|
newnode->nreg_next = NodeRegList;
|
|
NodeRegList = newnode;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
*----------------------------------------------------------------
|
|
* SimFreeNodeRegs
|
|
*
|
|
* This procedure frees the label regions stored in the list.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* The list is set to NULL.
|
|
*
|
|
*----------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
SimFreeNodeRegs(void)
|
|
{
|
|
NodeRegion *p, *q;
|
|
|
|
if( NodeRegList != (NodeRegion *) NULL ) /* sanity */
|
|
ExtFreeLabRegions((LabRegion *) NodeRegList );
|
|
|
|
NodeRegList = (NodeRegion *) NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
*----------------------------------------------------------------
|
|
* SimInitConnTables --
|
|
*
|
|
* Initialize the connectivity tables for finding transistors connected
|
|
* to the region being searched.
|
|
*----------------------------------------------------------------
|
|
*/
|
|
int
|
|
SimInitConnTables(void)
|
|
{
|
|
int i, t, sd, p;
|
|
ExtDevice *devptr;
|
|
|
|
SimTransMask = ExtCurStyle->exts_deviceMask;
|
|
|
|
TTMaskZero( &SimSDMask );
|
|
for( t = TT_TECHDEPBASE; t < DBNumTypes; t++ )
|
|
{
|
|
devptr = ExtCurStyle->exts_device[t];
|
|
for (i = 0; !TTMaskHasType(&devptr->exts_deviceSDTypes[i],
|
|
TT_SPACE); i++)
|
|
{
|
|
TTMaskSetMask( &SimSDMask, &devptr->exts_deviceSDTypes[i] );
|
|
TTMaskZero( &SimFetMask[t] );
|
|
}
|
|
}
|
|
|
|
SimFetPlanes = 0;
|
|
for (t = TT_TECHDEPBASE; t < DBNumTypes; t++)
|
|
{
|
|
if (TTMaskHasType(&SimTransMask, t))
|
|
{
|
|
devptr = ExtCurStyle->exts_device[t];
|
|
for (sd = TT_TECHDEPBASE; sd < DBNumTypes; sd++)
|
|
{
|
|
for (i = 0; !TTMaskHasType(&devptr->exts_deviceSDTypes[i],
|
|
TT_SPACE); i++)
|
|
{
|
|
if (TTMaskHasType(&devptr->exts_deviceSDTypes[i], sd))
|
|
{
|
|
TTMaskSetType(&SimFetMask[sd], t);
|
|
SimFetPlanes |= PlaneNumToMaskBit(DBPlane(t));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
simExtStyle = ExtCurStyle;
|
|
return 0;
|
|
}
|
|
|
|
#define IsTransGate( T ) ( TTMaskHasType( &SimTransMask, T ) )
|
|
#define IsTransTerm( T ) ( TTMaskHasType( &SimSDMask, T ) )
|
|
|
|
|
|
typedef struct
|
|
{
|
|
NodeRegion *region; /* Node to which this terminal is connected */
|
|
int pnum; /* Lowest numbered plane in this region */
|
|
Point pos; /* Lower-leftmost point for this node */
|
|
} TransTerm;
|
|
|
|
|
|
typedef struct
|
|
{
|
|
LabRegion *t_dummy; /* UNUSED */
|
|
int t_pnum; /* Lowest numbered plane in this region */
|
|
int t_type; /* Type of tile that contains lreg_ll */
|
|
Point t_ll; /* Lower-leftmost point of 'gate' region */
|
|
int t_nterm; /* number of terminals (at most 2) */
|
|
bool t_do_terms; /* Set if we should collect terminals */
|
|
TransTerm t_term[10]; /* transistor 'source/drain' terminal(s) */
|
|
} SimTrans;
|
|
|
|
|
|
static Tile *gateTile; /* Set to point to a transistor tile
|
|
* whose gate is connected to the
|
|
* node being searched
|
|
*/
|
|
static Tile *sdTile; /* Set to point to a transistor tile
|
|
* whose source/drain is connected
|
|
* to the node being searched
|
|
*/
|
|
static SimTrans transistor; /* Transistor being extracted */
|
|
|
|
|
|
typedef enum { ND_REGION, ND_NAME } RegOrName;
|
|
|
|
|
|
typedef struct /* return value from SimFindOneNode */
|
|
{
|
|
RegOrName nd_what; /* ND_REGION, => region, ND_NAME => nd_name */
|
|
NodeRegion *nd_region; /* The node region extracted */
|
|
char *nd_name; /* The 'final' node name */
|
|
} NodeSpec;
|
|
|
|
|
|
/*
|
|
*----------------------------------------------------------------
|
|
* SimTxtorLabel --
|
|
*
|
|
* Return a string that identifies a node as a function of a transistor
|
|
* position.
|
|
*
|
|
*----------------------------------------------------------------
|
|
*/
|
|
char *
|
|
SimTxtorLabel(
|
|
int nterm,
|
|
const Transform *tm,
|
|
SimTrans *trans)
|
|
{
|
|
static char name[30];
|
|
Rect r1, r2;
|
|
|
|
r1.r_ll = trans->t_ll;
|
|
r1.r_xtop = r1.r_xbot + 1;
|
|
r1.r_ytop = r1.r_ybot + 1;
|
|
GeoTransRect( tm, &r1, &r2 );
|
|
if( nterm > 1 )
|
|
nterm = 1;
|
|
sprintf( name, "@=%c%d,%d", "gsd"[nterm+1], r2.r_xbot, r2.r_ybot );
|
|
|
|
return( name );
|
|
}
|
|
|
|
int
|
|
SimSDTransFunc(
|
|
Tile *tile,
|
|
Tile **ptile)
|
|
{
|
|
*ptile = tile;
|
|
return( 1 );
|
|
}
|
|
|
|
|
|
int
|
|
SimTransTerms(
|
|
Boundary *bp,
|
|
SimTrans *trans)
|
|
{
|
|
TransTerm *term;
|
|
Tile *tile = bp->b_outside;
|
|
TileType type;
|
|
NodeRegion *reg = (NodeRegion *) TiGetClientPTR(tile);
|
|
int pNum;
|
|
int i;
|
|
|
|
if (IsSplit(tile)) {
|
|
switch(bp->b_direction) {
|
|
case BD_LEFT:
|
|
type = TiGetRightType(tile);
|
|
break;
|
|
case BD_RIGHT:
|
|
type = TiGetLeftType(tile);
|
|
break;
|
|
case BD_TOP:
|
|
type = TiGetBottomType(tile);
|
|
break;
|
|
case BD_BOTTOM:
|
|
type = TiGetTopType(tile);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
type = TiGetTypeExact(tile);
|
|
|
|
pNum = DBPlane(type);
|
|
|
|
for( i = 0; i < trans->t_nterm; i++ )
|
|
{
|
|
term = &trans->t_term[i];
|
|
if( term->region == reg )
|
|
{
|
|
if( pNum < term->pnum )
|
|
{
|
|
term->pnum = pNum;
|
|
term->pos = tile->ti_ll;
|
|
}
|
|
else if( pNum == term->pnum )
|
|
{
|
|
if( LEFT(tile) < term->pos.p_x )
|
|
term->pos = tile->ti_ll;
|
|
else if( LEFT(tile) == term->pos.p_x &&
|
|
BOTTOM(tile) < term->pos.p_y )
|
|
term->pos.p_y = BOTTOM(tile);
|
|
}
|
|
return( 0 );
|
|
}
|
|
}
|
|
|
|
term = &trans->t_term[ trans->t_nterm++ ];
|
|
term->region = reg;
|
|
term->pnum = pNum;
|
|
term->pos = tile->ti_ll;
|
|
return( 0 );
|
|
}
|
|
|
|
|
|
int
|
|
SimTermNum(
|
|
SimTrans *trans,
|
|
NodeRegion *reg)
|
|
{
|
|
int i, changed;
|
|
TransTerm *p1, *p2, tmp;
|
|
|
|
do
|
|
{
|
|
changed = 0;
|
|
for( i = 0; i < trans->t_nterm-1; i++ )
|
|
{
|
|
p1 = &(trans->t_term[i]);
|
|
p2 = &(trans->t_term[i+1]);
|
|
if( p2->pnum > p1->pnum )
|
|
continue;
|
|
else if( p2->pnum == p1->pnum )
|
|
{
|
|
if( p2->pos.p_x > p1->pos.p_x )
|
|
continue;
|
|
else if( p2->pos.p_x == p1->pos.p_x &&
|
|
p2->pos.p_y > p1->pos.p_y )
|
|
continue;
|
|
}
|
|
changed = 1;
|
|
tmp = *p1;
|
|
*p1 = *p2;
|
|
*p2 = tmp;
|
|
}
|
|
}
|
|
while( changed );
|
|
|
|
for( i = 0; i < trans->t_nterm; i++ )
|
|
{
|
|
if( trans->t_term[i].region == reg )
|
|
return( i );
|
|
}
|
|
/* should never get here */
|
|
return( -1 );
|
|
}
|
|
|
|
|
|
int
|
|
SimTransistorTile(
|
|
Tile *tile,
|
|
int pNum,
|
|
FindRegion *arg)
|
|
{
|
|
int i;
|
|
TileType t;
|
|
ExtDevice *devptr;
|
|
|
|
extSetNodeNum((LabRegion *)&transistor, pNum, tile);
|
|
if (transistor.t_do_terms)
|
|
{
|
|
t = TiGetType(tile);
|
|
devptr = ExtCurStyle->exts_device[t];
|
|
for (i = 0; !TTMaskHasType(&devptr->exts_deviceSDTypes[i],
|
|
TT_SPACE); i++)
|
|
extEnumTilePerim(tile, &devptr->exts_deviceSDTypes[i], pNum,
|
|
SimTransTerms, (ClientData) &transistor );
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
|
|
int
|
|
SimFindTxtor(
|
|
Tile *tile,
|
|
int pNum,
|
|
FindRegion *arg)
|
|
{
|
|
TileType type;
|
|
|
|
extSetNodeNum( (LabRegion *) arg->fra_region, pNum, tile );
|
|
|
|
if( ! SimUseCoords ) /* keep searching, forget transistors */
|
|
return( 0 );
|
|
|
|
type = TiGetType( tile );
|
|
|
|
if( IsTransGate( type ) )
|
|
{
|
|
gateTile = tile; /* found a transistor gate, stop searching */
|
|
return( 1 );
|
|
}
|
|
else if( IsTransTerm( type ) && sdTile == (Tile *) NULL )
|
|
{
|
|
Rect area;
|
|
|
|
TITORECT( tile, &area );
|
|
GEO_EXPAND( &area, 1, &area );
|
|
for( pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++ )
|
|
if( PlaneMaskHasPlane( SimFetPlanes, pNum ) )
|
|
{
|
|
if( DBSrPaintArea((Tile *) NULL,
|
|
arg->fra_def->cd_planes[pNum], &area, &SimFetMask[type],
|
|
SimSDTransFunc, (ClientData) &sdTile ) )
|
|
break;
|
|
}
|
|
}
|
|
return( 0 );
|
|
}
|
|
|
|
|
|
/*
|
|
*----------------------------------------------------------------
|
|
* SimFindOneNode
|
|
*
|
|
* This procedure returns the node region for a tile which lies
|
|
* in the node.
|
|
*
|
|
* Results:
|
|
* A pointer to the node's node region data structure is returned.
|
|
*
|
|
* Side effects:
|
|
* None.
|
|
*
|
|
*----------------------------------------------------------------
|
|
*/
|
|
|
|
NodeSpec *
|
|
SimFindOneNode(
|
|
SearchContext *sx,
|
|
Tile *tile)
|
|
{
|
|
CellDef *def = sx->scx_use->cu_def;
|
|
NodeRegion *reg;
|
|
FindRegion arg;
|
|
TileType type, loctype;
|
|
static NodeSpec ret;
|
|
|
|
/* Allocate a new node */
|
|
reg = (NodeRegion *) mallocMagic((unsigned) (sizeof(NodeRegion) ));
|
|
reg->nreg_labels = (LabelList *) NULL;
|
|
reg->nreg_cap = 0;
|
|
reg->nreg_resist = 0;
|
|
reg->nreg_pnum = DBNumPlanes;
|
|
reg->nreg_next = (NodeRegion *) NULL;
|
|
|
|
gateTile = sdTile = (Tile *) NULL;
|
|
|
|
/* Find all connected paint in this cell */
|
|
arg.fra_connectsTo = ExtCurStyle->exts_nodeConn;
|
|
arg.fra_def = def;
|
|
|
|
if (IsSplit(tile))
|
|
type = SplitSide(tile) ? TiGetRightType(tile) : TiGetLeftType(tile);
|
|
else
|
|
type = TiGetTypeExact(tile);
|
|
|
|
arg.fra_pNum = DBPlane(type);
|
|
arg.fra_uninit = (ClientData) extUnInit;
|
|
arg.fra_region = (ExtRegion *) reg;
|
|
arg.fra_each = SimFindTxtor;
|
|
(void) ExtFindNeighbors( tile, arg.fra_pNum, &arg );
|
|
|
|
if( gateTile != (Tile *) NULL )
|
|
{
|
|
/* Determine the transistor position (leftmost-lowest tile) */
|
|
transistor.t_pnum = DBNumPlanes;
|
|
transistor.t_do_terms = FALSE;
|
|
|
|
TiSetClient(gateTile, extUnInit);
|
|
arg.fra_connectsTo = &SimTransMask;
|
|
|
|
if (IsSplit(tile))
|
|
loctype = SplitSide(gateTile) ? TiGetRightType(gateTile)
|
|
: TiGetLeftType(gateTile);
|
|
else
|
|
loctype = TiGetTypeExact(gateTile);
|
|
|
|
arg.fra_pNum = DBPlane(loctype);
|
|
arg.fra_uninit = (ClientData) extUnInit;
|
|
arg.fra_region = (ExtRegion *) reg;
|
|
arg.fra_each = SimTransistorTile;
|
|
(void) ExtFindNeighbors( gateTile, arg.fra_pNum, &arg );
|
|
|
|
/* Unmark current region since not all paint was traced */
|
|
arg.fra_connectsTo = ExtCurStyle->exts_nodeConn;
|
|
arg.fra_pNum = DBPlane(type);
|
|
arg.fra_uninit = (ClientData) reg;
|
|
arg.fra_region = (ExtRegion *) extUnInit;
|
|
arg.fra_each = (int (*)()) NULL;
|
|
(void) ExtFindNeighbors( tile, arg.fra_pNum, &arg );
|
|
|
|
freeMagic( reg );
|
|
|
|
ret.nd_name = SimTxtorLabel( -1, &sx->scx_trans, &transistor );
|
|
ret.nd_what = ND_NAME;
|
|
}
|
|
else if( sdTile != (Tile *) NULL )
|
|
{
|
|
int tNum;
|
|
|
|
SimAddNodeList( reg );
|
|
SimAddDefList( def );
|
|
|
|
transistor.t_pnum = DBNumPlanes;
|
|
transistor.t_nterm = 0;
|
|
transistor.t_do_terms = TRUE;
|
|
|
|
/* collect the transistor position, and its terminals */
|
|
arg.fra_connectsTo = &SimTransMask;
|
|
|
|
if (IsSplit(tile))
|
|
loctype = SplitSide(sdTile) ? TiGetRightType(sdTile)
|
|
: TiGetLeftType(sdTile);
|
|
else
|
|
loctype = TiGetTypeExact(sdTile);
|
|
|
|
arg.fra_pNum = DBPlane(loctype);
|
|
arg.fra_uninit = TiGetClient(sdTile);
|
|
arg.fra_region = (ExtRegion *) &ret;
|
|
arg.fra_each = SimTransistorTile;
|
|
(void) ExtFindNeighbors( sdTile, arg.fra_pNum, &arg );
|
|
|
|
/* Unmark the transitor, since its not part of this region */
|
|
arg.fra_region = (ExtRegion *) arg.fra_uninit;
|
|
arg.fra_uninit = (ClientData) &ret;
|
|
arg.fra_each = (int (*)()) NULL;
|
|
(void) ExtFindNeighbors( sdTile, arg.fra_pNum, &arg );
|
|
|
|
if( (tNum = SimTermNum( &transistor, reg )) < 0 )
|
|
{
|
|
TxPrintf( "\tSimFindOneNode: bad transistor terminal number\n" );
|
|
goto use_name;
|
|
}
|
|
|
|
ret.nd_name = SimTxtorLabel( tNum, &sx->scx_trans, &transistor );
|
|
ret.nd_what = ND_NAME;
|
|
}
|
|
else /* no transistors found, get the regions labels */
|
|
{
|
|
SimAddNodeList( reg );
|
|
SimAddDefList( def );
|
|
|
|
use_name:
|
|
ExtLabelOneRegion( def, ExtCurStyle->exts_nodeConn, reg );
|
|
ret.nd_region = reg;
|
|
ret.nd_what = ND_REGION;
|
|
}
|
|
return( &ret );
|
|
}
|
|
|
|
|
|
/*
|
|
*----------------------------------------------------------------
|
|
* SimGetNodeName
|
|
*
|
|
* This procedure uses the Magic circuit extraction code to generate
|
|
* the node name. The node is extracted by searching the database
|
|
* for all tiles electrically connected to the node. Each tile is
|
|
* marked with a pointer to the node region it belongs to. It is
|
|
* the node region data structure which contains the labels for a
|
|
* node. The "preferred" label for the node is taken, and this
|
|
* is combined with the path name to produce the complete node name.
|
|
*
|
|
* Results:
|
|
* A pointer to the node name is returned. This is a pointer to
|
|
* statically allocated memory, so subsequent calls to this procedure
|
|
* will change the node name the returned pointer references.
|
|
*
|
|
* Side effects:
|
|
* Any node region created is added to the node region list.
|
|
*----------------------------------------------------------------
|
|
*/
|
|
|
|
char *
|
|
SimGetNodeName(
|
|
SearchContext *sx, /* current search context */
|
|
Tile *tp, /* tile in this cell which is part
|
|
* of the node
|
|
*/
|
|
const char *path) /* path name of hierarchy of search */
|
|
{
|
|
CellDef *def = sx->scx_use->cu_def;
|
|
NodeRegion *nodeList;
|
|
LabelList *ll;
|
|
static char nodename[256];
|
|
char buff[256];
|
|
char *text;
|
|
char *nname;
|
|
|
|
SimSawAbortString = FALSE;
|
|
|
|
if( SimUseCoords && simExtStyle != ExtCurStyle )
|
|
SimInitConnTables();
|
|
|
|
/* check to see if this tile has been extracted before */
|
|
|
|
if (TiGetClient(tp) == extUnInit)
|
|
{
|
|
NodeSpec *ns;
|
|
|
|
ns = SimFindOneNode(sx, tp);
|
|
if( ns->nd_what == ND_NAME )
|
|
{
|
|
SimSawAbortString = TRUE;
|
|
return( ns->nd_name );
|
|
}
|
|
nodeList = ns->nd_region;
|
|
}
|
|
else
|
|
{
|
|
nodeList = (NodeRegion *)TiGetClientPTR(tp);
|
|
}
|
|
|
|
/* generate the node name from the label region and the path name */
|
|
|
|
text = extNodeName((LabRegion *)nodeList);
|
|
strcpy(buff, text);
|
|
strcpy(nodename, path);
|
|
strcat(nodename, text);
|
|
|
|
/* check to see if we should abort the search on the node name */
|
|
|
|
if (!SimInitGetnode) {
|
|
if (HashLookOnly(&SimGetnodeTbl, buff) != (HashEntry *) NULL) {
|
|
SimSawAbortString = TRUE;
|
|
if (HashLookOnly(&SimAbortSeenTbl, buff) == (HashEntry *) NULL) {
|
|
HashFind(&SimAbortSeenTbl, buff);
|
|
TxPrintf("Node name search aborted on \"%s\"\n", buff);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Check whether or not to print out node name aliases. Each alias
|
|
* found is hashed in a table in order to suppress printing of
|
|
* duplicate aliases.
|
|
*/
|
|
|
|
if (SimGetnodeAlias && SimIsGetnode) {
|
|
if (HashLookOnly(&SimGNAliasTbl, nodename) == (HashEntry *) NULL) {
|
|
HashFind(&SimGNAliasTbl, nodename);
|
|
#ifdef MAGIC_WRAPPER
|
|
Tcl_AppendElement(magicinterp, nodename);
|
|
#else
|
|
TxPrintf("alias: %s\n", nodename);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/* search the list of all labels for this node, creating the full
|
|
* node name and returning the "best" node name found.
|
|
*/
|
|
for (ll = nodeList->nreg_labels; ll; ll = ll->ll_next) {
|
|
if (ll->ll_label->lab_text == text) {
|
|
for (ll = ll->ll_next; ll; ll = ll->ll_next) {
|
|
nname = ll->ll_label->lab_text;
|
|
if (extLabType(nname, LABTYPE_NAME)) {
|
|
strcpy(nodename, path);
|
|
strcat(nodename, nname);
|
|
if (efPreferredName(nname, buff)) {
|
|
strcpy(buff, nname);
|
|
}
|
|
if (SimGetnodeAlias && SimIsGetnode) {
|
|
if (HashLookOnly(&SimGNAliasTbl, nodename)
|
|
== (HashEntry *) NULL) {
|
|
HashFind(&SimGNAliasTbl, nodename);
|
|
#ifdef MAGIC_WRAPPER
|
|
Tcl_AppendElement(magicinterp, nodename);
|
|
#else
|
|
TxPrintf("alias: %s\n", nodename);
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
strcpy(nodename, path);
|
|
strcat(nodename, buff);
|
|
return(nodename);
|
|
}
|
|
|
|
/*
|
|
*----------------------------------------------------------------
|
|
* SimGetNodeCleanup
|
|
*
|
|
* This procedure is called to clean up the data structures and the
|
|
* tile database after a node name is extracted.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* The node region list and cell def lists are re-initialized.
|
|
*----------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
SimGetNodeCleanUp(void)
|
|
{
|
|
SimFreeNodeRegs();
|
|
SimInitDefList();
|
|
}
|