Final (I hope!) corrections to the "def write" command.

This commit is contained in:
Tim Edwards 2022-11-19 22:02:44 -05:00
parent 6369c44821
commit 65ef9a1ad3
10 changed files with 167 additions and 130 deletions

View File

@ -1 +1 @@
8.3.342
8.3.343

View File

@ -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;

View File

@ -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);
}

View File

@ -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) ?

View File

@ -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++;

View File

@ -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);
}
}

View File

@ -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.

View File

@ -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;
}

View File

@ -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();

View File

@ -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. */