diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile | 3 | ||||
-rw-r--r-- | src/Makefile.in | 1 | ||||
-rw-r--r-- | src/blifFanout.c | 103 | ||||
-rw-r--r-- | src/readliberty.c | 3 | ||||
-rw-r--r-- | src/vesta.c | 2 |
5 files changed, 87 insertions, 25 deletions
diff --git a/src/Makefile b/src/Makefile index 63bdb06..dca79aa 100644 --- a/src/Makefile +++ b/src/Makefile @@ -3,7 +3,7 @@ # # Main compiler arguments -CFLAGS = -g -O2 +CFLAGS = -g DEFS = -DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\" -DPACKAGE_STRING=\"\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE_URL=\"\" -DSTDC_HEADERS=1 -DHAVE_SETENV=1 -DHAVE_PUTENV=1 -DTCLSH_PATH=\"/bin/tclsh\" -DQFLOW_MAGIC_PATH=\"/usr/local/bin/magic\" -DQFLOW_QROUTER_PATH=\"/usr/local/bin/qrouter\" -DQFLOW_GRAYWOLF_PATH=\"/usr/local/bin/graywolf\" -DQFLOW_YOSYS_PATH=\"/usr/local/bin/yosys\" LIBS = LDFLAGS = @@ -59,6 +59,7 @@ install: $(TARGETS) (cd $(DESTDIR)${BININSTALL}; $(RM) -f magic; ln -s $(QFLOW_MAGIC_PATH) magic) @if test "${HAVE_YOSYS}" = "1"; then \ (cd $(DESTDIR)${BININSTALL}; $(RM) -f yosys; ln -s $(QFLOW_YOSYS_PATH) yosys); \ + (cd $(DESTDIR)${BININSTALL}; $(RM) -f yosys-abc; ln -s $(QFLOW_YOSYS_PATH)-abc yosys-abc); \ fi uninstall: diff --git a/src/Makefile.in b/src/Makefile.in index 09e164d..03bc2fd 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -59,6 +59,7 @@ install: $(TARGETS) (cd $(DESTDIR)${BININSTALL}; $(RM) -f magic; ln -s $(QFLOW_MAGIC_PATH) magic) @if test "${HAVE_YOSYS}" = "1"; then \ (cd $(DESTDIR)${BININSTALL}; $(RM) -f yosys; ln -s $(QFLOW_YOSYS_PATH) yosys); \ + (cd $(DESTDIR)${BININSTALL}; $(RM) -f yosys-abc; ln -s $(QFLOW_YOSYS_PATH)-abc yosys-abc); \ fi uninstall: diff --git a/src/blifFanout.c b/src/blifFanout.c index c566ac6..d812aeb 100644 --- a/src/blifFanout.c +++ b/src/blifFanout.c @@ -95,11 +95,11 @@ double MaxOverload = 0.0; int MaxFanout = 16; // Maximum fanout per node allowed without // additional buffering. -double MaxLatency = 100.0; // Maximum variable latency (ps) for which we +double MaxLatency = 1000.0; // Maximum variable latency (ps) for which we // are solving. Represents the largest delay // allowed for any gate caused by total load // capacitance. This is empirically derived. -double MaxOutputCap = 18.0; // Maximum capacitance for an output node (fF). +double MaxOutputCap = 30.0; // Maximum capacitance for an output node (fF). // Outputs should be able to drive this much // capacitance within MaxLatency time (ps). double WireCap = 10.0; // Base capacitance for an output node, estimate @@ -163,7 +163,7 @@ void showgatelist(void); void helpmessage(void); void registernode(char *nodename, int type, struct Gatelist *gl, char *pinname); void shownodes(void); -void write_output(FILE *infptr, FILE *outfptr); +void write_output(int doLoadBalance, FILE *infptr, FILE *outfptr); struct Gatelist *best_size(struct Gatelist *gl, double amount, char *overload); void count_gatetype(struct Gatelist *gl, int num_in, int num_out); @@ -201,6 +201,36 @@ char *find_suffix(char *gatename) /* *--------------------------------------------------------------------------- + * Check if a liberty file function describes a buffer. Since this is the + * function of the output pin, it needs only be the input pin (e.g., + * func(Q) = "A"). However, some liberty files repeat the output pin (e.g., + * func(Q) = "Q = A"). Check for both styles. + *--------------------------------------------------------------------------- + */ + +int is_buffer_func(char *func_text, char *pin_in, char *pin_out) { + char *eqptr, esav, *tptr; + + if (!strcmp(func_text, pin_in)) return 1; + + else if ((eqptr = strchr(func_text, '=')) != NULL) { + tptr = eqptr + 1; + while (isspace(*tptr) && (*tptr != '\0')) tptr++; + while ((eqptr > func_text) && isspace(*(eqptr - 1))) eqptr--; + esav = *eqptr; + *eqptr = '\0'; + if (!strcmp(func_text, pin_out) && (*tptr != '\0') && + !strcmp(tptr, pin_in)) { + *eqptr = esav; + return 1; + } + *eqptr = esav; + } + return 0; +} + +/* + *--------------------------------------------------------------------------- *--------------------------------------------------------------------------- */ @@ -211,6 +241,8 @@ int main (int argc, char *argv[]) int inputcount; int gateinputs; int gatecount; + int doLoadBalance = 1; + int doFanout = 1; char *pinname; char *test; char *s, *t; @@ -233,7 +265,7 @@ int main (int argc, char *argv[]) InitializeHashTable(Drivehash); InitializeHashTable(Gatehash); - while ((i = getopt(argc, argv, "gnhvl:c:b:i:o:p:s:f:F:")) != EOF) { + while ((i = getopt(argc, argv, "fLgnhvl:c:b:i:o:p:s:I:F:")) != EOF) { switch (i) { case 'b': Buffername = strdup(optarg); @@ -247,7 +279,13 @@ int main (int argc, char *argv[]) case 'p': Gatepath = strdup(optarg); break; - case 'f': + case 'f': // fanout only + doLoadBalance = 0; + break; + case 'L': // load balance only + doFanout = 0; + break; + case 'I': Ignorepath = strdup(optarg); break; case 'F': @@ -357,17 +395,21 @@ int main (int argc, char *argv[]) if (ctest->pins && ctest->pins->next && !ctest->pins->next->next) { if (ctest->pins->type == PIN_INPUT && ctest->pins->next->type == PIN_OUTPUT) { - if (!strcmp(ctest->function, ctest->pins->name)) { + if (is_buffer_func(ctest->function, ctest->pins->name, + ctest->pins->next->name)) { fprintf(stdout, "Using cell \"%s\" for buffers.\n", ctest->name); + Buffername = strdup(ctest->name); break; } } else if (ctest->pins->type == PIN_OUTPUT && ctest->pins->next->type == PIN_INPUT) { - if (!strcmp(ctest->function, ctest->pins->next->name)) { + if (is_buffer_func(ctest->function, ctest->pins->next->name, + ctest->pins->name)) { fprintf(stdout, "Using cell \"%s\" for buffers.\n", ctest->name); + Buffername = strdup(ctest->name); break; } } @@ -379,7 +421,10 @@ int main (int argc, char *argv[]) gl = (struct Gatelist *)HashLookup(Buffername, Gatehash); if (gl == NULL) { - fprintf(stderr, "blifFanout: Buffer cell %s cannot be found.\n", + if (Buffername == NULL) + fprintf(stderr, "blifFanout: No suitable buffer cell in library.\n"); + else + fprintf(stderr, "blifFanout: Buffer cell %s cannot be found.\n", Buffername); return -1; } @@ -388,7 +433,7 @@ int main (int argc, char *argv[]) if (buf_in_pin == NULL) buf_in_pin = strdup(curpin->name); } - else if (curpin->type == PIN_INPUT) { + else if (curpin->type == PIN_OUTPUT) { if (buf_out_pin == NULL) buf_out_pin = strdup(curpin->name); } @@ -527,18 +572,20 @@ int main (int argc, char *argv[]) fflush(stdout); fprintf(stderr, "Top internal fanout is %d (load %g) from node %s,\n" - "driven by %s with strength %g\n", + "driven by %s with strength %g (fF driven at latency %g)\n", Topfanout, Topload, nlmax->nodename, nlmax->outputgate->gatename, - nlmax->outputgatestrength); + nlmax->outputgatestrength, + MaxLatency); - fprintf(stderr, "Top fanout load-to-strength ratio is %g\n", Topratio); + fprintf(stderr, "Top fanout load-to-strength ratio is %g (latency = %g ps)\n", + Topratio, MaxLatency * Topratio); fprintf(stderr, "Top input node fanout is %d (load %g) from node %s.\n", Inputfanout, Inputload, nlimax->nodename); Buffer_count = 0; - if ((Topfanout > MaxFanout) || (Inputfanout > MaxFanout)) { + if (doFanout && ((Topfanout > MaxFanout) || (Inputfanout > MaxFanout))) { /* Insert buffer trees */ nl = (struct Nodelist *)HashFirst(Nodehash); @@ -580,7 +627,7 @@ int main (int argc, char *argv[]) nl = (struct Nodelist *)HashNext(Nodehash); } } - write_output(infptr, outfptr); + write_output(doLoadBalance, infptr, outfptr); fprintf(stderr, "%d gates exceed specified minimum load.\n", stren_err_counter); fprintf(stderr, "%d buffers were added.\n", Buffer_count); @@ -689,6 +736,10 @@ int read_gate_file(char *gate_file_name) /* substitutions (this does not include internal, constant */ /* delays in each gate). */ + // (Diagnostic, for debug) + // fprintf(stderr, "Parsing cell \"%s\", \"%s\", function \"%s\"\n", + // gl->gatename, gl->gatecell->name, gl->gatecell->function); + gl->strength = MaxLatency / gl->delay; HashPtrInstall(gl->gatename, gl, Gatehash); gatecount++; @@ -909,7 +960,7 @@ void shownodes(void) nl = (struct Nodelist *)HashFirst(Nodehash); while (nl != NULL) { - printf("\n\nnode: %s with %d fanout and %g cap", + printf("\n\nnode: %s with %d fanout and %g fF cap", nl->nodename, nl->num_inputs, nl->total_load); printf("\ndriven by %s, with %g strength.\n", nl->outputgate->gatename, nl->outputgatestrength); @@ -922,7 +973,7 @@ void shownodes(void) *--------------------------------------------------------------------------- */ -void write_output(FILE *infptr, FILE *outfptr) +void write_output(int doLoadBalance, FILE *infptr, FILE *outfptr) { char *s, *t; char line[MAXLINE]; @@ -1109,7 +1160,7 @@ void write_output(FILE *infptr, FILE *outfptr) if (VerboseFlag) printf("\nOutput node %s", t); nl = (struct Nodelist *)HashLookup(t, Nodehash); - if (nl != NULL) { + if (doLoadBalance && (nl != NULL)) { if ((nl->ignore == FALSE) && (nl->ratio > 1.0)) { if (VerboseFlag) printf("\nGate should be %g times stronger", nl->ratio); @@ -1128,10 +1179,12 @@ void write_output(FILE *infptr, FILE *outfptr) glbest = best_size(gl, nl->total_load + MaxOutputCap + WireCap, NULL); if (glbest && (glbest != gl)) { - needscorrecting = TRUE; - if (VerboseFlag) - printf("\nOutput Gate changed from %s to %s\n", + if (doLoadBalance) { + needscorrecting = TRUE; + if (VerboseFlag) + printf("\nOutput Gate changed from %s to %s\n", gl->gatename, glbest->gatename); + } } } // Don't attempt to correct gates for which we cannot find a suffix @@ -1210,7 +1263,7 @@ void write_output(FILE *infptr, FILE *outfptr) bbest->gatename, buf_in_pin, s, buf_out_pin, nl->nodename); } - if (gl != glbest) { + if ((gl != NULL) && (gl != glbest)) { s = strstr(gateline, gl->gatename); if (s) { int glen = strlen(gl->gatename); @@ -1358,6 +1411,8 @@ void helpmessage(void) printf("Typically, it will be iterated until convergence (return value 0).\n\n"); printf("valid switches are:\n"); + printf("\t-f\t\tRun gate fanout buffering only (no load balancing)\n"); + printf("\t-L\t\tRun gate load balance optimization only (no fanout buffering)\n"); printf("\t-g\t\tDebug mode: parse and print the gate.cfg table\n"); printf("\t-n\t\tDebug mode: parse and print the node list\n"); printf("\t-v\t\tDebug mode: verbose output\n"); @@ -1366,11 +1421,13 @@ void helpmessage(void) printf("\t-F value\tSet the maximum fanout per node (default %g)\n", MaxFanout); printf("\t-b buffername\tSet the name of a buffer gate\n"); + printf("\t-i pin_name\tSet the name of the buffer gate input pin (used with -b)\n"); + printf("\t-o pin_name\tSet the name of the buffer gate output pin (used with -b)\n"); printf("\t-s separator\tGate names have \"separator\" before drive strength\n"); - printf("\t-o value\tSet the maximum output capacitance (fF). (default %g)\n", + printf("\t-c value\tSet the maximum output capacitance (fF). (default %g)\n", MaxOutputCap); printf("\t-p filepath\tSpecify an alternate path and filename for gate.cfg\n"); - printf("\t-f filepath\tSpecify a path and filename for list of nets to ignore\n"); + printf("\t-I filepath\tSpecify a path and filename for list of nets to ignore\n"); printf("\t-h\t\tprint this help message\n\n"); printf("This will not work at all for tristate gates.\n"); diff --git a/src/readliberty.c b/src/readliberty.c index 37ee151..991a28f 100644 --- a/src/readliberty.c +++ b/src/readliberty.c @@ -529,6 +529,7 @@ read_liberty(char *libfile, char *pattern) newtable->times = NULL; newtable->caps = NULL; newtable->next = tables; + newtable->invert = 0; tables = newtable; token = advancetoken(flib, 0); @@ -800,7 +801,7 @@ read_liberty(char *libfile, char *pattern) } else if (!strcasecmp(token, "dont_use")) { free(newcell->name); - newcell->name == NULL; + newcell->name = NULL; } else if (!strcasecmp(token, "pin")) { token = advancetoken(flib, 0); // Open parens diff --git a/src/vesta.c b/src/vesta.c index bac0c7f..65d7046 100644 --- a/src/vesta.c +++ b/src/vesta.c @@ -1426,6 +1426,8 @@ int find_clock_to_term_paths(connlistptr clockedlist, ddataptr *masterlist, netp // Find the sources of the clock at the path end destdir = (testinst->refcell->type & CLK_SENSE_MASK) ? FALLING : RISING; testconn = find_register_clock(testinst); + // If testconn is NULL, this is not a register (latch, maybe?) + if (testconn == NULL) continue; find_clock_source(testconn, &clock2list, destdir); selecteddest = find_clock_transition(clock2list, testconn, destdir, ~minmax); |