1 /*
2 * readdef.c --
3 *
4 * This module incorporates the LEF/DEF format for standard-cell place and
5 * route.
6 *
7 * Version 0.1 (September 26, 2003): DEF input of designs.
8 *
9 * Written by Tim Edwards, Open Circuit Design
10 * Modified April 2013 for use with qrouter
11 * Modified December 2018 for use with qflow (DEF2Verilog, back-annotate verilog
12 * netlist from DEF output).
13 *
14 * It is assumed that the LEF files have been read in prior to this, and
15 * layer information is already known. The DEF file should have information
16 * primarily on die are, track placement, pins, components, and nets.
17 *
18 * Routed nets have their routes dropped into track obstructions, and the
19 * nets are ignored.
20 *
21 */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <ctype.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <stdarg.h>
29 #include <math.h> /* for roundf() function, if std=c99 */
30
31 #include "readlef.h"
32 #include "readdef.h"
33 #include "hash.h"
34
35 int numSpecial = 0; /* Tracks number of specialnets */
36 int Numnets = 0; /* Total nets, including special nets */
37 int Numgates = 0; /* Number of components */
38 int Numpins = 0; /* Number of pins */
39
40 /* These hash tables speed up DEF file reading */
41
42 struct hashtable InstanceTable;
43 struct hashtable NetTable;
44 struct hashtable RowTable;
45 char *DEFDesignName;
46
47 DSEG UserObs = NULL;
48 double Xlowerbound = 0, Xupperbound = 0, Ylowerbound = 0, Yupperbound = 0;
49 double PitchX = 1.0, PitchY = 1.0;
50 NET *Nlnets = NULL;
51 GATE Nlgates = NULL;
52 GATE PinMacro;
53
54 /*--------------------------------------------------------------*/
55 /* Cell macro lookup based on the hash table */
56 /*--------------------------------------------------------------*/
57
58 static void
DefHashInit(void)59 DefHashInit(void)
60 {
61 /* Initialize the macro hash table */
62
63 InitializeHashTable(&InstanceTable, LARGEHASHSIZE);
64 InitializeHashTable(&NetTable, LARGEHASHSIZE);
65 InitializeHashTable(&RowTable, TINYHASHSIZE);
66 }
67
68 GATE
DefFindGate(char * name)69 DefFindGate(char *name)
70 {
71 GATE ginst;
72
73 ginst = (GATE)HashLookup(name, &InstanceTable);
74 return ginst;
75 }
76
77 ROW
DefFindRow(int yval)78 DefFindRow(int yval)
79 {
80 ROW row;
81 char namepos[32];
82
83 sprintf(namepos, "%d", yval);
84 row = (ROW)HashLookup(namepos, &RowTable);
85 return row;
86 }
87
88 /*--------------------------------------------------------------*/
89 /* Find the lowest row and return the row record. */
90 /*--------------------------------------------------------------*/
91
rowfindlowest(struct hashlist * p,void * clientdata)92 struct nlist *rowfindlowest(struct hashlist *p, void *clientdata)
93 {
94 ROW row = (ROW)(p->ptr);
95 ROW *lrow = (ROW *)clientdata;
96
97 if ((*lrow == NULL) || (row->y < (*lrow)->y))
98 *lrow = row;
99
100 return NULL;
101 }
102
103 /*--------------------------------------------------------------*/
104
105 ROW
DefLowestRow()106 DefLowestRow()
107 {
108 ROW row = NULL;
109
110 RecurseHashTablePointer(&RowTable, rowfindlowest, (void *)(&row));
111
112 return row;
113 }
114
115 /*--------------------------------------------------------------*/
116
117 NET
DefFindNet(char * name)118 DefFindNet(char *name)
119 {
120 NET net;
121
122 // Guard against calls to find nets before DEF file is read
123 if (Numnets == 0) return NULL;
124
125 net = (NET)HashLookup(name, &NetTable);
126 return net;
127 }
128
129 /*--------------------------------------------------------------*/
130 /* Cell macro hash table generation */
131 /* Given an instance record, create an entry in the hash table */
132 /* for the instance name, with the record entry pointing to the */
133 /* instance record. */
134 /*--------------------------------------------------------------*/
135
136 static void
DefHashInstance(GATE gateginfo)137 DefHashInstance(GATE gateginfo)
138 {
139 HashPtrInstall(gateginfo->gatename, gateginfo, &InstanceTable);
140 }
141
142 /*--------------------------------------------------------------*/
143
144 char *
DefDesign()145 DefDesign()
146 {
147 return DEFDesignName;
148 }
149
150 /*--------------------------------------------------------------*/
151 /* Net hash table generation */
152 /* Given a net record, create an entry in the hash table for */
153 /* the net name, with the record entry pointing to the net */
154 /* record. */
155 /*--------------------------------------------------------------*/
156
157 static void
DefHashNet(NET net)158 DefHashNet(NET net)
159 {
160 HashPtrInstall(net->netname, net, &NetTable);
161 }
162
163 /*
164 *------------------------------------------------------------
165 *
166 * DefAddRoutes --
167 *
168 * Parse a network route statement from the DEF file.
169 * If "special" is 1, then, add the geometry to the
170 * list of obstructions. If "special" is 0, then read
171 * the geometry into a route structure for the net.
172 *
173 * Results:
174 * Returns the last token encountered.
175 *
176 * Side Effects:
177 * Reads from input stream;
178 * Adds information to the layout database.
179 *
180 *------------------------------------------------------------
181 */
182
183 static char *
DefAddRoutes(FILE * f,float oscale,NET net,char special)184 DefAddRoutes(FILE *f, float oscale, NET net, char special)
185 {
186 char *token;
187 DSEG lr, drect;
188 struct point_ refp;
189 char valid = FALSE; /* is there a valid reference point? */
190 char noobstruct;
191 char initial = TRUE;
192 struct dseg_ locarea;
193 double x, y, lx, ly, w, hw, s;
194 int routeLayer = -1, paintLayer;
195 LefList lefl;
196
197 refp.x1 = 0;
198 refp.y1 = 0;
199
200 /* Don't create obstructions or routes on routed specialnets inputs */
201 noobstruct = (special == (char)1) ? TRUE : FALSE;
202
203 while (initial || (token = LefNextToken(f, TRUE)) != NULL)
204 {
205 /* Get next point, token "NEW", or via name */
206 if (initial || !strcmp(token, "NEW") || !strcmp(token, "new"))
207 {
208 /* initial pass is like a NEW record, but has no NEW keyword */
209 initial = FALSE;
210
211 /* invalidate reference point */
212 valid = FALSE;
213
214 token = LefNextToken(f, TRUE);
215 routeLayer = LefFindLayerNum(token);
216
217 if (routeLayer < 0)
218 {
219 LefError(DEF_ERROR, "Unknown layer type \"%s\" for NEW route\n", token);
220 continue;
221 }
222 paintLayer = routeLayer;
223
224 if (special == (char)1)
225 {
226 /* SPECIALNETS has the additional width */
227 token = LefNextToken(f, TRUE);
228 if (sscanf(token, "%lg", &w) != 1)
229 {
230 LefError(DEF_ERROR, "Bad width in special net\n");
231 continue;
232 }
233 if (w != 0)
234 w /= oscale;
235 else
236 w = LefGetRouteWidth(paintLayer);
237 }
238 else
239 w = LefGetRouteWidth(paintLayer);
240
241 }
242 else if (*token != '(') /* via name */
243 {
244 /* A '+' or ';' record ends the route */
245 if (*token == ';' || *token == '+')
246 break;
247
248 else if (valid == FALSE)
249 {
250 LefError(DEF_ERROR, "Route has via name \"%s\" but no points!\n", token);
251 continue;
252 }
253 lefl = LefFindLayer(token);
254 if (lefl != NULL)
255 {
256 /* The area to paint is derived from the via definitions. */
257
258 if (lefl != NULL)
259 {
260 if (lefl->lefClass == CLASS_VIA) {
261
262 // Note: layers may be defined in any order, metal or cut.
263 // Check both via.area and via.lr layers, and reject those
264 // that exceed the number of metal layers (those are cuts).
265
266 paintLayer = 100;
267 routeLayer = -1;
268 routeLayer = lefl->info.via.area.layer;
269 if (routeLayer < paintLayer) paintLayer = routeLayer;
270 if ((routeLayer >= 0) && (special == (char)1) &&
271 (valid == TRUE) && (noobstruct == FALSE)) {
272 s = LefGetRouteSpacing(routeLayer);
273 drect = (DSEG)malloc(sizeof(struct dseg_));
274 drect->x1 = x + (lefl->info.via.area.x1 / 2.0) - s;
275 drect->x2 = x + (lefl->info.via.area.x2 / 2.0) + s;
276 drect->y1 = y + (lefl->info.via.area.y1 / 2.0) - s;
277 drect->y2 = y + (lefl->info.via.area.y2 / 2.0) + s;
278 drect->layer = routeLayer;
279 drect->next = UserObs;
280 UserObs = drect;
281 }
282 for (lr = lefl->info.via.lr; lr; lr = lr->next) {
283 routeLayer = lr->layer;
284 if (routeLayer < paintLayer) paintLayer = routeLayer;
285 if ((routeLayer >= 0) && (special == (char)1) &&
286 (valid == TRUE) && (noobstruct == FALSE)) {
287 s = LefGetRouteSpacing(routeLayer);
288 drect = (DSEG)malloc(sizeof(struct dseg_));
289 drect->x1 = x + (lr->x1 / 2.0) - s;
290 drect->x2 = x + (lr->x2 / 2.0) + s;
291 drect->y1 = y + (lr->y1 / 2.0) - s;
292 drect->y2 = y + (lr->y2 / 2.0) + s;
293 drect->layer = routeLayer;
294 drect->next = UserObs;
295 UserObs = drect;
296 }
297 }
298 if (routeLayer == -1) paintLayer = lefl->type;
299 }
300 else {
301 paintLayer = lefl->type;
302 if (special == (char)1)
303 s = LefGetRouteSpacing(paintLayer);
304 }
305 }
306 else
307 {
308 LefError(DEF_ERROR, "Error: Via \"%s\" named but undefined.\n", token);
309 paintLayer = routeLayer;
310 }
311 }
312 else
313 LefError(DEF_ERROR, "Via name \"%s\" unknown in route.\n", token);
314 }
315 else
316 {
317 /* Revert to the routing layer type, in case we painted a via */
318 paintLayer = routeLayer;
319
320 /* Record current reference point */
321 locarea.x1 = refp.x1;
322 locarea.y1 = refp.y1;
323 lx = x;
324 ly = y;
325
326 /* Read an (X Y) point */
327 token = LefNextToken(f, TRUE); /* read X */
328 if (*token == '*')
329 {
330 if (valid == FALSE)
331 {
332 LefError(DEF_ERROR, "No reference point for \"*\" wildcard\n");
333 goto endCoord;
334 }
335 }
336 else if (sscanf(token, "%lg", &x) == 1)
337 {
338 x /= oscale; // In microns
339 /* Note: offsets and stubs are always less than half a pitch, */
340 /* so round to the nearest integer grid point. */
341 refp.x1 = (int)(0.5 + ((x - Xlowerbound) / PitchX));
342 }
343 else
344 {
345 LefError(DEF_ERROR, "Cannot parse X coordinate.\n");
346 goto endCoord;
347 }
348 token = LefNextToken(f, TRUE); /* read Y */
349 if (*token == '*')
350 {
351 if (valid == FALSE)
352 {
353 LefError(DEF_ERROR, "No reference point for \"*\" wildcard\n");
354 goto endCoord;
355 }
356 }
357 else if (sscanf(token, "%lg", &y) == 1)
358 {
359 y /= oscale; // In microns
360 refp.y1 = (int)(0.5 + ((y - Ylowerbound) / PitchY));
361 }
362 else
363 {
364 LefError(DEF_ERROR, "Cannot parse Y coordinate.\n");
365 goto endCoord;
366 }
367
368 /* Indicate that we have a valid reference point */
369
370 if (valid == FALSE)
371 {
372 valid = TRUE;
373 }
374 else if ((locarea.x1 != refp.x1) && (locarea.y1 != refp.y1))
375 {
376 /* Skip over nonmanhattan segments, reset the reference */
377 /* point, and output a warning. */
378
379 LefError(DEF_ERROR, "Can't deal with nonmanhattan geometry in route.\n");
380 locarea.x1 = refp.x1;
381 locarea.y1 = refp.y1;
382 lx = x;
383 ly = y;
384 }
385 else
386 {
387 locarea.x2 = refp.x1;
388 locarea.y2 = refp.y1;
389
390 if (special != (char)0) {
391 if ((valid == TRUE) && (noobstruct == FALSE)) {
392 s = LefGetRouteSpacing(routeLayer);
393 hw = w / 2;
394 drect = (DSEG)malloc(sizeof(struct dseg_));
395 if (lx > x) {
396 drect->x1 = x - s;
397 drect->x2 = lx + s;
398 }
399 else if (lx < x) {
400 drect->x1 = lx - s;
401 drect->x2 = x + s;
402 }
403 else {
404 drect->x1 = x - hw - s;
405 drect->x2 = x + hw + s;
406 }
407 if (ly > y) {
408 drect->y1 = y - s;
409 drect->y2 = ly + s;
410 }
411 else if (ly < y) {
412 drect->y1 = ly - s;
413 drect->y2 = y + s;
414 }
415 else {
416 drect->y1 = y - hw - s;
417 drect->y2 = y + hw + s;
418 }
419 drect->layer = routeLayer;
420 drect->next = UserObs;
421 UserObs = drect;
422 }
423 }
424 }
425
426 endCoord:
427 /* Find the closing parenthesis for the coordinate pair */
428 while (*token != ')')
429 token = LefNextToken(f, TRUE);
430 }
431 }
432
433 return token; /* Pass back the last token found */
434 }
435
436 /*
437 *------------------------------------------------------------
438 *
439 * DefReadGatePin ---
440 *
441 * Given a gate name and a pin name in a net from the
442 * DEF file NETS section, find the position of the
443 * gate, then the position of the pin within the gate,
444 * and add pin and obstruction information to the grid
445 * network.
446 *
447 *------------------------------------------------------------
448 */
449
450 static void
DefReadGatePin(NET net,NODE node,char * instname,char * pinname)451 DefReadGatePin(NET net, NODE node, char *instname, char *pinname)
452 {
453 int i;
454 GATE gateginfo;
455 DSEG drect;
456 GATE g;
457 double dx, dy;
458 int gridx, gridy;
459 DPOINT dp;
460
461 g = DefFindGate(instname);
462 if (g) {
463
464 gateginfo = g->gatetype;
465
466 if (!gateginfo) {
467 // Instances marked "<net>/pin have a NULL gatetype; this is okay.
468 if (strcmp(pinname, "pin"))
469 LefError(DEF_ERROR, "Endpoint %s/%s of net %s not found\n",
470 instname, pinname, net->netname);
471 return;
472 }
473 for (i = 0; i < gateginfo->nodes; i++) {
474 if (!strcasecmp(gateginfo->node[i], pinname)) {
475 node->taps = (DPOINT)NULL;
476 node->extend = (DPOINT)NULL;
477
478 for (drect = g->taps[i]; drect; drect = drect->next) {
479
480 // Add all routing gridpoints that fall inside
481 // the rectangle. Much to do here:
482 // (1) routable area should extend 1/2 route width
483 // to each side, as spacing to obstructions allows.
484 // (2) terminals that are wide enough to route to
485 // but not centered on gridpoints should be marked
486 // in some way, and handled appropriately.
487
488 gridx = (int)((drect->x1 - Xlowerbound) / PitchX) - 1;
489
490 if (gridx < 0) gridx = 0;
491 while (1) {
492 dx = (gridx * PitchX) + Xlowerbound;
493 if (dx > drect->x2) break;
494 if (dx < drect->x1) {
495 gridx++;
496 continue;
497 }
498 gridy = (int)((drect->y1 - Ylowerbound) / PitchY) - 1;
499
500 if (gridy < 0) gridy = 0;
501 while (1) {
502 dy = (gridy * PitchY) + Ylowerbound;
503 if (dy > drect->y2) break;
504 if (dy < drect->y1) {
505 gridy++;
506 continue;
507 }
508
509 // Routing grid point is an interior point
510 // of a gate port. Record the position
511
512 dp = (DPOINT)malloc(sizeof(struct dpoint_));
513 dp->layer = drect->layer;
514 dp->x = dx;
515 dp->y = dy;
516 dp->gridx = gridx;
517 dp->gridy = gridy;
518
519 if ((dy >= drect->y1) &&
520 (dx >= drect->x1) &&
521 (dy <= drect->y2) &&
522 (dx <= drect->x2)) {
523 dp->next = node->taps;
524 node->taps = dp;
525 }
526 else {
527 dp->next = node->extend;
528 node->extend = dp;
529 }
530 gridy++;
531 }
532 gridx++;
533 }
534 }
535 node->netnum = net->netnum;
536 g->netnum[i] = net->netnum;
537 g->noderec[i] = node;
538 node->netname = net->netname;
539 node->next = net->netnodes;
540 net->netnodes = node;
541 break;
542 }
543 }
544 if (i < gateginfo->nodes) return;
545 }
546 }
547
548 /*
549 *------------------------------------------------------------
550 *
551 * DefReadNets --
552 *
553 * Read a NETS or SPECIALNETS section from a DEF file.
554 *
555 * Results:
556 * Return the total number of fixed or cover nets,
557 * excluding power and ground nets. This gives the
558 * base number of nets to be copied verbatim from
559 * input to output (used only for SPECIALNETS, as
560 * regular nets are tracked with the NET_IGNORED flag).
561 *
562 * Side Effects:
563 * Many. Networks are created, and geometry may be
564 * painted into the database top-level cell.
565 *
566 *------------------------------------------------------------
567 */
568
569 enum def_net_keys {DEF_NET_START = 0, DEF_NET_END};
570 enum def_netprop_keys {
571 DEF_NETPROP_USE = 0, DEF_NETPROP_ROUTED, DEF_NETPROP_FIXED,
572 DEF_NETPROP_COVER, DEF_NETPROP_SHAPE, DEF_NETPROP_SOURCE,
573 DEF_NETPROP_WEIGHT, DEF_NETPROP_PROPERTY};
574
575 static int
DefReadNets(FILE * f,char * sname,float oscale,char special,int total)576 DefReadNets(FILE *f, char *sname, float oscale, char special, int total)
577 {
578 char *token;
579 int keyword, subkey;
580 int i, processed = 0;
581 int nodeidx;
582 int fixed = 0;
583 char instname[MAX_NAME_LEN], pinname[MAX_NAME_LEN];
584 u_char is_new;
585
586 NET net;
587 int netidx;
588 NODE node;
589
590 static char *net_keys[] = {
591 "-",
592 "END",
593 NULL
594 };
595
596 static char *net_property_keys[] = {
597 "USE",
598 "ROUTED",
599 "FIXED",
600 "COVER",
601 "SHAPE",
602 "SOURCE",
603 "WEIGHT",
604 "PROPERTY",
605 NULL
606 };
607
608 if (Numnets == 0)
609 {
610 // Initialize net and node records
611 netidx = 0;
612 Nlnets = (NET *)malloc(total * sizeof(NET));
613 for (i = 0; i < total; i++) Nlnets[i] = NULL;
614 }
615 else {
616 netidx = Numnets;
617 Nlnets = (NET *)realloc(Nlnets, (Numnets + total) * sizeof(NET));
618 for (i = Numnets; i < (Numnets + total); i++) Nlnets[i] = NULL;
619 }
620
621 while ((token = LefNextToken(f, TRUE)) != NULL)
622 {
623 keyword = Lookup(token, net_keys);
624 if (keyword < 0)
625 {
626 LefError(DEF_WARNING, "Unknown keyword \"%s\" in NET "
627 "definition; ignoring.\n", token);
628 LefEndStatement(f);
629 continue;
630 }
631
632 switch (keyword)
633 {
634 case DEF_NET_START:
635
636 /* Get net name */
637 token = LefNextToken(f, TRUE);
638 net = DefFindNet(token);
639
640 if (net == NULL) {
641 net = (NET)malloc(sizeof(struct net_));
642 Nlnets[Numnets++] = net;
643 net->numnodes = 0;
644 net->netname = strdup(token);
645 net->netnodes = (NODE)NULL;
646 net->Flags = (special) ? NET_SPECIAL : 0;
647
648 /* Check for backslash-escape names modified by other tools */
649 /* (e.g., vlog2Cel) which replace the trailing space with a */
650 /* backslash, making the name verilog-incompatible. */
651
652 if (*net->netname == '\\') {
653 char *sptr, *bptr;
654 sptr = strchr(net->netname, ' ');
655 if (sptr == NULL) {
656 bptr = strrchr(net->netname + 1, '\\');
657 if (bptr != NULL) *bptr = ' ';
658 }
659 }
660
661 net->netnum = netidx++;
662 DefHashNet(net);
663
664 nodeidx = 0;
665 is_new = TRUE;
666 }
667 else {
668 nodeidx = net->numnodes;
669 is_new = FALSE;
670 }
671
672 /* Update the record of the number of nets processed */
673 /* and spit out a message for every 5% finished. */
674
675 processed++;
676
677 /* Get next token; will be '(' if this is a netlist */
678 token = LefNextToken(f, TRUE);
679
680 /* Process all properties */
681 while (token && (*token != ';'))
682 {
683 /* Find connections for the net */
684 if (*token == '(')
685 {
686 token = LefNextToken(f, TRUE); /* get pin or gate */
687 strcpy(instname, token);
688
689 /* Check for instname with sanitized backslash syntax */
690 if (*instname == '\\') {
691 char *sptr, *bptr;
692 sptr = strchr(instname, ' ');
693 if (sptr == NULL) {
694 bptr = strrchr(instname + 1, '\\');
695 if (bptr != NULL) *bptr = ' ';
696 }
697 }
698
699 token = LefNextToken(f, TRUE); /* get node name */
700
701 if (!strcasecmp(instname, "pin")) {
702 strcpy(instname, token);
703 strcpy(pinname, "pin");
704 }
705 else
706 strcpy(pinname, token);
707
708 node = (NODE)calloc(1, sizeof(struct node_));
709 node->nodenum = nodeidx++;
710 DefReadGatePin(net, node, instname, pinname);
711
712 token = LefNextToken(f, TRUE); /* should be ')' */
713
714 continue;
715 }
716 else if (*token != '+')
717 {
718 token = LefNextToken(f, TRUE); /* Not a property */
719 continue; /* Ignore it, whatever it is */
720 }
721 else
722 token = LefNextToken(f, TRUE);
723
724 subkey = Lookup(token, net_property_keys);
725 if (subkey < 0)
726 {
727 LefError(DEF_WARNING, "Unknown net property \"%s\" in "
728 "NET definition; ignoring.\n", token);
729 continue;
730 }
731 switch (subkey)
732 {
733 case DEF_NETPROP_USE:
734 /* Presently, we ignore this */
735 break;
736 case DEF_NETPROP_SHAPE:
737 /* Ignore this too, along with the next keyword */
738 token = LefNextToken(f, TRUE);
739 break;
740 case DEF_NETPROP_FIXED:
741 case DEF_NETPROP_COVER:
742 /* Read in fixed nets like regular nets but mark
743 * them as NET_IGNORED. HOWEVER, if the net
744 * already exists and is not marked NET_IGNORED,
745 * then don't force it to be ignored. That is
746 * particularly an issue for a net like power or
747 * ground, which may need to be routed like a
748 * regular net but also has fixed portions. */
749 if (is_new) {
750 fixed++;
751 }
752 // fall through
753 case DEF_NETPROP_ROUTED:
754 // Read in the route; qrouter now takes
755 // responsibility for this route.
756 while (token && (*token != ';'))
757 token = DefAddRoutes(f, oscale, net, special);
758 // Treat power and ground nets in specialnets as fixed
759 if (subkey == DEF_NETPROP_ROUTED && special == (char)1)
760 fixed++;
761 break;
762 }
763 }
764 break;
765
766 case DEF_NET_END:
767 if (!LefParseEndStatement(f, sname))
768 {
769 LefError(DEF_ERROR, "Net END statement missing.\n");
770 keyword = -1;
771 }
772 break;
773 }
774 if (keyword == DEF_NET_END) break;
775 }
776
777 // Set the number of nodes per net for each node on the net
778
779 if (special == FALSE) {
780
781 // Fill in the netnodes list for each net, needed for checking
782 // for isolated routed groups within a net.
783
784 for (i = 0; i < Numnets; i++) {
785 net = Nlnets[i];
786 for (node = net->netnodes; node; node = node->next)
787 net->numnodes++;
788 for (node = net->netnodes; node; node = node->next)
789 node->numnodes = net->numnodes;
790 }
791 }
792
793 if (processed == total) {
794 if (Verbose > 0)
795 fprintf(stdout, " Processed %d%s nets total.\n", processed,
796 (special) ? " special" : "");
797 }
798 else
799 LefError(DEF_WARNING, "Warning: Number of nets read (%d) does not match "
800 "the number declared (%d).\n", processed, total);
801 return fixed;
802 }
803
804 /*
805 *------------------------------------------------------------
806 *
807 * DefReadUseLocation --
808 *
809 * Read location and orientation of a cell use
810 * Syntax: ( X Y ) O
811 *
812 * Results:
813 * 0 on success, -1 on failure
814 *
815 * Side Effects:
816 * GATE definition for the use has the placedX, placedY,
817 * and orient values filled.
818 *------------------------------------------------------------
819 */
820 enum def_orient {DEF_NORTH, DEF_SOUTH, DEF_EAST, DEF_WEST,
821 DEF_FLIPPED_NORTH, DEF_FLIPPED_SOUTH, DEF_FLIPPED_EAST,
822 DEF_FLIPPED_WEST};
823
824 static int
DefReadLocation(gate,f,oscale)825 DefReadLocation(gate, f, oscale)
826 GATE gate;
827 FILE *f;
828 float oscale;
829 {
830 int keyword;
831 char *token;
832 float x, y;
833 char mxflag, myflag;
834
835 static char *orientations[] = {
836 "N", "S", "E", "W", "FN", "FS", "FE", "FW"
837 };
838 static int oflags[] = {
839 RN, RS, RE, RW, RN | RF, RS | RF, RE | RF, RW | RF
840 };
841
842 token = LefNextToken(f, TRUE);
843 if (*token != '(') goto parse_error;
844 token = LefNextToken(f, TRUE);
845 if (sscanf(token, "%f", &x) != 1) goto parse_error;
846 token = LefNextToken(f, TRUE);
847 if (sscanf(token, "%f", &y) != 1) goto parse_error;
848 token = LefNextToken(f, TRUE);
849 if (*token != ')') goto parse_error;
850 token = LefNextToken(f, TRUE);
851
852 keyword = Lookup(token, orientations);
853 if (keyword < 0)
854 {
855 LefError(DEF_ERROR, "Unknown macro orientation \"%s\".\n", token);
856 return -1;
857 }
858
859 mxflag = myflag = (char)0;
860
861 switch (keyword)
862 {
863 case DEF_NORTH:
864 break;
865 case DEF_SOUTH:
866 mxflag = 1;
867 myflag = 1;
868 break;
869 case DEF_FLIPPED_NORTH:
870 mxflag = 1;
871 break;
872 case DEF_FLIPPED_SOUTH:
873 myflag = 1;
874 break;
875 }
876
877 if (gate) {
878 gate->placedX = x / oscale;
879 gate->placedY = y / oscale;
880 gate->orient = MNONE;
881 if (mxflag) gate->orient |= MX;
882 if (myflag) gate->orient |= MY;
883 gate->orient |= oflags[keyword];
884 }
885 return 0;
886
887 parse_error:
888 LefError(DEF_ERROR, "Cannot parse location: must be ( X Y ) orient\n");
889 return -1;
890 }
891
892 /*
893 *------------------------------------------------------------
894 *
895 * DefReadPins --
896 *
897 * Read a PINS section from a DEF file.
898 *
899 * Results:
900 * None.
901 *
902 * Side Effects:
903 * Generates paint and labels in the layout.
904 *
905 *------------------------------------------------------------
906 */
907
908 enum def_pins_keys {DEF_PINS_START = 0, DEF_PINS_END};
909 enum def_pins_prop_keys {
910 DEF_PINS_PROP_NET = 0, DEF_PINS_PROP_DIR,
911 DEF_PINS_PROP_LAYER, DEF_PINS_PROP_PLACED,
912 DEF_PINS_PROP_USE, DEF_PINS_PROP_FIXED,
913 DEF_PINS_PROP_COVER};
914
915 static void
DefReadPins(FILE * f,char * sname,float oscale,int total)916 DefReadPins(FILE *f, char *sname, float oscale, int total)
917 {
918 char *token;
919 char pinname[MAX_NAME_LEN];
920 int keyword, subkey;
921 int processed = 0;
922 DSEG currect, drect;
923 GATE gate;
924 int curlayer;
925 double hwidth;
926 u_char pin_use;
927
928 static char *pin_keys[] = {
929 "-",
930 "END",
931 NULL
932 };
933
934 static char *pin_property_keys[] = {
935 "NET",
936 "DIRECTION",
937 "LAYER",
938 "PLACED",
939 "USE",
940 "FIXED",
941 "COVER",
942 NULL
943 };
944
945 static char *pin_classes[] = {
946 "DEFAULT",
947 "INPUT",
948 "OUTPUT TRISTATE",
949 "OUTPUT",
950 "INOUT",
951 "FEEDTHRU",
952 NULL
953 };
954
955 static char *pin_uses[] = {
956 "DEFAULT",
957 "SIGNAL",
958 "ANALOG",
959 "POWER",
960 "GROUND",
961 "CLOCK",
962 "TIEOFF",
963 "SCAN",
964 "RESET",
965 NULL
966 };
967
968 pin_use = PORT_USE_DEFAULT;
969
970 while ((token = LefNextToken(f, TRUE)) != NULL)
971 {
972 keyword = Lookup(token, pin_keys);
973
974 if (keyword < 0)
975 {
976 LefError(DEF_WARNING, "Unknown keyword \"%s\" in PINS "
977 "definition; ignoring.\n", token);
978 LefEndStatement(f);
979 continue;
980 }
981 switch (keyword)
982 {
983 case DEF_PINS_START: /* "-" keyword */
984
985 /* Update the record of the number of pins */
986 /* processed and spit out a message for every 5% done. */
987
988 processed++;
989
990 /* Get pin name */
991 token = LefNextToken(f, TRUE);
992 if (sscanf(token, "%2047s", pinname) != 1)
993 {
994 LefError(DEF_ERROR, "Bad pin statement: Need pin name\n");
995 LefEndStatement(f);
996 break;
997 }
998
999 /* Create the pin record */
1000 gate = (GATE)malloc(sizeof(struct gate_));
1001 gate->gatetype = PinMacro;
1002 gate->gatename = NULL; /* Use NET, but if none, use */
1003 /* the pin name, set at end. */
1004 gate->width = gate->height = 0;
1005 curlayer = -1;
1006
1007 /* Pin record has one node; allocate memory for it */
1008 gate->taps = (DSEG *)malloc(sizeof(DSEG));
1009 gate->noderec = (NODE *)malloc(sizeof(NODE));
1010 gate->direction = (u_char *)malloc(sizeof(u_char));
1011 gate->area = (float *)malloc(sizeof(float));
1012 gate->netnum = (int *)malloc(sizeof(int));
1013 gate->node = (char **)malloc(sizeof(char *));
1014 gate->taps[0] = NULL;
1015 gate->noderec[0] = NULL;
1016 gate->netnum[0] = -1;
1017 gate->node[0] = NULL;
1018 gate->direction[0] = PORT_CLASS_DEFAULT;
1019 gate->area[0] = 0.0;
1020 gate->nomirror = FALSE;
1021 gate->clientdata = (void *)NULL;
1022
1023 /* Now do a search through the line for "+" entries */
1024 /* And process each. */
1025
1026 while ((token = LefNextToken(f, TRUE)) != NULL)
1027 {
1028 if (*token == ';') break;
1029 if (*token != '+') continue;
1030
1031 token = LefNextToken(f, TRUE);
1032 subkey = Lookup(token, pin_property_keys);
1033 if (subkey < 0)
1034 {
1035 LefError(DEF_WARNING, "Unknown pin property \"%s\" in "
1036 "PINS definition; ignoring.\n", token);
1037 continue;
1038 }
1039 switch (subkey)
1040 {
1041 case DEF_PINS_PROP_NET:
1042 /* Get the net name */
1043 token = LefNextToken(f, TRUE);
1044 gate->gatename = strdup(token);
1045 gate->node[0] = strdup(token);
1046 break;
1047 case DEF_PINS_PROP_DIR:
1048 token = LefNextToken(f, TRUE);
1049 subkey = Lookup(token, pin_classes);
1050 if (subkey < 0)
1051 LefError(DEF_ERROR, "Unknown pin class %s\n", token);
1052 else
1053 gate->direction[0] = subkey;
1054 break;
1055 case DEF_PINS_PROP_LAYER:
1056 curlayer = LefReadLayer(f, FALSE);
1057 currect = LefReadRect(f, curlayer, oscale);
1058 /* Warn if pin is on layer above routing layer limit? */
1059 if (currect) {
1060 gate->width = currect->x2 - currect->x1;
1061 gate->height = currect->y2 - currect->y1;
1062 }
1063 break;
1064 case DEF_PINS_PROP_USE:
1065 token = LefNextToken(f, TRUE);
1066 subkey = Lookup(token, pin_uses);
1067 if (subkey < 0)
1068 LefError(DEF_ERROR, "Unknown pin use %s\n", token);
1069 else
1070 pin_use = subkey;
1071 break;
1072 case DEF_PINS_PROP_PLACED:
1073 case DEF_PINS_PROP_FIXED:
1074 case DEF_PINS_PROP_COVER:
1075 DefReadLocation(gate, f, oscale);
1076 break;
1077 }
1078 }
1079
1080 /* If no NET was declared for pin, use pinname */
1081 if (gate->gatename == NULL)
1082 gate->gatename = strdup(pinname);
1083
1084 /* Make sure pin is at least the size of the route layer */
1085 drect = (DSEG)malloc(sizeof(struct dseg_));
1086 gate->taps[0] = drect;
1087 drect->next = (DSEG)NULL;
1088
1089 hwidth = LefGetRouteWidth(curlayer);
1090 if (gate->width < hwidth) gate->width = hwidth;
1091 if (gate->height < hwidth) gate->height = hwidth;
1092 hwidth /= 2.0;
1093 drect->x1 = gate->placedX - hwidth;
1094 drect->y1 = gate->placedY - hwidth;
1095 drect->x2 = gate->placedX + hwidth;
1096 drect->y2 = gate->placedY + hwidth;
1097 drect->layer = curlayer;
1098 gate->obs = (DSEG)NULL;
1099 gate->nodes = 1;
1100 gate->next = Nlgates;
1101 gate->last = (GATE)NULL;
1102 if (Nlgates) Nlgates->last = gate;
1103 Nlgates = gate;
1104 Numpins++;
1105
1106 // Used by Tcl version of qrouter
1107 DefHashInstance(gate);
1108
1109 break;
1110
1111 case DEF_PINS_END:
1112 if (!LefParseEndStatement(f, sname))
1113 {
1114 LefError(DEF_ERROR, "Pins END statement missing.\n");
1115 keyword = -1;
1116 }
1117 if (pin_use != PORT_USE_DEFAULT && gate->direction[0] ==
1118 PORT_CLASS_DEFAULT)
1119 {
1120 /* Derive pin use from pin class, if needed */
1121 switch (pin_use) {
1122 case PORT_USE_SIGNAL:
1123 case PORT_USE_RESET:
1124 case PORT_USE_CLOCK:
1125 case PORT_USE_SCAN:
1126 gate->direction[0] = PORT_CLASS_INPUT;
1127 break;
1128
1129 case PORT_USE_POWER:
1130 case PORT_USE_GROUND:
1131 case PORT_USE_TIEOFF:
1132 case PORT_USE_ANALOG:
1133 gate->direction[0] = PORT_CLASS_BIDIRECTIONAL;
1134 break;
1135 }
1136 }
1137 break;
1138 }
1139 if (keyword == DEF_PINS_END) break;
1140 }
1141
1142 if (processed == total) {
1143 if (Verbose > 0)
1144 fprintf(stdout, " Processed %d pins total.\n", processed);
1145 }
1146 else
1147 LefError(DEF_WARNING, "Warning: Number of pins read (%d) does not match "
1148 "the number declared (%d).\n", processed, total);
1149 }
1150
1151 /*
1152 *------------------------------------------------------------
1153 *
1154 * DefReadVias --
1155 *
1156 * Read a VIAS section from a DEF file.
1157 *
1158 * Results:
1159 * None.
1160 *
1161 * Side Effects:
1162 * Technically, this routine should be creating a cell for
1163 * each defined via. For now, it just computes the bounding
1164 * rectangle and layer.
1165 *
1166 *------------------------------------------------------------
1167 */
1168
1169 enum def_vias_keys {DEF_VIAS_START = 0, DEF_VIAS_END};
1170 enum def_vias_prop_keys {
1171 DEF_VIAS_PROP_RECT = 0};
1172
1173 static void
DefReadVias(f,sname,oscale,total)1174 DefReadVias(f, sname, oscale, total)
1175 FILE *f;
1176 char *sname;
1177 float oscale;
1178 int total;
1179 {
1180 char *token;
1181 char vianame[LEF_LINE_MAX];
1182 int keyword, subkey;
1183 int processed = 0;
1184 int curlayer;
1185 LefList lefl;
1186
1187 static char *via_keys[] = {
1188 "-",
1189 "END",
1190 NULL
1191 };
1192
1193 static char *via_property_keys[] = {
1194 "RECT",
1195 NULL
1196 };
1197
1198 while ((token = LefNextToken(f, TRUE)) != NULL)
1199 {
1200 keyword = Lookup(token, via_keys);
1201
1202 if (keyword < 0)
1203 {
1204 LefError(DEF_WARNING, "Unknown keyword \"%s\" in VIAS "
1205 "definition; ignoring.\n", token);
1206 LefEndStatement(f);
1207 continue;
1208 }
1209 switch (keyword)
1210 {
1211 case DEF_VIAS_START: /* "-" keyword */
1212
1213 /* Update the record of the number of vias */
1214 /* processed and spit out a message for every 5% done. */
1215
1216 processed++;
1217
1218 /* Get via name */
1219 token = LefNextToken(f, TRUE);
1220 if (sscanf(token, "%2047s", vianame) != 1)
1221 {
1222 LefError(DEF_ERROR, "Bad via statement: Need via name\n");
1223 LefEndStatement(f);
1224 break;
1225 }
1226 lefl = LefFindLayer(token);
1227 if (lefl == NULL)
1228 {
1229 lefl = (LefList)calloc(1, sizeof(lefLayer));
1230 lefl->type = -1;
1231 lefl->obsType = -1;
1232 lefl->lefClass = CLASS_VIA;
1233 lefl->info.via.area.x1 = 0.0;
1234 lefl->info.via.area.y1 = 0.0;
1235 lefl->info.via.area.x2 = 0.0;
1236 lefl->info.via.area.y2 = 0.0;
1237 lefl->info.via.area.layer = -1;
1238 lefl->info.via.cell = (GATE)NULL;
1239 lefl->info.via.lr = (DSEG)NULL;
1240 /* Note: "generated" flag only refers to vias that */
1241 /* are internally generated by qrouter. All others */
1242 /* in the DEF file are read/written verbatim. */
1243 lefl->info.via.generated = FALSE;
1244 lefl->lefName = strdup(token);
1245
1246 lefl->next = LefInfo;
1247 LefInfo = lefl;
1248 }
1249 else
1250 {
1251 LefError(DEF_WARNING, "Warning: Composite via \"%s\" "
1252 "redefined.\n", vianame);
1253 lefl = LefRedefined(lefl, vianame);
1254 }
1255
1256 /* Now do a search through the line for "+" entries */
1257 /* And process each. */
1258
1259 while ((token = LefNextToken(f, TRUE)) != NULL)
1260 {
1261 if (*token == ';') break;
1262 if (*token != '+') continue;
1263
1264 token = LefNextToken(f, TRUE);
1265 subkey = Lookup(token, via_property_keys);
1266 if (subkey < 0)
1267 {
1268 LefError(DEF_WARNING, "Unknown via property \"%s\" in "
1269 "VIAS definition; ignoring.\n", token);
1270 continue;
1271 }
1272 switch (subkey)
1273 {
1274 case DEF_VIAS_PROP_RECT:
1275 curlayer = LefReadLayer(f, FALSE);
1276 LefAddViaGeometry(f, lefl, curlayer, oscale);
1277 break;
1278 }
1279 }
1280 break;
1281
1282 case DEF_VIAS_END:
1283 if (!LefParseEndStatement(f, sname))
1284 {
1285 LefError(DEF_ERROR, "Vias END statement missing.\n");
1286 keyword = -1;
1287 }
1288 break;
1289 }
1290 if (keyword == DEF_VIAS_END) break;
1291 }
1292
1293 if (processed == total) {
1294 if (Verbose > 0)
1295 fprintf(stdout, " Processed %d vias total.\n", processed);
1296 }
1297 else
1298 LefError(DEF_WARNING, "Warning: Number of vias read (%d) does not match "
1299 "the number declared (%d).\n", processed, total);
1300 }
1301
1302 /*
1303 *------------------------------------------------------------
1304 *
1305 * DefReadBlockages --
1306 *
1307 * Read a BLOCKAGES section from a DEF file.
1308 *
1309 * Results:
1310 * None.
1311 *
1312 * Side Effects:
1313 * UserObs list is updated with the additional
1314 * obstructions.
1315 *
1316 *------------------------------------------------------------
1317 */
1318
1319 enum def_block_keys {DEF_BLOCK_START = 0, DEF_BLOCK_END};
1320
1321 static void
DefReadBlockages(FILE * f,char * sname,float oscale,int total)1322 DefReadBlockages(FILE *f, char *sname, float oscale, int total)
1323 {
1324 char *token;
1325 int keyword;
1326 int processed = 0;
1327 DSEG drect, rsrch;
1328 LefList lefl;
1329
1330 static char *blockage_keys[] = {
1331 "-",
1332 "END",
1333 NULL
1334 };
1335
1336 while ((token = LefNextToken(f, TRUE)) != NULL)
1337 {
1338 keyword = Lookup(token, blockage_keys);
1339
1340 if (keyword < 0)
1341 {
1342 LefError(DEF_WARNING, "Unknown keyword \"%s\" in BLOCKAGE "
1343 "definition; ignoring.\n", token);
1344 LefEndStatement(f);
1345 continue;
1346 }
1347 switch (keyword)
1348 {
1349 case DEF_BLOCK_START: /* "-" keyword */
1350
1351 /* Update the record of the number of components */
1352 /* processed and spit out a message for every 5% done. */
1353
1354 processed++;
1355
1356 /* Get layer name */
1357 token = LefNextToken(f, TRUE);
1358 lefl = LefFindLayer(token);
1359 if (lefl != NULL)
1360 {
1361 drect = LefReadGeometry(NULL, f, oscale);
1362 if (UserObs == NULL)
1363 UserObs = drect;
1364 else {
1365 for (rsrch = UserObs; rsrch->next; rsrch = rsrch->next);
1366 rsrch->next = drect;
1367 }
1368 }
1369 else
1370 {
1371 LefError(DEF_ERROR, "Bad blockage statement: Need layer name\n");
1372 LefEndStatement(f);
1373 break;
1374 }
1375 break;
1376
1377 case DEF_BLOCK_END:
1378 if (!LefParseEndStatement(f, sname))
1379 {
1380 LefError(DEF_ERROR, "Blockage END statement missing.\n");
1381 keyword = -1;
1382 }
1383 break;
1384 }
1385 if (keyword == DEF_BLOCK_END) break;
1386 }
1387
1388 if (processed == total) {
1389 if (Verbose > 0)
1390 fprintf(stdout, " Processed %d blockages total.\n", processed);
1391 }
1392 else
1393 LefError(DEF_WARNING, "Warning: Number of blockages read (%d) does not match "
1394 "the number declared (%d).\n", processed, total);
1395 }
1396
1397 /*
1398 *------------------------------------------------------------
1399 *
1400 * DefAddGateInstance --
1401 *
1402 * Add a gate instance to the list of instances and
1403 * instance hash table. The instance is assumed to
1404 * have records gatename, gatetype, placedX, and
1405 * placedY already set. The gate macro is found from
1406 * the gatetype record, and all information about the
1407 * cell macro is copied to the instance record, with
1408 * positions adjusted for the instance.
1409 *
1410 * Results:
1411 * None.
1412 *
1413 * Side Effects:
1414 * Many. Cell instances are created and added to
1415 * the database.
1416 *
1417 *------------------------------------------------------------
1418 */
1419
1420 void
DefAddGateInstance(GATE gate)1421 DefAddGateInstance(GATE gate)
1422 {
1423 GATE gateginfo;
1424 int i;
1425 DSEG drect, newrect;
1426 double tmp;
1427
1428 if (gate == NULL) return;
1429 gateginfo = gate->gatetype;
1430 if (gateginfo == NULL) return;
1431
1432 /* Process the gate */
1433 gate->width = gateginfo->width;
1434 gate->height = gateginfo->height;
1435 gate->nodes = gateginfo->nodes;
1436 gate->nomirror = gateginfo->nomirror;
1437 gate->obs = (DSEG)NULL;
1438
1439 gate->taps = (DSEG *)malloc(gate->nodes * sizeof(DSEG));
1440 gate->noderec = (NODE *)malloc(gate->nodes * sizeof(NODE));
1441 gate->direction = (u_char *)malloc(gate->nodes * sizeof(u_char));
1442 gate->area = (float *)malloc(gate->nodes * sizeof(float));
1443 gate->netnum = (int *)malloc(gate->nodes * sizeof(int));
1444 gate->node = (char **)malloc(gate->nodes * sizeof(char *));
1445
1446 /* Let the node names point to the master cell; */
1447 /* this is just diagnostic; allows us, for */
1448 /* instance, to identify vdd and gnd nodes, so */
1449 /* we don't complain about them being */
1450 /* disconnected. */
1451
1452 for (i = 0; i < gate->nodes; i++) {
1453 gate->node[i] = gateginfo->node[i]; /* copy pointer */
1454 gate->direction[i] = gateginfo->direction[i]; /* copy */
1455 gate->area[i] = gateginfo->area[i];
1456 gate->taps[i] = (DSEG)NULL;
1457 gate->netnum[i] = 0; /* Until we read NETS */
1458 gate->noderec[i] = NULL;
1459
1460 /* Make a copy of the gate nodes and adjust for */
1461 /* instance position and number of layers */
1462
1463 for (drect = gateginfo->taps[i]; drect; drect = drect->next) {
1464 newrect = (DSEG)malloc(sizeof(struct dseg_));
1465 *newrect = *drect;
1466 newrect->next = gate->taps[i];
1467 gate->taps[i] = newrect;
1468 }
1469
1470 for (drect = gate->taps[i]; drect; drect = drect->next) {
1471 // handle offset from gate origin
1472 drect->x1 -= gateginfo->placedX;
1473 drect->x2 -= gateginfo->placedX;
1474 drect->y1 -= gateginfo->placedY;
1475 drect->y2 -= gateginfo->placedY;
1476
1477 // handle rotations and orientations here
1478 if (gate->orient & MX) {
1479 tmp = drect->x1;
1480 drect->x1 = -drect->x2;
1481 drect->x1 += gate->placedX + gateginfo->width;
1482 drect->x2 = -tmp;
1483 drect->x2 += gate->placedX + gateginfo->width;
1484 }
1485 else {
1486 drect->x1 += gate->placedX;
1487 drect->x2 += gate->placedX;
1488 }
1489 if (gate->orient & MY) {
1490 tmp = drect->y1;
1491 drect->y1 = -drect->y2;
1492 drect->y1 += gate->placedY + gateginfo->height;
1493 drect->y2 = -tmp;
1494 drect->y2 += gate->placedY + gateginfo->height;
1495 }
1496 else {
1497 drect->y1 += gate->placedY;
1498 drect->y2 += gate->placedY;
1499 }
1500 }
1501 }
1502
1503 /* Make a copy of the gate obstructions and adjust */
1504 /* for instance position */
1505 for (drect = gateginfo->obs; drect; drect = drect->next) {
1506 newrect = (DSEG)malloc(sizeof(struct dseg_));
1507 *newrect = *drect;
1508 newrect->next = gate->obs;
1509 gate->obs = newrect;
1510 }
1511
1512 for (drect = gate->obs; drect; drect = drect->next) {
1513 drect->x1 -= gateginfo->placedX;
1514 drect->x2 -= gateginfo->placedX;
1515 drect->y1 -= gateginfo->placedY;
1516 drect->y2 -= gateginfo->placedY;
1517
1518 // handle rotations and orientations here
1519 if (gate->orient & MX) {
1520 tmp = drect->x1;
1521 drect->x1 = -drect->x2;
1522 drect->x1 += gate->placedX + gateginfo->width;
1523 drect->x2 = -tmp;
1524 drect->x2 += gate->placedX + gateginfo->width;
1525 }
1526 else {
1527 drect->x1 += gate->placedX;
1528 drect->x2 += gate->placedX;
1529 }
1530 if (gate->orient & MY) {
1531 tmp = drect->y1;
1532 drect->y1 = -drect->y2;
1533 drect->y1 += gate->placedY + gateginfo->height;
1534 drect->y2 = -tmp;
1535 drect->y2 += gate->placedY + gateginfo->height;
1536 }
1537 else {
1538 drect->y1 += gate->placedY;
1539 drect->y2 += gate->placedY;
1540 }
1541 }
1542 gate->next = Nlgates;
1543 gate->last = (GATE)NULL;
1544 if (Nlgates) Nlgates->last = gate;
1545 Nlgates = gate;
1546 Numgates++;
1547
1548 // Used by Tcl version of qrouter
1549 DefHashInstance(gate);
1550 }
1551
1552 /*
1553 *------------------------------------------------------------
1554 *
1555 * DefReadComponents --
1556 *
1557 * Read a COMPONENTS section from a DEF file.
1558 *
1559 * Results:
1560 * 0 on success, 1 on fatal error.
1561 *
1562 * Side Effects:
1563 * Many. Cell instances are created and added to
1564 * the database.
1565 *
1566 *------------------------------------------------------------
1567 */
1568
1569 enum def_comp_keys {DEF_COMP_START = 0, DEF_COMP_END};
1570 enum def_prop_keys {
1571 DEF_PROP_FIXED = 0, DEF_PROP_COVER,
1572 DEF_PROP_PLACED, DEF_PROP_UNPLACED,
1573 DEF_PROP_SOURCE, DEF_PROP_WEIGHT, DEF_PROP_FOREIGN,
1574 DEF_PROP_REGION, DEF_PROP_GENERATE, DEF_PROP_PROPERTY,
1575 DEF_PROP_EEQMASTER};
1576
1577 static int
DefReadComponents(FILE * f,char * sname,float oscale,int total)1578 DefReadComponents(FILE *f, char *sname, float oscale, int total)
1579 {
1580 GATE gateginfo;
1581 GATE gate = NULL;
1582 char *token;
1583 char usename[512];
1584 int keyword, subkey, i;
1585 int processed = 0;
1586 char OK;
1587 int err_fatal = 0;
1588
1589 static char *component_keys[] = {
1590 "-",
1591 "END",
1592 NULL
1593 };
1594
1595 static char *property_keys[] = {
1596 "FIXED",
1597 "COVER",
1598 "PLACED",
1599 "UNPLACED",
1600 "SOURCE",
1601 "WEIGHT",
1602 "FOREIGN",
1603 "REGION",
1604 "GENERATE",
1605 "PROPERTY",
1606 "EEQMASTER",
1607 NULL
1608 };
1609
1610 while ((token = LefNextToken(f, TRUE)) != NULL)
1611 {
1612 keyword = Lookup(token, component_keys);
1613
1614 if (keyword < 0)
1615 {
1616 LefError(DEF_WARNING, "Unknown keyword \"%s\" in COMPONENT "
1617 "definition; ignoring.\n", token);
1618 LefEndStatement(f);
1619 continue;
1620 }
1621 switch (keyword)
1622 {
1623 case DEF_COMP_START: /* "-" keyword */
1624
1625 /* Update the record of the number of components */
1626 /* processed and spit out a message for every 5% done. */
1627
1628 processed++;
1629
1630 /* Get use and macro names */
1631 token = LefNextToken(f, TRUE);
1632 if (sscanf(token, "%511s", usename) != 1)
1633 {
1634 LefError(DEF_ERROR, "Bad component statement: Need use "
1635 "and macro names\n");
1636 LefEndStatement(f);
1637 err_fatal++;
1638 break;
1639 }
1640 token = LefNextToken(f, TRUE);
1641
1642 // Watch for backslash-escaped instance names that have
1643 // been sanitized for use in SPICE netlists with an
1644 // extra backslash replacing the space, which needs to
1645 // be converted back.
1646
1647 if (*usename == '\\') {
1648 char *sptr, *bptr;
1649 sptr = strchr(usename, ' ');
1650 if (sptr == NULL) {
1651 bptr = strrchr(usename + 1, '\\');
1652 if (bptr != NULL) *bptr = ' ';
1653 }
1654 }
1655
1656 /* Find the corresponding macro */
1657 OK = 0;
1658 for (gateginfo = GateInfo; gateginfo; gateginfo = gateginfo->next) {
1659 if (!strcasecmp(gateginfo->gatename, token)) {
1660 OK = 1;
1661 break;
1662 }
1663 }
1664 if (!OK) {
1665 LefError(DEF_ERROR, "Could not find a macro definition for \"%s\"\n",
1666 token);
1667 gate = NULL;
1668 err_fatal++;
1669 }
1670 else {
1671 gate = (GATE)malloc(sizeof(struct gate_));
1672 gate->gatename = strdup(usename);
1673 gate->gatetype = gateginfo;
1674 gate->nomirror = FALSE;
1675 gate->clientdata = (void *)NULL;
1676 }
1677
1678 /* Now do a search through the line for "+" entries */
1679 /* And process each. */
1680
1681 while ((token = LefNextToken(f, TRUE)) != NULL)
1682 {
1683 if (*token == ';') break;
1684 if (*token != '+') continue;
1685
1686 token = LefNextToken(f, TRUE);
1687 subkey = Lookup(token, property_keys);
1688 if (subkey < 0)
1689 {
1690 LefError(DEF_WARNING, "Unknown component property \"%s\" in "
1691 "COMPONENT definition; ignoring.\n", token);
1692 continue;
1693 }
1694 switch (subkey)
1695 {
1696 case DEF_PROP_PLACED:
1697 case DEF_PROP_UNPLACED:
1698 case DEF_PROP_FIXED:
1699 case DEF_PROP_COVER:
1700 DefReadLocation(gate, f, oscale);
1701 break;
1702 case DEF_PROP_SOURCE:
1703 case DEF_PROP_WEIGHT:
1704 case DEF_PROP_FOREIGN:
1705 case DEF_PROP_REGION:
1706 case DEF_PROP_GENERATE:
1707 case DEF_PROP_PROPERTY:
1708 case DEF_PROP_EEQMASTER:
1709 token = LefNextToken(f, TRUE);
1710 break;
1711 }
1712 }
1713 DefAddGateInstance(gate);
1714 break;
1715
1716 case DEF_COMP_END:
1717 if (!LefParseEndStatement(f, sname))
1718 {
1719 LefError(DEF_ERROR, "Component END statement missing.\n");
1720 keyword = -1;
1721 err_fatal++;
1722 }
1723
1724 /* Finish final call by placing the cell use */
1725 if ((total > 0) && (gate != NULL))
1726 {
1727 // Nothing to do. . . gate has already been placed in list.
1728 gate = NULL;
1729 }
1730 break;
1731 }
1732 if (keyword == DEF_COMP_END) break;
1733 }
1734
1735 if (processed == total) {
1736 if (Verbose > 0)
1737 fprintf(stdout, " Processed %d subcell instances total.\n", processed);
1738 }
1739 else
1740 LefError(DEF_WARNING, "Warning: Number of subcells read (%d) does not match "
1741 "the number declared (%d).\n", processed, total);
1742 return err_fatal;
1743 }
1744
1745 /*
1746 *------------------------------------------------------------
1747 *
1748 * DefRead --
1749 *
1750 * Read a .def file and parse die area, track positions,
1751 * components, pins, and nets.
1752 *
1753 * Results:
1754 * Returns the units scale, so the routed output can be
1755 * scaled to match the DEF file header.
1756 *
1757 * Side Effects:
1758 * Many.
1759 *
1760 *------------------------------------------------------------
1761 */
1762
1763 /* Enumeration of sections defined in DEF files */
1764
1765 enum def_sections {DEF_VERSION = 0, DEF_NAMESCASESENSITIVE,
1766 DEF_UNITS, DEF_DESIGN, DEF_REGIONS, DEF_ROW, DEF_TRACKS,
1767 DEF_GCELLGRID, DEF_DIVIDERCHAR, DEF_BUSBITCHARS,
1768 DEF_PROPERTYDEFINITIONS, DEF_DEFAULTCAP, DEF_TECHNOLOGY,
1769 DEF_HISTORY, DEF_DIEAREA, DEF_COMPONENTS, DEF_VIAS,
1770 DEF_PINS, DEF_PINPROPERTIES, DEF_SPECIALNETS,
1771 DEF_NETS, DEF_IOTIMINGS, DEF_SCANCHAINS, DEF_BLOCKAGES,
1772 DEF_CONSTRAINTS, DEF_GROUPS, DEF_EXTENSION,
1773 DEF_END};
1774
1775 int
DefRead(char * inName,float * retscale)1776 DefRead(char *inName, float *retscale)
1777 {
1778 FILE *f;
1779 char filename[256];
1780 char namepos[32];
1781 char *token;
1782 int keyword, dscale, total;
1783 int curlayer = -1, channels;
1784 int i;
1785 int err_fatal = 0;
1786 float oscale;
1787 double start, step;
1788 double llx, lly, urx, ury, locpitch;
1789 double dXlowerbound, dYlowerbound, dXupperbound, dYupperbound;
1790 char corient = '.';
1791 DSEG diearea;
1792 ROW newrow;
1793
1794 static char *orientations[] = {
1795 "N", "S", "E", "W", "FN", "FS", "FE", "FW"
1796 };
1797 static int oflags[] = {
1798 RN, RS, RE, RW, RN | RF, RS | RF, RE | RF, RW | RF
1799 };
1800
1801 static char *sections[] = {
1802 "VERSION",
1803 "NAMESCASESENSITIVE",
1804 "UNITS",
1805 "DESIGN",
1806 "REGIONS",
1807 "ROW",
1808 "TRACKS",
1809 "GCELLGRID",
1810 "DIVIDERCHAR",
1811 "BUSBITCHARS",
1812 "PROPERTYDEFINITIONS",
1813 "DEFAULTCAP",
1814 "TECHNOLOGY",
1815 "HISTORY",
1816 "DIEAREA",
1817 "COMPONENTS",
1818 "VIAS",
1819 "PINS",
1820 "PINPROPERTIES",
1821 "SPECIALNETS",
1822 "NETS",
1823 "IOTIMINGS",
1824 "SCANCHAINS",
1825 "BLOCKAGES",
1826 "CONSTRAINTS",
1827 "GROUPS",
1828 "BEGINEXT",
1829 "END",
1830 NULL
1831 };
1832
1833 if (!strrchr(inName, '.'))
1834 sprintf(filename, "%s.def", inName);
1835 else
1836 strcpy(filename, inName);
1837
1838 f = fopen(filename, "r");
1839
1840 if (f == NULL)
1841 {
1842 fprintf(stderr, "Cannot open input file: ");
1843 perror(filename);
1844 *retscale = (float)0.0;
1845 return 1;
1846 }
1847
1848 /* Initialize */
1849
1850 if (Verbose > 0) {
1851 fprintf(stdout, "Reading DEF data from file %s.\n", filename);
1852 fflush(stdout);
1853 }
1854
1855 oscale = 1;
1856 lefCurrentLine = 0;
1857
1858 DefHashInit();
1859
1860 /* Read file contents */
1861
1862 while ((token = LefNextToken(f, TRUE)) != NULL)
1863 {
1864 keyword = Lookup(token, sections);
1865 if (keyword < 0)
1866 {
1867 LefError(DEF_WARNING, "Unknown keyword \"%s\" in DEF file; "
1868 "ignoring.\n", token);
1869 LefEndStatement(f);
1870 continue;
1871 }
1872 if (keyword != DEF_TRACKS) corient = '.';
1873
1874 switch (keyword)
1875 {
1876 case DEF_VERSION:
1877 LefEndStatement(f);
1878 break;
1879 case DEF_NAMESCASESENSITIVE:
1880 LefEndStatement(f);
1881 break;
1882 case DEF_TECHNOLOGY:
1883 token = LefNextToken(f, TRUE);
1884 if (Verbose > 0)
1885 fprintf(stdout, "Diagnostic: DEF file technology: \"%s\"\n",
1886 token);
1887 LefEndStatement(f);
1888 break;
1889 case DEF_REGIONS:
1890 LefSkipSection(f, sections[DEF_REGIONS]);
1891 break;
1892 case DEF_DESIGN:
1893 token = LefNextToken(f, TRUE);
1894 if (Verbose > 0)
1895 fprintf(stdout, "Diagnostic: Design name: \"%s\"\n", token);
1896 DEFDesignName = strdup(token);
1897 LefEndStatement(f);
1898 break;
1899 case DEF_UNITS:
1900 token = LefNextToken(f, TRUE);
1901 token = LefNextToken(f, TRUE);
1902 token = LefNextToken(f, TRUE);
1903 if (sscanf(token, "%d", &dscale) != 1)
1904 {
1905 LefError(DEF_ERROR, "Invalid syntax for UNITS statement.\n");
1906 LefError(DEF_WARNING, "Assuming default value of 100\n");
1907 dscale = 100;
1908 }
1909 /* We don't care if the scale is 100, 200, 1000, or 2000. */
1910 /* Do we need to deal with numeric roundoff issues? */
1911 oscale *= (float)dscale;
1912 LefEndStatement(f);
1913 break;
1914 case DEF_ROW:
1915 newrow = (ROW)malloc(sizeof(struct row_));
1916 token = LefNextToken(f, TRUE);
1917 newrow->rowname = strdup(token);
1918 token = LefNextToken(f, TRUE);
1919 newrow->sitename = strdup(token);
1920 token = LefNextToken(f, TRUE);
1921 sscanf(token, "%d", &newrow->x);
1922 token = LefNextToken(f, TRUE);
1923 sscanf(token, "%d", &newrow->y);
1924 token = LefNextToken(f, TRUE);
1925 keyword = Lookup(token, orientations);
1926 if (keyword < 0)
1927 newrow->orient = 0;
1928 else
1929 newrow->orient = oflags[keyword];
1930 token = LefNextToken(f, TRUE); /* skip "DO" */
1931 token = LefNextToken(f, TRUE);
1932 sscanf(token, "%d", &newrow->xnum);
1933 token = LefNextToken(f, TRUE); /* skip "BY" */
1934 token = LefNextToken(f, TRUE);
1935 sscanf(token, "%d", &newrow->ynum);
1936 token = LefNextToken(f, TRUE); /* skip "STEP" */
1937 token = LefNextToken(f, TRUE);
1938 sscanf(token, "%d", &newrow->xstep);
1939 token = LefNextToken(f, TRUE);
1940 sscanf(token, "%d", &newrow->ystep);
1941 sprintf(namepos, "%d", newrow->y);
1942 HashPtrInstall(namepos, newrow, &RowTable);
1943 LefEndStatement(f);
1944 break;
1945 case DEF_TRACKS:
1946 token = LefNextToken(f, TRUE);
1947 if (strlen(token) != 1) {
1948 LefError(DEF_ERROR, "Problem parsing track orientation (X or Y).\n");
1949 }
1950 corient = tolower(token[0]); // X or Y
1951 token = LefNextToken(f, TRUE);
1952 if (sscanf(token, "%lg", &start) != 1) {
1953 LefError(DEF_ERROR, "Problem parsing track start position.\n");
1954 err_fatal++;
1955 }
1956 token = LefNextToken(f, TRUE);
1957 if (strcmp(token, "DO")) {
1958 LefError(DEF_ERROR, "TRACKS missing DO loop.\n");
1959 err_fatal++;
1960 }
1961 token = LefNextToken(f, TRUE);
1962 if (sscanf(token, "%d", &channels) != 1) {
1963 LefError(DEF_ERROR, "Problem parsing number of track channels.\n");
1964 err_fatal++;
1965 }
1966 token = LefNextToken(f, TRUE);
1967 if (strcmp(token, "STEP")) {
1968 LefError(DEF_ERROR, "TRACKS missing STEP size.\n");
1969 err_fatal++;
1970 }
1971 token = LefNextToken(f, TRUE);
1972 if (sscanf(token, "%lg", &step) != 1) {
1973 LefError(DEF_ERROR, "Problem parsing track step size.\n");
1974 err_fatal++;
1975 }
1976 token = LefNextToken(f, TRUE);
1977 if (!strcmp(token, "LAYER")) {
1978 curlayer = LefReadLayer(f, FALSE);
1979 }
1980 if (corient == 'x') {
1981 locpitch = step / oscale;
1982 if ((PitchX == 0.0) || ((locpitch < PitchX) && (locpitch != 0)))
1983 PitchX = locpitch;
1984 llx = start;
1985 urx = start + step * channels;
1986 if ((llx / oscale) < Xlowerbound)
1987 Xlowerbound = llx / oscale;
1988 if ((urx / oscale) > Xupperbound)
1989 Xupperbound = urx / oscale;
1990 }
1991 else {
1992 locpitch = step / oscale;
1993 if ((PitchY == 0.0) || ((locpitch < PitchY) && (locpitch != 0)))
1994 PitchY = locpitch;
1995 lly = start;
1996 ury = start + step * channels;
1997 if ((lly / oscale) < Ylowerbound)
1998 Ylowerbound = lly / oscale;
1999 if ((ury / oscale) > Yupperbound)
2000 Yupperbound = ury / oscale;
2001 }
2002 LefEndStatement(f);
2003 break;
2004 case DEF_GCELLGRID:
2005 LefEndStatement(f);
2006 break;
2007 case DEF_DIVIDERCHAR:
2008 LefEndStatement(f);
2009 break;
2010 case DEF_BUSBITCHARS:
2011 LefEndStatement(f);
2012 break;
2013 case DEF_HISTORY:
2014 LefEndStatement(f);
2015 break;
2016 case DEF_DIEAREA:
2017 diearea = LefReadRect(f, 0, oscale); // no current layer, use 0
2018 dXlowerbound = diearea->x1;
2019 dYlowerbound = diearea->y1;
2020 dXupperbound = diearea->x2;
2021 dYupperbound = diearea->y2;
2022 /* Seed actual lower/upper bounds with the midpoint */
2023 Xlowerbound = (diearea->x1 + diearea->x2) / 2;
2024 Ylowerbound = (diearea->y1 + diearea->y2) / 2;
2025 Xupperbound = Xlowerbound;
2026 Yupperbound = Ylowerbound;
2027 LefEndStatement(f);
2028 break;
2029 case DEF_PROPERTYDEFINITIONS:
2030 LefSkipSection(f, sections[DEF_PROPERTYDEFINITIONS]);
2031 break;
2032 case DEF_DEFAULTCAP:
2033 LefSkipSection(f, sections[DEF_DEFAULTCAP]);
2034 break;
2035 case DEF_COMPONENTS:
2036 token = LefNextToken(f, TRUE);
2037 if (sscanf(token, "%d", &total) != 1) total = 0;
2038 LefEndStatement(f);
2039 err_fatal += DefReadComponents(f, sections[DEF_COMPONENTS], oscale, total);
2040 break;
2041 case DEF_BLOCKAGES:
2042 token = LefNextToken(f, TRUE);
2043 if (sscanf(token, "%d", &total) != 1) total = 0;
2044 LefEndStatement(f);
2045 DefReadBlockages(f, sections[DEF_BLOCKAGES], oscale, total);
2046 break;
2047 case DEF_VIAS:
2048 token = LefNextToken(f, TRUE);
2049 if (sscanf(token, "%d", &total) != 1) total = 0;
2050 LefEndStatement(f);
2051 DefReadVias(f, sections[DEF_VIAS], oscale, total);
2052 break;
2053 case DEF_PINS:
2054 token = LefNextToken(f, TRUE);
2055 if (sscanf(token, "%d", &total) != 1) total = 0;
2056 LefEndStatement(f);
2057 DefReadPins(f, sections[DEF_PINS], oscale, total);
2058 break;
2059 case DEF_PINPROPERTIES:
2060 LefSkipSection(f, sections[DEF_PINPROPERTIES]);
2061 break;
2062 case DEF_SPECIALNETS:
2063 token = LefNextToken(f, TRUE);
2064 if (sscanf(token, "%d", &total) != 1) total = 0;
2065 LefEndStatement(f);
2066 numSpecial = DefReadNets(f, sections[DEF_SPECIALNETS], oscale, TRUE,
2067 total);
2068 break;
2069 case DEF_NETS:
2070 token = LefNextToken(f, TRUE);
2071 if (sscanf(token, "%d", &total) != 1) total = 0;
2072 LefEndStatement(f);
2073 DefReadNets(f, sections[DEF_NETS], oscale, FALSE, total);
2074 break;
2075 case DEF_IOTIMINGS:
2076 LefSkipSection(f, sections[DEF_IOTIMINGS]);
2077 break;
2078 case DEF_SCANCHAINS:
2079 LefSkipSection(f, sections[DEF_SCANCHAINS]);
2080 break;
2081 case DEF_CONSTRAINTS:
2082 LefSkipSection(f, sections[DEF_CONSTRAINTS]);
2083 break;
2084 case DEF_GROUPS:
2085 LefSkipSection(f, sections[DEF_GROUPS]);
2086 break;
2087 case DEF_EXTENSION:
2088 LefSkipSection(f, sections[DEF_EXTENSION]);
2089 break;
2090 case DEF_END:
2091 if (!LefParseEndStatement(f, "DESIGN"))
2092 {
2093 LefError(DEF_ERROR, "END statement out of context.\n");
2094 keyword = -1;
2095 }
2096 break;
2097 }
2098 if (keyword == DEF_END) break;
2099 }
2100 if (Verbose > 0)
2101 fprintf(stdout, "DEF read: Processed %d lines.\n", lefCurrentLine);
2102 LefError(DEF_ERROR, NULL); /* print statement of errors, if any, and reset */
2103
2104 /* If there were no TRACKS statements, then use the DIEAREA */
2105 if (Xlowerbound == Xupperbound) {
2106 Xlowerbound = dXlowerbound;
2107 Xupperbound = dXupperbound;
2108 }
2109 if (Ylowerbound == Yupperbound) {
2110 Ylowerbound = dYlowerbound;
2111 Yupperbound = dYupperbound;
2112 }
2113
2114 /* Cleanup */
2115
2116 if (f != NULL) fclose(f);
2117 *retscale = oscale;
2118 return err_fatal;
2119 }
2120