1 /*
2 * EFbuild.c -
3 *
4 * Procedures for building up the hierarchical representation
5 * of a circuit. These are all called from efReadDef() in EFread.c.
6 *
7 * *********************************************************************
8 * * Copyright (C) 1985, 1990 Regents of the University of California. *
9 * * Permission to use, copy, modify, and distribute this *
10 * * software and its documentation for any purpose and without *
11 * * fee is hereby granted, provided that the above copyright *
12 * * notice appear in all copies. The University of California *
13 * * makes no representations about the suitability of this *
14 * * software for any purpose. It is provided "as is" without *
15 * * express or implied warranty. Export of this software outside *
16 * * of the United States of America may require an export license. *
17 * *********************************************************************
18 */
19
20 #ifndef lint
21 static char rcsid[] __attribute__ ((unused)) = "$Header$";
22 #endif /* not lint */
23
24 #include <stdio.h>
25 #include <stdlib.h> /* for atof() */
26 #include <string.h>
27
28 #include "utils/magic.h"
29 #include "utils/geometry.h"
30 #include "utils/hash.h"
31 #include "utils/utils.h"
32 #include "utils/malloc.h"
33 #include "tiles/tile.h"
34 #include "database/database.h" /* for TileType definition */
35 #include "extflat/extflat.h"
36 #include "extflat/EFint.h"
37 #include "extract/extract.h" /* for device class list */
38
39 /*
40 * To avoid allocating ridiculously large amounts of memory to hold
41 * transistor types and the names of node types, we maintain the following
42 * string tables. Each string (transistor type or Magic layername) appears
43 * exactly once in its respective table; each Dev structure's dev_type field
44 * is an index into EFDevTypes[], and each node layer name an index into
45 * EFLayerNames[].
46 */
47
48 /* The following are ridiculously high */
49 #define MAXTYPES 100
50
51 /* Table of transistor types */
52 char *EFDevTypes[TT_MAXTYPES];
53 int EFDevNumTypes;
54
55 /* Table of Magic layers */
56 char *EFLayerNames[MAXTYPES] = { "space" };
57 int EFLayerNumNames;
58
59 /* Forward declarations */
60 Connection *efAllocConn();
61 EFNode *efBuildDevNode();
62 void efNodeAddName();
63 void efNodeMerge();
64
65 bool efConnBuildName();
66 bool efConnInitSubs();
67
68 extern float locScale;
69
70
71 /*
72 * ----------------------------------------------------------------------------
73 *
74 * efBuildNode --
75 *
76 * Process a "node" line from a .ext file.
77 * Creates a new node with an initial name of 'nodeName'
78 * and capacitance to substrate 'nodeCap'. If there is
79 * already a node by the name of 'nodeName', adds 'nodeCap'
80 * to its existing capacitance.
81 *
82 * In addition, the arguments 'av' and 'ac' are an (argv, argc)
83 * vector of pairs of perimeters and areas for each of the
84 * resist classes; these are either stored in the newly created
85 * node, or added to the values already stored in an existing one.
86 *
87 * Results:
88 * None.
89 *
90 * Side effects:
91 * Updates the HashTable and node list of 'def'.
92 *
93 * EFNode tables:
94 * Each hash table of nodes is organized in the following way.
95 * This organization is true both for the node tables for each
96 * Def, and for the global table of flattened nodes maintained
97 * in EFflatten.c (although the flattened nodes use the HierName
98 * struct for representing hierarchical names efficiently).
99 *
100 * Each HashEntry points to a EFNodeName struct. The EFNodeName
101 * is a link back to the hash key (a HierName), as well as
102 * a link to the actual EFNode for that name. The EFNode points
103 * to the first EFNodeName in the NULL-terminated list of all
104 * EFNodeNames pointing to that EFNode; the intent is that this
105 * first EFNodeName is the "official" or highest-precedence
106 * name for the node.
107 *
108 * The nodes themselves are linked into a circular, doubly
109 * linked list, for ease in merging two nodes into a single
110 * one as a result of a "connect" statement.
111 *
112 * HashEntries EFNodeNames EFNodes
113 *
114 * +---------------+
115 * | |
116 * V | to from
117 * +-------+ +-------+ | prev prev
118 * | | ----> | |-+ | ^ |
119 * +-------+ +-------+ | | | |
120 * | | | | V
121 * V | +---------------+
122 * +-------+ +-------+ +---> | |
123 * | | ----> | | ----> | |
124 * +-------+ +-------+ +---> | |
125 * | | +---------------+
126 * V | ^ |
127 * +-------+ +-------+ | | |
128 * | | ----> | |-+ | V
129 * +-------+ +-------+ from to
130 * | next next
131 * V
132 * NIL
133 *
134 * ----------------------------------------------------------------------------
135 */
136
137 void
efBuildNode(def,isSubsnode,nodeName,nodeCap,x,y,layerName,av,ac)138 efBuildNode(def, isSubsnode, nodeName, nodeCap, x, y, layerName, av, ac)
139 Def *def; /* Def to which this connection is to be added */
140 bool isSubsnode; /* TRUE if the node is the substrate */
141 char *nodeName; /* One of the names for this node */
142 double nodeCap; /* Capacitance of this node to ground */
143 int x; int y; /* Location of a point inside this node */
144 char *layerName; /* Name of tile type */
145 char **av; /* Pairs of area, perimeter strings */
146 int ac; /* Number of strings in av */
147 {
148 EFNodeName *newname;
149 EFNode *newnode;
150 HashEntry *he;
151 unsigned size;
152 int n;
153
154 he = HashFind(&def->def_nodes, nodeName);
155 if (newname = (EFNodeName *) HashGetValue(he))
156 {
157 if (efWarn)
158 efReadError("Warning: duplicate node name %s\n", nodeName);
159
160 /* newnode should exist if newname does. Having a NULL node */
161 /* may be caused by detached labels "connected" to space. */
162
163 if ((newnode = newname->efnn_node) != NULL)
164 {
165 /* Just add to C, perim, area of existing node */
166 newnode->efnode_cap += (EFCapValue) nodeCap;
167 for (n = 0; n < efNumResistClasses && ac > 1; n++, ac -= 2)
168 {
169 newnode->efnode_pa[n].pa_area += atoi(*av++);
170 newnode->efnode_pa[n].pa_perim += atoi(*av++);
171 }
172
173 /* If this node is identified as substrate, ensure that */
174 /* the flag is set. */
175 if (isSubsnode == TRUE)
176 newnode->efnode_flags |= EF_SUBS_NODE;
177
178 return;
179 }
180 }
181
182 if (!newname)
183 {
184 /* Allocate a new node with 'nodeName' as its single name */
185 newname = (EFNodeName *) mallocMagic((unsigned)(sizeof (EFNodeName)));
186 newname->efnn_hier = EFStrToHN((HierName *) NULL, nodeName);
187 newname->efnn_port = -1; /* No port assignment */
188 newname->efnn_refc = 0; /* Only reference is self */
189 newname->efnn_next = NULL;
190 HashSetValue(he, (char *) newname);
191 }
192
193 /* New node itself */
194 size = sizeof (EFNode) + (efNumResistClasses - 1) * sizeof (EFPerimArea);
195 newnode = (EFNode *) mallocMagic((unsigned)(size));
196 newnode->efnode_flags = (isSubsnode == TRUE) ? EF_SUBS_NODE : 0;
197 newnode->efnode_cap = nodeCap;
198 newnode->efnode_attrs = (EFAttr *) NULL;
199 newnode->efnode_loc.r_xbot = (int)(0.5 + (float)x * locScale);
200 newnode->efnode_loc.r_ybot = (int)(0.5 + (float)y * locScale);
201 newnode->efnode_loc.r_xtop = newnode->efnode_loc.r_xbot + 1;
202 newnode->efnode_loc.r_ytop = newnode->efnode_loc.r_ybot + 1;
203 newnode->efnode_client = (ClientData) NULL;
204 newnode->efnode_num = 1;
205 if (layerName) newnode->efnode_type =
206 efBuildAddStr(EFLayerNames, &EFLayerNumNames, MAXTYPES, layerName);
207 else newnode->efnode_type = 0;
208
209 for (n = 0; n < efNumResistClasses && ac > 1; n++, ac -= 2)
210 {
211 newnode->efnode_pa[n].pa_area = atoi(*av++);
212 newnode->efnode_pa[n].pa_perim = atoi(*av++);
213 }
214 for ( ; n < efNumResistClasses; n++)
215 newnode->efnode_pa[n].pa_area = newnode->efnode_pa[n].pa_perim = 0;
216
217 /* Update back pointers */
218 newnode->efnode_name = newname;
219 newname->efnn_node = newnode;
220
221 /* Link the node into the list for this def */
222 newnode->efnode_next = def->def_firstn.efnode_next;
223 newnode->efnode_prev = (EFNodeHdr *) &def->def_firstn;
224 def->def_firstn.efnode_next->efnhdr_prev = (EFNodeHdr *) newnode;
225 def->def_firstn.efnode_next = (EFNodeHdr *) newnode;
226
227 /* If isSubsnode was TRUE, then turn off backwards compatibility mode */
228 if (isSubsnode == TRUE) EFCompat = FALSE;
229 }
230
231 /*
232 * Process a "subcap" line by adding the specified adjustment
233 * value to the indicated node's substrate capacitance.
234 */
235
236 void
efAdjustSubCap(def,nodeName,nodeCapAdjust)237 efAdjustSubCap(def, nodeName, nodeCapAdjust)
238 Def *def; /* Def to which this connection is to be added */
239 char *nodeName; /* One of the names for this node */
240 double nodeCapAdjust; /* Substrate capacitance adjustment */
241 {
242 EFNodeName *nodename;
243 EFNode *node;
244 HashEntry *he;
245
246 he = HashLookOnly(&def->def_nodes, nodeName);
247 if (he && (nodename = (EFNodeName *) HashGetValue(he)))
248 {
249 node = nodename->efnn_node;
250 node->efnode_cap += (EFCapValue) nodeCapAdjust;
251 return;
252 }
253 else
254 {
255 if (efWarn)
256 efReadError("Error: subcap has unknown node %s\n", nodeName);
257 }
258 }
259
260 /*
261 * ----------------------------------------------------------------------------
262 *
263 * efBuildAttr --
264 *
265 * Prepend another node attribute to the list for node 'nodeName'.
266 * The attribute is located at the coordinates given by 'r' and
267 * is on the layer 'layerName'. The text of the attribute is 'text'.
268 *
269 * Results:
270 * None.
271 *
272 * Side effects:
273 * See above.
274 *
275 * ----------------------------------------------------------------------------
276 */
277
278 void
efBuildAttr(def,nodeName,r,layerName,text)279 efBuildAttr(def, nodeName, r, layerName, text)
280 Def *def;
281 char *nodeName;
282 Rect *r;
283 char *layerName;
284 char *text;
285 {
286 HashEntry *he;
287 EFNodeName *nn;
288 EFAttr *ap;
289 int size;
290
291 he = HashLookOnly(&def->def_nodes, nodeName);
292 if (he == NULL || HashGetValue(he) == NULL)
293 {
294 efReadError("Attribute for nonexistent node %s ignored\n", nodeName);
295 return;
296 }
297 nn = (EFNodeName *) HashGetValue(he);
298
299 size = ATTRSIZE(strlen(text));
300 ap = (EFAttr *) mallocMagic((unsigned)(size));
301 (void) strcpy(ap->efa_text, text);
302 ap->efa_type =
303 efBuildAddStr(EFLayerNames, &EFLayerNumNames, MAXTYPES, layerName);
304 ap->efa_loc = *r;
305 ap->efa_next = nn->efnn_node->efnode_attrs;
306 nn->efnn_node->efnode_attrs = ap;
307 }
308
309 /*
310 * ----------------------------------------------------------------------------
311 *
312 * efBuildDist --
313 *
314 * Process a "dist" line from a .ext file.
315 * Both of the names driver and receiver are pathnames with slashes.
316 * Add a new Distance record to the hash table for Def, or update
317 * an existing Distance record.
318 *
319 * This strategy allows the .ext file to contain several distance
320 * lines for the same pair of points; we do the compression here
321 * rather than requiring it be done during extraction. It's necessary
322 * to do compression at some point before flattening; see the description
323 * in efFlatDists().
324 *
325 * Results:
326 * None.
327 *
328 * Side effects:
329 * See above.
330 *
331 * ----------------------------------------------------------------------------
332 */
333
334 void
efBuildDist(def,driver,receiver,min,max)335 efBuildDist(def, driver, receiver, min, max)
336 Def *def; /* Def for which we're adding a new Distance */
337 char *driver; /* Source terminal */
338 char *receiver; /* Destination terminal */
339 int min, max; /* Minimum and maximum acyclic distance from source
340 * to destination.
341 */
342 {
343 Distance *dist, distKey;
344 HierName *hn1, *hn2;
345 HashEntry *he;
346
347 hn1 = EFStrToHN((HierName *) NULL, driver);
348 hn2 = EFStrToHN((HierName *) NULL, receiver);
349 distKey.dist_min = min;
350 distKey.dist_max = max;
351 if (EFHNBest(hn1, hn2))
352 {
353 distKey.dist_1 = hn1;
354 distKey.dist_2 = hn2;
355 }
356 else
357 {
358 distKey.dist_1 = hn2;
359 distKey.dist_2 = hn1;
360 }
361 #ifdef notdef
362 TxError("ADD %s ", EFHNToStr(distKey.dist_1));
363 TxError("%s ", EFHNToStr(distKey.dist_2));
364 TxError("%d %d\n", min, max);
365 #endif /* notdef */
366
367 he = HashFind(&def->def_dists, (char *) &distKey);
368 if (dist = (Distance *) HashGetValue(he))
369 {
370 /*
371 * There was already an entry in the table; update it
372 * to reflect new minimum and maximum distances. We
373 * can free the keys since they were already in the
374 * table.
375 */
376 dist->dist_min = MIN(dist->dist_min, min);
377 dist->dist_max = MAX(dist->dist_max, max);
378 EFHNFree(hn1, (HierName *) NULL, HN_ALLOC);
379 EFHNFree(hn2, (HierName *) NULL, HN_ALLOC);
380 }
381 else
382 {
383 /*
384 * When the key was installed in the hash table, it was
385 * a copy of the Distance 'distKey'. Leave this as the
386 * value of the HashEntry.
387 */
388 HashSetValue(he, (ClientData) he->h_key.h_ptr);
389 }
390 }
391
392 /*
393 * ----------------------------------------------------------------------------
394 *
395 * efBuildKill --
396 *
397 * Process a "killnode" line from a .ext file.
398 * Prepends a Kill to the list for def.
399 *
400 * Results:
401 * None.
402 *
403 * Side effects:
404 * See above.
405 *
406 * ----------------------------------------------------------------------------
407 */
408
409 void
efBuildKill(def,name)410 efBuildKill(def, name)
411 Def *def; /* Def for which we're adding a new Kill */
412 char *name; /* Name of node to die */
413 {
414 Kill *kill;
415
416 kill = (Kill *) mallocMagic((unsigned)(sizeof (Kill)));
417 kill->kill_name = EFStrToHN((HierName *) NULL, name);
418 kill->kill_next = def->def_kills;
419 def->def_kills = kill;
420 }
421
422 /*
423 * ----------------------------------------------------------------------------
424 *
425 * efBuildEquiv --
426 *
427 * Process an "equiv" line from a .ext file.
428 * One of the names 'nodeName1' or 'nodeName2' should be a name for
429 * an existing node in the def 'def'. We simply prepend this name to
430 * the list of names for that node.
431 *
432 * Results:
433 * None.
434 *
435 * Side effects:
436 * See above.
437 *
438 * ----------------------------------------------------------------------------
439 */
440
441 void
efBuildEquiv(def,nodeName1,nodeName2)442 efBuildEquiv(def, nodeName1, nodeName2)
443 Def *def; /* Def for which we're adding a new node name */
444 char *nodeName1; /* One of node names to be made equivalent */
445 char *nodeName2; /* Other name to be made equivalent. One of nodeName1
446 * or nodeName2 must already be known.
447 */
448 {
449 EFNodeName *nn1, *nn2;
450 HashEntry *he1, *he2;
451
452 /* Look up both names in the hash table for this def */
453 he1 = HashFind(&def->def_nodes, nodeName1);
454 he2 = HashFind(&def->def_nodes, nodeName2);
455
456 nn1 = (EFNodeName *) HashGetValue(he1);
457 nn2 = (EFNodeName *) HashGetValue(he2);
458
459 if (nn1 == nn2) return; /* These nodes already merged */
460
461 if (nn2 == (EFNodeName *) NULL)
462 {
463 /* Create nodeName1 if it doesn't exist */
464 if (nn1 == (EFNodeName *) NULL)
465 {
466 if (efWarn)
467 efReadError("Creating new node %s\n", nodeName1);
468 efBuildNode(def, FALSE,
469 nodeName1, (double)0, 0, 0,
470 (char *) NULL, (char **) NULL, 0);
471 nn1 = (EFNodeName *) HashGetValue(he1);
472 }
473
474 /* Make nodeName2 be another alias for node1 */
475 efNodeAddName(nn1->efnn_node, he2,
476 EFStrToHN((HierName *) NULL, nodeName2));
477 return;
478 }
479 else if (nn2->efnn_node == (EFNode *)NULL)
480 return; /* Repeated "equiv" statement */
481
482 /* If both names exist and are for different ports, then keep */
483 /* them separate and add a zero ohm resistor or a zero volt */
484 /* source between them, based on the method set by "ext2spice */
485 /* shorts". */
486
487 if (nn1 && nn2 && (nn1->efnn_port >= 0) && (nn2->efnn_port >= 0) &&
488 (nn1->efnn_port != nn2->efnn_port))
489 {
490 if ((EFOutputFlags & EF_SHORT_MASK) != EF_SHORT_NONE)
491 {
492 int i;
493 int sdev;
494 char *argv[10], zeroarg[] = "0";
495
496 if ((EFOutputFlags & EF_SHORT_MASK) == EF_SHORT_R)
497 sdev = DEV_RES;
498 else
499 sdev = DEV_VOLT;
500
501 for (i = 0; i < 10; i++) argv[i] = zeroarg;
502 argv[0] = StrDup((char **)NULL, "0.0");
503 argv[1] = StrDup((char **)NULL, "dummy");
504 argv[4] = StrDup((char **)NULL, nodeName1);
505 argv[7] = StrDup((char **)NULL, nodeName2);
506 efBuildDevice(def, sdev, "None", &GeoNullRect, 10, argv);
507 freeMagic(argv[0]);
508 freeMagic(argv[1]);
509 freeMagic(argv[4]);
510 freeMagic(argv[7]);
511 return;
512 }
513 else
514 {
515 /* Flag a strong warning */
516 TxError("Warning: Ports \"%s\" and \"%s\" are electrically shorted.\n",
517 nodeName1, nodeName2);
518 }
519 }
520
521 /* If both names exist and are for different nodes, merge them */
522 if (nn1)
523 {
524 if (nn1->efnn_node == (EFNode *)NULL)
525 return; /* Repeated "equiv" statement */
526 if (nn1->efnn_node != nn2->efnn_node)
527 {
528 struct efnode *node1 = nn1->efnn_node;
529 struct efnode *node2 = nn2->efnn_node;
530 HashSearch hs;
531
532 if (efWarn)
533 efReadError("Merged nodes %s and %s\n", nodeName1, nodeName2);
534 efNodeMerge(&nn1->efnn_node, &nn2->efnn_node);
535 if (nn1->efnn_port > 0) nn2->efnn_port = nn1->efnn_port;
536 else if (nn2->efnn_port > 0) nn1->efnn_port = nn2->efnn_port;
537
538 /* If a node has been merged away, make sure that its name */
539 /* and all aliases point to the merged name's hash. */
540
541 if (nn1->efnn_node == NULL)
542 {
543 nn2->efnn_refc += nn1->efnn_refc + 1;
544 HashStartSearch(&hs);
545 while (he1 = HashNext(&def->def_nodes, &hs))
546 if ((EFNodeName *)HashGetValue(he1) == nn1)
547 HashSetValue(he1, (char *)nn2);
548 }
549 else if (nn2->efnn_node == NULL)
550 {
551 nn1->efnn_refc += nn2->efnn_refc + 1;
552 HashStartSearch(&hs);
553 while (he2 = HashNext(&def->def_nodes, &hs))
554 if ((EFNodeName *)HashGetValue(he2) == nn2)
555 HashSetValue(he2, (char *)nn1);
556 }
557 }
558 return;
559 }
560
561 /* Make nodeName1 be another alias for node2 */
562 efNodeAddName(nn2->efnn_node, he1,
563 EFStrToHN((HierName *) NULL, nodeName1));
564 }
565
566
567 /*
568 * ----------------------------------------------------------------------------
569 *
570 *
571 * ----------------------------------------------------------------------------
572 */
573
574 DevParam *
efGetDeviceParams(name)575 efGetDeviceParams(name)
576 char *name;
577 {
578 HashEntry *he;
579 DevParam *plist = NULL;
580
581 he = HashLookOnly(&efDevParamTable, (char *)name);
582 if (he != NULL)
583 plist = (DevParam *)HashGetValue(he);
584 return plist;
585 }
586
587 /*
588 * ----------------------------------------------------------------------------
589 *
590 * efBuildDeviceParams --
591 *
592 * Fill in a device parameter hash table entry from a "parameters" line in
593 * the .ext file.
594 *
595 * ----------------------------------------------------------------------------
596 */
597
598 void
efBuildDeviceParams(name,argc,argv)599 efBuildDeviceParams(name, argc, argv)
600 char *name;
601 int argc;
602 char *argv[];
603 {
604 HashEntry *he;
605 DevParam *plist = NULL, *newparm;
606 char *pptr;
607 int n;
608
609 he = HashFind(&efDevParamTable, name);
610 plist = (DevParam *)HashGetValue(he);
611 if (plist != NULL) return; /* Already got one! */
612
613 /* Parse arguments for each parameter */
614 for (n = 0; n < argc; n++)
615 {
616 char *mult;
617
618 pptr = strchr(argv[n], '=');
619 if (pptr == NULL)
620 {
621 efReadError("Bad parameter assignment \"%s\" for device \"%s\"\n",
622 argv[n], name);
623 continue;
624 }
625 newparm = (DevParam *)mallocMagic(sizeof(DevParam));
626 newparm->parm_type[0] = *argv[n];
627 if ((pptr - argv[n]) == 1)
628 newparm->parm_type[1] = '\0';
629 else
630 newparm->parm_type[1] = *(argv[n] + 1);
631
632 if ((mult = strchr(pptr + 1, '*')) != NULL)
633 {
634 *mult = '\0';
635 newparm->parm_scale = atof(mult + 1);
636 }
637 else
638 newparm->parm_scale = 1.0;
639
640 // For parameters defined for cell defs, copy the whole
641 // expression verbatim into parm_name. parm_type is
642 // reassigned to be a numerical order.
643
644 if (name[0] == ':')
645 {
646 newparm->parm_name = StrDup((char **)NULL, argv[n]);
647 newparm->parm_type[0] = '0' + n / 10;
648 newparm->parm_type[1] = '0' + n % 10;
649 }
650 else
651 newparm->parm_name = StrDup((char **)NULL, pptr + 1);
652 newparm->parm_next = plist;
653 plist = newparm;
654 }
655 HashSetValue(he, (char *)plist);
656 }
657
658 /*
659 * ----------------------------------------------------------------------------
660 *
661 * efBuildDevice --
662 *
663 * Process a device line from a .ext file.
664 * The number of terminals in the dev is argc/3 (which must be integral).
665 * Each block of 3 strings in argv describes a single terminal; see the
666 * comments below for their interpretation.
667 *
668 * Results:
669 * Returns 0 on success, 1 on failure to parse any terminal's values
670 *
671 * Side effects:
672 * Prepends this dev to the list for the def 'def'.
673 *
674 * ----------------------------------------------------------------------------
675 */
676
677 int
efBuildDevice(def,class,type,r,argc,argv)678 efBuildDevice(def, class, type, r, argc, argv)
679 Def *def; /* Def to which this connection is to be added */
680 char class; /* Class (dev, bjt, etc.) of this device */
681 char *type; /* Type (name) of this device */
682 Rect *r; /* Coordinates of 1x1 rectangle entirely inside device */
683 int argc; /* Size of argv */
684 char *argv[]; /* Tokens for the rest of the dev line.
685 * Starts with the last two position values, used to
686 * hash the device record. The next arguments depend
687 * on the type of device. The rest are taken in groups
688 * of 3, one for each terminal. Each group of 3 consists
689 * of the node name to which the terminal connects, the
690 * length of the terminal, and an attribute list (or the
691 * token 0).
692 */
693 {
694 int n, nterminals, pn;
695 HashEntry *he;
696 DevTerm *term;
697 Dev *newdev, devtmp;
698 DevParam *newparm, *devp, *sparm;
699 TileType ttype;
700 int dev_type;
701 char ptype, *pptr, **av;
702 char devhash[64];
703 int argstart = 1; /* start of terminal list in argv[] */
704 bool hasModel = strcmp(type, "None") ? TRUE : FALSE;
705
706 int area, perim; /* Total area, perimeter of primary type (i.e., channel) */
707
708 newdev = (Dev *)NULL;
709 devtmp.dev_subsnode = NULL;
710 devtmp.dev_cap = 0.0;
711 devtmp.dev_res = 0.0;
712 devtmp.dev_area = 0;
713 devtmp.dev_perim = 0;
714 devtmp.dev_length = 0;
715 devtmp.dev_width = 0;
716 devtmp.dev_params = NULL;
717
718 switch (class)
719 {
720 case DEV_FET:
721 case DEV_MOSFET:
722 case DEV_ASYMMETRIC:
723 case DEV_BJT:
724 argstart = 3;
725 break;
726 case DEV_DIODE:
727 case DEV_NDIODE:
728 case DEV_PDIODE:
729 argstart = 0;
730 break;
731 case DEV_RES:
732 case DEV_CAP:
733 case DEV_CAPREV:
734 if (hasModel)
735 argstart = 2;
736 break;
737 case DEV_SUBCKT:
738 case DEV_MSUBCKT:
739 case DEV_RSUBCKT:
740 case DEV_CSUBCKT:
741 argstart = 0;
742 }
743
744 devp = efGetDeviceParams(type);
745
746 /* Parse initial arguments for parameters */
747 while ((pptr = strchr(argv[argstart], '=')) != NULL)
748 {
749 // Check if this parameter is in the table.
750 // If so, handle appropriately. Otherwise, the
751 // parameter gets saved verbatim locally. The
752 // "parameters" line comes before any "device" line
753 // in the .ext file, so the table should be complete.
754
755 *pptr = '\0';
756 for (sparm = devp; sparm; sparm = sparm->parm_next)
757 if (!strcasecmp(sparm->parm_type, argv[argstart]))
758 break;
759 *pptr = '=';
760 if (sparm == NULL)
761 {
762 /* Copy the parameter into dev_params */
763 /* (parm_type and parm_scale records are not used) */
764 newparm = (DevParam *)mallocMagic(sizeof(DevParam));
765 newparm->parm_name = StrDup((char **)NULL, argv[argstart]);
766 newparm->parm_next = devtmp.dev_params;
767 devtmp.dev_params = newparm;
768 argstart++;
769 continue;
770 }
771
772 pptr++;
773 switch(*argv[argstart])
774 {
775 case 'a':
776 if ((pptr - argv[argstart]) == 2)
777 devtmp.dev_area = atoi(pptr);
778 else
779 {
780 pn = *(argv[argstart] + 1) - '0';
781 if (pn == 0)
782 devtmp.dev_area = (int)(0.5 + (float)atoi(pptr)
783 * locScale * locScale);
784 /* Otherwise, punt */
785 }
786 break;
787 case 'p':
788 if ((pptr - argv[argstart]) == 2)
789 devtmp.dev_perim = atoi(pptr);
790 else
791 {
792 pn = *(argv[argstart] + 1) - '0';
793 if (pn == 0)
794 devtmp.dev_perim = (int)(0.5 + (float)atoi(pptr) * locScale);
795 /* Otherwise, use verbatim */
796 }
797 break;
798 case 'l':
799 devtmp.dev_length = (int)(0.5 + (float)atoi(pptr) * locScale);
800 break;
801 case 'w':
802 devtmp.dev_width = (int)(0.5 + (float)atoi(pptr) * locScale);
803 break;
804 case 'c':
805 devtmp.dev_cap = (float)atof(pptr);
806 break;
807 case 'r':
808 devtmp.dev_res = (float)atof(pptr);
809 break;
810 }
811 argstart++;
812 }
813
814 /* Check for optional substrate node */
815 switch (class)
816 {
817 case DEV_RES:
818 case DEV_CAP:
819 case DEV_CAPREV:
820 case DEV_RSUBCKT:
821 case DEV_CSUBCKT:
822 case DEV_MSUBCKT:
823 case DEV_SUBCKT:
824 case DEV_DIODE:
825 case DEV_NDIODE:
826 case DEV_PDIODE:
827 n = argc - argstart;
828 if ((n % 3) == 1)
829 {
830 if (strncmp(argv[argstart], "None", 4) != 0)
831 devtmp.dev_subsnode = efBuildDevNode(def, argv[argstart], TRUE);
832
833 argstart++;
834 }
835 break;
836 }
837
838 /* Between argstart and argc, we should only have terminal triples */
839 if (((argc - argstart) % 3) != 0)
840 return 1;
841
842 nterminals = (argc - argstart) / 3;
843
844 dev_type = efBuildAddStr(EFDevTypes, &EFDevNumTypes, TT_MAXTYPES, type);
845
846 /* Determine if this device has been seen before */
847 /* NOTE: This is done by tile type, not name, because the extresist
848 * device extraction is less sophisticated than the standard extraction
849 * and does not differentiate between different device names belonging
850 * to the same tile type. The extGetDevType() function is not efficient,
851 * and all of this needs to be done better.
852 */
853
854 ttype = extGetDevType(type);
855 if (ttype < 0)
856 {
857 /* For zero-ohm resistors used to separate ports on the same */
858 /* net, generate a unique devhash. */
859 ttype = DBNumTypes;
860 while (1)
861 {
862 sprintf(devhash, "%dx%d_%d", r->r_xbot, r->r_ybot, ttype);
863 he = HashLookOnly(&def->def_devs, devhash);
864 if (he == NULL) break;
865 ttype++;
866 }
867 }
868
869 sprintf(devhash, "%dx%d_%d", r->r_xbot, r->r_ybot, ttype);
870 he = HashFind(&def->def_devs, devhash);
871 newdev = (Dev *)HashGetValue(he);
872
873 if (newdev)
874 {
875 /* Duplicate device. Duplicates will only appear in res.ext files
876 * where a device has nodes changed. Merge all properties of the
877 * original device with nodes from the new device. Keep the
878 * original device and discard the new one.
879 *
880 * Check that the device is actually the same device type and number
881 * of terminals. If not, throw an error and abandon the new device.
882 *
883 * NOTE: Quick check is made on dev_type, but for the reason stated
884 * above for the calculation of ttype, only the tile types need to
885 * match, so make an additional (expensive) check on tile type.
886 */
887
888 if ((newdev->dev_class != class) || ((newdev->dev_type != dev_type)
889 && (ttype != extGetDevType(EFDevTypes[newdev->dev_type]))))
890 {
891 TxError("Device %s %s at (%d, %d) overlaps incompatible device %s %s!\n",
892 extDevTable[class], type, r->r_xbot, r->r_ybot,
893 extDevTable[newdev->dev_class], EFDevTypes[newdev->dev_type]);
894 return 0;
895 }
896 else if (newdev->dev_nterm != nterminals)
897 {
898 TxError("Device %s %s at (%d, %d) overlaps device with incompatible"
899 " number of terminals (%d vs. %d)!\n",
900 extDevTable[class], type, r->r_xbot, r->r_ybot, nterminals,
901 newdev->dev_nterm);
902 return 0;
903 }
904 }
905 else
906 {
907 newdev = (Dev *) mallocMagic((unsigned) DevSize(nterminals));
908
909 /* Add this dev to the hash table for def */
910 HashSetValue(he, (ClientData)newdev);
911
912 newdev->dev_cap = devtmp.dev_cap;
913 newdev->dev_res = devtmp.dev_res;
914 newdev->dev_area = devtmp.dev_area;
915 newdev->dev_perim = devtmp.dev_perim;
916 newdev->dev_length = devtmp.dev_length;
917 newdev->dev_width = devtmp.dev_width;
918 newdev->dev_params = devtmp.dev_params;
919
920 newdev->dev_nterm = nterminals;
921 newdev->dev_rect = *r;
922 newdev->dev_type = dev_type;
923 newdev->dev_class = class;
924
925 switch (class)
926 {
927 case DEV_FET: /* old-style "fet" record */
928 newdev->dev_area = atoi(argv[0]);
929 newdev->dev_perim = atoi(argv[1]);
930 break;
931 case DEV_MOSFET: /* new-style "device mosfet" record */
932 case DEV_ASYMMETRIC:
933 case DEV_BJT:
934 newdev->dev_length = atoi(argv[0]);
935 newdev->dev_width = atoi(argv[1]);
936 break;
937 case DEV_RES:
938 if (hasModel && StrIsInt(argv[0]) && StrIsInt(argv[1]))
939 {
940 newdev->dev_length = atoi(argv[0]);
941 newdev->dev_width = atoi(argv[1]);
942 }
943 else if (StrIsNumeric(argv[0]))
944 {
945 newdev->dev_res = (float)atof(argv[0]);
946 }
947 else
948 {
949 if (hasModel)
950 {
951 efReadError("Error: expected L and W, got %s %s\n", argv[0],
952 argv[1]);
953 newdev->dev_length = 0;
954 newdev->dev_width = 0;
955 }
956 else
957 {
958 efReadError("Error: expected resistance value, got %s\n",
959 argv[0]);
960 newdev->dev_res = 0.0;
961 }
962 }
963 break;
964 case DEV_CAP:
965 case DEV_CAPREV:
966 if (hasModel && StrIsInt(argv[0]) && StrIsInt(argv[1]))
967 {
968 newdev->dev_length = atoi(argv[0]);
969 newdev->dev_width = atoi(argv[1]);
970 }
971 else if (StrIsNumeric(argv[0]))
972 {
973 newdev->dev_cap = (float)atof(argv[0]);
974 }
975 else
976 {
977 if (hasModel)
978 {
979 efReadError("Error: expected L and W, got %s %s\n", argv[0],
980 argv[1]);
981 newdev->dev_length = 0;
982 newdev->dev_width = 0;
983 }
984 else
985 {
986 efReadError("Error: expected capacitance value, got %s\n",
987 argv[0]);
988 newdev->dev_cap = 0.0;
989 }
990 }
991 break;
992 }
993 }
994
995 newdev->dev_subsnode = devtmp.dev_subsnode;
996 switch (class)
997 {
998 case DEV_FET: /* old-style "fet" record */
999 newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE);
1000 break;
1001 case DEV_MOSFET: /* new-style "device mosfet" record */
1002 case DEV_ASYMMETRIC:
1003 case DEV_BJT:
1004 /* "None" in the place of the substrate name means substrate is ignored */
1005 if ((argstart == 3) && (strncmp(argv[2], "None", 4) != 0))
1006 newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE);
1007 break;
1008 case DEV_RES:
1009 if ((argstart == 3) && (strncmp(argv[2], "None", 4) != 0))
1010 newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE);
1011
1012 break;
1013 case DEV_CAP:
1014 case DEV_CAPREV:
1015 if ((argstart == 3) && (strncmp(argv[2], "None", 4) != 0))
1016 newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE);
1017
1018 break;
1019 }
1020
1021 #define TERM_NAME 0
1022 #define TERM_PERIM 1
1023 #define TERM_ATTRS 2
1024
1025 for (av = &argv[argstart], n = 0; n < nterminals; n++, av += 3)
1026 {
1027 term = &newdev->dev_terms[n];
1028 term->dterm_node = efBuildDevNode(def, av[TERM_NAME], FALSE);
1029 term->dterm_length = atoi(av[TERM_PERIM]);
1030 term->dterm_area = 0;
1031 term->dterm_perim = 0;
1032
1033 /* If the attr list is '0', this signifies no attributes */
1034 if (av[TERM_ATTRS][0] == '0' && av[TERM_ATTRS][1] == '\0')
1035 term->dterm_attrs = (char *) NULL;
1036 else
1037 term->dterm_attrs = StrDup((char **) NULL, av[TERM_ATTRS]);
1038 }
1039
1040 #undef TERM_NAME
1041 #undef TERM_PERIM
1042 #undef TERM_ATTRS
1043
1044 return 0;
1045 }
1046
1047 /*
1048 * ----------------------------------------------------------------------------
1049 *
1050 * efBuildPortNode --
1051 *
1052 * Look for the node named 'name' in the local table for 'def', or in
1053 * the global node name table. If it doesn't already exist, create a
1054 * EFNode for it, and set capacitance and area/perimeter to zero.
1055 * Set the efnode_flags value to EF_PORT, with the port number encoded
1056 * in the efNodeName structure.
1057 *
1058 * ----------------------------------------------------------------------------
1059 */
1060
1061 void
efBuildPortNode(def,name,idx,x,y,layername,toplevel)1062 efBuildPortNode(def, name, idx, x, y, layername, toplevel)
1063 Def *def; /* Def to which this connection is to be added */
1064 char *name; /* One of the names for this node */
1065 int idx; /* Port number (order) */
1066 int x; int y; /* Location of a point inside this node */
1067 char *layername; /* Name of tile type */
1068 bool toplevel; /* 1 if the cell def is the top level cell */
1069 {
1070 HashEntry *he;
1071 EFNodeName *nn;
1072
1073 he = HashFind(&def->def_nodes, name);
1074 nn = (EFNodeName *) HashGetValue(he);
1075 if (nn == (EFNodeName *) NULL)
1076 {
1077 /* Create node if it doesn't already exist */
1078 efBuildNode(def, FALSE, name, (double)0, x, y,
1079 layername, (char **) NULL, 0);
1080
1081 nn = (EFNodeName *) HashGetValue(he);
1082 }
1083 if (nn != (EFNodeName *) NULL)
1084 {
1085 nn->efnn_node->efnode_flags |= EF_PORT;
1086 if (toplevel)
1087 nn->efnn_node->efnode_flags |= EF_TOP_PORT;
1088 nn->efnn_port = idx;
1089 }
1090 }
1091
1092 /*
1093 * ----------------------------------------------------------------------------
1094 *
1095 * EFGetPortMax --
1096 *
1097 * Find the highest port number in the cell def and return the value.
1098 *
1099 * Results:
1100 * Value of highest port number in the cell def's node list
1101 *
1102 * Side effects:
1103 * Larger value including the implicit ports is placed in the
1104 * location of the pointer imp_max.
1105 *
1106 * ----------------------------------------------------------------------------
1107 */
1108
1109 int
EFGetPortMax(def,imp_max)1110 EFGetPortMax(def, imp_max)
1111 Def *def;
1112 int *imp_max;
1113 {
1114 EFNode *snode;
1115 EFNodeName *nodeName;
1116 int portmax, portorder;
1117
1118 portmax = -1;
1119 if (imp_max) *imp_max = -1;
1120
1121 for (snode = (EFNode *) def->def_firstn.efnode_next;
1122 snode != &def->def_firstn;
1123 snode = (EFNode *) snode->efnode_next)
1124 {
1125 if (snode->efnode_flags & EF_PORT)
1126 {
1127 for (nodeName = snode->efnode_name; nodeName != NULL; nodeName =
1128 nodeName->efnn_next)
1129 {
1130 portorder = nodeName->efnn_port;
1131 if (portorder > portmax) portmax = portorder;
1132 }
1133 }
1134 else if (imp_max && (snode->efnode_flags & EF_SUBS_PORT))
1135 {
1136 nodeName = snode->efnode_name;
1137 portorder = nodeName->efnn_port;
1138 if (portorder > (*imp_max)) (*imp_max) = portorder;
1139 }
1140 }
1141 if (imp_max)
1142 if (portmax > (*imp_max)) (*imp_max) = portmax;
1143 return portmax;
1144 }
1145
1146 /*
1147 * ----------------------------------------------------------------------------
1148 *
1149 * efBuildDevNode --
1150 *
1151 * Look for the node named 'name' in the local table for 'def', or
1152 * in the global node name table. If it doesn't already exist,
1153 * create a EFNode for it. If 'isSubsNode' is TRUE, this is node
1154 * is a substrate node and may not exist yet; otherwise, the node
1155 * must already exist.
1156 *
1157 * Results:
1158 * Returns a pointer to the EFNode for 'name'.
1159 *
1160 * Side effects:
1161 * May create a new node, as per above.
1162 *
1163 * ----------------------------------------------------------------------------
1164 */
1165
1166 EFNode *
efBuildDevNode(def,name,isSubsNode)1167 efBuildDevNode(def, name, isSubsNode)
1168 Def *def;
1169 char *name;
1170 bool isSubsNode;
1171 {
1172 HashEntry *he;
1173 EFNodeName *nn;
1174 bool isNewNode = FALSE;
1175
1176 he = HashFind(&def->def_nodes, name);
1177 nn = (EFNodeName *) HashGetValue(he);
1178 if (nn == (EFNodeName *) NULL)
1179 {
1180 /* Create node if it doesn't already exist */
1181 if (efWarn && !isSubsNode)
1182 efReadError("Node %s doesn't exist so creating it\n", name);
1183 efBuildNode(def, isSubsNode, name, (double)0, 0, 0,
1184 (char *) NULL, (char **) NULL, 0);
1185
1186 nn = (EFNodeName *) HashGetValue(he);
1187 isNewNode = TRUE;
1188 }
1189 if (isSubsNode)
1190 {
1191 if (!EFHNIsGlob(nn->efnn_hier))
1192 {
1193 /* This node is declared to be an implicit port */
1194 nn->efnn_node->efnode_flags |= EF_SUBS_PORT;
1195 nn->efnn_port = -1;
1196 def->def_flags |= DEF_SUBSNODES;
1197 }
1198 nn->efnn_node->efnode_flags |= EF_SUBS_NODE;
1199 if (isNewNode)
1200 nn->efnn_node->efnode_flags |= EF_DEVTERM;
1201 }
1202 return nn->efnn_node;
1203 }
1204
1205 /*
1206 * ----------------------------------------------------------------------------
1207 *
1208 * efBuildAddStr --
1209 *
1210 * Return the index of 'str' in 'table'.
1211 * Add the string 'str' to the table 'table' if it's not already there.
1212 *
1213 * Results:
1214 * See above.
1215 *
1216 * Side effects:
1217 * Increments *pMax if we add an entry to the table.
1218 *
1219 * ----------------------------------------------------------------------------
1220 */
1221
1222 int
efBuildAddStr(table,pMax,size,str)1223 efBuildAddStr(table, pMax, size, str)
1224 char *table[]; /* Table to search */
1225 int *pMax; /* Increment this if we add an entry */
1226 int size; /* Maximum size of table */
1227 char *str; /* String to add */
1228 {
1229 int n, max;
1230
1231 max = *pMax;
1232 for (n = 0; n < max; n++)
1233 if (strcmp(table[n], str) == 0)
1234 return n;
1235
1236 if (max >= size)
1237 {
1238 printf("Too many entries in table (max is %d) to add %s\n", size, str);
1239 printf("Recompile libextflat.a with a bigger table size\n");
1240 exit (1);
1241 }
1242
1243 table[n++] = StrDup((char **) NULL, str);
1244 *pMax = n;
1245
1246 return max;
1247 }
1248
1249 /*
1250 * ----------------------------------------------------------------------------
1251 *
1252 * efBuildUse --
1253 *
1254 * Process a "use" line from a .ext file.
1255 * Creates a new use by the name 'subUseId' of the def named 'subDefName'.
1256 * If 'subDefName' doesn't exist, it is created, but left marked as
1257 * unavailable so that readfile() will read it in after it is done
1258 * with this file. If 'subUseId' ends in an array subscript, e.g,
1259 * useid[xlo:xhi:xsep][ylo:yhi:ysep]
1260 * its ArrayInfo is filled in from this information; otherwise, its
1261 * ArrayInfo is marked as not being needed (xlo == xhi, ylo == yhi).
1262 *
1263 * Results:
1264 * None.
1265 *
1266 * Side effects:
1267 * See above.
1268 *
1269 * ----------------------------------------------------------------------------
1270 */
1271
1272 void
efBuildUse(def,subDefName,subUseId,ta,tb,tc,td,te,tf)1273 efBuildUse(def, subDefName, subUseId, ta, tb, tc, td, te, tf)
1274 Def *def; /* Def to which this connection is to be added */
1275 char *subDefName; /* Def of which this a use */
1276 char *subUseId; /* Use identifier for the def 'subDefName' */
1277 int ta, tb, tc,
1278 td, te, tf; /* Elements of a transform from coordinates of
1279 * subDefName up to def.
1280 */
1281 {
1282 Use *newuse;
1283 Def *newdef;
1284 char *cp;
1285 HashEntry *he;
1286
1287 newdef = efDefLook(subDefName);
1288 if (newdef == NULL)
1289 newdef = efDefNew(subDefName);
1290
1291 newuse = (Use *) mallocMagic((unsigned)(sizeof (Use)));
1292 newuse->use_def = newdef;
1293 newuse->use_trans.t_a = ta;
1294 newuse->use_trans.t_b = tb;
1295 newuse->use_trans.t_c = tc;
1296 newuse->use_trans.t_d = td;
1297 newuse->use_trans.t_e = te;
1298 newuse->use_trans.t_f = tf;
1299
1300 /* Set the use identifier and array information */
1301 if ((cp = strchr(subUseId, '[')) == NULL)
1302 {
1303 newuse->use_id = StrDup((char **) NULL, subUseId);
1304 newuse->use_xlo = newuse->use_xhi = 0;
1305 newuse->use_ylo = newuse->use_yhi = 0;
1306 newuse->use_xsep = newuse->use_ysep = 0;
1307 }
1308 else
1309 {
1310 /* Note: Preserve any use of brackets as-is other than the */
1311 /* standard magic array notation below. This allows, for */
1312 /* example, verilog instance arrays read from DEF files to */
1313 /* be passed through correctly. */
1314
1315 if ((sscanf(cp, "[%d:%d:%d][%d:%d:%d]",
1316 &newuse->use_xlo, &newuse->use_xhi, &newuse->use_xsep,
1317 &newuse->use_ylo, &newuse->use_yhi, &newuse->use_ysep)) == 6)
1318 {
1319 *cp = '\0';
1320 newuse->use_id = StrDup((char **) NULL, subUseId);
1321 *cp = '[';
1322 }
1323 else
1324 {
1325 newuse->use_id = StrDup((char **) NULL, subUseId);
1326 newuse->use_xlo = newuse->use_xhi = 0;
1327 newuse->use_ylo = newuse->use_yhi = 0;
1328 newuse->use_xsep = newuse->use_ysep = 0;
1329 }
1330 }
1331
1332 he = HashFind(&def->def_uses, newuse->use_id);
1333 if (HashGetValue(he))
1334 TxError("Warning: use %s appears more than once in def!\n", newuse->use_id);
1335 HashSetValue(he, (ClientData)newuse);
1336 }
1337
1338 /*
1339 * ----------------------------------------------------------------------------
1340 *
1341 * efBuildConnect --
1342 *
1343 * Process a "connect" line from a .ext file.
1344 * Creates a connection record for the names 'nodeName1' and
1345 * 'nodeName2'.
1346 *
1347 * Results:
1348 * None.
1349 *
1350 * Side effects:
1351 * Allocates a new connection record, and prepends it to the
1352 * list for def.
1353 *
1354 * ----------------------------------------------------------------------------
1355 */
1356
1357 void
efBuildConnect(def,nodeName1,nodeName2,deltaC,av,ac)1358 efBuildConnect(def, nodeName1, nodeName2, deltaC, av, ac)
1359 Def *def; /* Def to which this connection is to be added */
1360 char *nodeName1; /* Name of first node in connection */
1361 char *nodeName2; /* Name of other node in connection */
1362 double deltaC; /* Adjustment in capacitance */
1363 char **av; /* Strings for area, perimeter adjustment */
1364 int ac; /* Number of strings in av */
1365 {
1366 int n;
1367 Connection *conn;
1368 unsigned size = sizeof (Connection)
1369 + (efNumResistClasses - 1) * sizeof (EFPerimArea);
1370
1371 conn = (Connection *) mallocMagic((unsigned)(size));
1372
1373 if (efConnInitSubs(conn, nodeName1, nodeName2))
1374 {
1375 conn->conn_cap = (EFCapValue) deltaC;
1376 conn->conn_next = def->def_conns;
1377 for (n = 0; n < efNumResistClasses && ac > 1; n++, ac -= 2)
1378 {
1379 conn->conn_pa[n].pa_area = (int)(0.5 + (float)atoi(*av++)
1380 * locScale * locScale);
1381 conn->conn_pa[n].pa_perim = (int)(0.5 + (float)atoi(*av++) * locScale);
1382 }
1383 for ( ; n < efNumResistClasses; n++)
1384 conn->conn_pa[n].pa_area = conn->conn_pa[n].pa_perim = 0;
1385 def->def_conns = conn;
1386 }
1387 }
1388
1389 /*
1390 * ----------------------------------------------------------------------------
1391 *
1392 * efBuildResistor --
1393 *
1394 * Process a "resistor" line from a .ext file.
1395 * Creates a resistor record for the names 'nodeName1' and
1396 * 'nodeName2'. Both 'nodeName1' and 'nodeName2' must be non-NULL.
1397 *
1398 * Results:
1399 * None.
1400 *
1401 * Side effects:
1402 * Allocates a new connection record, and prepends it to the
1403 * def_resistors list for def.
1404 *
1405 * ----------------------------------------------------------------------------
1406 */
1407
1408 void
efBuildResistor(def,nodeName1,nodeName2,resistance)1409 efBuildResistor(def, nodeName1, nodeName2, resistance)
1410 Def *def; /* Def to which this connection is to be added */
1411 char *nodeName1; /* Name of first node in resistor */
1412 char *nodeName2; /* Name of second node in resistor */
1413 int resistance; /* Resistor value */
1414 {
1415 Connection *conn;
1416
1417 conn = (Connection *) mallocMagic((unsigned)(sizeof (Connection)));
1418 if (efConnInitSubs(conn, nodeName1, nodeName2))
1419 {
1420 conn->conn_res = (float)resistance;
1421 conn->conn_next = def->def_resistors;
1422 def->def_resistors = conn;
1423 }
1424 }
1425
1426 /*
1427 * ----------------------------------------------------------------------------
1428 *
1429 * efBuildCap --
1430 *
1431 * Process a "cap" line from a .ext file.
1432 * Creates a capacitor record for the names 'nodeName1' and
1433 * 'nodeName2'. Both 'nodeName1' and 'nodeName2' must be non-NULL.
1434 *
1435 * Results:
1436 * None.
1437 *
1438 * Side effects:
1439 * Allocates a new connection record, and prepends it to the
1440 * def_caps list for def.
1441 *
1442 * ----------------------------------------------------------------------------
1443 */
1444
1445 void
efBuildCap(def,nodeName1,nodeName2,cap)1446 efBuildCap(def, nodeName1, nodeName2, cap)
1447 Def *def; /* Def to which this connection is to be added */
1448 char *nodeName1; /* Name of first node in capacitor */
1449 char *nodeName2; /* Name of second node in capacitor */
1450 double cap; /* Capacitor value */
1451 {
1452 Connection *conn;
1453
1454 conn = (Connection *) mallocMagic((unsigned)(sizeof (Connection)));
1455 if (efConnInitSubs(conn, nodeName1, nodeName2))
1456 {
1457 conn->conn_cap = (EFCapValue) cap;
1458 conn->conn_next = def->def_caps;
1459 def->def_caps = conn;
1460 }
1461 }
1462
1463 /*
1464 * ----------------------------------------------------------------------------
1465 *
1466 * efConnInitSubs --
1467 *
1468 * Fill in and check the subscript information for the newly allocated
1469 * Connection 'conn'.
1470 *
1471 * Results:
1472 * Returns TRUE if successful, FALSE on error.
1473 *
1474 * Side effects:
1475 * Fills in the two ConnNames conn->conn_1 and conn->conn_2.
1476 * Frees 'conn' in the event of an error.
1477 *
1478 * ----------------------------------------------------------------------------
1479 */
1480
1481 bool
efConnInitSubs(conn,nodeName1,nodeName2)1482 efConnInitSubs(conn, nodeName1, nodeName2)
1483 Connection *conn;
1484 char *nodeName1, *nodeName2;
1485 {
1486 ConnName *c1, *c2;
1487 int n;
1488
1489 c1 = &conn->conn_1;
1490 c2 = &conn->conn_2;
1491 if (!efConnBuildName(c1, nodeName1) || !efConnBuildName(c2, nodeName2))
1492 goto bad;
1493
1494 if (c1->cn_nsubs != c2->cn_nsubs)
1495 {
1496 efReadError("Number of subscripts doesn't match\n");
1497 goto bad;
1498 }
1499
1500 for (n = 0; n < c1->cn_nsubs; n++)
1501 {
1502 if (c1->cn_subs[n].r_hi - c1->cn_subs[n].r_lo
1503 != c2->cn_subs[n].r_hi - c2->cn_subs[n].r_lo)
1504 {
1505 efReadError("Subscript %d range mismatch\n", n);
1506 goto bad;
1507 }
1508 }
1509 return TRUE;
1510
1511 bad:
1512 if (c1->cn_name) freeMagic((char *) c1->cn_name);
1513 if (c2->cn_name) freeMagic((char *) c2->cn_name);
1514 freeMagic((char *) conn);
1515 return FALSE;
1516 }
1517
1518 /*
1519 * ----------------------------------------------------------------------------
1520 *
1521 * efConnBuildName --
1522 *
1523 * Fill in the fields of 'cnp' from the string 'name'.
1524 * If 'name' contains no trailing subscript ranges (which are
1525 * of the form [lo1:hi1] or [lo1:hi1,lo2:hi2], or [lo1:hi1][lo2:hi2] for
1526 * compatibility with older versions of Magic), we set cnp->cn_nsubs
1527 * to zero and cnp->cn_name to a copy of 'name'. Otherwise, we decode
1528 * the subscripts and fill in cnp->cn_subs and cnp->cn_nsubs appropriately.
1529 *
1530 * Results:
1531 * Returns TRUE if successful, FALSE on error.
1532 *
1533 * Side effects:
1534 * Fills in the fields of the ConnName 'cnp'.
1535 *
1536 * ----------------------------------------------------------------------------
1537 */
1538
1539 bool
efConnBuildName(cnp,name)1540 efConnBuildName(cnp, name)
1541 ConnName *cnp;
1542 char *name;
1543 {
1544 char *srcp, *dstp, *cp, *dp;
1545 int nsubs;
1546 Range *rp;
1547 char newname[1024];
1548 char c;
1549
1550 cnp->cn_nsubs = 0;
1551 if (name == NULL)
1552 {
1553 cnp->cn_name = NULL;
1554 return TRUE;
1555 }
1556
1557 cp = name;
1558 /* Make sure it's an array subscript range before treating it specially */
1559 again:
1560 if ((cp = strchr(cp, '[')) == NULL)
1561 {
1562 cnp->cn_name = StrDup((char **) NULL, name);
1563 return TRUE;
1564 }
1565 for (dp = cp + 1; *dp && *dp != ':'; dp++)
1566 {
1567 if (*dp == ']')
1568 {
1569 cp = dp+1;
1570 goto again;
1571 }
1572 }
1573
1574 /* Copy the initial part of the name */
1575 for (srcp = name, dstp = newname; srcp < cp; *dstp++ = *srcp++)
1576 /* Nothing */;
1577
1578 /* Replace each subscript range with %d */
1579 for (nsubs = 0, rp = cnp->cn_subs; (c = *cp) == '[' || c == ','; nsubs++)
1580 {
1581 if (nsubs >= MAXSUBS)
1582 {
1583 efReadError("Too many array subscripts (maximum=2)\n");
1584 return FALSE;
1585 }
1586 if (sscanf(++cp, "%d:%d", &rp[nsubs].r_lo, &rp[nsubs].r_hi) != 2)
1587 {
1588 efReadError("Subscript syntax error\n");
1589 return FALSE;
1590 }
1591 if (rp[nsubs].r_lo > rp[nsubs].r_hi)
1592 {
1593 efReadError("Backwards subscript range [%d:%d]\n",
1594 rp[nsubs].r_lo, rp[nsubs].r_hi);
1595 return FALSE;
1596 }
1597
1598 while (*cp && *cp != ']' && *cp != ',')
1599 cp++;
1600 if (*cp == ']') cp++;
1601 }
1602
1603 /* Generate format for sprintf */
1604 *dstp++ = '[';
1605 *dstp++ = '%';
1606 *dstp++ = 'd';
1607 if (nsubs == 2)
1608 {
1609 *dstp++ = ',';
1610 *dstp++ = '%';
1611 *dstp++ = 'd';
1612 }
1613 *dstp++ = ']';
1614
1615 /* Copy remainder of path */
1616 while (*dstp++ = *cp++)
1617 /* Nothing */;
1618
1619 cnp->cn_name = StrDup((char **) NULL, newname);
1620 cnp->cn_nsubs = nsubs;
1621 return TRUE;
1622 }
1623
1624 /*
1625 * ----------------------------------------------------------------------------
1626 *
1627 * efNodeAddName --
1628 *
1629 * Add a name to the list for 'node'.
1630 * We already have a HashEntry for the new name.
1631 * The new name is added to the front of the list
1632 * for 'node' only if it is higher in precedence
1633 * than the name already at the front of the list.
1634 * Sets the value of 'he' to be the newly allocated
1635 * EFNodeName.
1636 *
1637 * Results:
1638 * None.
1639 *
1640 * Side effects:
1641 * See above.
1642 *
1643 * ----------------------------------------------------------------------------
1644 */
1645
1646 void
efNodeAddName(node,he,hn)1647 efNodeAddName(node, he, hn)
1648 EFNode *node;
1649 HashEntry *he;
1650 HierName *hn;
1651 {
1652 EFNodeName *newnn;
1653 EFNodeName *oldnn;
1654 bool topport; // New node to add is a top-level port
1655
1656 newnn = (EFNodeName *) mallocMagic((unsigned)(sizeof (EFNodeName)));
1657 newnn->efnn_node = node;
1658 newnn->efnn_hier = hn;
1659 newnn->efnn_port = -1;
1660 newnn->efnn_refc = 0;
1661 HashSetValue(he, (char *) newnn);
1662
1663 /* If the node is a port of the top level cell, denoted by flag */
1664 /* EF_TOP_PORT, then the name given to the port always stays at the */
1665 /* head of the list. */
1666
1667 topport = (node->efnode_flags & EF_TOP_PORT) ? TRUE : FALSE;
1668
1669 /* Link in the new name */
1670 oldnn = node->efnode_name;
1671 if (oldnn == NULL || (EFHNBest(newnn->efnn_hier, oldnn->efnn_hier) && !topport))
1672 {
1673 /* New head of list */
1674 newnn->efnn_next = oldnn;
1675 node->efnode_name = newnn;
1676 }
1677 else
1678 {
1679 /* Link it in behind the head of the list */
1680 newnn->efnn_next = oldnn->efnn_next;
1681 oldnn->efnn_next = newnn;
1682 }
1683 }
1684
1685 /*
1686 * ----------------------------------------------------------------------------
1687 *
1688 * efNodeMerge --
1689 *
1690 * Combine two nodes. The resistances and capacitances are summed.
1691 * The attribute lists are appended. The location chosen is the
1692 * lower-leftmost, with lowest being considered before leftmost.
1693 * The canonical name of the new node is taken to be the highest
1694 * precedence among the names for all nodes.
1695 *
1696 * One of the nodes will no longer be referenced, so we arbitrarily
1697 * make this node2 and free its memory.
1698 *
1699 * Results:
1700 * Return 0 if node1 has precedence, 1 if node2 has precedence
1701 *
1702 * Side effects:
1703 * See above.
1704 *
1705 * ----------------------------------------------------------------------------
1706 */
1707
1708 void
efNodeMerge(node1ptr,node2ptr)1709 efNodeMerge(node1ptr, node2ptr)
1710 EFNode **node1ptr, **node2ptr; /* Pointers to hierarchical nodes */
1711 {
1712 EFNodeName *nn, *nnlast;
1713 EFAttr *ap;
1714 int n;
1715 EFNode *keeping, *removing;
1716
1717 /* Sanity check: ignore if same node */
1718 if (*node1ptr == *node2ptr)
1719 return;
1720
1721 /* Keep the node with the greater number of entries, and merge */
1722 /* the node with fewer entries into it. */
1723
1724 if ((*node1ptr)->efnode_num >= (*node2ptr)->efnode_num)
1725 {
1726 keeping = *node1ptr;
1727 removing = *node2ptr;
1728 }
1729 else
1730 {
1731 keeping = *node2ptr;
1732 removing = *node1ptr;
1733 }
1734
1735 if (efWatchNodes)
1736 {
1737 if (HashLookOnly(&efWatchTable, (char *) keeping->efnode_name->efnn_hier)
1738 || (removing->efnode_name
1739 && HashLookOnly(&efWatchTable,
1740 (char *) removing->efnode_name->efnn_hier)))
1741 {
1742 printf("\ncombine: %s\n",
1743 EFHNToStr(keeping->efnode_name->efnn_hier));
1744 printf(" with %s\n\n",
1745 removing->efnode_name
1746 ? EFHNToStr(removing->efnode_name->efnn_hier)
1747 : "(unnamed)");
1748 }
1749 }
1750
1751 /* Sum capacitances, perimeters, areas */
1752 keeping->efnode_cap += removing->efnode_cap;
1753 for (n = 0; n < efNumResistClasses; n++)
1754 {
1755 keeping->efnode_pa[n].pa_area += removing->efnode_pa[n].pa_area;
1756 keeping->efnode_pa[n].pa_perim += removing->efnode_pa[n].pa_perim;
1757 }
1758
1759 /* Make all EFNodeNames point to "keeping" */
1760 if (removing->efnode_name)
1761 {
1762 bool topportk, topportr;
1763
1764 for (nn = removing->efnode_name; nn; nn = nn->efnn_next)
1765 {
1766 nnlast = nn;
1767 nn->efnn_node = keeping;
1768 }
1769
1770 topportk = (keeping->efnode_flags & EF_TOP_PORT) ? TRUE : FALSE;
1771 topportr = (removing->efnode_flags & EF_TOP_PORT) ? TRUE : FALSE;
1772
1773 /* Concatenate list of EFNodeNames, taking into account precedence */
1774 if ((!keeping->efnode_name) || (!topportk && (topportr
1775 || EFHNBest(removing->efnode_name->efnn_hier,
1776 keeping->efnode_name->efnn_hier))))
1777 {
1778 /*
1779 * New official name is that of "removing".
1780 * The new list of names is:
1781 * removing-names, keeping-names
1782 */
1783 nnlast->efnn_next = keeping->efnode_name;
1784 keeping->efnode_name = removing->efnode_name;
1785
1786 /*
1787 * Choose the new location only if "removing"'s location is a valid one,
1788 * i.e, "removing" wasn't created before it was mentioned. This is mainly
1789 * to deal with new fets, resistors, and capacitors created by resistance
1790 * extraction, which appear with their full hierarchical names in the
1791 * .ext file for the root cell.
1792 *
1793 * This code has been moved up from below so that the original
1794 * location and type will be prefered when the original name
1795 * is preferred.
1796 *
1797 * I am purposefully subverting the original specification that
1798 * the node refer to the bottom corner of the network. Does
1799 * this have any effect on exttosim or exttospice?
1800 *
1801 * Tim, 6/14/04
1802 */
1803 if (removing->efnode_type > 0)
1804 {
1805 keeping->efnode_loc = removing->efnode_loc;
1806 keeping->efnode_type = removing->efnode_type;
1807 }
1808 }
1809 else
1810 {
1811 /*
1812 * Keep old official name.
1813 * The new list of names is:
1814 * keeping-names[0], removing-names, keeping-names[1-]
1815 */
1816 nnlast->efnn_next = keeping->efnode_name->efnn_next;
1817 keeping->efnode_name->efnn_next = removing->efnode_name;
1818 }
1819 }
1820
1821 /* Merge list counts */
1822 keeping->efnode_num += removing->efnode_num;
1823
1824 /* Merge attribute lists */
1825 if (ap = removing->efnode_attrs)
1826 {
1827 while (ap->efa_next)
1828 ap = ap->efa_next;
1829 ap->efa_next = keeping->efnode_attrs;
1830 keeping->efnode_attrs = ap;
1831 removing->efnode_attrs = (EFAttr *) NULL; /* Sanity */
1832 }
1833
1834 /* Unlink "removing" from list for def */
1835 removing->efnode_prev->efnhdr_next = removing->efnode_next;
1836 removing->efnode_next->efnhdr_prev = removing->efnode_prev;
1837
1838 /*
1839 * Only if both nodes were EF_DEVTERM do we keep EF_DEVTERM set
1840 * in the resultant node.
1841 */
1842 if ((removing->efnode_flags & EF_DEVTERM) == 0)
1843 keeping->efnode_flags &= ~EF_DEVTERM;
1844
1845 /*
1846 * If "removing" has the EF_PORT flag set, then copy the port
1847 * record in the flags to node1.
1848 */
1849 if (removing->efnode_flags & EF_PORT)
1850 keeping->efnode_flags |= EF_PORT;
1851 if (removing->efnode_flags & EF_TOP_PORT)
1852 keeping->efnode_flags |= EF_TOP_PORT;
1853 if (removing->efnode_flags & EF_SUBS_PORT)
1854 keeping->efnode_flags |= EF_SUBS_PORT;
1855
1856 /*
1857 * If "removing" has the EF_SUBS_NODE flag set, then copy the port
1858 * record in the flags to "keeping".
1859 */
1860 if (removing->efnode_flags & EF_SUBS_NODE)
1861 keeping->efnode_flags |= EF_SUBS_NODE;
1862
1863 /* Get rid of "removing" */
1864 freeMagic((char *) removing);
1865
1866 /* Make sure that the active node is always node1 */
1867 *node1ptr = keeping;
1868 *node2ptr = (EFNode *)NULL; /* Sanity check */
1869 }
1870
1871
1872 /*
1873 * ----------------------------------------------------------------------------
1874 *
1875 * efFreeUseTable --
1876 *
1877 * Free the cell IDs allocated for each entry in the use hash table, and
1878 * the memory allocated by the cell use, leaving the hash entry null.
1879 *
1880 * ----------------------------------------------------------------------------
1881 */
1882
1883 void
efFreeUseTable(table)1884 efFreeUseTable(table)
1885 HashTable *table;
1886 {
1887 HashSearch hs;
1888 HashEntry *he;
1889 Use *use;
1890 HierName *hn;
1891 EFNodeName *nn;
1892
1893 HashStartSearch(&hs);
1894 while (he = HashNext(table, &hs))
1895 if (use = (Use *) HashGetValue(he))
1896 {
1897 if (use->use_id != NULL) freeMagic((char *)use->use_id);
1898 freeMagic(use);
1899 }
1900 }
1901
1902 /*
1903 * ----------------------------------------------------------------------------
1904 *
1905 * efFreeDevTable --
1906 *
1907 * Free the device records allocated for each entry in the device hash table,
1908 * the memory allocated by the device, leaving the hash entry null.
1909 *
1910 * ----------------------------------------------------------------------------
1911 */
1912
1913 void
efFreeDevTable(table)1914 efFreeDevTable(table)
1915 HashTable *table;
1916 {
1917 Dev *dev;
1918 HashSearch hs;
1919 HashEntry *he;
1920 int n;
1921
1922 HashStartSearch(&hs);
1923 while (he = HashNext(table, &hs))
1924 {
1925 dev = (Dev *)HashGetValue(he);
1926 for (n = 0; n < (int)dev->dev_nterm; n++)
1927 if (dev->dev_terms[n].dterm_attrs)
1928 freeMagic((char *) dev->dev_terms[n].dterm_attrs);
1929 freeMagic((char *) dev);
1930 }
1931 }
1932
1933 /*
1934 * ----------------------------------------------------------------------------
1935 *
1936 * efFreeNodeTable --
1937 *
1938 * Free the EFNodeNames (and the HierNames they point to) pointed to by
1939 * the entries in the HashTable 'table'. Each EFNodeName is assumed to
1940 * be pointed to by exactly one HashEntry, but each HierName can be
1941 * pointed to by many entries (some of which may be in other HashTables).
1942 * As a result, the HierNames aren't freed here; instead, an entry is
1943 * added to efFreeHashTable for each HierName encountered. Everything
1944 * is then freed at the end by EFDone().
1945 *
1946 * Results:
1947 * None.
1948 *
1949 * Side effects:
1950 * Frees memory.
1951 * Adds an entry to hnTable for each HierName.
1952 *
1953 * ----------------------------------------------------------------------------
1954 */
1955
1956 void
efFreeNodeTable(table)1957 efFreeNodeTable(table)
1958 HashTable *table;
1959 {
1960 HashSearch hs;
1961 HashEntry *he;
1962 HierName *hn;
1963 EFNodeName *nn;
1964
1965 HashStartSearch(&hs);
1966 while (he = HashNext(table, &hs))
1967 if (nn = (EFNodeName *) HashGetValue(he))
1968 {
1969 for (hn = nn->efnn_hier; hn; hn = hn->hn_parent)
1970 (void) HashFind(&efFreeHashTable, (char *) hn);
1971
1972 /* Node equivalences made by "equiv" statements are handled */
1973 /* by reference count. Don't free the node structure until */
1974 /* all references have been seen. */
1975
1976 if (nn->efnn_refc > 0)
1977 nn->efnn_refc--;
1978 else
1979 freeMagic((char *) nn);
1980 }
1981 }
1982
1983 /*
1984 * ----------------------------------------------------------------------------
1985 *
1986 * efFreeNodeList --
1987 *
1988 * Free the circular list of nodes of which 'head' is the head.
1989 * Don't free 'head' itself, since it's statically allocated.
1990 *
1991 * If the client (e.g., ext2spice, ext2sim, ...) allocates memory for a
1992 * node, then that client needs to provide a function "func" of the form:
1993 *
1994 * int func(client)
1995 * ClientData client;
1996 * {
1997 * }
1998 *
1999 * The return value is unused but should be zero for consistency.
2000 *
2001 * Results:
2002 * None.
2003 *
2004 * Side effects:
2005 * Frees memory. Calls func() to free additional memory allocated
2006 * in the node structure by a client.
2007 *
2008 * ----------------------------------------------------------------------------
2009 */
2010
2011 void
efFreeNodeList(head,func)2012 efFreeNodeList(head, func)
2013 EFNode *head;
2014 int (*func)();
2015 {
2016 EFNode *node;
2017 EFAttr *ap;
2018
2019 for (node = (EFNode *) head->efnode_next;
2020 node != head;
2021 node = (EFNode *) node->efnode_next)
2022 {
2023 for (ap = node->efnode_attrs; ap; ap = ap->efa_next)
2024 freeMagic((char *) ap);
2025 if (node->efnode_client != (ClientData)NULL)
2026 {
2027 if (func != NULL)
2028 (*func)(node->efnode_client);
2029 freeMagic((char *)node->efnode_client);
2030 }
2031 freeMagic((char *) node);
2032 }
2033 }
2034
2035 /*
2036 * ----------------------------------------------------------------------------
2037 *
2038 * efFreeConn --
2039 *
2040 * Free the Connection *conn.
2041 *
2042 * Results:
2043 * None.
2044 *
2045 * Side effects:
2046 * Frees memory.
2047 *
2048 * ----------------------------------------------------------------------------
2049 */
2050
2051 void
efFreeConn(conn)2052 efFreeConn(conn)
2053 Connection *conn;
2054 {
2055 if (conn->conn_name1) freeMagic(conn->conn_name1);
2056 if (conn->conn_name2) freeMagic(conn->conn_name2);
2057 freeMagic((char *) conn);
2058 }
2059