1 /*--------------------------------------------------------------*/
2 /* vesta.c ---                                                  */
3 /*                                                              */
4 /*      This file reads two files:  (1) A verilog netlist file  */
5 /*      of a circuit (structural verilog, that is, gate-level   */
6 /*      information only), and (2) a liberty format file        */
7 /*      containing timing information for the standard cell     */
8 /*      macros instantiated in the verilog netlist.  In         */
9 /*      addition, it may take an optional third file containing */
10 /*      information about the resistance and capacitance of the */
11 /*      wiring (see below).                                     */
12 /*                                                              */
13 /*      Options are supplied as command-line arguments:         */
14 /*                                                              */
15 /*              -d <delay_file> Wiring delays (see below)       */
16 /*              -p <value>      Clock period, in ps             */
17 /*              -l <value>      Output load, in fF              */
18 /*              -v <level>      set verbose mode                */
19 /*              -D <level>      set debug mode                  */
20 /*              -V              report version number           */
21 /*		-n <number>	number of paths to print	*/
22 /*		-L 		Long format (print paths)	*/
23 /*              -e              exhaustive search               */
24 /*		-s <file>	summary file or directory	*/
25 /*		-c		cleanup of net name syntax	*/
26 /*                                                              */
27 /*      Currently the only output this tool generates is a      */
28 /*      list of paths with negative slack.  If no paths have    */
29 /*      negative slack, then the 20 paths with the smallest     */
30 /*      positive slack are output, following a "success"        */
31 /*      message.  If no clock period is supplied, then the      */
32 /*      clock period is set to equal the delay of the longest   */
33 /*      delay path, and the 20 paths with the smallest positive */
34 /*      slack are output, following a statement indicated the   */
35 /*      computed minimum clock period.                          */
36 /*								*/
37 /*	Debug level (developer diagnostics):			*/
38 /*	    Not cumulative.  Each number does something unique.	*/
39 /*		1:  Print delay file parsing information	*/
40 /*		2:  Print liberty file parsing information	*/
41 /*								*/
42 /*	Verbose level (user diagnostics):			*/
43 /*	    Cumulative.  The higher the number, the more	*/
44 /* 	    output is generated.				*/
45 /*		1: Report on total lines processed.		*/
46 /*		2: Report on each path processed.		*/
47 /*		3: Report on verilog source file		*/
48 /*		4: Report on liberty file			*/
49 /*--------------------------------------------------------------*/
50 /*	(c) 2013-2019 Tim Edwards, Open Circuit Design		*/
51 /*	Released under GPL as part of the qflow package		*/
52 /*--------------------------------------------------------------*/
53 
54 /*--------------------------------------------------------------*/
55 /*      Wiring delay file:                                      */
56 /*      For qflow, the wiring delay is generated by the tool    */
57 /*      "def2delays".  The file format is as follows:           */
58 /*                                                              */
59 /*      <net_name>                                              */
60 /*      <output_terminal>  <net_capacitance>                    */
61 /*      <input_terminal_1> <delay_1>                            */
62 /*      ...                                                     */
63 /*      <input_terminal_N> <delay_N>                            */
64 /*                                                              */
65 /*      -<net_capacitance> is in pF                             */
66 /*      -Values <delay_i> are in ps                             */
67 /*      -<input_terminal_N> line *must* be following by a blank */
68 /*       line                                                   */
69 /*--------------------------------------------------------------*/
70 
71 #include <stdio.h>
72 #include <stdlib.h>
73 #include <ctype.h>
74 #include <string.h>
75 #include <errno.h>
76 #include <stdarg.h>
77 #include <sys/types.h>	// For mkdir()
78 #include <sys/stat.h>	// For mkdir()
79 #include <math.h>       // Temporary, for fabs()
80 #include "hash.h"       // For net hash table
81 #include "readverilog.h"
82 
83 #define LIB_LINE_MAX  65535
84 
85 #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__)
86 // Linux defines a comparison function prototype, the Mac doesn't. . .
87 typedef int (*__compar_fn_t)(const void *, const void *);
88 #endif
89 
90 int fileCurrentLine;
91 
92 // Analysis types --- note that maximum flop-to-flop delay
93 // requires calculating minimum clock skew time, and vice
94 // versa, so it is necessary that these have TRUE/FALSE
95 // values.
96 
97 #define MINIMUM_TIME    0
98 #define MAXIMUM_TIME    1
99 
100 #define INITVAL		-1.0E50		/* Value to detect uninitialized delay */
101 
102 // Multiple-use definition
103 #define UNKNOWN         -1
104 
105 // Sections of liberty file
106 #define INIT            0
107 #define LIBBLOCK        1
108 #define CELLDEF         2
109 #define PINDEF          3
110 #define FLOPDEF         4
111 #define LATCHDEF        5
112 #define TIMING          6
113 
114 // Sections of verilog file
115 #define MODULE          0
116 #define IOINLINE        1
117 #define IOLIST          2
118 #define GATELIST        3
119 #define INSTANCE        4
120 #define INSTPIN         5
121 #define PINCONN         6
122 
123 // Pin types (these are masks---e.g., a pin can be an INPUT and a CLOCK)
124 #define INPUT           0x01    // The default
125 #define OUTPUT          0x02
126 #define DFFCLK          0x04
127 #define DFFIN           0x08    // Flop input
128 #define DFFOUT          0x10    // Flop output
129 #define DFFSET          0x20    // Flop set (preset)
130 #define DFFRST          0x40    // Flop reset (clear)
131 #define LATCHIN         0x80    // Latch input
132 #define LATCHEN         0x100   // Latch enable
133 #define LATCHOUT        0x200   // Latch output
134 
135 // Timing type (for tables)
136 
137 #define TIMING_PROP_TRANS       0
138 #define TIMING_HOLD             1
139 #define TIMING_SETUP            2
140 #define TIMING_SET_RESET        3
141 #define TIMING_RECOVERY         4
142 #define TIMING_REMOVAL          5
143 #define TIMING_TRISTATE         6
144 
145 // A few short-hand definitions
146 #define DFF_ALL_IN      (DFFCLK | DFFIN | DFFSET | DFFRST)
147 #define LATCH_ALL_IN    (LATCHIN | LATCHEN)
148 
149 #define DFF_IN_NOT_CLK  (DFFIN | DFFSET | DFFRST)
150 #define LATCH_IN_NOT_EN (LATCHIN)
151 
152 #define REGISTER_IN     (DFF_ALL_IN | LATCH_ALL_IN)
153 #define REG_IN_NOT_CLK  (DFF_IN_NOT_CLK | LATCH_IN_NOT_EN)
154 
155 #define IOMASK          0x03
156 #define DFFMASK         0x7c
157 #define LATCHMASK       0x180
158 
159 // Pin sense
160 #define SENSE_UNKNOWN   0       // Sense unknown
161 #define SENSE_NONE      1       // Non-unate
162 #define SENSE_POSITIVE  2       // Positive-unate
163 #define SENSE_NEGATIVE  3       // Negative-unate
164 
165 // Signal transition direction
166 #define EDGE_UNKNOWN    0
167 #define RISING          1
168 #define FALLING         2
169 #define EITHER          3
170 
171 // Function translation
172 #define GROUPBEGIN      1
173 #define GROUPEND        2
174 #define SIGNAL          3
175 #define OPERATOR        4
176 #define XOPERATOR       5
177 #define SEPARATOR       6
178 
179 // Net types
180 #define NET             0x00    // Ordinary net (default)
181 #define CLOCK           0x01    // Clock net (path start)
182 #define OUTTERM         0x02    // Module output
183 #define ASYNC           0x04    // Asynchronous set/reset
184 #define TERMINAL        0x08    // DFF input (path terminal)
185 #define LATCHTERM       0x10    // Latch input (dependent path terminal)
186 #define ENABLE          0x20    // Latch enable (path start)
187 
188 // Cell types
189 #define GATE            0x00    // Combinatorial gate (default)
190 #define DFF             0x01    // Flip-flop (shared bit field)
191 #define CLK_SENSE_MASK  0x02    // Clock edge mask (0=positive, 1=negative)
192 #define RST_MASK        0x04    // Reset mask (0=no reset, 1=reset)
193 #define RST_SENSE_MASK  0x08    // Reset edge mask (0=positive, 1=negative)
194 #define SET_MASK        0x10    // Set mask (0=no set, 1=set)
195 #define SET_SENSE_MASK  0x20    // Set edge mask (0=positive, 1=negative)
196 #define LATCH           0x40    // Latch type
197 #define EN_SENSE_MASK   0x80    // Latch enable edge mask (0=positive, 1=negative)
198 
199 // Some names for cell types based on masks
200 
201 #define DFFCP           0x01    // Pos clock
202 #define DFFCN           0x03    // Neg clock
203 #define DFFCPRP         0x05    // Pos clock, Pos reset
204 #define DFFCNRP         0x07    // Neg clock, Pos reset
205 #define DFFCPRN         0x0d    // Pos clock, Neg reset
206 #define DFFCNRN         0x0f    // Neg clock, Neg reset
207 #define DFFCPSP         0x11    // Pos clock, Pos set
208 #define DFFCNSP         0x13    // Neg clock, Pos set
209 #define DFFCPRPSP       0x15    // Pos clock, Pos reset, Pos set
210 #define DFFCNRPSP       0x17    // Neg clock, Pos reset, Pos set
211 #define DFFCPRNSP       0x1d    // Pos clock, Neg reset, Pos set
212 #define DFFCNRNSP       0x1f    // Neg clock, Neg reset, Pos set
213 #define DFFCPSN         0x31    // Pos clock, Neg set
214 #define DFFCNSN         0x33    // Neg clock, Neg set
215 #define DFFCPRPSN       0x35    // Pos clock, Pos reset, Neg set
216 #define DFFCNRPSN       0x37    // Neg clock, Pos reset, Neg set
217 #define DFFCPRNSN       0x3d    // Pos clock, Neg reset, Neg set
218 #define DFFCNRNSN       0x3f    // Neg clock, Neg reset, Neg set
219 
220 /*--------------------------------------------------------------*/
221 /* Liberty file database                                        */
222 /*--------------------------------------------------------------*/
223 
224 // Types of array
225 
226 // Array type 1:  Propagation time
227 #define OUTPUT_CAP              0
228 #define TRANSITION_TIME         1
229 
230 // Array type 2:  Setup, hold, recovery, removal times
231 #define RELATED_TIME            2
232 #define CONSTRAINED_TIME        3
233 
234 typedef struct _lutable *lutableptr;
235 
236 typedef struct _lutable {
237     char *name;
238     char invert;        // 0 if times x caps, 1 if caps x times
239     int  var1;          // Type of array in index1
240     int  var2;          // Type of array in index2
241     int  size1;         // Number of entries in time array
242     int  size2;         // Number of entries in cap (or constrained timing) array
243     union {
244         double *times;  // Time array (units ps)
245         double *rel;    // Related pin transition time array (units ps)
246     } idx1;
247     union {
248         double *caps;   // Cap array (units fF)
249         double *cons;   // Constrained pin transition time array (units ps)
250     } idx2;
251     double *values;     // Matrix of values (used locally, not for templates)
252     lutableptr next;
253 } lutable;
254 
255 typedef struct _bustype *bustypeptr;
256 typedef struct _pin *pinptr;
257 typedef struct _cell *cellptr;
258 
259 typedef struct _bustype {
260     char *name;
261     int   from;
262     int   to;
263     bustypeptr next;
264 } bus;
265 
266 typedef struct _pin {
267     char *name;
268     short type;
269 
270     double capr;        // Capacitance for rising input
271     double capf;        // Capacitance for falling input (optional)
272 
273     short sense;        // Sense (positive-unate, negative-unate, non-unate)
274     lutable *propdelr;  // Reference table for rising output prop delay relative to driver
275     lutable *propdelf;  // Reference table for falling output prop delay relative to driver
276     lutable *transr;    // Reference table for transition rise time
277     lutable *transf;    // Reference table for transition fall time
278 
279     cellptr refcell;    // Pointer back to parent cell
280 
281     pinptr next;
282 } pin;
283 
284 typedef struct _cell {
285     short type;
286     char *name;
287     char *function;
288     pin  *pins;         /* List of input pins with timing info */
289     double area;
290     double maxtrans;    /* Maximum transition time */
291     double maxcap;      /* Maximum allowable load */
292     cellptr next;
293 } cell;
294 
295 /*--------------------------------------------------------------*/
296 /* Verilog netlist database                                     */
297 /*--------------------------------------------------------------*/
298 
299 typedef struct _net *netptr;
300 typedef struct _connect *connptr;
301 typedef struct _delaydata *ddataptr;
302 
303 typedef struct _net {
304    char *name;
305    connptr driver;
306    short type;
307    int fanout;
308    connptr *receivers;
309    double loadr;        /* Total load capacitance for rising input */
310    double loadf;        /* Total load capacitance for falling input */
311    netptr next;
312 } net;
313 
314 typedef struct _instance *instptr;
315 
316 typedef struct _connect {
317    double   metric;             /* Delay metric at connection */
318    double   icDelay;            /* interconnect delay in ps */
319    instptr  refinst;
320    pinptr   refpin;
321    netptr   refnet;
322    unsigned char visited;	/* To check for common clock points */
323    ddataptr tag;                /* Tag value for checking for loops and endpoints */
324    double   *prvector;          /* Prop delay rising (at load condition) vector */
325    double   *pfvector;          /* Prop delay falling (at load condition) vector */
326    double   *trvector;          /* Transition time rising (at load condition) vector */
327    double   *tfvector;          /* Transition time falling (at load condition) vector */
328    connptr  next;
329 } connect;
330 
331 typedef struct _instance {
332    char *name;
333    cellptr refcell;
334    connptr in_connects;
335    connptr out_connects;
336    instptr next;
337 } instance;
338 
339 // Linked list of delays (backtrace to source)
340 
341 typedef struct _btdata *btptr;
342 
343 typedef struct _btdata {
344    double  delay;       /* Propagation delay to this point */
345    double  trans;       /* Transition time at this point */
346    short   dir;         /* Edge direction at this point */
347    connptr receiver;    /* Receiver connection at end of path */
348    int     refcnt;      /* Reference counter for backtrace data */
349    btptr   next;        /* Path of propagation */
350 } btdata;
351 
352 // Linked list of backtrace records
353 
354 typedef struct _delaydata {
355    double delay;        /* Total delay, including setup and clock skew */
356    double skew;		/* Part of total delay attributed to clock skew */
357    double setup;	/* Part of total delay attributed to setup (+) or hold (-) */
358    double trans;        /* Transition time at destination, used to find setup */
359    btptr backtrace;
360    ddataptr  next;
361 } delaydata;
362 
363 // Linked list of connection pointers
364 // (Much like delaydata, but without all the timing information)
365 
366 typedef struct _connlist *connlistptr;
367 
368 typedef struct _connlist {
369    connptr connection;
370    connlistptr next;
371 } connlist;
372 
373 /* Global variables */
374 
375 unsigned char verbose;       /* Level of user output generated */
376 unsigned char debug;	     /* Level of debug output generated */
377 unsigned char exhaustive;    /* Exhaustive search mode */
378 unsigned char cleanup;       /* Clean up net name syntax */
379 
380 /*--------------------------------------------------------------*/
381 /* Grab a token from the input                                  */
382 /* Return the token, or NULL if we have reached end-of-file.    */
383 /*--------------------------------------------------------------*/
384 
385 char *
advancetoken0(FILE * flib,char delimiter,char nocontline)386 advancetoken0(FILE *flib, char delimiter, char nocontline)
387 {
388     static char *token = NULL;
389     static char line[LIB_LINE_MAX];
390     static char *linepos = NULL;
391     static int token_max_length = LIB_LINE_MAX - 5;
392 
393     char *lineptr = linepos;
394     char *lptr, *tptr;
395     char *result;
396     int commentblock, concat, nest;
397 
398     if (token == NULL) token = (char *)malloc(LIB_LINE_MAX);
399 
400     commentblock = 0;
401     concat = 0;
402     nest = 0;
403     while (1) {         /* Keep processing until we get a token or hit EOF */
404 
405         if (lineptr != NULL && *lineptr == '/' && *(lineptr + 1) == '*') {
406             commentblock = 1;
407         }
408 
409         if (commentblock == 1) {
410             if ((lptr = strstr(lineptr, "*/")) != NULL) {
411                 lineptr = lptr + 2;
412                 commentblock = 0;
413             }
414             else lineptr = NULL;
415         }
416 
417 	// Sloppy liberty spec was supposed to have ';' terminating
418 	// lines but it allows them to go missing.  Fix this by adding
419 	// semicolons to statements missing them.
420 
421 	if (lineptr && *lineptr == '\n' && delimiter == ';') *lineptr = ';';
422 
423         if (lineptr == NULL || *lineptr == '\n' || *lineptr == '\0') {
424             result = fgets(line, LIB_LINE_MAX, flib);
425             fileCurrentLine++;
426 	    if (verbose > 0) {
427 		if ((fileCurrentLine % 10000) == 0) {
428 		    fprintf(stdout, "Processed %d lines.\n", fileCurrentLine);
429 		    fflush(stdout);
430 		}
431 	    }
432             if (result == NULL) return NULL;
433 
434             /* Keep pulling stuff in if the line ends with a continuation character */
435             lptr = line;
436             while (*lptr != '\n' && *lptr != '\0') {
437                 if ((*lptr == '\\') && (nocontline == 0)) {
438                     // To be considered a line continuation marker, there must be
439                     // only whitespace or newline between the backslash and the
440                     // end of the string.
441                     char *eptr = lptr + 1;
442                     while (isblank(*eptr)) eptr++;
443                     if (*eptr == '\n') {
444                         result = fgets(lptr, LIB_LINE_MAX - (lptr - line), flib);
445                         fileCurrentLine++;
446                         if (result == NULL) break;
447                     }
448                     else
449                         lptr++;
450                 }
451                 else
452                     lptr++;
453             }
454             if (result == NULL) return NULL;
455             lineptr = line;
456         }
457 
458         if (commentblock == 1) continue;
459 
460         while (isblank(*lineptr)) lineptr++;
461         if (concat == 0)
462             tptr = token;
463 
464         // Find the next token and return just the token.  Update linepos
465         // to the position just beyond the token.  All delimiters like
466         // parentheses, quotes, etc., are returned as single tokens
467 
468         // If delimiter is declared, then we stop when we reach the
469         // delimiter character, and return all the text preceding it
470         // as the token.  If delimiter is 0, then we look for standard
471         // delimiters, and separate them out and return them as tokens
472         // if found.
473 
474         while (1) {
475             if (*lineptr == '\n' || *lineptr == '\0')
476                 break;
477             if (*lineptr == '/' && *(lineptr + 1) == '*')
478                 break;
479             if (delimiter != 0 && *lineptr == delimiter) {
480                 if (nest > 0)
481                     nest--;
482                 else
483                     break;
484             }
485 
486 	    // Watch for overruns, and allocate more memory
487 	    // for the token if needed.
488 
489 	    if ((tptr - token) > token_max_length) {
490 		char *tsave = token;
491 		token_max_length <<= 1;
492 		token = (char *)realloc(token, token_max_length);
493 		tptr += (token - tsave);
494 	    }
495 
496             // Watch for nested delimiters!
497             if (delimiter == '}' && *lineptr == '{') nest++;
498             if (delimiter == ')' && *lineptr == '(') nest++;
499 
500             if (delimiter == 0)
501                 if (*lineptr == ' ' || *lineptr == '\t')
502                     break;
503 
504             if (delimiter == 0) {
505                 if (*lineptr == '(' || *lineptr == ')') {
506                     if (tptr == token) *tptr++ = *lineptr++;
507                     break;
508                 }
509                 if (*lineptr == '{' || *lineptr == '}') {
510                     if (tptr == token) *tptr++ = *lineptr++;
511                     break;
512                 }
513                 if (*lineptr == '\"' || *lineptr == ':' || *lineptr == ';') {
514                     if (tptr == token) *tptr++ = *lineptr++;
515                     break;
516                 }
517             }
518 
519             *tptr++ = *lineptr++;
520         }
521         *tptr = '\0';
522         if ((delimiter != 0) && (*lineptr != delimiter))
523             concat = 1;
524         else if ((delimiter != 0) && (*lineptr == delimiter))
525             break;
526         else if (tptr > token)
527             break;
528     }
529     if (delimiter != 0) lineptr++;
530 
531     while (isblank(*lineptr)) lineptr++;
532     linepos = lineptr;
533 
534     // Final:  Remove trailing whitespace
535     tptr = token + strlen(token) - 1;
536     while ((tptr > token) && isblank(*tptr)) {
537         *tptr = '\0';
538         tptr--;
539     }
540     return token;
541 }
542 
543 /*--------------------------------------------------------------*/
544 /* Wrapper for advancetoken0():  Default nocontline = 0		*/
545 /*--------------------------------------------------------------*/
546 
547 char *
advancetoken(FILE * flib,char delimiter)548 advancetoken(FILE *flib, char delimiter)
549 {
550     return advancetoken0(flib, delimiter, 0);
551 }
552 
553 /*--------------------------------------------------------------*/
554 /* Wrapper for advancetoken0():  nocontline = 1	for delay file	*/
555 /*--------------------------------------------------------------*/
556 
557 char *
advancetokennocont(FILE * flib,char delimiter)558 advancetokennocont(FILE *flib, char delimiter)
559 {
560     return advancetoken0(flib, delimiter, 1);
561 }
562 
563 /*--------------------------------------------------------------*/
564 /* Wrapper around strdup() to remove any quotes from around the	*/
565 /* text being copied.						*/
566 /*--------------------------------------------------------------*/
567 
568 char *
tokendup(char * token)569 tokendup(char *token)
570 {
571     char *ss, *sf, *result;
572 
573     ss = token;
574     sf = NULL;
575     while (*ss == '\"') ss++;
576     if (ss != token) {
577         sf = ss + 1;
578 	while (*sf && (*sf != '\"')) sf++;
579 	if (*sf == '\"')
580 	    *sf = '\0';
581 	else
582 	    sf = NULL;
583     }
584 
585     result = strdup(ss);
586 
587     if (sf != NULL) *sf = '\"';
588 
589     return result;
590 }
591 
592 
593 /*--------------------------------------------------------------*/
594 /* Parse a pin name.  Check if the cell has a pin of that name, */
595 /* and if not, add the pin to the cell, giving it default       */
596 /* values.  The pin name may contain quotes, parentheses, or    */
597 /* negations ("!" or "'");  these should be ignored.            */
598 /*--------------------------------------------------------------*/
599 
parse_pin(cellptr newcell,char * token)600 pinptr parse_pin(cellptr newcell, char *token)
601 {
602     pinptr newpin, lastpin;
603     char *pinname, *sptr;
604 
605     // Advance to first legal pin name character
606 
607     pinname = token;
608     while (isblank(*pinname) || (*pinname == '\'') || (*pinname == '\"') ||
609                 (*pinname == '!') || (*pinname == '(') || (*pinname == ')'))
610         pinname++;
611 
612     sptr = pinname;
613     while (*sptr != '\0') {
614         if (isblank(*sptr) || (*sptr == '\'') || (*sptr == '\"') ||
615                 (*sptr == '!') || (*sptr == '(') || (*sptr == ')')) {
616             *sptr = '\0';
617             break;
618         }
619         sptr++;
620     }
621 
622     // Check if pin was already defined
623 
624     lastpin = NULL;
625     newpin = newcell->pins;
626     while (newpin) {
627         lastpin = newpin;
628         if (!strcmp(newpin->name, pinname))
629             return newpin;
630         newpin = newpin->next;
631     }
632 
633     // Pin was not defined, so create a new one and add it to the cell
634     // at the end of the cell's pin list.
635 
636     newpin = (pin *)malloc(sizeof(pin));
637     newpin->name = tokendup(pinname);
638     newpin->next = NULL;
639 
640     if (lastpin != NULL)
641         lastpin->next = newpin;
642     else
643         newcell->pins = newpin;
644 
645     newpin->type = INPUT;       // The default; modified later, if not an input
646     newpin->capr = 0.0;
647     newpin->capf = 0.0;
648     newpin->sense = SENSE_NONE;
649     newpin->propdelr = NULL;
650     newpin->propdelf = NULL;
651     newpin->transr = NULL;
652     newpin->transf = NULL;
653     newpin->refcell = newcell;  // Create link back to cell
654     return newpin;
655 }
656 
657 /*--------------------------------------------------------------*/
658 /* Create a new net record                                      */
659 /*--------------------------------------------------------------*/
660 
create_net(netptr * netlist)661 netptr create_net(netptr *netlist) {
662 
663     netptr newnet;
664 
665     newnet = (netptr)malloc(sizeof(net));
666     newnet->name = NULL;
667     newnet->next = *netlist;
668     *netlist = newnet;
669     newnet->driver = NULL;
670     newnet->fanout = 0;
671     newnet->receivers = NULL;
672     newnet->loadr = 0.0;
673     newnet->loadf = 0.0;
674     newnet->type = NET;
675 
676     return newnet;
677 }
678 
679 /*----------------------------------------------------------------------*/
680 /* Interpolate or extrapolate a vector from a time vs. capacitance      */
681 /* lookup table.                                                        */
682 /*----------------------------------------------------------------------*/
683 
table_collapse(lutableptr tableptr,double load)684 double *table_collapse(lutableptr tableptr, double load)
685 {
686     double *vector;
687     double cfrac, vlow, vhigh;
688     int i, j;
689 
690     vector = (double *)malloc(tableptr->size1 * sizeof(double));
691 
692     // If the table is 1-dimensional, then just return a copy of the table.
693     if (tableptr->size2 <= 1) {
694        for (i = 0; i < tableptr->size1; i++) {
695           *(vector + i) = *(tableptr->values + i);
696        }
697        return vector;
698     }
699 
700     // Find cap load index entries bounding  "load", or the two nearest
701     // entries, if extrapolating
702 
703     if (load < tableptr->idx2.caps[0])
704         j = 1;
705     else if (load >= tableptr->idx2.caps[tableptr->size2 - 1])
706         j = tableptr->size2 - 1;
707     else {
708         for (j = 0; j < tableptr->size2; j++)
709             if (tableptr->idx2.caps[j] > load)
710                 break;
711     }
712 
713     cfrac = (load - tableptr->idx2.caps[j - 1]) /
714                         (tableptr->idx2.caps[j] - tableptr->idx2.caps[j - 1]);
715 
716     for (i = 0; i < tableptr->size1; i++) {
717 
718         // Interpolate value at cap load for each transition value
719 
720         vlow = *(tableptr->values + i * tableptr->size2 + (j - 1));
721         vhigh = *(tableptr->values + i * tableptr->size2 + j);
722         *(vector + i) = vlow + (vhigh - vlow) * cfrac;
723     }
724     return vector;
725 }
726 
727 /*----------------------------------------------------------------------*/
728 /* Interpolate/extrapolate a delay or transition value from a vector of */
729 /* values at a known output load.  The original full 2D table contains  */
730 /* the transition time index values.                                    */
731 /*----------------------------------------------------------------------*/
732 
vector_get_value(lutableptr tableptr,double * vector,double trans)733 double vector_get_value(lutableptr tableptr, double *vector, double trans)
734 {
735     int i;
736     double tfrac, vlow, vhigh, value;
737 
738     // Find time index entries bounding  "trans", or the two nearest
739     // entries, if extrapolating
740 
741     if (trans < tableptr->idx1.times[0])
742         i = 1;
743     else if (trans >= tableptr->idx1.times[tableptr->size1 - 1])
744         i = tableptr->size1 - 1;
745     else {
746         for (i = 0; i < tableptr->size1; i++)
747             if (tableptr->idx1.times[i] > trans)
748                 break;
749     }
750 
751     // Compute transition time as a fraction of the nearest table indexes
752     // for transition times
753 
754     tfrac = (trans - tableptr->idx1.times[i - 1]) /
755                 (tableptr->idx1.times[i] - tableptr->idx1.times[i - 1]);
756 
757     // Interpolate value
758     vlow = *(vector + (i - 1));
759     vhigh = *(vector + i);
760     value = vlow + (vhigh - vlow) * tfrac;
761     return value;
762 }
763 
764 /*----------------------------------------------------------------------*/
765 /* Interpolate or extrapolate a value from a related time vs.           */
766 /* constrained time lookup table.                                       */
767 /*----------------------------------------------------------------------*/
768 
binomial_get_value(lutableptr tableptr,double rtrans,double ctrans)769 double binomial_get_value(lutableptr tableptr, double rtrans, double ctrans)
770 {
771     int i, j;
772     double rfrac, cfrac, vlow, vhigh, valuel, valueh, value;
773 
774     /* Tables have been arranged such that idx1 is related time,        */
775     /* idx2 is constrained time */
776 
777     // Find time index entries bounding  "rtrans", or the two nearest
778     // entries, if extrapolating
779 
780     if (rtrans < tableptr->idx1.rel[0])
781         i = 1;
782     else if (rtrans >= tableptr->idx1.rel[tableptr->size1 - 1])
783         i = tableptr->size1 - 1;
784     else {
785         for (i = 0; i < tableptr->size1; i++)
786             if (tableptr->idx1.rel[i] > rtrans)
787                 break;
788     }
789 
790     // Compute transition time as a fraction of the nearest table indexes
791     // for transition times
792 
793     rfrac = (rtrans - tableptr->idx1.rel[i - 1]) /
794                 (tableptr->idx1.rel[i] - tableptr->idx1.rel[i - 1]);
795 
796     // 1-dimensional computation, if this table is 1-dimensional
797 
798     if (tableptr->size2 == 0) {
799         vlow = *(tableptr->values + (i - 1));
800         vhigh = *(tableptr->values + i);
801         value = vlow + (vhigh - vlow) * rfrac;
802         return value;
803     }
804 
805     // Find cons index entries bounding  "ctrans", or the two nearest
806     // entries, if extrapolating
807 
808     if (ctrans < tableptr->idx2.cons[0])
809         j = 1;
810     else if (ctrans >= tableptr->idx2.cons[tableptr->size2 - 1])
811         j = tableptr->size2 - 1;
812     else {
813         for (j = 0; j < tableptr->size2; j++)
814             if (tableptr->idx2.cons[j] > ctrans)
815                 break;
816     }
817 
818     // Compute cons transition as a fraction of the nearest table indexes for cons
819 
820     cfrac = (ctrans - tableptr->idx2.cons[j - 1]) /
821                         (tableptr->idx2.cons[j] - tableptr->idx2.cons[j - 1]);
822 
823     // Interpolate value at cons lower bound
824     vlow = *(tableptr->values + (i - 1) * tableptr->size1 + (j - 1));
825     vhigh = *(tableptr->values + i * tableptr->size1 + (j - 1));
826     valuel = vlow + (vhigh - vlow) * rfrac;
827 
828     // Interpolate value at cons upper bound
829     vlow = *(tableptr->values + (i - 1) * tableptr->size1 + j);
830     vhigh = *(tableptr->values + i * tableptr->size1 + j);
831     valueh = vlow + (vhigh - vlow) * rfrac;
832 
833     // Final interpolation (binomial interpolation)
834     value = valuel + (valueh - valuel) * cfrac;
835     return value;
836 }
837 
838 /*----------------------------------------------------------------------*/
839 /* Determine how the sense of a signal changes going from a gate's      */
840 /* input to its output.  If the gate's input pin is positive unate      */
841 /* relative to the gate output, then the signal sense remains the same. */
842 /* If it is negative unate, then the signal sense inverts.  If it is    */
843 /* non-unate, then the signal sense becomes non-unate, and we calculate */
844 /* timing for both edges from that point forward, always accepting the  */
845 /* maximum time.                                                        */
846 /*----------------------------------------------------------------------*/
847 
calc_dir(pinptr testpin,short dir)848 short calc_dir(pinptr testpin, short dir)
849 {
850     short outdir;
851 
852     outdir = UNKNOWN;
853     if (testpin == NULL) return dir;
854 
855     switch(dir) {
856         case RISING:
857             if (testpin->sense == SENSE_POSITIVE)
858                 outdir = RISING;        /* rising input, rising output */
859             else if (testpin->sense == SENSE_NEGATIVE)
860                 outdir = FALLING;       /* rising input, falling output */
861             else
862                 outdir = EITHER;        /* output can be rising or falling */
863             break;
864         case FALLING:
865             if (testpin->sense == SENSE_POSITIVE)
866                 outdir = FALLING;       /* falling input, falling output */
867             else if (testpin->sense == SENSE_NEGATIVE)
868                 outdir = RISING;        /* falling input, rising output */
869             else
870                 outdir = EITHER;                /* output can be rising or falling */
871             break;
872         case EITHER:
873             outdir = EITHER;            /* output can be rising or falling */
874             break;
875     }
876     return outdir;
877 }
878 
879 /*----------------------------------------------------------------------*/
880 /* Calculate the propagation delay from "testpin" to the output         */
881 /* of the gate to which "testpin" is an input.                          */
882 /*                                                                      */
883 /* "sense" is a pointer to the sense at the input.  SENSE_POSITIVE      */
884 /* indicates a rising edge at the pin, SENSE_NEGATIVE indicates a       */
885 /* falling edge at the pin.  "sense" is updated to indicate if the      */
886 /* output transition is rising, falling, or unknown (SENSE_NONE).       */
887 /*                                                                      */
888 /* "loadnet" is a pointer to the net connected to the cell instance's   */
889 /* output pin.  Load values will be taken from this net, depending on   */
890 /* the sense of the output.                                             */
891 /*                                                                      */
892 /* "testpin" is the pin receiving the input signal, and the pin record  */
893 /* containing the relevant timing tables.                               */
894 /*----------------------------------------------------------------------*/
895 
calc_prop_delay(double trans,connptr testconn,short sense,char minmax)896 double calc_prop_delay(double trans, connptr testconn, short sense, char minmax)
897 {
898     pinptr testpin;
899     double propdelayr, propdelayf;
900 
901     propdelayr = 0.0;
902     propdelayf = 0.0;
903 
904     testpin = testconn->refpin;
905     if (testpin == NULL) return 0.0;
906 
907     if (sense != SENSE_NEGATIVE) {
908         if (testconn->prvector)
909             propdelayr = vector_get_value(testpin->propdelr, testconn->prvector, trans);
910 	if (propdelayr < 0.0) propdelayr = 0.0;
911         if (sense == SENSE_POSITIVE) return propdelayr;
912     }
913 
914     if (sense != SENSE_POSITIVE) {
915         if (testconn->pfvector)
916             propdelayf = vector_get_value(testpin->propdelf, testconn->pfvector, trans);
917 	if (propdelayf < 0.0) propdelayf = 0.0;
918         if (sense == SENSE_NEGATIVE) return propdelayf;
919     }
920 
921     if (minmax == MAXIMUM_TIME)
922         return (propdelayr > propdelayf) ? propdelayr : propdelayf;
923     else
924         return (propdelayr < propdelayf) ? propdelayr : propdelayf;
925 }
926 
927 /*----------------------------------------------------------------------*/
928 /* Calculate the transition time from "testpin" to the output           */
929 /* of the gate to which "testpin" is an input.  This is equivalent to   */
930 /* the propagation delay calculation routine above, apart from using    */
931 /* the lookup tables for transition time instead of propagation delay.  */
932 /*----------------------------------------------------------------------*/
933 
calc_transition(double trans,connptr testconn,short sense,char minmax)934 double calc_transition(double trans, connptr testconn, short sense, char minmax)
935 {
936     pinptr testpin;
937     double transr, transf;
938 
939     testpin = testconn->refpin;
940     if (testpin == NULL) return 0.0;
941 
942     transr = 0.0;
943     transf = 0.0;
944 
945     if (sense != SENSE_NEGATIVE) {
946         if (testconn->trvector)
947             transr = vector_get_value(testpin->transr, testconn->trvector, trans);
948 	if (transr < 0.0) transr = 0.0;
949         if (sense == SENSE_POSITIVE) return transr;
950     }
951 
952     if (sense != SENSE_POSITIVE) {
953         if (testconn->tfvector)
954             transf = vector_get_value(testpin->transf, testconn->tfvector, trans);
955 	if (transf < 0.0) transf = 0.0;
956         if (sense == SENSE_NEGATIVE) return transf;
957     }
958 
959     if (minmax == MAXIMUM_TIME)
960         return (transr > transf) ? transr : transf;
961     else
962         return (transr < transf) ? transr : transf;
963 }
964 
965 /*----------------------------------------------------------------------*/
966 /* Calculate the hold time for a flop input "testpin" relative to the   */
967 /* flop clock, where "trans" is the transition time of the signal at    */
968 /* "testpin", and "clktrans" is the transition time of the clock        */
969 /* signal at the clock pin.  "sense" is the sense of the input signal   */
970 /* at "testpin".                                                        */
971 /*----------------------------------------------------------------------*/
972 
calc_hold_time(double trans,pinptr testpin,double clktrans,short sense,char minmax)973 double calc_hold_time(double trans, pinptr testpin, double clktrans, short sense,
974                 char minmax)
975 {
976     double holdr, holdf;
977 
978     if (testpin == NULL) return 0.0;
979 
980     holdr = 0.0;
981     holdf = 0.0;
982 
983     if (sense != SENSE_NEGATIVE) {
984         if (testpin->transr)
985             holdr = binomial_get_value(testpin->transr, trans, clktrans);
986         if (sense == SENSE_POSITIVE) return holdr;
987     }
988 
989     if (sense != SENSE_POSITIVE) {
990         if (testpin->transf)
991             holdf = binomial_get_value(testpin->transf, trans, clktrans);
992         if (sense == SENSE_NEGATIVE) return holdf;
993     }
994 
995     if (minmax == MAXIMUM_TIME)
996         return (holdr < holdf) ? holdr : holdf;
997     else
998         return (holdr > holdf) ? holdr : holdf;
999 }
1000 
1001 /*----------------------------------------------------------------------*/
1002 /* Calculate the setup time for a flop input "testpin" relative to the  */
1003 /* flop clock, where "trans" is the transition time of the signal at    */
1004 /* "testpin", and "clktrans" is the transition time of the clock        */
1005 /* signal at the clock pin.  "sense" is the sense of the input signal   */
1006 /* at "testpin".                                                        */
1007 /*----------------------------------------------------------------------*/
1008 
calc_setup_time(double trans,pinptr testpin,double clktrans,short sense,char minmax)1009 double calc_setup_time(double trans, pinptr testpin, double clktrans, short sense,
1010                 char minmax)
1011 {
1012     double setupr, setupf;
1013 
1014     if (testpin == NULL) return 0.0;
1015 
1016     setupr = 0.0;
1017     setupf = 0.0;
1018 
1019     if (sense != SENSE_NEGATIVE) {
1020         if (testpin->propdelr)
1021             setupr = binomial_get_value(testpin->propdelr, trans, clktrans);
1022         if (sense == SENSE_POSITIVE) return setupr;
1023     }
1024 
1025     if (sense != SENSE_POSITIVE) {
1026         if (testpin->propdelf)
1027             setupf = binomial_get_value(testpin->propdelf, trans, clktrans);
1028         if (sense == SENSE_NEGATIVE) return setupf;
1029     }
1030 
1031     if (minmax == MAXIMUM_TIME)
1032         return (setupr > setupf) ? setupr : setupf;
1033     else
1034         return (setupr < setupf) ? setupr : setupf;
1035 }
1036 
1037 /*--------------------------------------------------------------*/
1038 /* Find the path from a clock back to all inputs or flop        */
1039 /* outputs.  This list will be used to find nodes that are      */
1040 /* common to other clocks.                                      */
1041 /*								*/
1042 /* For each pair of registers involved in a delay path		*/
1043 /* calculation, this routine is called once for both devices.	*/
1044 /* Set mode = 0 for the first device, and the connections are	*/
1045 /* marked when found.  Set mode = 1 for the second device, and	*/
1046 /* the search stops when a marked connection is found---this is	*/
1047 /* the common clock net between the devices.  If no common	*/
1048 /* clock is found, then return NULL---these endpoints are	*/
1049 /* asynchronously clocked.					*/
1050 /*								*/
1051 /* Modified 5/23/2019:  Cascaded clocks should be traced	*/
1052 /* through a flop.  i.e., if a clock is found to come from a	*/
1053 /* DFF output, then add the clock-to-Q delay and keep tracing	*/
1054 /* from the DFF clock.						*/
1055 /*								*/
1056 /* If mode == 2, return TRUE if the search ended on a		*/
1057 /* connection found in a mode 1 search.  Otherwise, return	*/
1058 /* FALSE.							*/
1059 /*--------------------------------------------------------------*/
1060 
1061 unsigned char
find_clock_source(connptr testlink,ddataptr * clocklist,btptr btrace,short dir,unsigned char mode)1062 find_clock_source(connptr testlink, ddataptr *clocklist, btptr btrace, short dir,
1063 		unsigned char mode)
1064 {
1065     netptr clknet;
1066     connptr driver, iinput;
1067     instptr iupstream;
1068     btptr newclock;
1069     ddataptr newdataptr;
1070     short newdir;
1071     unsigned char result = 0;
1072 
1073     /* Add this connection record to the backtrace */
1074 
1075     newclock = (btptr)malloc(sizeof(btdata));
1076     newclock->delay = -1.0E50;	/* Initialization constant */
1077     newclock->trans = 0.0;
1078     newclock->dir = dir;
1079     newclock->refcnt = 0;
1080     newclock->receiver = testlink;
1081     newclock->next = btrace;
1082     if (btrace) btrace->refcnt++;
1083 
1084     /* On mode 2, stop when a node marked 1 is reached. */
1085     if ((mode == (unsigned char)2) && (testlink->visited == (unsigned char)1)) {
1086 	result = (unsigned char)1;
1087 	goto makehead;
1088     }
1089 
1090     /* Mark connection as visited */
1091     testlink->visited = mode;
1092 
1093     clknet = testlink->refnet;
1094     driver = clknet->driver;
1095     if (driver == NULL) goto makehead;		/* Reached a module input */
1096     iupstream = driver->refinst;
1097 
1098     if (iupstream == NULL) goto makehead;         /* Not supposed to happen? */
1099 
1100     /* If a flop or latch output is reached, add the clock-to-output delay  */
1101     /* and continue tracing from the DFF clock or LATCH input.		    */
1102 
1103     if (driver->refpin->type & DFFOUT) {
1104 	for (iinput = driver->refinst->in_connects; iinput; iinput = iinput->next) {
1105 	    if (iinput->refpin->type & DFFCLK) {
1106 		newdir = calc_dir(iinput->refpin, dir);
1107 		result = find_clock_source(iinput, clocklist, newclock, newdir, mode);
1108 		if (result == (unsigned char)1) return result;
1109 	    }
1110 	}
1111     }
1112     else if (driver->refpin->type & LATCHOUT) {
1113 	for (iinput = driver->refinst->in_connects; iinput; iinput = iinput->next) {
1114 	    if (iinput->refpin->type & LATCHIN) {
1115 		newdir = calc_dir(iinput->refpin, dir);
1116 		result = find_clock_source(iinput, clocklist, newclock, newdir, mode);
1117 		if (result == (unsigned char)1) return result;
1118 	    }
1119 	}
1120     }
1121     else {
1122 	for (iinput = iupstream->in_connects; iinput; iinput = iinput->next) {
1123 	    newdir = calc_dir(iinput->refpin, dir);
1124 	    result = find_clock_source(iinput, clocklist, newclock, newdir, mode);
1125 	    if (result == (unsigned char)1) return result;
1126 	}
1127     }
1128     return (unsigned char)0;
1129 
1130 makehead:
1131     /* Reached the head of a clock tree, so save the position	*/
1132     /* in the list of backtraces.				*/
1133 
1134     newdataptr = (ddataptr)malloc(sizeof(delaydata));
1135     newdataptr->backtrace = newclock;
1136     if (newclock) newclock->refcnt++;
1137     newdataptr->delay = 0.0;
1138     newdataptr->skew = 0.0;
1139     newdataptr->setup = 0.0;
1140     newdataptr->trans = 0.0;
1141     newdataptr->next = *clocklist;
1142     *clocklist = newdataptr;
1143 
1144     return result;
1145 }
1146 
1147 /*--------------------------------------------------------------*/
1148 /* Determine the delay to a clock pin from the farthest point   */
1149 /* back in the network, either to an input pin or the output of */
1150 /* another flop (e.g., a ripple counter).  If there is more     */
1151 /* than one such source (which can happen with, say, a gated    */
1152 /* clock, because this routine will not differentiate between   */
1153 /* the clock signal and the gating signal), then all sources    */
1154 /* recorded (it is only necessary to find a common root of all  */
1155 /* other related clocks downstream).                            */
1156 /*                                                              */
1157 /* This is a recursive routine, continuing to find all delays   */
1158 /* through the circuit until it reaches "terminal".  The        */
1159 /* "delaylist" linked list is not modified by this routine.     */
1160 /* However, it depends on routine find_clock_source marking	*/
1161 /* each connection as visited, so that the search is restricted	*/
1162 /* to the space visited on the upstream search, so it is not	*/
1163 /* blindly recursive.						*/
1164 /*--------------------------------------------------------------*/
1165 
find_clock_delay(int dir,double delay,double trans,btptr backtrace,connptr terminal,char minmax,unsigned char mode)1166 void find_clock_delay(int dir, double delay, double trans,
1167                 btptr backtrace, connptr terminal, char minmax,
1168 		unsigned char mode) {
1169 
1170     pinptr  testpin;
1171     netptr  loadnet;
1172     cellptr testcell;
1173     connptr receiver;
1174     connptr nextrcvr;
1175     instptr testinst;
1176     btptr   testbtdata, newbtdata;
1177     double  newdelayr, newdelayf, newtransr, newtransf;
1178     short   outdir;
1179     int     i;
1180 
1181     receiver = backtrace->receiver;
1182 
1183     if (minmax == MAXIMUM_TIME) {
1184         /* Is delay greater than that already recorded?  If so, replace it */
1185         if ((delay > backtrace->delay) || (backtrace->delay == INITVAL)) {
1186             backtrace->delay = delay;
1187             backtrace->trans = trans;
1188             backtrace->dir = dir;
1189         }
1190     }
1191     else {
1192         /* Is delay less than that already recorded?  If so, replace it */
1193         if ((delay < backtrace->delay) || (backtrace->delay == INITVAL)) {
1194             backtrace->delay = delay;
1195             backtrace->trans = trans;
1196             backtrace->dir = dir;
1197         }
1198     }
1199 
1200     // Stop when receiver matches terminal.
1201 
1202     if (receiver != terminal) {
1203 
1204         // Don't follow signal through any DFF pins
1205 	testpin = receiver->refpin;
1206         testinst = receiver->refinst;
1207         testcell = (testpin) ? testpin->refcell : NULL;
1208         if (testcell && (testcell->type & DFF)) return;
1209 
1210         // Compute delay from gate input to output
1211 
1212         outdir = calc_dir(testpin, dir);
1213         if (outdir & RISING) {
1214             newdelayr = backtrace->delay +
1215 			calc_prop_delay(trans, receiver, RISING, minmax);
1216             newtransr = calc_transition(trans, receiver, RISING, minmax);
1217         }
1218         if (outdir & FALLING) {
1219             newdelayf = backtrace->delay +
1220 			calc_prop_delay(trans, receiver, FALLING, minmax);
1221             newtransf = calc_transition(trans, receiver, FALLING, minmax);
1222         }
1223 
1224         /* Continue calculating down the backtrace */
1225 
1226 	if (outdir & RISING)
1227 	    find_clock_delay(RISING, newdelayr, newtransr, backtrace->next,
1228 			terminal, minmax, mode);
1229 	if (outdir & FALLING)
1230 	    find_clock_delay(FALLING, newdelayf, newtransf, backtrace->next,
1231 			terminal, minmax, mode);
1232     }
1233 }
1234 
1235 /*--------------------------------------------------------------*/
1236 /* Determine the delay from input to output through a gate      */
1237 /*                                                              */
1238 /* This is a recursive routine, continuing to find all delays   */
1239 /* through the circuit until it reaches a terminal or flop      */
1240 /* input.  It is similar to find_clock_delay, but stops on all  */
1241 /* terminal points found in the path, rather than stopping on   */
1242 /* a specific connection.                                       */
1243 /*                                                              */
1244 /* Also unlike find_clock_delay, the routine keeps a running    */
1245 /* record of the path followed from the source, as a character  */
1246 /* string.  When a terminal is found, the path and delay are    */
1247 /* saved and added to "delaylist".  After the recursive search, */
1248 /* "delaylist" contains a list of all paths starting from the   */
1249 /* original connection "receiver" and ending on a clock or an   */
1250 /* output pin.  Where multiple paths exist between source and   */
1251 /* destination, only the path with the longest delay is kept.   */
1252 /*                                                              */
1253 /* Return the number of new paths recorded.                     */
1254 /*--------------------------------------------------------------*/
1255 
find_path_delay(int dir,double delay,double trans,connptr receiver,btptr backtrace,ddataptr * delaylist,char minmax)1256 int find_path_delay(int dir, double delay, double trans, connptr receiver,
1257                 btptr backtrace, ddataptr *delaylist, char minmax) {
1258 
1259     pinptr   testpin;
1260     netptr   loadnet;
1261     cellptr  testcell;
1262     instptr  testinst;
1263     btptr    newbtdata, freebt, testbt;
1264     ddataptr testddata, newddata;
1265     double   newdelayr, newdelayf, newtransr, newtransf;
1266     short    outdir;
1267     char     replace;
1268     int      i, numpaths;
1269 
1270     numpaths = 0;
1271     testpin = receiver->refpin;
1272 
1273     // Prevent exhaustive search by stopping on a metric.  Note that the
1274     // nonlinear table-based delay data requires an exhaustive search;
1275     // generally, the tables can be assumed to be monotonic, in which case
1276     // we can stop if the delay is less than the greatest delay recorded
1277     // at this point AND the transition time is less than the transition
1278     // time recorded along with that delay.  A more relaxed metric is to
1279     // use the delay plus the transition time, and an even more relaxed
1280     // metric is to use only the delay.  Any relaxing of the metric
1281     // implies that the final result may not be the absolute maximum delay,
1282     // although it will typically vary by less than an average gate delay.
1283 
1284     if (!exhaustive) {
1285         if (minmax == MAXIMUM_TIME) {
1286             if (delay <= receiver->metric)
1287                 return numpaths;
1288         }
1289         else {
1290             if (delay >= receiver->metric)
1291                 return numpaths;
1292         }
1293     }
1294 
1295     // Check for a logic loop, and truncate the path to avoid infinite
1296     // looping in the path search.
1297 
1298     if (receiver->tag == (ddataptr)(-1)) return numpaths;
1299     else if (receiver->tag == NULL) receiver->tag = (ddataptr)(-1);
1300 
1301     // Record this position and delay/transition information
1302 
1303     newbtdata = (btptr)malloc(sizeof(btdata));
1304     newbtdata->receiver = receiver;
1305     newbtdata->delay = delay + newbtdata->receiver->icDelay;
1306     newbtdata->trans = trans;
1307     newbtdata->dir = dir;
1308     newbtdata->refcnt = 0;
1309     newbtdata->next = backtrace;
1310     if (backtrace) backtrace->refcnt++;
1311 
1312     // Stop when we hit a module output pin or any flop/latch input.
1313     // We must allow the routine to pass through the 1st register clock (on the first
1314     // time through, backtrace is NULL).
1315 
1316     if ((backtrace == NULL) || (testpin && ((testpin->type & REGISTER_IN) == 0))) {
1317 
1318         testinst = receiver->refinst;
1319         testcell = (testpin) ? testpin->refcell : NULL;
1320 
1321         // Compute delay from gate input to output
1322 
1323         outdir = calc_dir(testpin, dir);
1324         if (outdir & RISING) {
1325             newdelayr = delay + calc_prop_delay(trans, receiver, RISING, minmax);
1326             newtransr = calc_transition(trans, receiver, RISING, minmax);
1327         }
1328         if (outdir & FALLING) {
1329             newdelayf = delay + calc_prop_delay(trans, receiver, FALLING, minmax);
1330             newtransf = calc_transition(trans, receiver, FALLING, minmax);
1331         }
1332 
1333 	if (!testinst || testinst->out_connects) {
1334 	    loadnet = (testinst) ?  testinst->out_connects->refnet : receiver->refnet;
1335 	    for (i = 0; i < loadnet->fanout; i++) {
1336 		if (outdir & RISING)
1337 		    numpaths += find_path_delay(RISING, newdelayr, newtransr,
1338 				loadnet->receivers[i], newbtdata, delaylist, minmax);
1339 		if (outdir & FALLING)
1340 		    numpaths += find_path_delay(FALLING, newdelayf, newtransf,
1341 				loadnet->receivers[i], newbtdata, delaylist, minmax);
1342 	    }
1343 	}
1344         receiver->tag = NULL;
1345     }
1346     else {
1347 
1348         /* Is receiver already in delaylist? */
1349         if ((receiver->tag != (ddataptr)(-1)) && (receiver->tag != NULL)) {
1350 
1351             /* Position in delaylist is recorded in tag field */
1352             testddata = receiver->tag;
1353 
1354             if (testddata->backtrace->receiver == receiver) {
1355                 replace = 0;
1356                 if (minmax == MAXIMUM_TIME) {
1357                     /* Is delay greater than that already recorded?  If so, replace it */
1358                     if (delay > testddata->backtrace->delay)
1359                         replace = 1;
1360                 }
1361                 else {
1362                     /* Is delay less than that already recorded?  If so, replace it */
1363                     if (delay < testddata->backtrace->delay)
1364                         replace = 1;
1365                 }
1366                 if (replace) {
1367 
1368                     /* Remove the existing path record and replace it */
1369                     while (testddata->backtrace != NULL) {
1370                         freebt = testddata->backtrace;
1371                         testddata->backtrace = testddata->backtrace->next;
1372                         freebt->refcnt--;
1373                         if (freebt->refcnt == 0) free(freebt);
1374 			else break;
1375                     }
1376                     testddata->backtrace = newbtdata;
1377 		    if (newbtdata) newbtdata->refcnt++;
1378 
1379 		    /* Update the delay at testddata */
1380 		    testddata->delay = newbtdata->delay + testddata->setup
1381 				+ testddata->skew;
1382                 }
1383             }
1384             else
1385                 fprintf(stderr, "ERROR:  Bad endpoint tag!\n");
1386         }
1387         else
1388             testddata = NULL;
1389 
1390         // If we have found a propagation path from source to dest,
1391         // record it in delaylist.
1392 
1393         if (testddata == NULL) {
1394             numpaths++;
1395             newddata = (ddataptr)malloc(sizeof(delaydata));
1396             newddata->delay = 0.0;
1397             newddata->setup = 0.0;
1398             newddata->skew = 0.0;
1399             newddata->trans = 0.0;
1400             newddata->backtrace = newbtdata;
1401 	    if (newbtdata) newbtdata->refcnt++;
1402             newddata->next = *delaylist;
1403             *delaylist = newddata;
1404 
1405             /* Mark the receiver as having been visited */
1406             receiver->tag = *delaylist;
1407         }
1408     }
1409 
1410     receiver->metric = delay;
1411     if (newbtdata->refcnt <= 0) free(newbtdata);
1412     return numpaths;
1413 }
1414 
1415 /*--------------------------------------------------------------*/
1416 /* Search the list "clocklist" for all points that are module   */
1417 /* inputs or flop outputs, and compute the worst-case           */
1418 /* transition time downstream at testlink.                      */
1419 /*                                                              */
1420 /* Upon return, the worst-case transition time is held in	*/
1421 /* returned backtrace pointer.					*/
1422 /*								*/
1423 /* If mode is non-zero, then only trace paths marked visited ==	*/
1424 /* mode.  This restricts the computation to nodes that were	*/
1425 /* found on the upstream search find_clock_source().		*/
1426 /*--------------------------------------------------------------*/
1427 
find_clock_transition(ddataptr clocklist,connptr testlink,short dir,char minmax,unsigned char mode)1428 void find_clock_transition(ddataptr clocklist, connptr testlink, short dir,
1429 	char minmax, unsigned char mode)
1430 {
1431     ddataptr testclock;
1432     btptr  backtrace;
1433     double tdriver, ddelay;
1434 
1435     ddelay = 0.0;
1436     for (testclock = clocklist; testclock; testclock = testclock->next) {
1437         backtrace = testclock->backtrace;
1438         tdriver = 0.0;          // to-do:  set to default input transition time
1439         find_clock_delay(RISING, ddelay, tdriver, backtrace, testlink,
1440                         minmax, mode);
1441         find_clock_delay(FALLING, ddelay, tdriver, backtrace, testlink,
1442                         minmax, mode);
1443 
1444         // In mode 2, only check timing from 1st item in the list
1445 	if (mode == (unsigned char)2) break;
1446     }
1447 }
1448 
1449 /*--------------------------------------------------------------*/
1450 /* Find the common point between two clock lists (it has	*/
1451 /* already been determined that a common point exists).		*/
1452 /* The 1st record of clock2list points to the connection	*/
1453 /* record that is the common point.  What is needed is to find	*/
1454 /* the backtrace record in clocklist that points to the same	*/
1455 /* connection record.						*/
1456 /*--------------------------------------------------------------*/
1457 
1458 btptr
find_common_clock(ddataptr clock2list,ddataptr clocklist)1459 find_common_clock(ddataptr clock2list, ddataptr clocklist)
1460 {
1461     ddataptr ddsearch;
1462     btptr btsearch;
1463     connptr ccommon;
1464 
1465     ccommon = clock2list->backtrace->receiver;
1466 
1467     for (ddsearch = clocklist; ddsearch; ddsearch = ddsearch->next)
1468 	for (btsearch = ddsearch->backtrace; btsearch; btsearch = btsearch->next)
1469 	    if (btsearch->receiver == ccommon)
1470 		return btsearch;
1471 
1472     return NULL;
1473 }
1474 
1475 /*--------------------------------------------------------------*/
1476 /* Given an instance record, find the pin of the instance that  */
1477 /* is the clock, if the instance is a flop.  If the instance is */
1478 /* not a flop, return NULL.                                     */
1479 /*--------------------------------------------------------------*/
1480 
find_register_clock(instptr testinst)1481 connptr find_register_clock(instptr testinst)
1482 {
1483     connptr testconn;
1484 
1485     for (testconn = testinst->in_connects; testconn; testconn = testconn->next)
1486         if (testconn->refpin && (testconn->refpin->type & DFFCLK))
1487             return testconn;
1488 
1489     return NULL;
1490 }
1491 
1492 /*--------------------------------------------------------------*/
1493 /* Given an edge direction (RISING or FALLING) at a source net, */
1494 /* and given a destination net, find the sense of the signal    */
1495 /* when it arrives at the destination net.                      */
1496 /*--------------------------------------------------------------*/
1497 
find_edge_dir(short dir,netptr sourcenet,netptr destnet)1498 short find_edge_dir(short dir, netptr sourcenet, netptr destnet) {
1499     int i;
1500     short outdir, rdir;
1501     connptr testconn, nextconn;
1502     instptr testinst;
1503     netptr nextnet;
1504 
1505     for (i = 0; i < sourcenet->fanout; i++) {
1506         testconn = sourcenet->receivers[i];
1507         testinst = testconn->refinst;
1508         if (testinst == NULL) continue;
1509         if (testconn->refpin == NULL) continue;
1510         if ((testconn->refpin->type & REGISTER_IN) != 0) continue;
1511         nextconn = testinst->out_connects;
1512         nextnet  = nextconn->refnet;
1513         outdir = calc_dir(testconn->refpin, dir);
1514         if (nextnet == destnet) return outdir;
1515 
1516         rdir = find_edge_dir(outdir, nextnet, destnet);
1517         if (rdir != 0) return rdir;
1518     }
1519     return 0;
1520 }
1521 
1522 /*--------------------------------------------------------------*/
1523 /* Reset all entries in the whole network.  Use sparingly.	*/
1524 /*--------------------------------------------------------------*/
1525 
1526 void
reset_all(netptr netlist,char minmax)1527 reset_all(netptr netlist, char minmax)
1528 {
1529     netptr testnet;
1530     connptr testconn;
1531     int i;
1532     double metric;
1533 
1534     metric = (minmax == MAXIMUM_TIME) ? -1.0 : 1.0E50;
1535 
1536     for (testnet = netlist; testnet; testnet = testnet->next) {
1537 	for (i = 0; i < testnet->fanout; i++) {
1538 	    testconn = testnet->receivers[i];
1539 	    testconn->tag = NULL;
1540 	    testconn->metric = metric;
1541 	}
1542     }
1543 }
1544 
1545 /*--------------------------------------------------------------*/
1546 /* Reset all entries in the feed-forward tree from connection	*/
1547 /* testconn (recursively).  Resets the tag entry, "visited"	*/
1548 /* flag, and stop metric.					*/
1549 /*--------------------------------------------------------------*/
1550 
1551 void
reset_path(connptr testconn,double metric)1552 reset_path(connptr testconn, double metric)
1553 {
1554     int i;
1555     instptr testinst;
1556     netptr loadnet;
1557     connptr nextconn;
1558 
1559     testconn->tag = NULL;
1560     testconn->visited = (unsigned char)0;
1561     testconn->metric = metric;
1562 
1563     testinst = testconn->refinst;
1564     loadnet = (testinst) ? testinst->out_connects->refnet : testconn->refnet;
1565 
1566     for (i = 0; i < loadnet->fanout; i++) {
1567 	nextconn = loadnet->receivers[i];
1568 	if (nextconn->tag != NULL)
1569 	    reset_path(loadnet->receivers[i], metric);
1570     }
1571 }
1572 
1573 /*--------------------------------------------------------------*/
1574 /* Search all paths from the clocked data outputs of            */
1575 /* "clockedlist" to either output pins or data inputs of other  */
1576 /* flops.                                                       */
1577 /*                                                              */
1578 /* Return a master list of all backtraces in "masterlist".      */
1579 /*                                                              */
1580 /* Return value is the number of paths recorded in masterlist.  */
1581 /*                                                              */
1582 /* If minmax == MAXIMUM_TIME, return the maximum delay.         */
1583 /* If minmax == MINIMUM_TIME, return the minimum delay.         */
1584 /*--------------------------------------------------------------*/
1585 
find_clock_to_term_paths(connlistptr clockedlist,ddataptr * masterlist,netptr netlist,char minmax)1586 int find_clock_to_term_paths(connlistptr clockedlist, ddataptr *masterlist, netptr netlist,
1587                 char minmax)
1588 {
1589     netptr      testnet;
1590     connptr     testconn, thisconn;
1591     connlistptr testlink;
1592     pinptr      testpin;
1593     cellptr     testcell;
1594     instptr     testinst;
1595     btptr       backtrace, freebt;
1596     ddataptr    delaylist, testddata, freeddata;
1597 
1598     short       srcdir, destdir;             // Signal direction in/out
1599     double      tdriver, setupdelay, holddelay, ddelay;
1600     int         numpaths, n, i, t, j;
1601     unsigned char result;
1602 
1603     delaylist = NULL;
1604 
1605     t = j = 0;
1606     if (verbose > 0) {
1607         for (testlink = clockedlist; testlink; testlink = testlink->next)
1608 	    t++;
1609 	fprintf(stdout, "Length of list of clocked nets = %d\n", t);
1610 	fflush(stdout);
1611     }
1612 
1613     numpaths = 0;
1614     for (testlink = clockedlist; testlink; testlink = testlink->next) {
1615 	if (verbose > 0) {
1616 	    j++;
1617 	    if ((j % 100) == 0) {
1618 		fprintf(stdout, "Completed %d traces (%3.1f%%).\n",
1619 			j, 100.0 * ((float)j / (float)t));
1620 		fflush(stdout);
1621 	    }
1622 	}
1623 
1624         // Remove all tags and reset delay metrics in testlink tree
1625 	// before each run
1626 
1627 	reset_path(testlink->connection, (minmax == MAXIMUM_TIME) ? -1.0 : 1E50);
1628 
1629         thisconn = testlink->connection;
1630         testpin = thisconn->refpin;
1631         if (testpin) {
1632             testcell = testpin->refcell;
1633 
1634             // Sense is positive for rising edge-triggered flops, negative for
1635             // falling edge-triggered flops
1636             srcdir = (testcell->type & CLK_SENSE_MASK) ? FALLING : RISING;
1637 
1638             // Report on paths and their maximum delays
1639             if (verbose > 1)
1640                 fprintf(stdout, "Paths starting at flop \"%s\" clock:\n\n",
1641                                 thisconn->refinst->name);
1642         }
1643         else {
1644             // Connection is an input pin;  must calculate both rising and falling edges.
1645             srcdir = EITHER;
1646 
1647             // Report on paths and their maximum delays
1648             if (verbose > 1)
1649                 fprintf(stdout, "Paths starting at input pin \"%s\"\n\n",
1650                                 thisconn->refnet->name);
1651         }
1652 
1653         if (verbose > 1) fflush(stdout);
1654 
1655         // Find all paths from "thisconn" to output or a flop input, and compute delay
1656         n = find_path_delay(srcdir, 0.0, 0.0, thisconn, NULL, &delaylist, minmax);
1657         numpaths += n;
1658 
1659         if (verbose > 1) fprintf(stdout, "%d paths traced (%d total).\n\n", n, numpaths);
1660 
1661         // Link delaylist data to the beginning of masterlist, and null out
1662         // delaylist for the next set of paths.
1663 
1664         if (delaylist) {
1665             for (testddata = delaylist; testddata->next; testddata = testddata->next);
1666             testddata->next = *masterlist;
1667             *masterlist = delaylist;
1668             delaylist = NULL;
1669         }
1670 
1671     }
1672     return numpaths;
1673 }
1674 
1675 /*--------------------------------------------------------------*/
1676 /* A version of strcasecmp() with a built-in check for		*/
1677 /* surrounding quotes (which are ignored).  Quotes are only	*/
1678 /* checked in str1.						*/
1679 /*--------------------------------------------------------------*/
1680 
1681 int
tokencasecmp(char * str1,char * str2)1682 tokencasecmp(char *str1, char *str2)
1683 {
1684     char *ss1, *sf1;
1685     int result;
1686 
1687     ss1 = str1;
1688     sf1 = NULL;
1689     while (*ss1 == '\"') ss1++;
1690     if (ss1 != str1) {
1691         sf1 = ss1 + 1;
1692 	while (*sf1 && (*sf1 != '\"')) sf1++;
1693 	if (*sf1 == '\"')
1694 	    *sf1 = '\0';
1695 	else
1696 	    sf1 = NULL;
1697     }
1698 
1699     result = strcasecmp(ss1, str2);
1700 
1701     if (sf1 != NULL) *sf1 = '\"';
1702 
1703     return result;
1704 }
1705 
1706 /*--------------------------------------------------------------*/
1707 /* Parse a table variable type from a liberty format file       */
1708 /*--------------------------------------------------------------*/
1709 
get_table_type(char * token)1710 int get_table_type(char *token) {
1711     if (!tokencasecmp(token, "input_net_transition"))
1712         return TRANSITION_TIME;
1713     else if (!tokencasecmp(token, "total_output_net_capacitance"))
1714         return OUTPUT_CAP;
1715     else if (!tokencasecmp(token, "related_pin_transition"))
1716         return RELATED_TIME;
1717     else if (!tokencasecmp(token, "constrained_pin_transition"))
1718         return CONSTRAINED_TIME;
1719     else
1720         return UNKNOWN;
1721 }
1722 
1723 /*--------------------------------------------------------------*/
1724 /* Expand a bus into individual pins.				*/
1725 /*--------------------------------------------------------------*/
1726 
1727 void
expand_buses(pin * curpin,bus * curbus,char * busformat)1728 expand_buses(pin *curpin, bus *curbus, char *busformat)
1729 {
1730     pin *newpin;
1731     char *rootname;
1732     int low, high, i;
1733     char busbit[1024];
1734 
1735     rootname = curpin->name;
1736 
1737     if (curbus == NULL) {
1738 	fprintf(stderr, "Error:  Pin %s is a bus, but no bus definition exists!\n",
1739 			curpin->name);
1740 	return;
1741     }
1742     if (curbus->from > curbus->to) {
1743 	low = curbus->to;
1744 	high = curbus->from;
1745     }
1746     else {
1747 	low = curbus->from;
1748 	high = curbus->to;
1749     }
1750 
1751     for (i = low; i <= high; i++) {
1752 	sprintf(busbit, busformat, rootname, i);
1753 
1754 	if (i == low)
1755 	    newpin = curpin;
1756 	else
1757 	    newpin = (pin *)malloc(sizeof(pin));
1758 	newpin->name = tokendup(busbit);
1759 	newpin->next = NULL;
1760 	if (i != low) {
1761 	    curpin->next = newpin;
1762 
1763 	    /* Copy all pin properties from the old pin to the new pin */
1764 	    newpin->type = curpin->type;
1765 	    newpin->capr = curpin->capr;
1766 	    newpin->capf = curpin->capf;
1767 	    newpin->sense = curpin->sense;
1768 	    newpin->transr = curpin->transr;
1769 	    newpin->transf = curpin->transf;
1770 	    newpin->propdelr = curpin->propdelr;
1771 	    newpin->propdelf = curpin->propdelf;
1772 	    newpin->refcell = curpin->refcell;
1773 
1774 	    curpin = newpin;
1775 	}
1776     }
1777     free(rootname);
1778 }
1779 
1780 /*--------------------------------------------------------------*/
1781 /* Read a liberty format file and collect information about     */
1782 /* the timing properties of each standard cell.                 */
1783 /*--------------------------------------------------------------*/
1784 
1785 void
libertyRead(FILE * flib,lutable ** tablelist,cell ** celllist)1786 libertyRead(FILE *flib, lutable **tablelist, cell **celllist)
1787 {
1788     char *token;
1789     char *libname = NULL;
1790     int section = INIT;
1791 
1792     double time_unit = 1.0;     // Time unit multiplier, to get ps
1793     double cap_unit = 1.0;      // Capacitive unit multiplier, to get fF
1794 
1795     pinptr testpin;
1796     lutable *tableptr;
1797 
1798     pin proxypin;
1799     int i, j;
1800     double gval;
1801     char *iptr;
1802     char *busformat;
1803     short timing_type;
1804 
1805     lutable *newtable, *reftable;
1806     cell *newcell, *lastcell;
1807     pin *newpin;
1808     bus *buses = NULL, *newbus, *curbus = NULL;
1809 
1810     lastcell = NULL;
1811     timing_type = UNKNOWN;
1812 
1813     /* Set up pin placeholder */
1814     proxypin.name = NULL;
1815     proxypin.type = GATE;
1816     proxypin.capr = 0.0;
1817     proxypin.capf = 0.0;
1818     proxypin.sense = SENSE_NONE;
1819     proxypin.propdelr = NULL;
1820     proxypin.propdelf = NULL;
1821     proxypin.transr = NULL;
1822     proxypin.transf = NULL;
1823     proxypin.refcell = NULL;
1824     proxypin.next = NULL;
1825 
1826     /* Set default bus format (verilog style) */
1827     busformat = strdup("%s[%d]");
1828 
1829     /* Read tokens off of the line */
1830     token = advancetoken(flib, 0);
1831 
1832     while (token != NULL) {
1833 
1834         switch (section) {
1835             case INIT:
1836 		if (debug == 2) fprintf(stdout, "INIT: %s\n", token);
1837                 if (!tokencasecmp(token, "library")) {
1838                     token = advancetoken(flib, 0);
1839                     if (strcmp(token, "("))
1840                         fprintf(stderr, "Library not followed by name\n");
1841                     else
1842                         token = advancetoken(flib, ')');
1843 		    /* Diagnostic */
1844                     fprintf(stdout, "Parsing library \"%s\"\n", token);
1845                     libname = tokendup(token);
1846                     token = advancetoken(flib, 0);
1847                     if (strcmp(token, "{")) {
1848                         fprintf(stderr, "Did not find opening brace "
1849                                         "on library block\n");
1850                         exit(1);
1851                     }
1852                     section = LIBBLOCK;
1853                 }
1854                 else
1855                     fprintf(stderr, "Unknown input \"%s\", looking for "
1856                                         "\"library\"\n", token);
1857                 break;
1858 
1859             case LIBBLOCK:
1860                 // Here we check for the main blocks, again not rigorously. . .
1861 
1862 		if (debug == 2) fprintf(stdout, "LIBBLOCK: %s\n", token);
1863                 if (!strcasecmp(token, "}")) {
1864                     fprintf(stdout, "End of library at line %d\n", fileCurrentLine);
1865                     section = INIT;                     // End of library block
1866                 }
1867                 else if (!tokencasecmp(token, "delay_model")) {
1868                     token = advancetoken(flib, 0);
1869                     if (strcmp(token, ":"))
1870                         fprintf(stderr, "Input missing colon\n");
1871                     token = advancetoken(flib, ';');
1872                     if (tokencasecmp(token, "table_lookup")) {
1873                         fprintf(stderr, "Sorry, only know how to "
1874                                         "handle table lookup!\n");
1875                         exit(1);
1876                     }
1877                 }
1878                 else if (!tokencasecmp(token, "lu_table_template") ||
1879                          !tokencasecmp(token, "power_lut_template")) {
1880                     // Read in template information;
1881                     newtable = (lutable *)malloc(sizeof(lutable));
1882                     newtable->name = NULL;
1883                     newtable->invert = 0;
1884                     newtable->var1 = UNKNOWN;
1885                     newtable->var2 = UNKNOWN;
1886                     newtable->size1 = 0;
1887                     newtable->size2 = 0;
1888                     newtable->idx1.times = NULL;
1889                     newtable->idx2.caps = NULL;
1890                     newtable->values = NULL;
1891                     newtable->next = *tablelist;
1892                     *tablelist = newtable;
1893 
1894                     token = advancetoken(flib, 0);
1895                     if (strcmp(token, "("))
1896                         fprintf(stderr, "Input missing open parens\n");
1897                     else
1898                         token = advancetoken(flib, ')');
1899                     newtable->name = tokendup(token);
1900                     while (*token != '}') {
1901                         token = advancetoken(flib, 0);
1902                         if (!tokencasecmp(token, "variable_1")) {
1903                             token = advancetoken(flib, 0);
1904                             token = advancetoken(flib, ';');
1905                             newtable->var1 = get_table_type(token);
1906                             if (newtable->var1 == OUTPUT_CAP || newtable->var1 == CONSTRAINED_TIME)
1907                                 newtable->invert = 1;
1908                         }
1909                         else if (!tokencasecmp(token, "variable_2")) {
1910                             token = advancetoken(flib, 0);
1911                             token = advancetoken(flib, ';');
1912                             newtable->var2 = get_table_type(token);
1913                             if (newtable->var2 == TRANSITION_TIME || newtable->var2 == RELATED_TIME)
1914                                 newtable->invert = 1;
1915                         }
1916                         else if (!tokencasecmp(token, "index_1")) {
1917 			    char dnum = ',';
1918 
1919                             token = advancetoken(flib, 0);      // Open parens
1920                             token = advancetoken(flib, 0);      // Quote
1921                             if (!strcmp(token, "\""))
1922                                 token = advancetoken(flib, '\"');
1923 
1924                             iptr = token;
1925 
1926 			    // Check if table is space or comma separated
1927 			    if (strchr(iptr, dnum) == NULL)
1928 				if (strchr(iptr, ' ') != NULL)
1929 				    dnum = ' ';
1930 
1931                             if (newtable->invert == 1) {
1932                                 // Count entries
1933                                 newtable->size2 = 1;
1934                                 while ((iptr = strchr(iptr, dnum)) != NULL) {
1935                                     iptr++;
1936                                     newtable->size2++;
1937                                 }
1938                                 newtable->idx2.caps = (double *)malloc(newtable->size2 *
1939                                         sizeof(double));
1940                                 newtable->size2 = 0;
1941                                 iptr = token;
1942                                 sscanf(iptr, "%lg", &newtable->idx2.caps[0]);
1943                                 if (newtable->var2 == OUTPUT_CAP)
1944                                     newtable->idx2.caps[0] *= cap_unit;
1945                                 else
1946                                     newtable->idx2.caps[0] *= time_unit;
1947 
1948                                 while ((iptr = strchr(iptr, dnum)) != NULL) {
1949                                     iptr++;
1950                                     newtable->size2++;
1951                                     sscanf(iptr, "%lg",
1952                                                 &newtable->idx2.caps[newtable->size2]);
1953                                     if (newtable->var2 == OUTPUT_CAP)
1954                                         newtable->idx2.caps[newtable->size2] *= cap_unit;
1955                                     else
1956                                         newtable->idx2.cons[newtable->size2] *= time_unit;
1957                                 }
1958                                 newtable->size2++;
1959                             }
1960                             else {      // newtable->invert = 0
1961                                 // Count entries
1962                                 newtable->size1 = 1;
1963                                 while ((iptr = strchr(iptr, dnum)) != NULL) {
1964                                     iptr++;
1965                                     newtable->size1++;
1966                                 }
1967                                 newtable->idx1.times = (double *)malloc(newtable->size1 *
1968                                         sizeof(double));
1969                                 newtable->size1 = 0;
1970                                 iptr = token;
1971                                 sscanf(iptr, "%lg", &newtable->idx1.times[0]);
1972                                 newtable->idx1.times[0] *= time_unit;
1973                                 while ((iptr = strchr(iptr, dnum)) != NULL) {
1974                                     iptr++;
1975                                     newtable->size1++;
1976                                     sscanf(iptr, "%lg",
1977                                                 &newtable->idx1.times[newtable->size1]);
1978                                     newtable->idx1.times[newtable->size1] *= time_unit;
1979                                 }
1980                                 newtable->size1++;
1981                             }
1982 
1983                             token = advancetoken(flib, ';'); // EOL semicolon
1984                         }
1985                         else if (!tokencasecmp(token, "index_2")) {
1986 			    char dnum = ',';
1987 
1988                             token = advancetoken(flib, 0);      // Open parens
1989                             token = advancetoken(flib, 0);      // Quote
1990                             if (!strcmp(token, "\""))
1991                                 token = advancetoken(flib, '\"');
1992 
1993                             iptr = token;
1994 
1995 			    // Check if table is space or comma separated
1996 			    if (strchr(iptr, dnum) == NULL)
1997 				if (strchr(iptr, ' ') != NULL)
1998 				    dnum = ' ';
1999 
2000                             if (newtable->invert == 0) {
2001                                 // Count entries
2002                                 newtable->size2 = 1;
2003                                 while ((iptr = strchr(iptr, dnum)) != NULL) {
2004                                     iptr++;
2005                                     newtable->size2++;
2006                                 }
2007                                 newtable->idx2.caps = (double *)malloc(newtable->size2 *
2008                                         sizeof(double));
2009                                 newtable->size2 = 0;
2010                                 iptr = token;
2011                                 sscanf(iptr, "%lg", &newtable->idx2.caps[0]);
2012                                 if (newtable->var2 == OUTPUT_CAP)
2013                                     newtable->idx2.caps[0] *= cap_unit;
2014                                 else
2015                                     newtable->idx2.cons[0] *= time_unit;
2016                                 while ((iptr = strchr(iptr, dnum)) != NULL) {
2017                                     iptr++;
2018                                     newtable->size2++;
2019                                     sscanf(iptr, "%lg",
2020                                                 &newtable->idx2.caps[newtable->size2]);
2021                                     if (newtable->var2 == OUTPUT_CAP)
2022                                         newtable->idx2.caps[newtable->size2] *= cap_unit;
2023                                     else
2024                                         newtable->idx2.cons[newtable->size2] *= time_unit;
2025                                 }
2026                                 newtable->size2++;
2027                             }
2028                             else {      // newtable->invert == 1
2029                                 // Count entries
2030                                 newtable->size1 = 1;
2031                                 while ((iptr = strchr(iptr, dnum)) != NULL) {
2032                                     iptr++;
2033                                     newtable->size1++;
2034                                 }
2035                                 newtable->idx1.times = (double *)malloc(newtable->size1 *
2036                                         sizeof(double));
2037                                 newtable->size1 = 0;
2038                                 iptr = token;
2039                                 sscanf(iptr, "%lg", &newtable->idx1.times[0]);
2040                                 newtable->idx1.times[0] *= time_unit;
2041                                 while ((iptr = strchr(iptr, dnum)) != NULL) {
2042                                     iptr++;
2043                                     newtable->size1++;
2044                                     sscanf(iptr, "%lg",
2045                                                 &newtable->idx1.times[newtable->size1]);
2046                                     newtable->idx1.times[newtable->size1] *= time_unit;
2047                                 }
2048                                 newtable->size1++;
2049                             }
2050 
2051                             token = advancetoken(flib, ';'); // EOL semicolon
2052                         }
2053                     }
2054                 }
2055                 else if (!strcasecmp(token, "cell")) {
2056                     newcell = (cell *)malloc(sizeof(cell));
2057                     newcell->next = NULL;
2058                     if (lastcell != NULL)
2059                         lastcell->next = newcell;
2060                     else
2061                         *celllist = newcell;
2062                     lastcell = newcell;
2063                     token = advancetoken(flib, 0);      // Open parens
2064                     if (!strcmp(token, "("))
2065                         token = advancetoken(flib, ')');        // Cellname
2066 		    if (debug == 2) fprintf(stdout, "   cell = %s\n", token);
2067                     newcell->name = tokendup(token);
2068                     token = advancetoken(flib, 0);      // Find start of block
2069                     if (strcmp(token, "{"))
2070                         fprintf(stderr, "Error: failed to find start of block\n");
2071                     newcell->type = GATE;               // Default type
2072                     newcell->function = NULL;
2073                     newcell->pins = NULL;
2074                     newcell->area = 1.0;
2075                     newcell->maxtrans = 0.0;
2076                     newcell->maxcap = 0.0;
2077                     section = CELLDEF;
2078                 }
2079                 else if (!strcasecmp(token, "time_unit")) {
2080                    char *metric;
2081 
2082                    token = advancetoken(flib, 0);
2083                    if (token == NULL) break;
2084                    if (!strcmp(token, ":")) {
2085                       token = advancetoken(flib, 0);
2086                       if (token == NULL) break;
2087                    }
2088                    if (!strcmp(token, "\"")) {
2089                       token = advancetoken(flib, '\"');
2090                       if (token == NULL) break;
2091                    }
2092                    time_unit = strtod(token, &metric);
2093                    if (*metric != '\0') {
2094                       if (!strcmp(metric, "ns"))
2095                          time_unit *= 1E3;
2096                       else if (!strcmp(metric, "us"))
2097                          time_unit *= 1E6;
2098                       else if (!strcmp(metric, "fs"))
2099                          time_unit *= 1E-3;
2100                       else if (strcmp(metric, "ps"))
2101                          fprintf(stderr, "Don't understand time units \"%s\"\n",
2102                                 token);
2103                    }
2104                    else {
2105                       token = advancetoken(flib, 0);
2106                       if (token == NULL) break;
2107                       if (!strcmp(token, "ns"))
2108                          time_unit *= 1E3;
2109                       else if (!strcmp(token, "us"))
2110                          time_unit *= 1E6;
2111                       else if (!strcmp(token, "fs"))
2112                          time_unit *= 1E-3;
2113                       else if (strcmp(token, "ps"))
2114                          fprintf(stderr, "Don't understand time units \"%s\"\n",
2115                                 token);
2116                    }
2117                    token = advancetoken(flib, ';');
2118                 }
2119                 else if (!strcasecmp(token, "capacitive_load_unit")) {
2120                    char *metric;
2121 
2122                    token = advancetoken(flib, 0);
2123                    if (token == NULL) break;
2124                    if (!strcmp(token, "(")) {
2125                       token = advancetoken(flib, ')');
2126                       if (token == NULL) break;
2127                    }
2128                    cap_unit = strtod(token, &metric);
2129                    if (*metric != '\0') {
2130                       while (isblank(*metric)) metric++;
2131                       if (*metric == ',') metric++;
2132                       while ((*metric != '\0') && isblank(*metric)) metric++;
2133 		      if (*metric == '\"') {
2134 			 char *qptr;
2135 			 metric++;
2136 			 qptr = metric;
2137 			 while ((*qptr != '\"') && (*qptr != '\0')) qptr++;
2138 			 *qptr = '\0';
2139 		      }
2140                       if (!tokencasecmp(metric, "af"))
2141                          cap_unit *= 1E-3;
2142                       else if (!tokencasecmp(metric, "pf"))
2143                          cap_unit *= 1000;
2144                       else if (!tokencasecmp(metric, "nf"))
2145                          cap_unit *= 1E6;
2146                       else if (!tokencasecmp(metric, "uf"))
2147                          cap_unit *= 1E9;
2148                       else if (tokencasecmp(metric, "ff"))
2149                          fprintf(stderr, "Don't understand capacitive units \"%s\"\n",
2150                                 token);
2151                    }
2152                    else {
2153                       token = advancetoken(flib, 0);
2154                       if (token == NULL) break;
2155                       if (!tokencasecmp(token, "af"))
2156                          cap_unit *= 1E-3;
2157                       else if (!tokencasecmp(token, "pf"))
2158                          cap_unit *= 1000;
2159                       else if (!tokencasecmp(token, "nf"))
2160                          cap_unit *= 1E6;
2161                       else if (!tokencasecmp(token, "uf"))
2162                          cap_unit *= 1E9;
2163                       else if (tokencasecmp(token, "ff"))
2164                          fprintf(stderr, "Don't understand capacitive units \"%s\"\n",
2165                                 token);
2166                    }
2167                    token = advancetoken(flib, ';');
2168                 }
2169 		else if (!strcasecmp(token, "bus_naming_style")) {
2170 		    token = advancetoken(flib, 0);
2171 		    if (token == NULL) break;
2172 		    if (!strcmp(token, ":")) {
2173 			token = advancetoken(flib, 0);
2174 			if (token == NULL) break;
2175 		    }
2176 		    if (!strcmp(token, "\"")) {
2177 			token = advancetoken(flib, '\"');
2178 			if (token == NULL) break;
2179 		    }
2180 		    free(busformat);
2181 		    busformat = tokendup(token);
2182                     token = advancetoken(flib, ';');
2183 		}
2184 		else if (!strcasecmp(token, "type")) {
2185 		    newbus = (bus *)malloc(sizeof(bus));
2186 		    newbus->from = 0;
2187 		    newbus->to = 0;
2188 		    newbus->next = buses;
2189 		    buses = newbus;
2190 
2191 		    token = advancetoken(flib, 0);
2192 		    if (strcmp(token, "("))
2193 			fprintf(stderr, "Input missing open parenthesis.\n");
2194 		    else
2195 			token = advancetoken(flib, ')');
2196 		    newbus->name = tokendup(token);
2197 		    while (*token != '}') {
2198 			token = advancetoken(flib, 0);
2199 			if (!strcasecmp(token, "bit_from")) {
2200 			    token = advancetoken(flib, 0);
2201 			    token = advancetoken(flib, ';');
2202 			    sscanf(token, "%d", &newbus->from);
2203 			}
2204 			else if (!strcasecmp(token, "bit_to")) {
2205 			    token = advancetoken(flib, 0);
2206 			    token = advancetoken(flib, ';');
2207 			    sscanf(token, "%d", &newbus->to);
2208 			}
2209 			else if (!strcasecmp(token, "{")) {
2210 			    /* All entries are <name> : <value> */
2211 			    /* Ignore unhandled tokens.		*/
2212 			    token = advancetoken(flib, 0);
2213 			    token = advancetoken(flib, ';');
2214 			}
2215 		    }
2216 		}
2217                 else {
2218                     // For unhandled tokens, read in tokens.  If it is
2219                     // a definition or function, read to end-of-line.  If
2220                     // it is a block definition, read to end-of-block.
2221                     while (1) {
2222                         token = advancetoken(flib, 0);
2223                         if (token == NULL) break;
2224                         if (!strcmp(token, ";")) break;
2225                         if (!strcmp(token, "\""))
2226                             token = advancetoken(flib, '\"');
2227                         if (!strcmp(token, "{")) {
2228                             token = advancetoken(flib, '}');
2229                             break;
2230                         }
2231                     }
2232                 }
2233                 break;
2234 
2235             case CELLDEF:
2236 
2237 		if (debug == 2) fprintf(stdout, "CELLDEF: %s\n", token);
2238                 if (!strcmp(token, "}")) {
2239                     section = LIBBLOCK;                 // End of cell def
2240                 }
2241                 else if (!strcasecmp(token, "pin") ||
2242 			 !strcasecmp(token, "bus")) {
2243                     token = advancetoken(flib, 0);      // Open parens
2244                     if (!strcmp(token, "("))
2245                         token = advancetoken(flib, ')');        // Close parens
2246 
2247                     newpin = parse_pin(newcell, token);
2248 		    if (debug == 2) fprintf(stdout, "   pin = %s\n", token);
2249 
2250                     token = advancetoken(flib, 0);      // Find start of block
2251                     if (strcmp(token, "{"))
2252                         fprintf(stderr, "Error: failed to find start of block\n");
2253                     section = PINDEF;
2254                 }
2255                 else if (!strcasecmp(token, "area")) {
2256                     token = advancetoken(flib, 0);      // Colon
2257                     token = advancetoken(flib, ';');    // To end-of-statement
2258                     sscanf(token, "%lg", &newcell->area);
2259                 }
2260                 else if (!strcasecmp(token, "ff")) {
2261                     newcell->type |= DFF;
2262                     token = advancetoken(flib, '{');
2263                     section = FLOPDEF;
2264                 }
2265                 else if (!strcasecmp(token, "latch")) {
2266                     newcell->type |= LATCH;
2267                     token = advancetoken(flib, '{');
2268                     section = LATCHDEF;
2269                 }
2270                 else {
2271                     // For unhandled tokens, read in tokens.  If it is
2272                     // a definition or function, read to end-of-line.  If
2273                     // it is a block definition, read to end-of-block.
2274                     while (1) {
2275                         token = advancetoken(flib, 0);
2276                         if (token == NULL) break;
2277                         if (!strcmp(token, ";")) break;
2278                         if (!strcmp(token, "\""))
2279                             token = advancetoken(flib, '\"');
2280                         if (!strcmp(token, "("))
2281                             token = advancetoken(flib, ')');
2282                         if (!strcmp(token, "{")) {
2283                             token = advancetoken(flib, '}');
2284                             break;
2285                         }
2286                     }
2287                 }
2288                 break;
2289 
2290             case FLOPDEF:
2291 
2292 		if (debug == 2) fprintf(stdout, "FLOPDEF: %s\n", token);
2293                 if (!strcmp(token, "}")) {
2294                     section = CELLDEF;                  // End of flop def
2295                 }
2296                 else if (!strcasecmp(token, "next_state")) {
2297                     token = advancetoken(flib, 0);      // Colon
2298                     token = advancetoken(flib, ';');    // To end-of-statement
2299                     newpin = parse_pin(newcell, token);
2300                     newpin->type |= DFFIN;
2301                 }
2302                 else if (!strcasecmp(token, "clocked_on")) {
2303                     token = advancetoken(flib, 0);      // Colon
2304                     token = advancetoken(flib, ';');    // To end-of-statement
2305                     if (strchr(token, '\'') != NULL)
2306                         newcell->type |= CLK_SENSE_MASK;
2307                     else if (strchr(token, '!') != NULL)
2308                         newcell->type |= CLK_SENSE_MASK;
2309                     newpin = parse_pin(newcell, token);
2310                     newpin->type |= DFFCLK;
2311                 }
2312                 else if (!strcasecmp(token, "clear")) {
2313                     newcell->type |= RST_MASK;
2314                     token = advancetoken(flib, 0);      // Colon
2315                     token = advancetoken(flib, ';');    // To end-of-statement
2316                     if (strchr(token, '\'') != NULL)
2317                         newcell->type |= RST_SENSE_MASK;
2318                     else if (strchr(token, '!') != NULL)
2319                         newcell->type |= RST_SENSE_MASK;
2320                     newpin = parse_pin(newcell, token);
2321                     newpin->type |= DFFRST;
2322                 }
2323                 else if (!strcasecmp(token, "preset")) {
2324                     newcell->type |= SET_MASK;
2325                     token = advancetoken(flib, 0);      // Colon
2326                     token = advancetoken(flib, ';');    // To end-of-statement
2327                     if (strchr(token, '\'') != NULL)
2328                         newcell->type |= SET_SENSE_MASK;
2329                     else if (strchr(token, '!') != NULL)
2330                         newcell->type |= SET_SENSE_MASK;
2331                     newpin = parse_pin(newcell, token);
2332                     newpin->type |= DFFSET;
2333                 }
2334                 else
2335                     token = advancetoken(flib, ';');    // Read to end-of-statement
2336 
2337                 break;
2338 
2339             case LATCHDEF:
2340 
2341 		if (debug == 2) fprintf(stdout, "LATCHDEF: %s\n", token);
2342                 if (!strcmp(token, "}")) {
2343                     section = CELLDEF;                  // End of flop def
2344                 }
2345                 else if (!strcasecmp(token, "data_in")) {
2346                     token = advancetoken(flib, 0);      // Colon
2347                     token = advancetoken(flib, ';');    // To end-of-statement
2348                     newpin = parse_pin(newcell, token);
2349                     newpin->type |= LATCHIN;
2350                 }
2351                 else if (!strcasecmp(token, "enable")) {
2352                     token = advancetoken(flib, 0);      // Colon
2353                     token = advancetoken(flib, ';');    // To end-of-statement
2354                     if (strchr(token, '\'') != NULL)
2355                         newcell->type |= EN_SENSE_MASK;
2356                     else if (strchr(token, '!') != NULL)
2357                         newcell->type |= EN_SENSE_MASK;
2358                     newpin = parse_pin(newcell, token);
2359                     newpin->type |= LATCHEN;
2360                 }
2361                 else
2362                     token = advancetoken(flib, ';');    // Read to end-of-statement
2363 
2364                 break;
2365 
2366             case PINDEF:
2367 
2368 		if (debug == 2) fprintf(stdout, "PINDEF: %s\n", token);
2369                 if (!strcmp(token, "}")) {
2370 		    if (curbus != NULL)
2371 			expand_buses(newpin, curbus, busformat);
2372 		    curbus = NULL;
2373                     section = CELLDEF;                  // End of pin def
2374                 }
2375                 else if (!strcasecmp(token, "capacitance")) {
2376                     token = advancetoken(flib, 0);      // Colon
2377                     token = advancetoken(flib, ';');    // To end-of-statement
2378                     sscanf(token, "%lg", &newpin->capr);
2379                     newpin->capr *= cap_unit;
2380                 }
2381                 else if (!strcasecmp(token, "rise_capacitance")) {
2382                     token = advancetoken(flib, 0);      // Colon
2383                     token = advancetoken(flib, ';');    // To end-of-statement
2384                     sscanf(token, "%lg", &newpin->capr);
2385                     newpin->capr *= cap_unit;
2386                 }
2387                 else if (!strcasecmp(token, "fall_capacitance")) {
2388                     token = advancetoken(flib, 0);      // Colon
2389                     token = advancetoken(flib, ';');    // To end-of-statement
2390                     sscanf(token, "%lg", &newpin->capf);
2391                     newpin->capf *= cap_unit;
2392                 }
2393                 else if (!strcasecmp(token, "function")) {
2394                     token = advancetoken(flib, 0);      // Colon
2395                     token = advancetoken(flib, 0);      // Open quote
2396                     if (!strcmp(token, "\""))
2397                         token = advancetoken(flib, '\"');       // Find function string
2398                     if (newpin->type & OUTPUT) {
2399                         newcell->function = tokendup(token);
2400                     }
2401                     token = advancetoken(flib, 0);
2402                     if (strcmp(token, ";")) {
2403                         if (!strcmp(token, "}"))
2404                             section = CELLDEF;          // End of pin def
2405                         else
2406                             fprintf(stderr, "Expected end-of-statement.\n");
2407                     }
2408                 }
2409 		else if (!strcasecmp(token, "bus_type")) {
2410                     token = advancetoken(flib, 0);      // Colon
2411                     token = advancetoken(flib, ';');
2412 		    /* Find the bus definition */
2413 		    for (curbus = buses; curbus; curbus = curbus->next)
2414 			if (!tokencasecmp(token, curbus->name))
2415 			    break;
2416 		    if (curbus == NULL)
2417 			fprintf(stderr, "Failed to find a valid bus type \"%s\"\n",
2418 				token);
2419 		}
2420                 else if (!strcasecmp(token, "direction")) {
2421                     token = advancetoken(flib, 0);      // Colon
2422                     token = advancetoken(flib, ';');
2423                     if (!tokencasecmp(token, "input")) {
2424                         newpin->type |= INPUT;
2425                     }
2426                     else if (!tokencasecmp(token, "output")) {
2427                         newpin->type |= OUTPUT;
2428                         if (newcell->type & DFF) newpin->type |= DFFOUT;
2429                         if (newcell->type & LATCH) newpin->type |= LATCHOUT;
2430                     }
2431                 }
2432                 else if (!strcasecmp(token, "max_transition")) {
2433                     token = advancetoken(flib, 0);      // Colon
2434                     token = advancetoken(flib, ';');    // To end-of-statement
2435                     sscanf(token, "%lg", &newcell->maxtrans);
2436                     newcell->maxtrans *= time_unit;
2437                 }
2438                 else if (!strcasecmp(token, "max_capacitance")) {
2439                     token = advancetoken(flib, 0);      // Colon
2440                     token = advancetoken(flib, ';');    // To end-of-statement
2441                     sscanf(token, "%lg", &newcell->maxcap);
2442                     newcell->maxcap *= cap_unit;
2443                 }
2444                 else if (!strcasecmp(token, "timing")) {
2445                     token = advancetoken(flib, 0);      // Arguments, if any
2446                     if (strcmp(token, "("))
2447                         fprintf(stderr, "Error: failed to find start of block\n");
2448                     else
2449                        token = advancetoken(flib, ')'); // Arguments, if any
2450                     token = advancetoken(flib, 0);      // Find start of block
2451                     if (strcmp(token, "{"))
2452                         fprintf(stderr, "Error: failed to find start of block\n");
2453                     testpin = &proxypin;    /* Placeholder */
2454                     section = TIMING;
2455                 }
2456                 else {
2457                     // For unhandled tokens, read in tokens.  If it is
2458                     // a definition or function, read to end-of-line.  If
2459                     // it is a block definition, read to end-of-block.
2460                     while (1) {
2461                         token = advancetoken(flib, 0);
2462                         if (token == NULL) break;
2463                         if (!strcmp(token, ";")) break;
2464                         if (!strcmp(token, "\""))
2465                             token = advancetoken(flib, '\"');
2466                         if (!strcmp(token, "{")) {
2467                             token = advancetoken(flib, '}');
2468                             break;
2469                         }
2470                     }
2471                 }
2472                 break;
2473 
2474             case TIMING:
2475 
2476 		if (debug == 2) fprintf(stdout, "TIMING: %s\n", token);
2477                 if (!strcmp(token, "}")) {
2478                     section = PINDEF;                   // End of timing def
2479                 }
2480                 else if (!strcasecmp(token, "related_pin")) {
2481                     token = advancetoken(flib, 0);      // Colon
2482                     token = advancetoken(flib, ';');    // Read to end of statement
2483 		    if (testpin != &proxypin) {
2484 			fprintf(stderr, "Error:  Record already created"
2485 				" for related_pin");
2486 			free(testpin);
2487 		    }
2488                     // Create the related pin
2489                     testpin = parse_pin(newcell, token);
2490 		    // Copy any records from the placeholder
2491 		    testpin->sense = proxypin.sense;
2492                     testpin->propdelr = proxypin.propdelr;
2493                     testpin->propdelf = proxypin.propdelf;
2494                     testpin->transr = proxypin.transr;
2495                     testpin->transf = proxypin.transf;
2496 		    // Reset the placeholder records
2497 		    proxypin.sense = SENSE_NONE;
2498 		    proxypin.propdelr = NULL;
2499 		    proxypin.propdelf = NULL;
2500 		    proxypin.transr = NULL;
2501 		    proxypin.transf = NULL;
2502                 }
2503                 else if (!strcasecmp(token, "timing_sense")) {
2504                     token = advancetoken(flib, 0);      // Colon
2505                     token = advancetoken(flib, ';');    // Read to end of statement
2506                     if (!tokencasecmp(token, "positive_unate"))
2507                         testpin->sense = SENSE_POSITIVE;
2508                     else if (!tokencasecmp(token, "negative_unate"))
2509                         testpin->sense = SENSE_NEGATIVE;
2510                     else if (!tokencasecmp(token, "non_unate"))
2511                         testpin->sense = SENSE_NONE;
2512                 }
2513                 else if (!strcasecmp(token, "timing_type")) {
2514                     token = advancetoken(flib, 0);      // Colon
2515                     token = advancetoken(flib, ';');    // Read to end of statement
2516 
2517                     // Note:  Timing type is apparently redundant information;
2518                     // e.g., "falling_edge" can be determined by "clocked_on : !CLK"
2519                     // in the ff {} block.  How reliable is this?
2520 
2521                     if (!tokencasecmp(token, "rising_edge"))
2522                         timing_type = TIMING_PROP_TRANS;
2523                     else if (!tokencasecmp(token, "falling_edge"))
2524                         timing_type = TIMING_PROP_TRANS;
2525                     else if (!tokencasecmp(token, "hold_rising"))
2526                         timing_type = TIMING_HOLD;
2527                     else if (!tokencasecmp(token, "hold_falling"))
2528                         timing_type = TIMING_HOLD;
2529                     else if (!tokencasecmp(token, "setup_rising"))
2530                         timing_type = TIMING_SETUP;
2531                     else if (!tokencasecmp(token, "setup_falling"))
2532                         timing_type = TIMING_SETUP;
2533                     else if (!tokencasecmp(token, "clear"))
2534                         timing_type = TIMING_SET_RESET;
2535                     else if (!tokencasecmp(token, "preset"))
2536                         timing_type = TIMING_SET_RESET;
2537                     else if (!tokencasecmp(token, "recovery_rising"))
2538                         timing_type = TIMING_RECOVERY;
2539                     else if (!tokencasecmp(token, "recovery_falling"))
2540                         timing_type = TIMING_RECOVERY;
2541                     else if (!tokencasecmp(token, "removal_rising"))
2542                         timing_type = TIMING_REMOVAL;
2543                     else if (!tokencasecmp(token, "removal_falling"))
2544                         timing_type = TIMING_REMOVAL;
2545                     else if (!tokencasecmp(token, "three_state_enable"))
2546                         timing_type = TIMING_TRISTATE;
2547                     else if (!tokencasecmp(token, "three_state_disable"))
2548                         timing_type = TIMING_TRISTATE;
2549                 }
2550                 else if ((!strcasecmp(token, "cell_rise")) ||
2551                         (!strcasecmp(token, "cell_fall")) ||
2552                         (!strcasecmp(token, "rise_transition")) ||
2553                         (!strcasecmp(token, "fall_transition")) ||
2554                         (!strcasecmp(token, "rise_constraint")) ||
2555                         (!strcasecmp(token, "fall_constraint"))) {
2556 
2557                     tableptr = (lutable *)malloc(sizeof(lutable));
2558                     tableptr->name = NULL;      // Not used
2559                     tableptr->invert = 0;
2560                     tableptr->var1 = UNKNOWN;
2561                     tableptr->var2 = UNKNOWN;
2562                     tableptr->size1 = 0;
2563                     tableptr->size2 = 0;
2564                     tableptr->idx1.times = NULL;
2565                     tableptr->idx2.caps = NULL;
2566                     tableptr->values = NULL;
2567                     tableptr->next = NULL;      // Not used
2568 
2569                     // Note that propagation delays (cell rise, cell fall) and
2570                     // transition times (rise transition, fall transition) have
2571                     // their lookup tables stored in the "related pin" pin record.
2572                     // Setup and hold times (rise constraint, fall constraint)
2573                     // have their lookup tables stored in the original pin record.
2574                     // These should not overlap.
2575 
2576                     // Recovery and removal tables are not yet handled. . .
2577 
2578                     if (!strcasecmp(token, "cell_rise"))
2579                         testpin->propdelr = tableptr;
2580                     else if (!strcasecmp(token, "cell_fall"))
2581                         testpin->propdelf = tableptr;
2582                     else if (!strcasecmp(token, "rise_transition"))
2583                         testpin->transr = tableptr;
2584                     else if (!strcasecmp(token, "fall_transition"))
2585                         testpin->transf = tableptr;
2586                     else if (!strcasecmp(token, "rise_constraint")) {
2587                         if (timing_type == TIMING_SETUP)
2588                             newpin->propdelr = tableptr;
2589                         else if (timing_type == TIMING_HOLD)
2590                             newpin->transr = tableptr;
2591                     }
2592                     else if (!strcasecmp(token, "fall_constraint")) {
2593                         if (timing_type == TIMING_SETUP)
2594                             newpin->propdelf = tableptr;
2595                         else if (timing_type == TIMING_HOLD)
2596                             newpin->transf = tableptr;
2597                     }
2598 
2599                     token = advancetoken(flib, 0);      // Open parens
2600                     if (!strcmp(token, "("))
2601                         token = advancetoken(flib, ')');
2602 
2603                     for (reftable = *tablelist; reftable; reftable = reftable->next)
2604                         if (!tokencasecmp(token, reftable->name))
2605                             break;
2606                     if (reftable == NULL)
2607                         fprintf(stderr, "Failed to find a valid table \"%s\"\n",
2608                                 token);
2609                     else {
2610                         // Fill in default values from template reftable
2611                         tableptr->invert = reftable->invert;
2612                         if (reftable->size1 > 0) {
2613                             tableptr->var1 = reftable->var1;
2614                             tableptr->size1 = reftable->size1;
2615                             tableptr->idx1.times = (double *)malloc(tableptr->size1 * sizeof(double));
2616                             memcpy(tableptr->idx1.times, reftable->idx1.times,
2617                                                 tableptr->size1 * sizeof(double));
2618                         }
2619                         if (reftable->size2 > 0) {
2620                             tableptr->var2 = reftable->var2;
2621                             tableptr->size2 = reftable->size2;
2622                             tableptr->idx2.caps = (double *)malloc(tableptr->size2 * sizeof(double));
2623                             memcpy(tableptr->idx2.caps, reftable->idx2.caps,
2624                                                 tableptr->size2 * sizeof(double));
2625                         }
2626                     }
2627 
2628                     token = advancetoken(flib, 0);
2629                     if (strcmp(token, "{"))
2630                         fprintf(stderr, "Failed to find start of timing block\n");
2631 
2632                     while (*token != '}') {
2633                         token = advancetoken(flib, 0);
2634                         if (!tokencasecmp(token, "index_1")) {
2635 			    char dnum = ',';
2636 
2637                             // Local index values override those in the template
2638 
2639                             token = advancetoken(flib, 0);      // Open parens
2640                             token = advancetoken(flib, 0);      // Quote
2641                             if (!strcmp(token, "\""))
2642                                 token = advancetoken(flib, '\"');
2643 
2644                             iptr = token;
2645 
2646 			    // Check if table is space or comma separated
2647 			    if (strchr(iptr, dnum) == NULL)
2648 				if (strchr(iptr, ' ') != NULL)
2649 				    dnum = ' ';
2650 
2651                             //-------------------------
2652 
2653                             if (reftable && (reftable->invert == 1)) {
2654                                 // Entries had better match the ref table
2655                                 i = 0;
2656                                 sscanf(iptr, "%lg", &tableptr->idx2.caps[0]);
2657                                 if (tableptr->var2 == OUTPUT_CAP)
2658                                     tableptr->idx2.caps[0] *= cap_unit;
2659                                 else
2660                                     tableptr->idx2.cons[0] *= time_unit;
2661                                 while ((iptr = strchr(iptr, dnum)) != NULL) {
2662                                     iptr++;
2663                                     i++;
2664                                     sscanf(iptr, "%lg", &tableptr->idx2.caps[i]);
2665                                     if (tableptr->var2 == OUTPUT_CAP)
2666                                         tableptr->idx2.caps[i] *= cap_unit;
2667                                     else
2668                                         tableptr->idx2.cons[i] *= time_unit;
2669                                 }
2670                             }
2671                             else if (reftable && (reftable->invert == 0)) {
2672                                 iptr = token;
2673                                 i = 0;
2674                                 sscanf(iptr, "%lg", &tableptr->idx1.times[0]);
2675                                 tableptr->idx1.times[0] *= time_unit;
2676                                 while ((iptr = strchr(iptr, dnum)) != NULL) {
2677                                     iptr++;
2678                                     i++;
2679                                     sscanf(iptr, "%lg", &tableptr->idx1.times[i]);
2680                                     tableptr->idx1.times[i] *= time_unit;
2681                                 }
2682                             }
2683 
2684                             token = advancetoken(flib, ')');    // Close paren
2685                             token = advancetoken(flib, ';');    // EOL semicolon
2686                         }
2687                         else if (!tokencasecmp(token, "index_2")) {
2688 			    char dnum = ',';
2689 
2690                             // Local index values override those in the template
2691 
2692                             token = advancetoken(flib, 0);      // Open parens
2693                             token = advancetoken(flib, 0);      // Quote
2694                             if (!strcmp(token, "\""))
2695                                 token = advancetoken(flib, '\"');
2696 
2697                             iptr = token;
2698 
2699 			    // Check if table is space or comma separated
2700 			    if (strchr(iptr, dnum) == NULL)
2701 				if (strchr(iptr, ' ') != NULL)
2702 				    dnum = ' ';
2703 
2704                             //-------------------------
2705 
2706                             if (reftable && (reftable->invert == 1)) {
2707                                 // Entries had better match the ref table
2708                                 i = 0;
2709                                 sscanf(iptr, "%lg", &tableptr->idx1.times[0]);
2710                                 tableptr->idx1.times[0] *= time_unit;
2711                                 while ((iptr = strchr(iptr, dnum)) != NULL) {
2712                                     iptr++;
2713                                     i++;
2714                                     sscanf(iptr, "%lg", &tableptr->idx1.times[i]);
2715                                     tableptr->idx1.times[i] *= time_unit;
2716                                 }
2717                             }
2718                             else if (reftable && (reftable->invert == 0)) {
2719                                 iptr = token;
2720                                 i = 0;
2721                                 sscanf(iptr, "%lg", &tableptr->idx2.caps[0]);
2722                                 tableptr->idx2.caps[0] *= cap_unit;
2723                                 while ((iptr = strchr(iptr, dnum)) != NULL) {
2724                                     iptr++;
2725                                     i++;
2726                                     sscanf(iptr, "%lg", &tableptr->idx2.caps[i]);
2727                                     tableptr->idx2.caps[i] *= cap_unit;
2728                                 }
2729                             }
2730 
2731                             token = advancetoken(flib, ')');    // Close paren
2732                             token = advancetoken(flib, ';');    // EOL semicolon
2733                         }
2734                         else if (!tokencasecmp(token, "values")) {
2735                             token = advancetoken(flib, 0);
2736                             if (strcmp(token, "("))
2737                                 fprintf(stderr, "Failed to find start of"
2738                                                 " value table\n");
2739                             token = advancetoken(flib, ')');
2740 
2741                             // Parse the string of values and enter it into the
2742                             // table "values", which is size size2 x size1
2743 
2744                             if (reftable && reftable->size1 > 0) {
2745                                 int locsize2;
2746                                 locsize2 = (reftable->size2 > 0) ? reftable->size2 : 1;
2747                                 if (reftable->invert) {
2748                                     tableptr->values = (double *)malloc(locsize2 *
2749                                                 reftable->size1 * sizeof(double));
2750                                     iptr = token;
2751                                     for (i = 0; i < reftable->size1; i++) {
2752                                         for (j = 0; j < locsize2; j++) {
2753                                             while (*iptr == ' ' || *iptr == '\"' ||
2754                                                         *iptr == ',' || *iptr == '\\')
2755                                                 iptr++;
2756                                             sscanf(iptr, "%lg", &gval);
2757                                             *(tableptr->values + j * reftable->size1
2758                                                         + i) = gval * time_unit;
2759                                             while (*iptr != ' ' && *iptr != '\"' &&
2760                                                         *iptr != ',' || *iptr == '\\')
2761                                                 iptr++;
2762                                         }
2763                                     }
2764                                 }
2765                                 else {
2766                                     tableptr->values = (double *)malloc(locsize2 *
2767                                                 reftable->size1 * sizeof(double));
2768                                     iptr = token;
2769                                     for (j = 0; j < locsize2; j++) {
2770                                         for (i = 0; i < reftable->size1; i++) {
2771                                             while (*iptr == ' ' || *iptr == '\"' ||
2772                                                         *iptr == ',' || *iptr == '\\')
2773                                                 iptr++;
2774                                             sscanf(iptr, "%lg", &gval);
2775                                             *(tableptr->values + j * reftable->size1
2776                                                         + i) = gval * time_unit;
2777                                             while (*iptr != ' ' && *iptr != '\"' &&
2778                                                         *iptr != ',' || *iptr == '\\')
2779                                                 iptr++;
2780                                         }
2781                                     }
2782                                 }
2783                             }
2784 
2785                             token = advancetoken(flib, 0);
2786                             if (strcmp(token, ";"))
2787                                 fprintf(stderr, "Failed to find end of value table\n");
2788 			}
2789                         else if (!tokencasecmp(token, "ecsm_waveform")) {
2790 			    /* Not handled:  this takes the form of index_1 */
2791 			    /* key : value or index_2 key : value and	    */
2792 			    /* values key : value.			    */
2793 			    token = advancetoken(flib, 0);	// Open parens
2794 			    token = advancetoken(flib, ')');	// Close parens
2795 			    token = advancetoken(flib, '{');	// Open brace
2796 			    token = advancetoken(flib, '}');	// Close brace
2797 			}
2798                         else if (!tokencasecmp(token, "ecsm_capacitance")) {
2799 			    /* Not handled:  this takes the form of index_1 */
2800 			    /* key : value or index_2 key : value and	    */
2801 			    /* values key : value.			    */
2802 			    token = advancetoken(flib, 0);	// Open parens
2803 			    token = advancetoken(flib, ')');	// Close parens
2804 			    token = advancetoken(flib, '{');	// Open brace
2805 			    token = advancetoken(flib, '}');	// Close brace
2806 			}
2807                         else if (strcmp(token, "{") && strcmp(token, "}")) {
2808 			    fprintf(stderr, "Unhandled feature %s at line %d\n",
2809 					token, fileCurrentLine);
2810                             token = advancetoken(flib, 0);
2811 			    if (!strcmp(token, "(")) {		 // Open parens
2812 				token = advancetoken(flib, ')'); // Close parens
2813 				token = advancetoken(flib, 0);
2814 			    }
2815 			    if (!strcmp(token, "{"))		 // Open brace
2816 				token = advancetoken(flib, '}'); // Close brace
2817 			}
2818                     }
2819                 }
2820                 else {
2821                     // For unhandled tokens, read in tokens.  If it is
2822                     // a definition or function, read to end-of-line.  If
2823                     // it is a block definition, read to end-of-block.
2824                     while (1) {
2825                         token = advancetoken(flib, 0);
2826                         if (token == NULL) break;
2827                         if (!strcmp(token, ";")) break;
2828                         if (!strcmp(token, "\""))
2829                             token = advancetoken(flib, '\"');
2830                         if (!strcmp(token, "{")) {
2831                             token = advancetoken(flib, '}');
2832                             break;
2833                         }
2834                     }
2835                 }
2836                 break;
2837         }
2838         token = advancetoken(flib, 0);
2839     }
2840 }
2841 
2842 /*--------------------------------------------------------------*/
2843 /* Read a verilog netlist and collect information about the     */
2844 /* cells instantiated and the network structure                 */
2845 /*--------------------------------------------------------------*/
2846 
2847 void
verilogRead(char * filename,cell * cells,net ** netlist,instance ** instlist,connect ** inputlist,connect ** outputlist,struct hashtable * Nethash)2848 verilogRead(char *filename, cell *cells, net **netlist, instance **instlist,
2849                 connect **inputlist, connect **outputlist, struct hashtable *Nethash)
2850 {
2851     struct portrec  *port;
2852     struct instance *inst;
2853     struct cellrec  *topcell;
2854     struct netrec   *net;
2855 
2856     connptr newconn, testconn;
2857     instptr newinst;
2858     pinptr testpin;
2859     netptr newnet, testnet;
2860     cellptr testcell;
2861 
2862     int vstart, vtarget;
2863 
2864     /* Get verilog netlist structure using routines in readverilog.c */
2865     topcell = ReadVerilog(filename);
2866     if (topcell && topcell->name) {
2867 	fprintf(stdout, "Parsing module \"%s\"\n", topcell->name);
2868     }
2869 
2870     /* Build local connection lists from returned netlist structure */
2871 
2872     for (port = topcell->portlist; port; port = port->next) {
2873 	testconn = NULL;
2874 
2875 	// Create a net entry for the input or output, add to the list of nets
2876 
2877 	net = HashLookup(port->name, &topcell->nets);
2878 	if (net->start == 0 && net->end == 0) {
2879 	    newnet = create_net(netlist);
2880 	    newnet->name = tokendup(port->name);
2881 	    HashPtrInstall(newnet->name, newnet, Nethash);
2882 
2883 	    testconn = (connptr)malloc(sizeof(connect));
2884 	    testconn->refnet = newnet;
2885 	    testconn->refpin = NULL;        // No associated pin
2886 	    testconn->refinst = NULL;       // No associated instance
2887 	    testconn->tag = NULL;
2888 	    testconn->metric = -1.0;
2889 	    testconn->icDelay = 0.0;
2890 	    testconn->visited = (unsigned char)0;
2891 	    testconn->prvector = NULL;
2892 	    testconn->pfvector = NULL;
2893 	    testconn->trvector = NULL;
2894 	    testconn->tfvector = NULL;
2895 
2896             if (port->direction == PORT_INPUT) {    // driver (input)
2897 		testconn->next = *inputlist;
2898 		*inputlist = testconn;
2899             }
2900             else {				    // receiver (output)
2901 		testconn->next = *outputlist;
2902 		*outputlist = testconn;
2903             }
2904 	}
2905 	else {
2906 	    vtarget = net->end + ((net->start < net->end) ? 1 : -1);
2907 	    vstart = net->start;
2908 	    while (vstart != vtarget) {
2909 		newnet = create_net(netlist);
2910 		newnet->name = (char *)malloc(strlen(port->name) + 6);
2911 		sprintf(newnet->name, "%s[%d]", port->name, vstart);
2912 		HashPtrInstall(newnet->name, newnet, Nethash);
2913 
2914 		vstart += (vtarget > net->end) ? 1 : -1;
2915 
2916 		testconn = (connptr)malloc(sizeof(connect));
2917 		testconn->refnet = newnet;
2918 		testconn->refpin = NULL;    // No associated pin
2919 		testconn->refinst = NULL;   // No associated instance
2920 		testconn->tag = NULL;
2921 		testconn->metric = -1.0;
2922 		testconn->icDelay = 0.0;
2923 		testconn->visited = (unsigned char)0;
2924 		testconn->prvector = NULL;
2925 		testconn->pfvector = NULL;
2926 		testconn->trvector = NULL;
2927 		testconn->tfvector = NULL;
2928 
2929 		if (port->direction == PORT_INPUT) {    // driver (input)
2930 		    testconn->next = *inputlist;
2931 		    *inputlist = testconn;
2932 		}
2933 		else {                      // receiver (output)
2934 		    testconn->next = *outputlist;
2935 		    *outputlist = testconn;
2936 		}
2937 	    }
2938 	}
2939     }
2940 
2941     for (inst = topcell->instlist; inst; inst = inst->next) {
2942         for (testcell = cells; testcell; testcell = testcell->next)
2943             if (!strcasecmp(testcell->name, inst->cellname))
2944                 break;
2945 
2946 	// NOTE:  testcell may be NULL for non-functional cells like
2947 	// filler cells which have no I/O and so have no timing.  Only
2948 	// report cells that are relevant to timing and do not show up
2949 	// in the liberty database (portlist is non-NULL).
2950 
2951         if ((testcell == NULL) && (inst->portlist != NULL)) {
2952 	    fprintf(stderr, "Cell \"%s\" was not in the liberty database!\n",
2953 		    inst->cellname);
2954 	    continue;
2955 	}
2956 
2957         newinst = (instptr)malloc(sizeof(instance));
2958         newinst->next = *instlist;
2959         *instlist = newinst;
2960         newinst->refcell = testcell;
2961         newinst->in_connects = NULL;
2962         newinst->out_connects = NULL;
2963         newinst->name = tokendup(inst->instname);
2964 
2965 	for (port = inst->portlist; port; port = port->next) {
2966             newconn = (connptr)malloc(sizeof(connect));
2967             for (testpin = testcell->pins; testpin; testpin = testpin->next) {
2968                 if (!strcmp(testpin->name, port->name))
2969                     break;
2970             }
2971             // Sanity check
2972             if (testpin == NULL) {
2973                 fprintf(stderr, "No such pin \"%s\" in cell \"%s\"!\n",
2974                         port->name, testcell->name);
2975             }
2976             else {
2977                 if (testpin->type & OUTPUT) {
2978                     newconn->next = newinst->out_connects;
2979                     newinst->out_connects = newconn;
2980                 }
2981                 else {
2982                     newconn->next = newinst->in_connects;
2983                     newinst->in_connects = newconn;
2984                 }
2985             }
2986             newconn->refinst = newinst;
2987             newconn->refpin = testpin;
2988             newconn->refnet = NULL;
2989             newconn->tag = NULL;
2990             newconn->metric = -1.0;
2991 	    newconn->icDelay = 0.0;
2992 	    newconn->visited = (unsigned char)0;
2993             newconn->prvector = NULL;
2994             newconn->pfvector = NULL;
2995             newconn->trvector = NULL;
2996             newconn->tfvector = NULL;
2997 
2998             testnet = (netptr)HashLookup(port->net, Nethash);
2999             if (testnet == NULL) {
3000                 // This is a new net, and we need to record it
3001                 newnet = create_net(netlist);
3002                 newnet->name = tokendup(port->net);
3003                 HashPtrInstall(newnet->name, newnet, Nethash);
3004                 newconn->refnet = newnet;
3005             }
3006             else
3007                 newconn->refnet = testnet;
3008 	}
3009     }
3010     FreeVerilog(topcell);   // All structures transferred
3011 }
3012 
3013 /*--------------------------------------------------------------*/
3014 /* For each net, go through the list of receivers and add the   */
3015 /* contributions of each to the total load.  This is either     */
3016 /* the input pin capacitance, if the receiver is a pin, or the  */
3017 /* designated output load (given on the command line), if the   */
3018 /* receiver is an output pin.                                   */
3019 /*--------------------------------------------------------------*/
3020 
3021 void
computeLoads(netptr netlist,instptr instlist,double out_load)3022 computeLoads(netptr netlist, instptr instlist, double out_load)
3023 {
3024     instptr testinst;
3025     pinptr testpin;
3026     netptr testnet, driver, loadnet;
3027     connptr testconn;
3028     int i;
3029 
3030     for (testnet = netlist; testnet; testnet = testnet->next) {
3031         for (i = 0; i < testnet->fanout; i++) {
3032             testconn = testnet->receivers[i];
3033             testpin = testconn->refpin;
3034             if (testpin == NULL) {
3035                 testnet->loadr += out_load;
3036                 testnet->loadf += out_load;
3037             }
3038             else {
3039                 testnet->loadr += testpin->capr;
3040                 testnet->loadf += testpin->capf;
3041             }
3042         }
3043     }
3044 
3045     // For each instance input pin, collapse the pin's lookup table
3046     // to a vector by interpolating/extrapolating the table at the
3047     // calculated output load.  Save this vector in the connection
3048     // record for the pin.
3049 
3050     for (testinst = instlist; testinst; testinst = testinst->next) {
3051 	double loadr, loadf;
3052 	if (testinst->out_connects != NULL) {
3053 	    loadnet = testinst->out_connects->refnet;
3054 	    loadr = loadnet->loadr;
3055 	    loadf = loadnet->loadf;
3056 	}
3057 	else {
3058 	    loadr = 0.0;
3059 	    loadf = 0.0;
3060 	}
3061 
3062 	for (testconn = testinst->in_connects; testconn; testconn = testconn->next) {
3063 	    testpin = testconn->refpin;
3064 
3065             if (testpin->propdelr)
3066                 testconn->prvector = table_collapse(testpin->propdelr, loadr);
3067             if (testpin->propdelf)
3068                 testconn->pfvector = table_collapse(testpin->propdelf, loadf);
3069             if (testpin->transr)
3070                 testconn->trvector = table_collapse(testpin->transr, loadr);
3071             if (testpin->transf)
3072                 testconn->tfvector = table_collapse(testpin->transf, loadf);
3073         }
3074     }
3075 }
3076 
3077 /*--------------------------------------------------------------*/
3078 /* Assign types to each net.  This identifies which nets are    */
3079 /* clock inputs, which are latch enable inputs, and which are   */
3080 /* asynchronous set/reset inputs,.                              */
3081 /*                                                              */
3082 /* Whenever a clock input to a flop is found, add the           */
3083 /* connection record to clockedlist                             */
3084 /*                                                              */
3085 /* For diagnostics, return the number of entries in clockedlist */
3086 /*--------------------------------------------------------------*/
3087 
assign_net_types(netptr netlist,connlistptr * clockedlist)3088 int assign_net_types(netptr netlist, connlistptr *clockedlist)
3089 {
3090     int i, numterms;
3091     netptr testnet;
3092     connptr testrcvr;
3093     pinptr testpin;
3094     connlistptr newclocked;
3095 
3096     numterms = 0;
3097 
3098     for (testnet = netlist; testnet; testnet = testnet->next) {
3099 	/* Nets with no fanout are by definition module outputs */
3100 	if (testnet->fanout == 0) testnet->type |= OUTTERM;
3101         for (i = 0; i < testnet->fanout; i++) {
3102             testrcvr = testnet->receivers[i];
3103             testpin = testrcvr->refpin;
3104             if (testpin == NULL)
3105                 testnet->type |= OUTTERM;
3106             else {
3107                 switch (testpin->type & (DFFMASK | LATCHMASK)) {
3108                     case DFFCLK:
3109                         testnet->type |= CLOCK;
3110                         newclocked = (connlistptr)malloc(sizeof(connlist));
3111                         newclocked->connection = testrcvr;
3112                         newclocked->next = *clockedlist;
3113                         *clockedlist = newclocked;
3114                         numterms++;
3115                         break;
3116                     case DFFIN:
3117                         testnet->type |= TERMINAL;
3118                         break;
3119                     case DFFSET:
3120                     case DFFRST:
3121                         testnet->type |= ASYNC;
3122                         break;
3123                     case LATCHIN:
3124                         testnet->type |= LATCHTERM;
3125                         break;
3126                     case LATCHEN:
3127                         testnet->type |= ENABLE;
3128                         break;
3129                 }
3130             }
3131         }
3132     }
3133     return numterms;
3134 }
3135 
3136 /*--------------------------------------------------------------*/
3137 /* Create the links representing the netlist connections.       */
3138 /*                                                              */
3139 /* The verilogRead() routine added all nets and instances, and  */
3140 /* for each instance, generated a list of net connections to    */
3141 /* each pin.  To make the netlist easily traversible, this      */
3142 /* routine does the following:                                  */
3143 /*                                                              */
3144 /* For each instance, work through the list of pin              */
3145 /*      connections.  If the pin is an output, then add the     */
3146 /*      connection as the net's driver entry.  If the pin is    */
3147 /*      an input, then add the connection to the list of the    */
3148 /*      net's receivers, and increment the net's fanout.        */
3149 /*                                                              */
3150 /* For each module input, add the input connection as the       */
3151 /*      net's driver (flag an error if the net already has a    */
3152 /*      driver).                                                */
3153 /*                                                              */
3154 /* For each module output, add the output connection as one of  */
3155 /*      the net's receivers (it may be the only one).           */
3156 /*                                                              */
3157 /*--------------------------------------------------------------*/
3158 
3159 void
createLinks(netptr netlist,instptr instlist,connptr inputlist,connptr outputlist)3160 createLinks(netptr netlist, instptr instlist, connptr inputlist, connptr outputlist)
3161 {
3162     netptr testnet;
3163     instptr testinst;
3164     connptr testconn;
3165 
3166     for (testinst = instlist; testinst; testinst = testinst->next) {
3167         for (testconn = testinst->in_connects; testconn; testconn = testconn->next) {
3168             testnet = testconn->refnet;
3169             testnet->fanout++;
3170             if (testnet->receivers == NULL)
3171                 testnet->receivers = (connptr *)malloc(sizeof(connptr));
3172 
3173             else
3174                 testnet->receivers = (connptr *)realloc(testnet->receivers,
3175                                 testnet->fanout * sizeof(connptr));
3176 
3177             testnet->receivers[testnet->fanout - 1] = testconn;
3178         }
3179 
3180         for (testconn = testinst->out_connects; testconn; testconn = testconn->next) {
3181             testnet = testconn->refnet;
3182             testnet->driver = testconn;
3183         }
3184     }
3185 
3186     for (testconn = inputlist; testconn; testconn = testconn->next) {
3187         testnet = testconn->refnet;
3188         if (testnet->driver != NULL)
3189             fprintf(stderr, "Error:  Input pin \"%s\" has an internal driver!\n",
3190                         testnet->name);
3191         // else
3192         //    testnet->driver = testconn;       // Don't do this, makes connectivity circular
3193     }
3194 
3195     for (testconn = outputlist; testconn; testconn = testconn->next) {
3196         testnet = testconn->refnet;
3197         testnet->fanout++;
3198         if (testnet->receivers == NULL)
3199             testnet->receivers = (connptr *)malloc(sizeof(connptr));
3200 
3201         else
3202             testnet->receivers = (connptr *)realloc(testnet->receivers,
3203                         testnet->fanout * sizeof(connptr));
3204 
3205         testnet->receivers[testnet->fanout - 1] = testconn;
3206     }
3207 }
3208 
3209 /*--------------------------------------------------------------*/
3210 /* Delay comparison used by qsort() to sort paths in order from */
3211 /* longest to shortest propagation delay.                       */
3212 /*--------------------------------------------------------------*/
3213 
3214 int
compdelay(ddataptr * a,ddataptr * b)3215 compdelay(ddataptr *a, ddataptr *b)
3216 {
3217     ddataptr p = *a;
3218     ddataptr q = *b;
3219 
3220     if (p->delay < q->delay)
3221         return (1);
3222     if (p->delay > q->delay)
3223         return (-1);
3224     return (0);
3225 }
3226 
3227 void
delayRead(FILE * fdly,struct hashtable * Nethash)3228 delayRead(FILE *fdly, struct hashtable *Nethash)
3229 {
3230     char c[128];
3231     char d[128];
3232     char *token;
3233     char *result;
3234     char *tokencopy = NULL;
3235 
3236     netptr newnet, testnet;
3237     connptr testconn;
3238     pinptr testpin;
3239     int i;
3240     int numRxers;
3241 
3242     if (debug == 1)
3243 	fprintf(stdout, "delayRead\n");
3244 
3245     /* NOTE:  Do not use 0 for delimiter, or else ':' is considered to	*/
3246     /* be a standard delimiter, breaking up certain yosys-generated	*/
3247     /* net names.							*/
3248 
3249     token = advancetokennocont(fdly, '\n');
3250     result = token;
3251 
3252     while (token != NULL) {
3253 
3254         char *saveptr;
3255         char *saveptr2;
3256 
3257         numRxers = 0;
3258         testnet = (netptr)HashLookup(token, Nethash);
3259 
3260 	/* Syntax cleanup for net renaming between various	*/
3261 	/* netlist formats.					*/
3262 
3263 	if ((testnet == NULL) && cleanup) {
3264 	    char *mchr, *dchr;
3265 	    /* Handle the insane backslash-escape names in verilog.
3266 	     * To make these compatible with SPICE, qflow opts to
3267 	     * replace the ending space character with another
3268 	     * backslash.  The 2nd backslash has to be replaced by
3269 	     * the original space character to match the original
3270 	     * verilog net name.
3271 	     */
3272 
3273 	    if (*token == '\\') {
3274 	        if ((mchr = strchr(token + 1, '\\')) != NULL) {
3275 		    dchr = strchr(token + 1, ' ');
3276 		    if ((dchr == NULL) || (dchr > mchr)) *mchr = ' ';
3277 		}
3278 	    }
3279 	    testnet = (netptr)HashLookup(token, Nethash);
3280 
3281 	    /* Other, legacy stuff. */
3282 	    if (testnet == NULL) {
3283 		tokencopy = strdup(token);
3284 		if ((mchr = strrchr(tokencopy, '<')) != NULL) {
3285 		    if ((dchr = strrchr(tokencopy, '>')) != NULL) {
3286 			if (mchr < dchr) {
3287 			    *mchr = '[';
3288 			    *dchr = ']';
3289 			}
3290 		    }
3291 		}
3292 		testnet = (netptr)HashLookup(tokencopy, Nethash);
3293 	    }
3294 
3295 	    if (testnet == NULL) {
3296 		for (mchr = tokencopy; *mchr != '\0'; mchr++) {
3297 		    if ((*mchr == ':') || (*mchr == '.') || (*mchr == '$')
3298 				|| (*mchr == '<') || (*mchr == '>'))
3299 			*mchr = '_';
3300 		}
3301 		testnet = (netptr)HashLookup(tokencopy, Nethash);
3302 	    }
3303 
3304 	    if (testnet == NULL) {
3305 		for (mchr = tokencopy; *mchr != '\0'; mchr++) {
3306 		    if ((*mchr == '[') || (*mchr == ']'))
3307 			*mchr = '_';
3308 		}
3309 		testnet = (netptr)HashLookup(tokencopy, Nethash);
3310 	    }
3311 	}
3312 	if (tokencopy != NULL) free(tokencopy);
3313 
3314 	if (testnet == NULL) {
3315 	    fprintf(stderr, "ERROR: Net %s not found in hash table\n", token);
3316 	    exit(-1);
3317 	}
3318 
3319         // Read driver of interconnect and total interconnect capacitance
3320         result = fgets(c, 128, fdly);
3321 	if (result == NULL) break;
3322 
3323         strtok_r(c, "/", &saveptr);
3324         if (debug == 1)
3325             fprintf(stdout, "\tDriver Inst: %s\n", saveptr);
3326         strtok_r(NULL, " ", &saveptr);
3327         if (debug == 1) {
3328             fprintf(stdout, "\tDriver Pin: %s\n", saveptr);
3329             fprintf(stdout, "\tTotC: %f\n", strtof(saveptr, NULL));
3330 	}
3331 
3332 	if (c[1] == '\0') {
3333 	    fprintf(stderr, "ERROR: Driver not found for net %s\n", testnet->name);
3334 	}
3335 
3336         /* Load in .dly file is in pF, but we keep fF in loadr/loadf */
3337         testnet->loadr = (strtod(saveptr, NULL)) * 1e3;
3338         testnet->loadf = testnet->loadr;
3339 
3340         result = fgets(c, 128, fdly);
3341 	if (result == NULL) break;
3342 
3343         while (c[0] != '\n') {
3344             if (debug == 1) fprintf(stdout, "\t%s\n", c);
3345 
3346             //separate receiver name and delay value
3347             strtok_r(c, " ", &saveptr);
3348 	    if (debug == 1) {
3349                 fprintf(stdout, "\tDelay: %s\n", saveptr);
3350                 fprintf(stdout, "\tRxer Name: %s\n", c);
3351 	    }
3352             strtok_r(c, "/", &saveptr2);
3353 	    if (debug == 1) {
3354                 fprintf(stdout, "\tRxer Name: %s\n", c);
3355                 fprintf(stdout, "\tRxer Name: %s\n", saveptr2);
3356                 fprintf(stdout, "\tDelay: %f\n", strtof(saveptr, NULL));
3357 	    }
3358 
3359             for (i = 0; i < testnet->fanout; i++) {
3360 
3361                 testconn = testnet->receivers[i];
3362 
3363                 if (testnet->type == OUTTERM) {
3364 		    if (debug == 1)
3365                         fprintf(stdout, "\tNet connects to output and has no "
3366 				"receiving instance pin\n");
3367                     testconn->icDelay = strtod(saveptr, NULL);
3368                 } else {
3369 		    if (debug == 1)
3370                         fprintf(stdout, "\trefinstname: %s\n", testconn->refinst->name);
3371 
3372                     if (!strcmp(testconn->refinst->name, c)) {
3373 
3374                         testconn->icDelay = strtod(saveptr, NULL);
3375                         break;
3376                     }
3377                 }
3378 		if (debug == 1)
3379                     fprintf(stdout, "\tName: %s\n", c);
3380             }
3381 
3382             result = fgets(c, 128, fdly);
3383 	    if (result == NULL) break;
3384             numRxers += 1;
3385         }
3386 	if (result == NULL) break;
3387 
3388         if (numRxers != testnet->fanout) {
3389 	    if (numRxers != 1 || testnet->fanout > 0 || testnet->type != OUTTERM)
3390 		fprintf(stderr, "ERROR: Net %s had %d receiver%s in delay file, "
3391 			" but expected a fanout of %d\n", testnet->name,
3392 			numRxers, (numRxers == 1) ? "" : "s",
3393 			testnet->fanout);
3394         }
3395 
3396         token = advancetokennocont(fdly, '\n');
3397     }
3398     if (result == NULL) {
3399 	fprintf(stderr, "ERROR: Unexpected end-of-file while reading delay file.\n");
3400     }
3401 }
3402 
3403 /*--------------------------------------------------------------*/
3404 /* Print a path component                                       */
3405 /* (code contributed by Karl-Filip Faxen)			*/
3406 /*--------------------------------------------------------------*/
3407 
3408 void
print_path_component(int netFWidth,int instFWidth,int pinFWidth,int recvFWidth,btptr backtrace,FILE * file)3409 print_path_component(int netFWidth, int instFWidth, int pinFWidth, int recvFWidth,
3410                      btptr backtrace, FILE *file)
3411 {
3412     // Return immediately if we have niether a driver or a receiver instance
3413     if (backtrace->receiver->refnet->driver == NULL &&
3414 		backtrace->receiver->refinst == NULL) return;
3415 
3416     fprintf(file, " %8.1f ps", backtrace->delay);
3417     if (backtrace->receiver->refnet != NULL) {
3418         netptr net = backtrace->receiver->refnet;
3419         fprintf(file, "  %*s: ", netFWidth, net->name);
3420         if (net->driver != NULL) {   // If the driver exists, it has a refinst
3421             fprintf(file, "%*s/%*s",
3422                     instFWidth, net->driver->refinst->name,
3423                     -pinFWidth, net->driver->refpin->name);
3424         }
3425         else {
3426             fprintf(file, "%*s", instFWidth + pinFWidth + 1, "");
3427         }
3428     }
3429     fprintf(file, " -> ");
3430     if (backtrace->receiver->refinst != NULL) {
3431         fprintf(file, "%*s/%s",
3432                 recvFWidth, backtrace->receiver->refinst->name,
3433                               backtrace->receiver->refpin->name);
3434     }
3435     else if (backtrace->receiver->refnet)
3436         fprintf(file, "%s", backtrace->receiver->refnet->name);
3437 
3438     fprintf(file, "\n");
3439 }
3440 
3441 /*--------------------------------------------------------------*/
3442 /* Print a path                                                 */
3443 /* (code contributed by Karl-Filip Faxen)			*/
3444 /*--------------------------------------------------------------*/
3445 
3446 void
print_path(btptr backtrace,FILE * file)3447 print_path(btptr backtrace, FILE *file)
3448 {
3449     int netFWidth = 0;
3450     int instFWidth = 0;
3451     int pinFWidth = 0;
3452     int recvFWidth = 0;
3453     btptr curr = backtrace, prev = NULL;
3454 
3455     // The back trace is last entry first, so we do one pointer reversal to
3456     // get it in first entry first order, then we reverse it back again.
3457 
3458     while (curr != NULL) {
3459         // Find max length of net name, inst name and pin name
3460         netptr net = curr->receiver->refnet;
3461         if (net != NULL) {
3462             int namelen = strlen(net->name);
3463             if (namelen > netFWidth) netFWidth = namelen;
3464             if (net->driver != NULL) { // If driver exists, it has an instance
3465                 int instlen = strlen(net->driver->refinst->name);
3466                 if (instlen > instFWidth) instFWidth = instlen;
3467                 int pinlen = strlen(net->driver->refpin->name);
3468                 if (pinlen > pinFWidth) pinFWidth = pinlen;
3469             }
3470         }
3471         // Find max length of receiving inst name
3472         if (curr->receiver->refinst != NULL) {
3473             int instlen = strlen(curr->receiver->refinst->name);
3474             if (instlen > recvFWidth) recvFWidth = instlen;
3475         }
3476         // Do the first pointer reversal
3477         btptr tmp = curr->next;
3478         curr->next = prev;
3479         prev = curr;
3480         curr = tmp;
3481     }
3482 
3483     curr = prev;
3484     prev = NULL;
3485 
3486     while (curr != NULL) {
3487         print_path_component(netFWidth, instFWidth, pinFWidth, recvFWidth, curr, file);
3488         // Do the second pointer reversal
3489         btptr tmp = curr->next;
3490         curr->next = prev;
3491         prev = curr;
3492         curr = tmp;
3493     }
3494     fprintf(file, "\n");
3495 }
3496 
3497 /*--------------------------------------------------------------*/
3498 /* Given a list of paths, find the clock at the source and the	*/
3499 /* destination (if neither is a pin), and compute the clock	*/
3500 /* skew between them.  Also compute the setup or hold at the	*/
3501 /* destination.	 Save these values in the path record.		*/
3502 /*--------------------------------------------------------------*/
3503 
3504 void
find_clock_skews(ddataptr pathlist,char minmax)3505 find_clock_skews(ddataptr pathlist, char minmax)
3506 {
3507     connptr testconn, thisconn;
3508     instptr  testinst;
3509 
3510     ddataptr testddata, srcddata, freeddata;
3511     ddataptr clocklist, clock2list;
3512     btptr    backtrace, freebt, pathbt, btcommon;
3513     btptr    selectedsource, selecteddest;
3514 
3515     short srcdir, destdir;		// Signal direction in/out
3516     double setupdelay, holddelay;
3517     unsigned char result;
3518     char	clk_invert, clk_sense_inv;
3519 
3520     clocklist = NULL;
3521     clock2list = NULL;
3522 
3523     for (testddata = pathlist; testddata; testddata = testddata->next) {
3524 
3525         // Find the end of the linked list, which is the path start.
3526         for (pathbt = testddata->backtrace; pathbt->next; pathbt = pathbt->next);
3527 	thisconn = pathbt->receiver;
3528 
3529         if (thisconn && thisconn->refpin) {
3530             // Find the sources of the clock at the path start.  Create
3531 	    // a tree of backtraces from thisconn to all clock sources,
3532 	    // and return clocklist, which is a list of the sources.
3533 
3534             find_clock_source(thisconn, &clocklist, NULL, srcdir, (unsigned char)1);
3535 
3536             // Calculate the worst-case transition times to testlink on
3537 	    // each clocklist backtrace.
3538 
3539             find_clock_transition(clocklist, thisconn, srcdir, minmax,
3540 			(unsigned char)1);
3541 	}
3542 
3543         // Copy last backtrace delay to testddata.
3544         testddata->delay = testddata->backtrace->delay;
3545         testddata->trans = testddata->backtrace->trans;
3546         testinst = testddata->backtrace->receiver->refinst;
3547         selecteddest = selectedsource = NULL;
3548 
3549         if (testinst != NULL) {
3550             // Find the sources of the clock at the path end
3551             destdir = (testinst->refcell->type & CLK_SENSE_MASK) ? FALLING : RISING;
3552             testconn = find_register_clock(testinst);
3553             // If testconn is NULL, this is not a register (latch, maybe?)
3554             if (testconn == NULL) continue;
3555 
3556             // Find the connection that is common to both clocks
3557             result = find_clock_source(testconn, &clock2list, NULL, destdir,
3558 			(unsigned char)2);
3559 
3560 	    if ((result == (unsigned char)0) && (clocklist != NULL)) {
3561 		// If both paths end on the same input net, then there
3562 		// is no connection pointer, so deal with that separately.
3563 
3564 		if (clocklist->backtrace->receiver->refnet !=
3565 			    	clock2list->backtrace->receiver->refnet) {
3566 
3567 		    // Warn about asynchronous clock sources
3568 		    if (verbose > 1) {
3569 		 	fflush(stdout);
3570 			fprintf(stderr, "Independent clock nets \"%s\" and \"%s\""
3571 					" drive related gates!\n",
3572 					testconn->refnet->name,
3573 					thisconn->refnet->name);
3574 		    }
3575 		    clk_invert = -1;
3576 		}
3577             }
3578 
3579 	    // If clocklist is NULL then this is an input and there is
3580 	    // no way to compute relative to a common clock, because
3581 	    // there is no common clock.
3582 
3583 	    if (clocklist != NULL) {
3584 		// Find clock arrival times from common clock point.  Note that
3585 		// the check is opposite to what is computed for the source;  if
3586 		// maximum time was used to find clock-to-source, then minimum
3587 		// time is used to find clock-to-destination.
3588 
3589 		btcommon = find_common_clock(clock2list, clocklist);
3590                 find_clock_transition(clock2list, testconn,
3591 				(btcommon) ? btcommon->dir : RISING,
3592 				~minmax, (unsigned char)2);
3593 
3594 		// selectedsource is the end of the btcommon backtrace
3595 		for (selectedsource = (btcommon) ? btcommon : clocklist->backtrace;
3596 				selectedsource->next;
3597 				selectedsource = selectedsource->next);
3598 		// selecteddest is the end of the clock2list backtrace
3599 		for (selecteddest = clock2list->backtrace; selecteddest->next;
3600 				selecteddest = selecteddest->next);
3601 
3602                 // Add or subtract difference in arrival times between source and
3603                 // destination clocks
3604 
3605                 testddata->skew = selectedsource->delay - selecteddest->delay -
3606 					((btcommon) ? btcommon->delay : 0.0);
3607                 testddata->delay += testddata->skew;
3608 	    }
3609 	    else if (clock2list) {
3610 		// Still need to know destination's clock source to
3611 		// calculate setup or hold time.
3612 		for (selecteddest = clock2list->backtrace; selecteddest->next;
3613 				selecteddest = selecteddest->next);
3614 		testddata->skew = 0.0;
3615 	    }
3616 
3617             if (minmax == MAXIMUM_TIME) {
3618                 // Add setup time for destination clocks
3619                 setupdelay = calc_setup_time(testddata->trans,
3620                                         testddata->backtrace->receiver->refpin,
3621                                         selecteddest->trans,
3622                                         testddata->backtrace->dir, minmax);
3623                 testddata->setup = setupdelay;
3624             }
3625             else {
3626                 // Subtract hold time for destination clocks (note that hold times
3627 		// are defined as typically negative values in the liberty format)
3628                 holddelay = calc_hold_time(testddata->trans,
3629                                         testddata->backtrace->receiver->refpin,
3630                                         selecteddest->trans,
3631                                         testddata->backtrace->dir, minmax);
3632                 testddata->setup = holddelay;
3633             }
3634             testddata->delay += testddata->setup;
3635 
3636             if (verbose > 1)
3637                 fprintf(stdout, "Path terminated on flop \"%s\" input with max delay %g ps\n",
3638                                 testconn->refinst->name, testddata->delay);
3639 
3640             for (backtrace = testddata->backtrace; backtrace->next;
3641                                 backtrace = backtrace->next) {
3642                 if (verbose > 1)
3643                     fprintf(stdout, "   %g (%s) %s/%s -> %s/%s\n",
3644                                 backtrace->delay,
3645                                 backtrace->receiver->refnet->name,
3646                                 backtrace->receiver->refnet->driver->refinst->name,
3647                                 backtrace->receiver->refnet->driver->refpin->name,
3648                                 backtrace->receiver->refinst->name,
3649                                 backtrace->receiver->refpin->name);
3650             }
3651             if (verbose > 1)
3652                 fprintf(stdout, "   000.000 (%s) %s/%s -> %s/%s\n",
3653                                 backtrace->receiver->refnet->name,
3654                                 backtrace->receiver->refinst->name,
3655                                 backtrace->receiver->refpin->name,
3656                                 backtrace->receiver->refinst->name,
3657                                 backtrace->receiver->refinst->out_connects->refpin->name);
3658 
3659             if (selecteddest != NULL && selectedsource != NULL) {
3660                 if (verbose > 1) {
3661                     if (selectedsource->receiver->refnet != selecteddest->receiver->refnet) {
3662                         fprintf(stdout, "   %g %s to %s clock skew\n",
3663                                 selecteddest->delay - selectedsource->delay
3664 				+ ((btcommon) ? btcommon->delay : 0.0),
3665                                 selectedsource->receiver->refnet->name,
3666                                 selecteddest->receiver->refnet->name);
3667                     }
3668                 }
3669 
3670                 /* Check if the flops have the same clock sense */
3671                 /* (both are clock rising edge or both are clock falling edge type) */
3672 
3673 		if (backtrace->receiver->refinst == NULL)
3674 		    clk_sense_inv = 1;
3675                 else if ((testinst->refcell->type & CLK_SENSE_MASK) !=
3676                                         (backtrace->receiver->refinst->refcell->type
3677                                         & CLK_SENSE_MASK))
3678                     clk_sense_inv = 1;
3679                 else
3680                     clk_sense_inv = 0;
3681 
3682                 /* If the two flops don't clock at the same time, then issue a  */
3683                 /* warning that the slack time loses half a clock period.       */
3684 
3685                 if ((verbose > 1) && (clk_invert != -1) && (clk_sense_inv != clk_invert)) {
3686                     fprintf(stdout, "   Clocks are inverted relative to one another,\n");
3687                     fprintf(stdout, "   implying a maximum propagation delay of 1/2 period.\n");
3688                 }
3689             }
3690             if (thisconn != NULL && testconn != NULL) {
3691                 if (verbose > 1) {
3692                     if (minmax == MAXIMUM_TIME)
3693                         fprintf(stdout, "   %g setup time at destination\n", setupdelay);
3694                     else
3695                         fprintf(stdout, "   %g hold time at destination\n", holddelay);
3696                 }
3697             }
3698 
3699             if (verbose > 1) fprintf(stdout, "\n");
3700         }
3701         else if (verbose > 1) {
3702             fprintf(stdout, "Path terminated on output \"%s\" with max delay %g ps\n",
3703                         testddata->backtrace->receiver->refnet->name, testddata->delay);
3704 
3705             backtrace = testddata->backtrace;
3706             fprintf(stdout, "   %g (%s) %s/%s -> [output pin]\n",
3707                         backtrace->delay,
3708                         backtrace->receiver->refnet->name,
3709                         backtrace->receiver->refnet->driver->refinst->name,
3710                         backtrace->receiver->refnet->driver->refpin->name);
3711 
3712             for (backtrace = backtrace->next; backtrace->next; backtrace = backtrace->next) {
3713                 fprintf(stdout, "   %g (%s) %s/%s -> %s/%s\n",
3714                         backtrace->delay,
3715                         backtrace->receiver->refnet->name,
3716                         backtrace->receiver->refnet->driver->refinst->name,
3717                         backtrace->receiver->refnet->driver->refpin->name,
3718                         backtrace->receiver->refinst->name,
3719                         backtrace->receiver->refpin->name);
3720             }
3721             fprintf(stdout, "   000.000 (%s) %s/%s -> %s/%s\n\n",
3722                         backtrace->receiver->refnet->name,
3723                         backtrace->receiver->refinst->name,
3724                         backtrace->receiver->refpin->name,
3725                         backtrace->receiver->refinst->name,
3726                         backtrace->receiver->refinst->out_connects->refpin->name);
3727         }
3728 
3729         // Clean up clock2list backtraces
3730 	for (freeddata = clock2list; freeddata; freeddata = freeddata->next) {
3731 	    while (freeddata->backtrace != NULL) {
3732 		freebt = freeddata->backtrace;
3733 		testconn = freebt->receiver;
3734 		freeddata->backtrace = freeddata->backtrace->next;
3735                 freebt->refcnt--;
3736 		if (freebt->refcnt == 0) free(freebt);
3737 		else break;
3738 		if (testconn->visited != (unsigned char)2)
3739 		    break;
3740 		testconn->visited = (unsigned char)0;
3741 	    }
3742 	}
3743 
3744         // Clean up clock2list
3745         while (clock2list != NULL) {
3746             freeddata = clock2list;
3747             clock2list = clock2list->next;
3748             free(freeddata);
3749         }
3750 
3751         // Free up clocklist backtraces
3752 	for (freeddata = clocklist; freeddata; freeddata = freeddata->next) {
3753             while (freeddata->backtrace != NULL) {
3754 		freebt = freeddata->backtrace;
3755 		testconn = freebt->receiver;
3756 		freeddata->backtrace = freeddata->backtrace->next;
3757                 freebt->refcnt--;
3758 		if (freebt->refcnt == 0) free(freebt);
3759 		else break;
3760 		if (testconn->visited != (unsigned char)1)
3761 		    break;
3762 		testconn->visited = (unsigned char)0;
3763 	    }
3764 	}
3765 
3766         // Free up clocklist
3767         while (clocklist != NULL) {
3768             freeddata = clocklist;
3769             clocklist = clocklist->next;
3770             free(freeddata);
3771         }
3772     }
3773 }
3774 
3775 /*--------------------------------------------------------------*/
3776 /* Main program                                                 */
3777 /*--------------------------------------------------------------*/
3778 
3779 int
main(int objc,char * argv[])3780 main(int objc, char *argv[])
3781 {
3782     FILE *flib;
3783     FILE *fsrc;
3784     FILE *fdly;
3785     FILE *fsum;
3786     double period = 0.0;
3787     double outLoad = 0.0;
3788     double inTrans = 0.0;
3789     char *delayfile = NULL;
3790     char *summaryfile = NULL;
3791     char *summarydir = NULL;
3792     int ival, firstarg = 1;
3793     int longFormat = 0;    // Is the long format option present
3794     int numReportPaths = 20;
3795 
3796     // Liberty database
3797 
3798     lutable *tables = NULL;
3799     cell *cells = NULL;
3800     lutable *scalar;
3801 
3802     // Verilog netlist database
3803 
3804     instptr     instlist = NULL;
3805     netptr      netlist = NULL;
3806     connlistptr clockconnlist = NULL;
3807     connlistptr newinputconn, inputconnlist = NULL;
3808     connptr     testconn, inputlist = NULL;
3809     connptr     outputlist = NULL;
3810 
3811     // Timing path database
3812     ddataptr    pathlist = NULL;
3813     ddataptr    freeddata, testddata, *orderedpaths;
3814     btptr       freebt, testbt;
3815     int         numpaths, numterms, i;
3816     char        badtiming;
3817     double      slack;
3818 
3819     // Net name hash table
3820     struct hashtable Nethash;
3821 
3822     verbose = 0;
3823     exhaustive = 0;
3824     cleanup = 0;
3825 
3826     while ((firstarg < objc) && (*argv[firstarg] == '-')) {
3827        if (!strcmp(argv[firstarg], "-d") || !strcmp(argv[firstarg], "--delay")) {
3828           delayfile = strdup(argv[firstarg + 1]);
3829           firstarg += 2;
3830        }
3831        else if (!strcmp(argv[firstarg], "-p") || !strcmp(argv[firstarg], "--period")) {
3832           period = strtod(argv[firstarg + 1], NULL);
3833           firstarg += 2;
3834        }
3835        else if (!strcmp(argv[firstarg], "-l") || !strcmp(argv[firstarg], "--load")) {
3836           outLoad = strtod(argv[firstarg + 1], NULL);
3837           firstarg += 2;
3838        }
3839        else if (!strcmp(argv[firstarg], "-t") || !strcmp(argv[firstarg], "--trans")) {
3840           inTrans = strtod(argv[firstarg + 1], NULL);
3841           firstarg += 2;
3842        }
3843        else if (!strcmp(argv[firstarg], "-L") || !strcmp(argv[firstarg], "--long")) {
3844           longFormat = 1;
3845           firstarg++;
3846        }
3847        else if (!strcmp(argv[firstarg], "-n") || !strcmp(argv[firstarg], "--num-paths")) {
3848 	  numReportPaths = strtod(argv[firstarg + 1], NULL);
3849 	  firstarg += 2;
3850        }
3851        else if (!strcmp(argv[firstarg], "-s") || !strcmp(argv[firstarg], "--summary")) {
3852           summaryfile = strdup(argv[firstarg + 1]);
3853           /* Rule:  If argument has a file extension, then treat it as a single	*/
3854 	  /* file and dump all output to it.  If not, then treat it as a	*/
3855 	  /* directory and create individual files for each timing check.	*/
3856           if (strrchr(summaryfile, '.') == NULL) {
3857 	     summarydir = summaryfile;
3858 	     summaryfile = NULL;
3859 	     /* Make directory if it doesn't exist */
3860 	     mkdir(summarydir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
3861 	  }
3862           firstarg += 2;
3863        }
3864        else if (!strcmp(argv[firstarg], "-v") || !strcmp(argv[firstarg], "--verbose")) {
3865           sscanf(argv[firstarg + 1], "%d", &ival);
3866           verbose = (unsigned char)ival;
3867           firstarg += 2;
3868        }
3869        else if (!strcmp(argv[firstarg], "-D") || !strcmp(argv[firstarg], "--debug")) {
3870           sscanf(argv[firstarg + 1], "%d", &ival);
3871           debug = (unsigned char)ival;
3872           firstarg += 2;
3873        }
3874        else if (!strcmp(argv[firstarg], "-e") || !strcmp(argv[firstarg], "--exhaustive")) {
3875           exhaustive = 1;
3876           firstarg++;
3877        }
3878        else if (!strcmp(argv[firstarg], "-c") || !strcmp(argv[firstarg], "--cleanup")) {
3879           cleanup = 1;
3880           firstarg++;
3881        }
3882        else if (!strcmp(argv[firstarg], "-V") || !strcmp(argv[firstarg], "--version")) {
3883           fprintf(stderr, "Vesta Static Timing Analyzer version 0.3\n");
3884           exit(0);
3885        }
3886        else {
3887           fprintf(stderr, "Unknown option \"%s\"\n", argv[firstarg]);
3888           firstarg++;
3889        }
3890     }
3891 
3892     if (objc - firstarg < 2) {
3893         fprintf(stderr, "Usage:  vesta [options] <name.v> <name.lib> [...]\n");
3894         fprintf(stderr, "Options:\n");
3895         fprintf(stderr, "--delay <delay_file>   or      -d <delay_file>\n");
3896         fprintf(stderr, "--period <period>      or      -p <period>\n");
3897         fprintf(stderr, "--load <load>          or      -l <load>\n");
3898 	fprintf(stderr, "--num-paths <numPaths>	or	-n <numPaths>\n");
3899         fprintf(stderr, "--long                 or      -L\n");
3900         fprintf(stderr, "--verbose <level>      or      -v <level>\n");
3901         fprintf(stderr, "--exhaustive           or      -e\n");
3902         fprintf(stderr, "--cleanup              or      -c\n");
3903         fprintf(stderr, "--version              or      -V\n");
3904         exit (1);
3905     }
3906     else {
3907         fflush(stdout);
3908         fprintf(stdout, "----------------------------------------------\n");
3909         fprintf(stdout, "Vesta static timing analysis tool\n");
3910 	fprintf(stdout, "for qflow " QFLOW_VERSION "." QFLOW_REVISION "\n");
3911         fprintf(stdout, "(c) 2013-2018 Tim Edwards, Open Circuit Design\n");
3912         fprintf(stdout, "----------------------------------------------\n\n");
3913         fflush(stdout);
3914     }
3915 
3916     fsrc = fopen(argv[firstarg], "r");
3917     if (fsrc == NULL) {
3918         fprintf(stderr, "Cannot open %s for reading\n", argv[firstarg]);
3919         exit (1);
3920     }
3921     fclose(fsrc);
3922 
3923     /*------------------------------------------------------------------*/
3924     /* Generate one table template for the "scalar" case                */
3925     /*------------------------------------------------------------------*/
3926 
3927     scalar = (lutable *)malloc(sizeof(lutable));
3928     scalar->name = strdup("scalar");
3929     scalar->invert = 0;
3930     scalar->var1 = CONSTRAINED_TIME;
3931     scalar->var2 = OUTPUT_CAP;
3932     scalar->size1 = 1;
3933     scalar->size2 = 1;
3934     scalar->idx1.times = (double *)malloc(sizeof(double));
3935     scalar->idx2.caps = (double *)malloc(sizeof(double));
3936     scalar->values = (double *)malloc(sizeof(double));
3937 
3938     scalar->idx1.times[0] = 0.0;
3939     scalar->idx2.caps[0] = 0.0;
3940     scalar->values[0] = 0.0;
3941 
3942     scalar->next = NULL;
3943     tables = scalar;
3944 
3945     /*------------------------------------------------------------------*/
3946     /* Read all liberty format files (everything on the command line	*/
3947     /* after the verilog source file).					*/
3948     /*------------------------------------------------------------------*/
3949 
3950     for (i = 1; firstarg + i < objc; i++) {
3951 
3952 	flib = fopen(argv[firstarg + i], "r");
3953 	if (flib == NULL) {
3954 	    fprintf(stderr, "Cannot open %s for reading\n", argv[firstarg + i]);
3955 	    exit (1);
3956 	}
3957 
3958 	/*------------------------------------------------------------------*/
3959 	/* Read the liberty format file.  This is not a rigorous parser!    */
3960 	/*------------------------------------------------------------------*/
3961 
3962 	fileCurrentLine = 0;
3963 	libertyRead(flib, &tables, &cells);
3964 	fflush(stdout);
3965 	fprintf(stdout, "Lib read %s:  Processed %d lines.\n", argv[firstarg + i],
3966 			fileCurrentLine);
3967 	if (flib != NULL) fclose(flib);
3968     }
3969 
3970     /*--------------------------------------------------*/
3971     /* Debug:  Print summary of liberty database        */
3972     /*--------------------------------------------------*/
3973 
3974     if (verbose > 3) {
3975 
3976         lutable *newtable;
3977         cell *newcell;
3978         pin *newpin;
3979 
3980         for (newtable = tables; newtable; newtable = newtable->next) {
3981             fprintf(stdout, "Table: %s\n", newtable->name);
3982         }
3983 
3984         for (newcell = cells; newcell; newcell = newcell->next) {
3985             fprintf(stdout, "Cell: %s\n", newcell->name);
3986             fprintf(stdout, "   Function: %s\n", newcell->function);
3987             for (newpin = newcell->pins; newpin; newpin = newpin->next) {
3988                 if (newpin->type == INPUT)
3989                     fprintf(stdout, "   Pin: %s  cap=%g\n", newpin->name, newpin->capr);
3990             }
3991             fprintf(stdout, "\n");
3992         }
3993     }
3994 
3995     /*------------------------------------------------------------------*/
3996     /* Read verilog netlist.  This is also not a rigorous parser!       */
3997     /*------------------------------------------------------------------*/
3998 
3999     /* See hash.c for these routines and variables */
4000     hashfunc = hash;
4001     matchfunc = match;
4002 
4003     /* Initialize net hash table */
4004     InitializeHashTable(&Nethash, LARGEHASHSIZE);
4005 
4006     fileCurrentLine = 0;
4007 
4008     verilogRead(argv[firstarg], cells, &netlist, &instlist, &inputlist, &outputlist,
4009 		&Nethash);
4010 
4011     if (delayfile != NULL) {
4012         fdly = fopen(delayfile, "r");
4013 
4014         if (fdly == NULL) {
4015             fprintf(stderr, "Cannot open %s for reading\n", delayfile);
4016             exit (1);
4017         }
4018     }
4019     else
4020 	fdly = NULL;
4021 
4022     fflush(stdout);
4023     fprintf(stdout, "Verilog netlist read:  Processed %d lines.\n", vlinenum);
4024 
4025     /*--------------------------------------------------*/
4026     /* Debug:  Print summary of verilog source          */
4027     /*--------------------------------------------------*/
4028 
4029     if (verbose > 2) {
4030         connect *testoutput;
4031         connect *testinput;
4032         net *testnet;
4033         instance *testinst;
4034 
4035         for (testinput = inputlist; testinput; testinput = testinput->next) {
4036             if (testinput->refnet)
4037                 fprintf(stdout, "   Input: %s\n", testinput->refnet->name);
4038         }
4039         for (testoutput = outputlist; testoutput; testoutput = testoutput->next) {
4040             if (testoutput->refnet)
4041                 fprintf(stdout, "   Output: %s\n", testoutput->refnet->name);
4042         }
4043         for (testnet = netlist; testnet; testnet = testnet->next) {
4044             fprintf(stdout, "   Net: %s\n", testnet->name);
4045         }
4046         for (testinst = instlist; testinst; testinst = testinst->next) {
4047             fprintf(stdout, "   Gate: %s\n", testinst->name);
4048         }
4049     }
4050 
4051     /*--------------------------------------------------*/
4052     /* Generate internal links representing the network */
4053     /*--------------------------------------------------*/
4054 
4055     createLinks(netlist, instlist, inputlist, outputlist);
4056 
4057     /* Generate a connection list from inputlist */
4058 
4059     for (testconn = inputlist; testconn; testconn = testconn->next) {
4060         newinputconn = (connlistptr)malloc(sizeof(connlist));
4061         newinputconn->connection = testconn;
4062         newinputconn->next = inputconnlist;
4063         inputconnlist = newinputconn;
4064     }
4065 
4066     /*--------------------------------------------------*/
4067     /* Assign net types, mainly to identify clocks      */
4068     /* Return a list of clock nets                      */
4069     /*--------------------------------------------------*/
4070 
4071     numterms = assign_net_types(netlist, &clockconnlist);
4072 
4073     if (verbose > 2)
4074         fprintf(stdout, "Number of terminals to check: %d\n", numterms);
4075 
4076     /*--------------------------------------------------*/
4077     /* Calculate total load on each net                 */
4078     /* To do:  Add wire models or computed wire delays  */
4079     /*--------------------------------------------------*/
4080 
4081     if (fdly != NULL) {
4082         delayRead(fdly, &Nethash);
4083         fclose(fdly);
4084     }
4085 
4086     /* Hash table no longer needed */
4087     HashKill(&Nethash);
4088 
4089     computeLoads(netlist, instlist, outLoad);
4090 
4091     /*--------------------------------------------------*/
4092     /* Identify all clock-to-terminal paths             */
4093     /*--------------------------------------------------*/
4094 
4095     if (verbose > 0) {
4096 	fprintf(stdout, "Starting timing analysis.\n");
4097 	fflush(stdout);
4098     }
4099     numpaths = find_clock_to_term_paths(clockconnlist, &pathlist, netlist, MAXIMUM_TIME);
4100     fprintf(stdout, "Number of paths analyzed:  %d\n", numpaths);
4101     fflush(stdout);
4102 
4103     /* For each terminal path, find the source and destination clocks	*/
4104     /* (where they exist) and compute clock skew.  Also compute setup	*/
4105     /* or hold at the destination.					*/
4106 
4107     find_clock_skews(pathlist, MAXIMUM_TIME);
4108 
4109     /*--------------------------------------------------*/
4110     /* Collect paths into a non-linked array so that    */
4111     /* they can be sorted by delay time                 */
4112     /*--------------------------------------------------*/
4113 
4114     orderedpaths = (ddataptr *)malloc(numpaths * sizeof(ddataptr));
4115 
4116     i = 0;
4117     for (testddata = pathlist; testddata; testddata = testddata->next) {
4118        orderedpaths[i] = testddata;
4119        i++;
4120     }
4121 
4122     qsort(orderedpaths, numpaths, sizeof(ddataptr), (__compar_fn_t)compdelay);
4123 
4124     /*----------------------------------------------------*/
4125     /* Report on top <numReportPaths> maximum delay paths */
4126     /*----------------------------------------------------*/
4127 
4128     if (summarydir != NULL) {
4129         summaryfile = (char *)malloc(256);
4130 	sprintf(summaryfile, "%s/reg_to_reg_max.log", summarydir);
4131     }
4132     if (summaryfile != NULL) {
4133         fsum = fopen(summaryfile, "w");
4134         if (fsum == NULL) {
4135             fprintf(stderr, "Cannot open %s for writing\n", summaryfile);
4136 	    if (summarydir == NULL) {
4137  		free(summaryfile);
4138 		summaryfile = NULL;
4139 	    }
4140         }
4141     }
4142     else
4143 	fsum = NULL;
4144     if (fsum)
4145 	fprintf(fsum, "Vesta static timing analysis, "
4146 			"register-to-register maximum timing\n");
4147 
4148     fprintf(stdout, "\nTop %d maximum delay paths:\n", (numpaths >= numReportPaths)
4149 		? numReportPaths : numpaths);
4150     if (fsum)
4151 	fprintf(fsum, "\nTop %d maximum delay paths:\n", (numpaths >= numReportPaths)
4152 		? numReportPaths : numpaths);
4153     badtiming = 0;
4154     for (i = 0; ((i < numReportPaths) && (i < numpaths)); i++) {
4155         testddata = orderedpaths[i];
4156         for (testbt = testddata->backtrace; testbt->next; testbt = testbt->next);
4157 
4158         if (testddata->backtrace->receiver->refinst != NULL) {
4159             fprintf(stdout, "Path %s/%s to %s/%s delay %g ps",
4160                         testbt->receiver->refinst->name,
4161                         testbt->receiver->refpin->name,
4162                         testddata->backtrace->receiver->refinst->name,
4163                         testddata->backtrace->receiver->refpin->name,
4164                         testddata->delay);
4165             if (fsum) fprintf(fsum, "Path %s/%s to %s/%s delay %g ps",
4166                         testbt->receiver->refinst->name,
4167                         testbt->receiver->refpin->name,
4168                         testddata->backtrace->receiver->refinst->name,
4169                         testddata->backtrace->receiver->refpin->name,
4170                         testddata->delay);
4171         }
4172         else {
4173             fprintf(stdout, "Path %s/%s to output pin %s delay %g ps",
4174                         testbt->receiver->refinst->name,
4175                         testbt->receiver->refpin->name,
4176                         testddata->backtrace->receiver->refnet->name,
4177                         testddata->delay);
4178             if (fsum) fprintf(fsum, "Path %s/%s to output pin %s delay %g ps",
4179                         testbt->receiver->refinst->name,
4180                         testbt->receiver->refpin->name,
4181                         testddata->backtrace->receiver->refnet->name,
4182                         testddata->delay);
4183         }
4184 
4185         if (period > 0.0) {
4186             slack = period - testddata->delay;
4187             fprintf(stdout, "   Slack = %g ps", slack);
4188             if (fsum) fprintf(fsum, "   Slack = %g ps", slack);
4189             if (slack < 0.0) badtiming = 1;
4190         }
4191         fprintf(stdout, "\n");
4192         if (fsum) fprintf(fsum, "\n");
4193         if (longFormat) print_path(testddata->backtrace, stdout);
4194         if (fsum) print_path(testddata->backtrace, fsum);
4195 
4196         if (testddata->backtrace->receiver->refinst != NULL) {
4197 	    if (longFormat) {
4198 		fprintf(stdout, "   clock skew at destination = %g\n", testddata->skew);
4199 		fprintf(stdout, "   setup at destination = %g\n", testddata->setup);
4200 		fprintf(stdout, "\n");
4201 	    }
4202 	    if (fsum) {
4203 		fprintf(fsum, "   clock skew at destination = %g\n", testddata->skew);
4204 		fprintf(fsum, "   setup at destination = %g\n", testddata->setup);
4205 		fprintf(fsum, "\n");
4206 	    }
4207 	}
4208     }
4209 
4210     if (period > 0.0) {
4211         if (badtiming) {
4212             fprintf(stdout, "ERROR:  Design fails timing requirements.\n");
4213             if (fsum) fprintf(fsum, "ERROR:  Design fails timing requirements.\n");
4214         }
4215         else {
4216             fprintf(stdout, "Design meets timing requirements.\n");
4217             if (fsum) fprintf(fsum, "Design meets timing requirements.\n");
4218         }
4219     }
4220     else if ((numpaths > 0) && (orderedpaths[0] != NULL)) {
4221         fprintf(stdout, "Computed maximum clock frequency (zero margin) = %g MHz\n",
4222                 (1.0E6 / orderedpaths[0]->delay));
4223         if (fsum) fprintf(fsum, "Computed maximum clock frequency "
4224 			"(zero margin) = %g MHz\n",
4225                 	(1.0E6 / orderedpaths[0]->delay));
4226     }
4227     fprintf(stdout, "-----------------------------------------\n\n");
4228     if (fsum) fprintf(fsum, "-----------------------------------------\n\n");
4229     fflush(stdout);
4230 
4231     /*--------------------------------------------------*/
4232     /* Clean up the path list                           */
4233     /*--------------------------------------------------*/
4234 
4235     while (pathlist != NULL) {
4236         freeddata = pathlist;
4237         pathlist = pathlist->next;
4238         while (freeddata->backtrace != NULL) {
4239             freebt = freeddata->backtrace;
4240             freeddata->backtrace = freeddata->backtrace->next;
4241             freebt->refcnt--;
4242             if (freebt->refcnt == 0) free(freebt);
4243 	    else break;
4244         }
4245         free(freeddata);
4246     }
4247 
4248     free(orderedpaths);
4249 
4250     /*--------------------------------------------------*/
4251     /* Now calculate minimum delay paths                */
4252     /*--------------------------------------------------*/
4253 
4254     reset_all(netlist, MINIMUM_TIME);
4255     numpaths = find_clock_to_term_paths(clockconnlist, &pathlist, netlist, MINIMUM_TIME);
4256     fprintf(stdout, "Number of paths analyzed:  %d\n", numpaths);
4257     fflush(stdout);
4258 
4259     find_clock_skews(pathlist, MINIMUM_TIME);
4260 
4261     /*--------------------------------------------------*/
4262     /* Collect paths into a non-linked array so that    */
4263     /* they can be sorted by delay time                 */
4264     /*--------------------------------------------------*/
4265 
4266     orderedpaths = (ddataptr *)malloc(numpaths * sizeof(ddataptr));
4267 
4268     i = 0;
4269     for (testddata = pathlist; testddata; testddata = testddata->next) {
4270        orderedpaths[i] = testddata;
4271        i++;
4272     }
4273 
4274     qsort(orderedpaths, numpaths, sizeof(ddataptr), (__compar_fn_t)compdelay);
4275 
4276     /*----------------------------------------------------*/
4277     /* Report on top <numReportPaths> minimum delay paths */
4278     /*----------------------------------------------------*/
4279 
4280     if (summarydir != NULL) {
4281         if (fsum != NULL) fclose(fsum);
4282 	sprintf(summaryfile, "%s/reg_to_reg_min.log", summarydir);
4283         fsum = fopen(summaryfile, "w");
4284         if (fsum == NULL) {
4285 	    fprintf(stderr, "Cannot open %s for writing\n", summaryfile);
4286 	}
4287     }
4288     if (fsum)
4289 	fprintf(fsum, "Vesta static timing analysis, "
4290 			"register-to-register minimum timing\n");
4291 
4292     fprintf(stdout, "\nTop %d minimum delay paths:\n", (numpaths >= numReportPaths) ?
4293 		numReportPaths : numpaths);
4294     if (fsum) fprintf(fsum, "\nTop %d minimum delay paths:\n",
4295 		(numpaths >= numReportPaths) ?  numReportPaths : numpaths);
4296     badtiming = 0;
4297     for (i = numpaths; (i > (numpaths - numReportPaths)) && (i > 0); i--) {
4298         testddata = orderedpaths[i - 1];
4299         for (testbt = testddata->backtrace; testbt->next; testbt = testbt->next);
4300 
4301         if (testddata->backtrace->receiver->refinst != NULL) {
4302             fprintf(stdout, "Path %s/%s to %s/%s delay %g ps\n",
4303                         testbt->receiver->refinst->name,
4304                         testbt->receiver->refpin->name,
4305                         testddata->backtrace->receiver->refinst->name,
4306                         testddata->backtrace->receiver->refpin->name,
4307                         testddata->delay);
4308             if (fsum) fprintf(fsum, "Path %s/%s to %s/%s delay %g ps\n",
4309                         testbt->receiver->refinst->name,
4310                         testbt->receiver->refpin->name,
4311                         testddata->backtrace->receiver->refinst->name,
4312                         testddata->backtrace->receiver->refpin->name,
4313                         testddata->delay);
4314         }
4315         else {
4316             fprintf(stdout, "Path %s/%s to output pin %s delay %g ps\n",
4317                         testbt->receiver->refinst->name,
4318                         testbt->receiver->refpin->name,
4319                         testddata->backtrace->receiver->refnet->name,
4320                         testddata->delay);
4321             if (fsum) fprintf(fsum, "Path %s/%s to output pin %s delay %g ps\n",
4322                         testbt->receiver->refinst->name,
4323                         testbt->receiver->refpin->name,
4324                         testddata->backtrace->receiver->refnet->name,
4325                         testddata->delay);
4326         }
4327         if (longFormat) print_path(testddata->backtrace, stdout);
4328         if (fsum) print_path(testddata->backtrace, fsum);
4329 
4330 	/* Print skew and hold unless destination is a pin */
4331         if (testddata->backtrace->receiver->refinst != NULL) {
4332 	    if (longFormat) {
4333 		fprintf(stdout, "   clock skew at destination = %g\n", testddata->skew);
4334 		fprintf(stdout, "   hold at destination = %g\n", testddata->setup);
4335 		fprintf(stdout, "\n");
4336 	    }
4337 	    if (fsum) {
4338 		fprintf(fsum, "   clock skew at destination = %g\n", testddata->skew);
4339 		fprintf(fsum, "   hold at destination = %g\n", testddata->setup);
4340 		fprintf(fsum, "\n");
4341 	    }
4342 	}
4343 
4344         if (testddata->delay < 0.0) badtiming = 1;
4345     }
4346     if (badtiming) {
4347         fprintf(stdout, "ERROR:  Design fails minimum hold timing.\n");
4348         if (fsum) fprintf(fsum, "ERROR:  Design fails minimum hold timing.\n");
4349     }
4350     else {
4351         fprintf(stdout, "Design meets minimum hold timing.\n");
4352         if (fsum) fprintf(fsum, "Design meets minimum hold timing.\n");
4353     }
4354 
4355     fprintf(stdout, "-----------------------------------------\n\n");
4356     if (fsum) fprintf(fsum, "-----------------------------------------\n\n");
4357     fflush(stdout);
4358 
4359     /*--------------------------------------------------*/
4360     /* Clean up the path list                           */
4361     /*--------------------------------------------------*/
4362 
4363     while (pathlist != NULL) {
4364         freeddata = pathlist;
4365         pathlist = pathlist->next;
4366         while (freeddata->backtrace != NULL) {
4367             freebt = freeddata->backtrace;
4368             freeddata->backtrace = freeddata->backtrace->next;
4369             freebt->refcnt--;
4370             if (freebt->refcnt == 0) free(freebt);
4371 	    else break;
4372         }
4373         free(freeddata);
4374     }
4375 
4376     free(orderedpaths);
4377 
4378     for (testconn = inputlist; testconn; testconn = testconn->next) {
4379         testconn->tag = NULL;
4380         testconn->metric = -1;
4381     }
4382 
4383     /*--------------------------------------------------*/
4384     /* Identify all input-to-terminal paths             */
4385     /*--------------------------------------------------*/
4386 
4387     reset_all(netlist, MAXIMUM_TIME);
4388     numpaths = find_clock_to_term_paths(inputconnlist, &pathlist, netlist, MAXIMUM_TIME);
4389     fprintf(stdout, "Number of paths analyzed:  %d\n", numpaths);
4390     fflush(stdout);
4391 
4392     find_clock_skews(pathlist, MAXIMUM_TIME);
4393 
4394     /*--------------------------------------------------*/
4395     /* Collect paths into a non-linked array so that    */
4396     /* they can be sorted by delay time                 */
4397     /*--------------------------------------------------*/
4398 
4399     orderedpaths = (ddataptr *)malloc(numpaths * sizeof(ddataptr));
4400 
4401     i = 0;
4402     for (testddata = pathlist; testddata; testddata = testddata->next) {
4403        orderedpaths[i] = testddata;
4404        i++;
4405     }
4406 
4407     qsort(orderedpaths, numpaths, sizeof(ddataptr), (__compar_fn_t)compdelay);
4408 
4409     /*----------------------------------------------------*/
4410     /* Report on top <numReportPaths> maximum delay paths */
4411     /*----------------------------------------------------*/
4412 
4413     if (summarydir != NULL) {
4414         if (fsum != NULL) fclose(fsum);
4415 	sprintf(summaryfile, "%s/pin_to_reg_max.log", summarydir);
4416         fsum = fopen(summaryfile, "w");
4417         if (fsum == NULL) {
4418 	    fprintf(stderr, "Cannot open %s for writing\n", summaryfile);
4419 	}
4420     }
4421     if (fsum)
4422 	fprintf(fsum, "Vesta static timing analysis, "
4423 			"pin-to-register and register-to-pin maximum timing\n");
4424 
4425     fprintf(stdout, "\nTop %d maximum delay paths:\n", (numpaths >= numReportPaths) ?
4426 			numReportPaths : numpaths);
4427     if (fsum) fprintf(fsum, "\nTop %d maximum delay paths:\n",
4428 			(numpaths >= numReportPaths) ?
4429 			numReportPaths : numpaths);
4430     for (i = 0; ((i < numReportPaths) && (i < numpaths)); i++) {
4431         testddata = orderedpaths[i];
4432         for (testbt = testddata->backtrace; testbt->next; testbt = testbt->next);
4433 
4434         if (testddata->backtrace->receiver->refinst != NULL) {
4435             fprintf(stdout, "Path input pin %s to %s/%s delay %g ps\n",
4436                         testbt->receiver->refnet->name,
4437                         testddata->backtrace->receiver->refinst->name,
4438                         testddata->backtrace->receiver->refpin->name,
4439                         testddata->delay);
4440             if (fsum) fprintf(fsum, "Path input pin %s to %s/%s delay %g ps\n",
4441                         testbt->receiver->refnet->name,
4442                         testddata->backtrace->receiver->refinst->name,
4443                         testddata->backtrace->receiver->refpin->name,
4444                         testddata->delay);
4445         }
4446         else {
4447             fprintf(stdout, "Path input pin %s to output pin %s delay %g ps\n",
4448                         testbt->receiver->refnet->name,
4449                         testddata->backtrace->receiver->refnet->name,
4450                         testddata->delay);
4451             if (fsum) fprintf(fsum, "Path input pin %s to output pin %s delay %g ps\n",
4452                         testbt->receiver->refnet->name,
4453                         testddata->backtrace->receiver->refnet->name,
4454                         testddata->delay);
4455         }
4456         if (longFormat) print_path(testddata->backtrace, stdout);
4457         if (fsum) print_path(testddata->backtrace, fsum);
4458 
4459         if (testddata->backtrace->receiver->refinst != NULL) {
4460 	    if (longFormat) {
4461 		fprintf(stdout, "   setup at destination = %g\n", testddata->setup);
4462 		fprintf(stdout, "\n");
4463 	    }
4464 	    if (fsum) {
4465 		fprintf(fsum, "   setup at destination = %g\n", testddata->setup);
4466 		fprintf(fsum, "\n");
4467 	    }
4468 	}
4469     }
4470 
4471     fprintf(stdout, "-----------------------------------------\n\n");
4472     if (fsum) fprintf(fsum, "-----------------------------------------\n\n");
4473     fflush(stdout);
4474 
4475     /*--------------------------------------------------*/
4476     /* Clean up the path list                           */
4477     /*--------------------------------------------------*/
4478 
4479     while (pathlist != NULL) {
4480         freeddata = pathlist;
4481         pathlist = pathlist->next;
4482         while (freeddata->backtrace != NULL) {
4483             freebt = freeddata->backtrace;
4484             freeddata->backtrace = freeddata->backtrace->next;
4485             freebt->refcnt--;
4486             if (freebt->refcnt == 0) free(freebt);
4487 	    else break;
4488         }
4489         free(freeddata);
4490     }
4491 
4492     free(orderedpaths);
4493 
4494     for (testconn = inputlist; testconn; testconn = testconn->next) {
4495         testconn->tag = NULL;
4496         testconn->metric = 1E50;
4497     }
4498 
4499     /*--------------------------------------------------*/
4500     /* Now calculate minimum delay paths from inputs    */
4501     /*--------------------------------------------------*/
4502 
4503     reset_all(netlist, MINIMUM_TIME);
4504     numpaths = find_clock_to_term_paths(inputconnlist, &pathlist, netlist, MINIMUM_TIME);
4505     fprintf(stdout, "Number of paths analyzed:  %d\n", numpaths);
4506     fflush(stdout);
4507 
4508     find_clock_skews(pathlist, MINIMUM_TIME);
4509 
4510     /*--------------------------------------------------*/
4511     /* Collect paths into a non-linked array so that    */
4512     /* they can be sorted by delay time                 */
4513     /*--------------------------------------------------*/
4514 
4515     orderedpaths = (ddataptr *)malloc(numpaths * sizeof(ddataptr));
4516 
4517     i = 0;
4518     for (testddata = pathlist; testddata; testddata = testddata->next) {
4519        orderedpaths[i] = testddata;
4520        i++;
4521     }
4522 
4523     qsort(orderedpaths, numpaths, sizeof(ddataptr), (__compar_fn_t)compdelay);
4524 
4525     /*----------------------------------------------------*/
4526     /* Report on top <numReportPaths> minimum delay paths */
4527     /*----------------------------------------------------*/
4528 
4529     if (summarydir != NULL) {
4530         if (fsum != NULL) fclose(fsum);
4531 	sprintf(summaryfile, "%s/pin_to_reg_min.log", summarydir);
4532         fsum = fopen(summaryfile, "w");
4533         if (fsum == NULL) {
4534 	    fprintf(stderr, "Cannot open %s for writing\n", summaryfile);
4535 	}
4536     }
4537     if (fsum)
4538 	fprintf(fsum, "Vesta static timing analysis, "
4539 			"pin-to-register and register-to-pin minimum timing\n");
4540 
4541     fprintf(stdout, "\nTop %d minimum delay paths:\n", (numpaths >= numReportPaths) ?
4542 			numReportPaths : numpaths);
4543     if (fsum) fprintf(fsum, "\nTop %d minimum delay paths:\n",
4544 			(numpaths >= numReportPaths) ?
4545 			numReportPaths : numpaths);
4546     for (i = numpaths; (i > (numpaths - numReportPaths)) && (i > 0); i--) {
4547         testddata = orderedpaths[i - 1];
4548         for (testbt = testddata->backtrace; testbt->next; testbt = testbt->next);
4549 
4550         if (testddata->backtrace->receiver->refinst != NULL) {
4551             fprintf(stdout, "Path input pin %s to %s/%s delay %g ps\n",
4552                         testbt->receiver->refnet->name,
4553                         testddata->backtrace->receiver->refinst->name,
4554                         testddata->backtrace->receiver->refpin->name,
4555                         testddata->delay);
4556             if (fsum) fprintf(fsum, "Path input pin %s to %s/%s delay %g ps\n",
4557                         testbt->receiver->refnet->name,
4558                         testddata->backtrace->receiver->refinst->name,
4559                         testddata->backtrace->receiver->refpin->name,
4560                         testddata->delay);
4561         }
4562         else {
4563             fprintf(stdout, "Path input pin %s to output pin %s delay %g ps\n",
4564                         testbt->receiver->refnet->name,
4565                         testddata->backtrace->receiver->refnet->name,
4566                         testddata->delay);
4567             if (fsum) fprintf(fsum, "Path input pin %s to output pin %s delay %g ps\n",
4568                         testbt->receiver->refnet->name,
4569                         testddata->backtrace->receiver->refnet->name,
4570                         testddata->delay);
4571         }
4572         if (longFormat) print_path(testddata->backtrace, stdout);
4573         if (fsum) print_path(testddata->backtrace, fsum);
4574 
4575         if (testddata->backtrace->receiver->refinst != NULL) {
4576 	    if (longFormat) {
4577 		fprintf(stdout, "   hold at destination = %g\n", testddata->setup);
4578 		fprintf(stdout, "\n");
4579 	    }
4580 	    if (fsum) {
4581 		fprintf(fsum, "   hold at destination = %g\n", testddata->setup);
4582 		fprintf(fsum, "\n");
4583 	    }
4584 	}
4585     }
4586 
4587     fprintf(stdout, "-----------------------------------------\n\n");
4588     if (fsum) fprintf(fsum, "-----------------------------------------\n\n");
4589     fflush(stdout);
4590 
4591     if (fsum != NULL) fclose(fsum);
4592     if (summaryfile != NULL) free(summaryfile);
4593     if (summarydir != NULL) free(summarydir);
4594 
4595     /*--------------------------------------------------*/
4596     /* Clean up the path list                           */
4597     /*--------------------------------------------------*/
4598 
4599     while (pathlist != NULL) {
4600         freeddata = pathlist;
4601         pathlist = pathlist->next;
4602         while (freeddata->backtrace != NULL) {
4603             freebt = freeddata->backtrace;
4604             freeddata->backtrace = freeddata->backtrace->next;
4605             freebt->refcnt--;
4606             if (freebt->refcnt == 0) free(freebt);
4607 	    else break;
4608         }
4609         free(freeddata);
4610     }
4611 
4612     free(orderedpaths);
4613 
4614     return 0;
4615 }
4616