Final (I hope!) corrections to the "def write" command.
This commit is contained in:
parent
6369c44821
commit
65ef9a1ad3
|
|
@ -1596,7 +1596,6 @@ int simnodeVisit(node, res, cap)
|
|||
char *fmt;
|
||||
EFAttr *ap;
|
||||
|
||||
if (node->efnode_flags & EF_UNIQUE_NODE) return 0;
|
||||
if (esDevNodesOnly && node->efnode_client == (ClientData) NULL)
|
||||
return 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -1252,7 +1252,6 @@ spcsubHierVisit(hc, node, res, cap, resstrptr)
|
|||
HierName *hierName;
|
||||
char *nsn;
|
||||
|
||||
if (node->efnode_flags & EF_UNIQUE_NODE) return 0;
|
||||
if (node->efnode_flags & EF_GLOB_SUBS_NODE)
|
||||
{
|
||||
hierName = (HierName *) node->efnode_name->efnn_hier;
|
||||
|
|
@ -1293,7 +1292,6 @@ spcnodeHierVisit(hc, node, res, cap)
|
|||
char *fmt, *nsn;
|
||||
EFAttr *ap;
|
||||
|
||||
if (node->efnode_flags & EF_UNIQUE_NODE) return 0;
|
||||
if (node->efnode_client)
|
||||
{
|
||||
if (esDistrJunct)
|
||||
|
|
@ -1735,8 +1733,8 @@ esMakePorts(hc, cdata)
|
|||
nn = (EFNodeName *) HashGetValue(he);
|
||||
if (nn == NULL)
|
||||
{
|
||||
efBuildNode(portdef, FALSE, FALSE, portname, 0.0,
|
||||
0, 0, NULL, NULL, 0);
|
||||
efBuildNode(portdef, FALSE, FALSE, FALSE, portname,
|
||||
0.0, 0, 0, NULL, NULL, 0);
|
||||
nn = (EFNodeName *) HashGetValue(he);
|
||||
}
|
||||
|
||||
|
|
@ -1869,8 +1867,8 @@ esMakePorts(hc, cdata)
|
|||
nn = (EFNodeName *) HashGetValue(he);
|
||||
if (nn == NULL)
|
||||
{
|
||||
efBuildNode(portdef, FALSE, FALSE, portname, 0.0,
|
||||
0, 0, NULL, NULL, 0);
|
||||
efBuildNode(portdef, FALSE, FALSE, FALSE, portname,
|
||||
0.0, 0, 0, NULL, NULL, 0);
|
||||
nn = (EFNodeName *) HashGetValue(he);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3344,7 +3344,6 @@ spcsubVisit(node, res, cap, resstr)
|
|||
HierName *hierName;
|
||||
char *nsn;
|
||||
|
||||
if (node->efnode_flags & EF_UNIQUE_NODE) return 0;
|
||||
if (node->efnode_flags & EF_GLOB_SUBS_NODE)
|
||||
{
|
||||
hierName = (HierName *) node->efnode_name->efnn_hier;
|
||||
|
|
@ -3384,7 +3383,6 @@ spcnodeVisit(node, res, cap)
|
|||
char *fmt, *nsn;
|
||||
EFAttr *ap;
|
||||
|
||||
if (node->efnode_flags & EF_UNIQUE_NODE) return 0;
|
||||
if (node->efnode_client)
|
||||
{
|
||||
isConnected = (esDistrJunct) ?
|
||||
|
|
|
|||
|
|
@ -135,7 +135,6 @@ nodeVisit(node, res, cap)
|
|||
cap = (cap + 500) / 1000;
|
||||
res = (res + 500) / 1000;
|
||||
|
||||
if (node->efnode_flags & EF_UNIQUE_NODE) return 0;
|
||||
ecNumNodes++;
|
||||
if (EFHNIsGlob(node->efnode_name->efnn_hier))
|
||||
ecNumGlobalNodes++;
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ extern float locScale;
|
|||
* node, or added to the values already stored in an existing one.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
* Return a pointer to the new node.
|
||||
*
|
||||
* Side effects:
|
||||
* Updates the HashTable and node list of 'def'.
|
||||
|
|
@ -139,10 +139,12 @@ extern float locScale;
|
|||
*/
|
||||
|
||||
void
|
||||
efBuildNode(def, isSubsnode, isDevSubsnode, nodeName, nodeCap, x, y, layerName, av, ac)
|
||||
efBuildNode(def, isSubsnode, isDevSubsnode, isExtNode, nodeName, nodeCap,
|
||||
x, y, layerName, av, ac)
|
||||
Def *def; /* Def to which this connection is to be added */
|
||||
bool isSubsnode; /* TRUE if the node is the global substrate */
|
||||
bool isDevSubsnode; /* TRUE if the node is a device body connection */
|
||||
bool isExtNode; /* TRUE if this was a "node" or "substrate" in .ext */
|
||||
char *nodeName; /* One of the names for this node */
|
||||
double nodeCap; /* Capacitance of this node to ground */
|
||||
int x; int y; /* Location of a point inside this node */
|
||||
|
|
@ -155,8 +157,9 @@ efBuildNode(def, isSubsnode, isDevSubsnode, nodeName, nodeCap, x, y, layerName,
|
|||
HashEntry *he;
|
||||
unsigned size;
|
||||
int n;
|
||||
char *uqname = nodeName;
|
||||
int uqidx;
|
||||
LinkedRect *lr;
|
||||
Rect rnew;
|
||||
int tnew = 0;
|
||||
|
||||
he = HashFind(&def->def_nodes, nodeName);
|
||||
if (newname = (EFNodeName *) HashGetValue(he))
|
||||
|
|
@ -186,31 +189,30 @@ efBuildNode(def, isSubsnode, isDevSubsnode, nodeName, nodeCap, x, y, layerName,
|
|||
|
||||
if (isSubsnode == TRUE)
|
||||
newnode->efnode_flags |= EF_GLOB_SUBS_NODE;
|
||||
|
||||
/* For tracking unique nodes (see below), the first
|
||||
* node entry for a port is not considered unique,
|
||||
* since the port itself is not a node.
|
||||
*/
|
||||
if (newnode->efnode_flags & EF_PORT_NONODE)
|
||||
{
|
||||
newnode->efnode_flags &= ~EF_PORT_NONODE;
|
||||
return;
|
||||
}
|
||||
|
||||
/* If tracking unique nodes (for "def write", for example),
|
||||
* collect unique node positions in the client data so that
|
||||
* all of them can be visited.
|
||||
*/
|
||||
uqname = mallocMagic(strlen(nodeName) + 8);
|
||||
uqidx = 0;
|
||||
while (1)
|
||||
/* The node is a duplicate port name at a different location. */
|
||||
/* If EFSaveLocs is TRUE, then save the layer and position in */
|
||||
/* newnode's efnode_disjoint list. */
|
||||
|
||||
if ((EFSaveLocs == TRUE) && (isExtNode == TRUE))
|
||||
{
|
||||
sprintf(uqname, "%s_uq%d", nodeName, uqidx);
|
||||
he = HashFind(&def->def_nodes, uqname);
|
||||
if ((newname = (EFNodeName *)HashGetValue(he)) == NULL)
|
||||
break;
|
||||
uqidx++;
|
||||
rnew.r_xbot = (int)(0.5 + (float)x * locScale);
|
||||
rnew.r_ybot = (int)(0.5 + (float)y * locScale);
|
||||
rnew.r_xtop = rnew.r_xbot + 1;
|
||||
rnew.r_ytop = rnew.r_ybot + 1;
|
||||
|
||||
if (layerName)
|
||||
tnew = efBuildAddStr(EFLayerNames, &EFLayerNumNames,
|
||||
MAXTYPES, layerName);
|
||||
else
|
||||
tnew = 0;
|
||||
lr = (LinkedRect *)mallocMagic(sizeof(LinkedRect));
|
||||
lr->r_r = rnew;
|
||||
lr->r_type = tnew;
|
||||
lr->r_next = newnode->efnode_disjoint;
|
||||
newnode->efnode_disjoint = lr;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -218,7 +220,7 @@ efBuildNode(def, isSubsnode, isDevSubsnode, nodeName, nodeCap, x, y, layerName,
|
|||
{
|
||||
/* Allocate a new node with 'nodeName' as its single name */
|
||||
newname = (EFNodeName *) mallocMagic((unsigned)(sizeof (EFNodeName)));
|
||||
newname->efnn_hier = EFStrToHN((HierName *) NULL, uqname);
|
||||
newname->efnn_hier = EFStrToHN((HierName *) NULL, nodeName);
|
||||
newname->efnn_port = -1; /* No port assignment */
|
||||
newname->efnn_refc = 0; /* Only reference is self */
|
||||
newname->efnn_next = NULL;
|
||||
|
|
@ -265,11 +267,17 @@ efBuildNode(def, isSubsnode, isDevSubsnode, nodeName, nodeCap, x, y, layerName,
|
|||
/* If isSubsnode was TRUE, then turn off backwards compatibility mode */
|
||||
if (isSubsnode == TRUE) EFCompat = FALSE;
|
||||
|
||||
if (uqname != nodeName)
|
||||
/* Save location of top-level geometry if EFSaveLocs is TRUE */
|
||||
if ((EFSaveLocs == TRUE) && (isExtNode == TRUE))
|
||||
{
|
||||
newnode->efnode_flags |= EF_UNIQUE_NODE;
|
||||
freeMagic(uqname);
|
||||
lr = (LinkedRect *)mallocMagic(sizeof(LinkedRect));
|
||||
lr->r_r = newnode->efnode_loc;
|
||||
lr->r_type = newnode->efnode_type;
|
||||
lr->r_next = (LinkedRect *)NULL;
|
||||
newnode->efnode_disjoint = lr;
|
||||
}
|
||||
else
|
||||
newnode->efnode_disjoint = (LinkedRect *)NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -510,7 +518,7 @@ efBuildEquiv(def, nodeName1, nodeName2, resist)
|
|||
{
|
||||
if (efWarn)
|
||||
efReadError("Creating new node %s\n", nodeName1);
|
||||
efBuildNode(def, FALSE, FALSE,
|
||||
efBuildNode(def, FALSE, FALSE, FALSE,
|
||||
nodeName1, (double)0, 0, 0,
|
||||
(char *) NULL, (char **) NULL, 0);
|
||||
nn1 = (EFNodeName *) HashGetValue(he1);
|
||||
|
|
@ -1123,14 +1131,10 @@ efBuildPortNode(def, name, idx, x, y, layername, toplevel)
|
|||
if (nn == (EFNodeName *) NULL)
|
||||
{
|
||||
/* Create node if it doesn't already exist */
|
||||
efBuildNode(def, FALSE, FALSE, name, (double)0, x, y,
|
||||
efBuildNode(def, FALSE, FALSE, FALSE, name, (double)0, x, y,
|
||||
layername, (char **) NULL, 0);
|
||||
|
||||
nn = (EFNodeName *) HashGetValue(he);
|
||||
|
||||
/* Flag this as a port where the corresponding node has not been seen. */
|
||||
if (nn != (EFNodeName *) NULL)
|
||||
nn->efnn_node->efnode_flags |= EF_PORT_NONODE;
|
||||
}
|
||||
if (nn != (EFNodeName *) NULL)
|
||||
{
|
||||
|
|
@ -1221,7 +1225,7 @@ efBuildDevNode(def, name, isSubsNode)
|
|||
/* Create node if it doesn't already exist */
|
||||
if (efWarn && !isSubsNode)
|
||||
efReadError("Node %s doesn't exist so creating it\n", name);
|
||||
efBuildNode(def, FALSE, isSubsNode, name, (double)0, 0, 0,
|
||||
efBuildNode(def, FALSE, isSubsNode, FALSE, name, (double)0, 0, 0,
|
||||
(char *) NULL, (char **) NULL, 0);
|
||||
|
||||
nn = (EFNodeName *) HashGetValue(he);
|
||||
|
|
@ -1901,7 +1905,22 @@ efNodeMerge(node1ptr, node2ptr)
|
|||
if (removing->efnode_flags & EF_SUBS_NODE)
|
||||
keeping->efnode_flags |= EF_SUBS_NODE;
|
||||
|
||||
/* Test! */
|
||||
/* If EFSaveLocs is set, then merge any disjoint segments from
|
||||
* removing to keeping.
|
||||
*/
|
||||
if (EFSaveLocs == TRUE)
|
||||
{
|
||||
LinkedRect *lr;
|
||||
|
||||
if (keeping->efnode_disjoint == NULL)
|
||||
keeping->efnode_disjoint = removing->efnode_disjoint;
|
||||
else
|
||||
{
|
||||
for (lr = keeping->efnode_disjoint; lr->r_next; lr = lr->r_next);
|
||||
lr->r_next = removing->efnode_disjoint;
|
||||
}
|
||||
}
|
||||
|
||||
removing->efnode_flags = 0;
|
||||
|
||||
/* Get rid of "removing" */
|
||||
|
|
@ -2059,6 +2078,7 @@ efFreeNodeList(head, func)
|
|||
{
|
||||
EFNode *node;
|
||||
EFAttr *ap;
|
||||
LinkedRect *lr;
|
||||
|
||||
for (node = (EFNode *) head->efnode_next;
|
||||
node != head;
|
||||
|
|
@ -2072,6 +2092,9 @@ efFreeNodeList(head, func)
|
|||
(*func)(node->efnode_client);
|
||||
freeMagic((char *)node->efnode_client);
|
||||
}
|
||||
for (lr = node->efnode_disjoint; lr; lr = lr->r_next)
|
||||
freeMagic((char *)lr);
|
||||
|
||||
freeMagic((char *) node);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -461,6 +461,7 @@ efAddNodes(hc, stdcell)
|
|||
EFNodeName *nn, *newname, *oldname;
|
||||
EFNode *node, *newnode;
|
||||
EFAttr *ap, *newap;
|
||||
LinkedRect *lr, *newlr;
|
||||
HierName *hierName;
|
||||
int size, asize;
|
||||
HashEntry *he;
|
||||
|
|
@ -489,6 +490,15 @@ efAddNodes(hc, stdcell)
|
|||
newap->efa_next = newnode->efnode_attrs;
|
||||
newnode->efnode_attrs = newap;
|
||||
}
|
||||
newnode->efnode_disjoint = (LinkedRect *)NULL;
|
||||
for (lr = node->efnode_disjoint; lr; lr = lr->r_next)
|
||||
{
|
||||
newlr = (LinkedRect *)mallocMagic(sizeof(LinkedRect));
|
||||
newlr->r_r = lr->r_r;
|
||||
newlr->r_type = lr->r_type;
|
||||
newlr->r_next = newnode->efnode_disjoint;
|
||||
newnode->efnode_disjoint = newlr;
|
||||
}
|
||||
|
||||
// If called with "hierarchy on", all local node caps and adjustments
|
||||
// have been output and should be ignored.
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ keyTable[] =
|
|||
char *efReadFileName; /* Name of file currently being read */
|
||||
int efReadLineNum; /* Current line number in above file */
|
||||
float locScale; /* Multiply values in the file by this on read-in */
|
||||
bool EFSaveLocs; /* If TRUE, save location of merged top-level nodes */
|
||||
|
||||
/* Data local to this file */
|
||||
static bool efReadDef();
|
||||
|
|
@ -181,6 +182,7 @@ efReadDef(def, dosubckt, resist, noscale, toplevel)
|
|||
int argc, ac, n;
|
||||
CellDef *dbdef;
|
||||
EFCapValue cap;
|
||||
EFNode *node;
|
||||
char *line = NULL, *argv[128], *name, *attrs;
|
||||
int size = 0;
|
||||
int rscale = 1; /* Multiply resistances by this */
|
||||
|
|
@ -241,6 +243,13 @@ efReadDef(def, dosubckt, resist, noscale, toplevel)
|
|||
}
|
||||
|
||||
readfile:
|
||||
/* NOTE: noscale == TRUE means that coordinates should be in database
|
||||
* coordinates. EFSaveLocs == TRUE means save the coordinates of
|
||||
* merged nodes for later searching. Since coordinates can only be
|
||||
* searched if they are in database units, these two settings are
|
||||
* effectively equivalent (and both are used by "def write" only).
|
||||
*/
|
||||
EFSaveLocs = noscale;
|
||||
efReadLineNum = 0;
|
||||
while ((argc = efReadLine(&line, &size, inf, argv)) >= 0)
|
||||
{
|
||||
|
|
@ -424,7 +433,7 @@ readfile:
|
|||
cap = atoCap(argv[3])*cscale;
|
||||
efBuildNode(def,
|
||||
(keyTable[n].k_key == SUBSTRATE) ? TRUE : FALSE,
|
||||
FALSE,
|
||||
FALSE, (toplevel) ? TRUE : FALSE,
|
||||
argv[1], (double) cap,
|
||||
atoi(argv[4]), atoi(argv[5]), argv[6],
|
||||
&argv[7], ac);
|
||||
|
|
@ -451,7 +460,7 @@ readfile:
|
|||
*/
|
||||
case RNODE:
|
||||
cap = atoCap(argv[3])*cscale;
|
||||
efBuildNode(def, FALSE, FALSE, argv[1], (double) cap,
|
||||
efBuildNode(def, FALSE, FALSE, FALSE, argv[1], (double) cap,
|
||||
atoi(argv[4]), atoi(argv[5]), argv[6],
|
||||
(char **) NULL, 0);
|
||||
break;
|
||||
|
|
@ -639,8 +648,7 @@ resistChanged:
|
|||
{
|
||||
use = (Use *)HashGetValue(he);
|
||||
if ((use->use_def->def_flags & DEF_AVAILABLE) == 0)
|
||||
if (efReadDef(use->use_def, DoSubCircuit, resist, noscale, FALSE)
|
||||
!= TRUE)
|
||||
if (efReadDef(use->use_def, DoSubCircuit, resist, noscale, FALSE) != TRUE)
|
||||
rc = FALSE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -212,21 +212,6 @@ typedef struct efnhdr
|
|||
* line of the .ext file as the global default substrate node.
|
||||
*/
|
||||
#define EF_GLOB_SUBS_NODE 0x80
|
||||
/*
|
||||
* EF_UNIQUE_NODE marks a node that has the same name as another
|
||||
* node, indicating that the nodes are electrically connected only
|
||||
* by name. The processing routine can determine whether to
|
||||
* process these individually. The capacitance and resistance
|
||||
* values are merged with the first node of the same name. The
|
||||
* location is maintained so that the net fragment can be found.
|
||||
*/
|
||||
#define EF_UNIQUE_NODE 0x100
|
||||
/*
|
||||
* EF_PORT_NONODE is used to mark a port for which no "node"
|
||||
* record has been seen. When a corresponding node record is
|
||||
* found, this flag is cleared.
|
||||
*/
|
||||
#define EF_PORT_NONODE 0x200
|
||||
|
||||
extern int efNumResistClasses; /* Number of resistance classes in efResists */
|
||||
|
||||
|
|
@ -246,6 +231,9 @@ typedef struct efnode
|
|||
* .ext file so it will be easy to map between
|
||||
* node names and locations.
|
||||
*/
|
||||
LinkedRect *efnode_disjoint; /* List of disjoint node locations, created
|
||||
* if EFSaveLocs is TRUE.
|
||||
*/
|
||||
EFAttr *efnode_attrs; /* Node attribute list */
|
||||
ClientData efnode_client; /* For hire */
|
||||
EFPerimArea efnode_pa[1]; /* Dummy; each node actually has
|
||||
|
|
@ -356,6 +344,9 @@ extern int EFLayerNumNames;
|
|||
/* Output control flags */
|
||||
extern int EFOutputFlags;
|
||||
|
||||
/* Behavior regarding disjoint node segments */
|
||||
extern bool EFSaveLocs;
|
||||
|
||||
/* -------------------------- Exported procedures --------------------- */
|
||||
|
||||
extern char *EFArgs();
|
||||
|
|
|
|||
135
lef/defWrite.c
135
lef/defWrite.c
|
|
@ -320,7 +320,7 @@ defnodeCount(node, res, cap, total)
|
|||
if (pwr)
|
||||
{
|
||||
/* Diagnostic */
|
||||
TxPrintf("Node %s is defined in the \"globals\" array\n", pwr);
|
||||
TxPrintf("Node %s is defined in the \"globals\" array\n", cp);
|
||||
node->efnode_flags |= EF_SPECIAL;
|
||||
}
|
||||
|
||||
|
|
@ -665,7 +665,9 @@ defnodeVisit(node, res, cap, defdata)
|
|||
CellDef *def = defdata->def;
|
||||
float oscale = defdata->scale;
|
||||
TileTypeBitMask tmask, *rmask;
|
||||
TileType magictype;
|
||||
TileType nodetype, magictype;
|
||||
Rect *nodeloc;
|
||||
LinkedRect *lr;
|
||||
EFNodeName *thisnn;
|
||||
int defNetGeometryFunc(); /* Forward declaration */
|
||||
|
||||
|
|
@ -732,76 +734,85 @@ defnodeVisit(node, res, cap, defdata)
|
|||
}
|
||||
}
|
||||
|
||||
/* TT_SPACE indicates that a layer name must be the next */
|
||||
/* thing to be written to the DEF file. */
|
||||
/* TT_SPACE indicates that a layer name must be the */
|
||||
/* next thing to be written to the DEF file. */
|
||||
defdata->type = TT_SPACE;
|
||||
defdata->tile = (Tile *)NULL;
|
||||
|
||||
/* Net geometry (this should be an option!)--- */
|
||||
/* Use the DBconnect routines to find all geometry */
|
||||
/* connected to a specific node. This is a */
|
||||
/* redundant search---we've already done this once */
|
||||
/* when extracting the circuit. But, because the */
|
||||
/* DEF file requires a count of nodes up front, we */
|
||||
/* would have to do it twice anyway. In this case, */
|
||||
/* we only do it once here, since the results of */
|
||||
/* the first pass are picked up from the .ext file. */
|
||||
/* Process all disjoint segments of the node */
|
||||
|
||||
magictype = DBTechNameType(EFLayerNames[node->efnode_type]);
|
||||
|
||||
/* Note that the type of the node might be defined by the type */
|
||||
/* in the subcircuit itself, so we need to search for any type */
|
||||
/* that might validly connect to it, not just the type itself. */
|
||||
/* TTMaskSetOnlyType(&tmask, magictype); */
|
||||
TTMaskZero(&tmask);
|
||||
TTMaskSetMask(&tmask, &DBConnectTbl[magictype]);
|
||||
|
||||
DBSrConnect(def, &node->efnode_loc, &tmask, DBConnectTbl,
|
||||
&TiPlaneRect, defNetGeometryFunc,
|
||||
(ClientData)defdata);
|
||||
|
||||
if (defdata->tile == (Tile *)NULL)
|
||||
for (lr = node->efnode_disjoint; lr; lr = lr->r_next)
|
||||
{
|
||||
/* No route layer? It's possible that something connects to */
|
||||
/* the port location but doesn't overlap. Try painting the */
|
||||
/* node type in def and trying again. */
|
||||
/* Watch for entries created from the substrate node */
|
||||
if ((lr->r_r.r_ll.p_x <= (MINFINITY + 2)) ||
|
||||
(lr->r_r.r_ll.p_y <= (MINFINITY + 2)))
|
||||
continue;
|
||||
|
||||
Rect rport;
|
||||
SearchContext scx;
|
||||
int defPortTileFunc(); /* Fwd declaration */
|
||||
/* Net geometry (this should be an option!)--- */
|
||||
/* Use the DBconnect routines to find all geometry */
|
||||
/* connected to a specific node. This is a */
|
||||
/* redundant search---we've already done this once */
|
||||
/* when extracting the circuit. But, because the */
|
||||
/* DEF file requires a count of nodes up front, we */
|
||||
/* would have to do it twice anyway. In this case, */
|
||||
/* we only do it once here, since the results of */
|
||||
/* the first pass are picked up from the .ext file. */
|
||||
|
||||
scx.scx_area = node->efnode_loc;
|
||||
scx.scx_use = def->cd_parents;
|
||||
scx.scx_trans = GeoIdentityTransform;
|
||||
magictype = DBTechNameType(EFLayerNames[lr->r_type]);
|
||||
|
||||
rport = GeoNullRect;
|
||||
DBTreeSrUniqueTiles(&scx, &tmask, 0, defPortTileFunc, (ClientData)&rport);
|
||||
/* Note that the type of the node might be defined by the type */
|
||||
/* in the subcircuit itself, so we need to search for any type */
|
||||
/* that might validly connect to it, not just the type itself. */
|
||||
/* TTMaskSetOnlyType(&tmask, magictype); */
|
||||
TTMaskZero(&tmask);
|
||||
TTMaskSetMask(&tmask, &DBConnectTbl[magictype]);
|
||||
|
||||
/* Add the residue types to any contact type */
|
||||
if (DBIsContact(magictype))
|
||||
{
|
||||
rmask = DBResidueMask(magictype);
|
||||
TTMaskSetMask(&tmask, rmask);
|
||||
TTMaskSetType(&tmask, magictype);
|
||||
}
|
||||
|
||||
/* Check if anything was found in the location (e.g., .ext file
|
||||
* could be invalid or outdated).
|
||||
*/
|
||||
if (GEO_RECTNULL(&rport))
|
||||
TxError("Nothing found at node %s location (bad .ext file?)!\n", ndn);
|
||||
else
|
||||
{
|
||||
|
||||
/* Expand the rectangle around the port to overlap any */
|
||||
/* connecting material. */
|
||||
rport.r_xbot--;
|
||||
rport.r_ybot--;
|
||||
rport.r_xtop++;
|
||||
rport.r_ytop++;
|
||||
DBSrConnect(def, &rport, &tmask, DBConnectTbl, &TiPlaneRect,
|
||||
DBSrConnect(def, &lr->r_r, &tmask, DBConnectTbl, &TiPlaneRect,
|
||||
defNetGeometryFunc, (ClientData)defdata);
|
||||
}
|
||||
|
||||
if (defdata->tile == (Tile *)NULL)
|
||||
{
|
||||
/* No route layer? It's possible that something connects */
|
||||
/* to the port location but doesn't overlap. Try painting */
|
||||
/* the node type in def and trying again. */
|
||||
|
||||
Rect rport;
|
||||
SearchContext scx;
|
||||
int defPortTileFunc(); /* Fwd declaration */
|
||||
|
||||
scx.scx_area = node->efnode_loc;
|
||||
scx.scx_use = def->cd_parents;
|
||||
scx.scx_trans = GeoIdentityTransform;
|
||||
|
||||
rport = GeoNullRect;
|
||||
DBTreeSrUniqueTiles(&scx, &tmask, 0, defPortTileFunc, (ClientData)&rport);
|
||||
|
||||
/* Add the residue types to any contact type */
|
||||
if (DBIsContact(magictype))
|
||||
{
|
||||
rmask = DBResidueMask(magictype);
|
||||
TTMaskSetMask(&tmask, rmask);
|
||||
TTMaskSetType(&tmask, magictype);
|
||||
}
|
||||
|
||||
/* Check if anything was found in the location (e.g., .ext file
|
||||
* could be invalid or outdated).
|
||||
*/
|
||||
if (GEO_RECTNULL(&rport))
|
||||
TxError("Nothing found at node %s location (floating label?)!\n", ndn);
|
||||
else
|
||||
{
|
||||
|
||||
/* Expand the rectangle around the port to overlap any */
|
||||
/* connecting material. */
|
||||
rport.r_xbot--;
|
||||
rport.r_ybot--;
|
||||
rport.r_xtop++;
|
||||
rport.r_ytop++;
|
||||
DBSrConnect(def, &rport, &tmask, DBConnectTbl, &TiPlaneRect,
|
||||
defNetGeometryFunc, (ClientData)defdata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Was there a last record pending? If so, write it. */
|
||||
|
|
|
|||
Loading…
Reference in New Issue