123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232 |
- /**
- @file
- @ingroup nanotrav
- @brief Functions to read in a boolean network.
- @author Fabio Somenzi
- @copyright@parblock
- Copyright (c) 1995-2015, Regents of the University of Colorado
- All rights reserved.
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- Neither the name of the University of Colorado nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- POSSIBILITY OF SUCH DAMAGE.
- @endparblock
- */
- #include "cuddInt.h"
- #include "bnet.h"
- /*---------------------------------------------------------------------------*/
- /* Constant declarations */
- /*---------------------------------------------------------------------------*/
- #define MAXLENGTH 131072
- /*---------------------------------------------------------------------------*/
- /* Stucture declarations */
- /*---------------------------------------------------------------------------*/
- /*---------------------------------------------------------------------------*/
- /* Type declarations */
- /*---------------------------------------------------------------------------*/
- /*---------------------------------------------------------------------------*/
- /* Variable declarations */
- /*---------------------------------------------------------------------------*/
- static char BuffLine[MAXLENGTH];
- static char *CurPos;
- static int newNameNumber = 0;
- /*---------------------------------------------------------------------------*/
- /* Macro declarations */
- /*---------------------------------------------------------------------------*/
- /** \cond */
- /*---------------------------------------------------------------------------*/
- /* Static function prototypes */
- /*---------------------------------------------------------------------------*/
- static char * readString (FILE *fp);
- static char ** readList (FILE *fp, int *n);
- static void printList (char **list, int n);
- static char ** bnetGenerateNewNames (st_table *hash, int n);
- static int bnetDumpReencodingLogic (DdManager *dd, char *mname, int noutputs, DdNode **outputs, char **inames, char **altnames, char **onames, FILE *fp);
- #if 0
- static int bnetBlifXnorTable (FILE *fp, int n);
- #endif
- static int bnetBlifWriteReencode (DdManager *dd, char *mname, char **inames, char **altnames, int *support, FILE *fp);
- static int * bnetFindVectorSupport (DdManager *dd, DdNode **list, int n);
- static int buildExorBDD (DdManager *dd, BnetNode *nd, st_table *hash, int params, int nodrop);
- static int buildMuxBDD (DdManager * dd, BnetNode * nd, st_table * hash, int params, int nodrop);
- static int bnetSetLevel (BnetNetwork *net);
- static int bnetLevelDFS (BnetNetwork *net, BnetNode *node);
- static BnetNode ** bnetOrderRoots (BnetNetwork *net, int *nroots);
- static int bnetLevelCompare (BnetNode **x, BnetNode **y);
- static int bnetDfsOrder (DdManager *dd, BnetNetwork *net, BnetNode *node);
- /** \endcond */
- /*---------------------------------------------------------------------------*/
- /* Definition of exported functions */
- /*---------------------------------------------------------------------------*/
- /**
- @brief Reads boolean network from blif file.
- @details A very restricted subset of blif is supported. Specifically:
- <ul>
- <li> The only directives recognized are:
- <ul>
- <li> .model
- <li> .inputs
- <li> .outputs
- <li> .latch
- <li> .names
- <li> .exdc
- <li> .wire_load_slope
- <li> .end
- </ul>
- <li> Latches must have an initial values and no other parameters
- specified.
- <li> Lines must not exceed MAXLENGTH-1 characters, and individual names must
- not exceed 1023 characters.
- </ul>
- Caveat emptor: There may be other limitations as well. One should
- check the syntax of the blif file with some other tool before relying
- on this parser.
- @return a pointer to the network if successful; NULL otherwise.
-
- @sideeffect None
- @see Bnet_PrintNetwork Bnet_FreeNetwork
- */
- BnetNetwork *
- Bnet_ReadNetwork(
- FILE * fp /**< pointer to the blif file */,
- int pr /**< verbosity level */)
- {
- char *savestring;
- char **list;
- int i, j, n;
- BnetNetwork *net;
- BnetNode *newnode;
- BnetNode *lastnode = NULL;
- BnetTabline *newline;
- BnetTabline *lastline;
- char ***latches = NULL;
- int maxlatches = 0;
- int exdc = 0;
- BnetNode *node;
- int count;
- /* Allocate network object and initialize symbol table. */
- net = ALLOC(BnetNetwork,1);
- if (net == NULL) goto failure;
- memset((char *) net, 0, sizeof(BnetNetwork));
- net->hash = st_init_table((st_compare_t) strcmp, st_strhash);
- if (net->hash == NULL) goto failure;
- savestring = readString(fp);
- if (savestring == NULL) goto failure;
- net->nlatches = 0;
- while (strcmp(savestring, ".model") == 0 ||
- strcmp(savestring, ".inputs") == 0 ||
- strcmp(savestring, ".outputs") == 0 ||
- strcmp(savestring, ".latch") == 0 ||
- strcmp(savestring, ".wire_load_slope") == 0 ||
- strcmp(savestring, ".exdc") == 0 ||
- strcmp(savestring, ".names") == 0 || strcmp(savestring,".end") == 0) {
- if (strcmp(savestring, ".model") == 0) {
- /* Read .model directive. */
- FREE(savestring);
- /* Read network name. */
- savestring = readString(fp);
- if (savestring == NULL) goto failure;
- if (savestring[0] == '.') {
- net->name = ALLOC(char, 1);
- if (net->name == NULL) goto failure;
- net->name[0] = '\0';
- } else {
- net->name = savestring;
- }
- } else if (strcmp(savestring, ".inputs") == 0) {
- /* Read .inputs directive. */
- FREE(savestring);
- /* Read input names. */
- list = readList(fp,&n);
- if (list == NULL) goto failure;
- if (pr > 2) printList(list,n);
- /* Expect at least one input. */
- if (n < 1) {
- (void) fprintf(stdout,"Empty input list.\n");
- goto failure;
- }
- if (exdc) {
- for (i = 0; i < n; i++)
- FREE(list[i]);
- FREE(list);
- savestring = readString(fp);
- if (savestring == NULL) goto failure;
- continue;
- }
- if (net->ninputs) {
- net->inputs = REALLOC(char *, net->inputs,
- (net->ninputs + n) * sizeof(char *));
- for (i = 0; i < n; i++)
- net->inputs[net->ninputs + i] = list[i];
- }
- else
- net->inputs = list;
- /* Create a node for each primary input. */
- for (i = 0; i < n; i++) {
- newnode = ALLOC(BnetNode,1);
- memset((char *) newnode, 0, sizeof(BnetNode));
- if (newnode == NULL) goto failure;
- newnode->name = list[i];
- newnode->inputs = NULL;
- newnode->type = BNET_INPUT_NODE;
- newnode->active = FALSE;
- newnode->nfo = 0;
- newnode->ninp = 0;
- newnode->f = NULL;
- newnode->polarity = 0;
- newnode->dd = NULL;
- newnode->next = NULL;
- if (lastnode == NULL) {
- net->nodes = newnode;
- } else {
- lastnode->next = newnode;
- }
- lastnode = newnode;
- }
- net->npis += n;
- net->ninputs += n;
- } else if (strcmp(savestring, ".outputs") == 0) {
- /* Read .outputs directive. We do not create nodes for the primary
- ** outputs, because the nodes will be created when the same names
- ** appear as outputs of some gates.
- */
- FREE(savestring);
- /* Read output names. */
- list = readList(fp,&n);
- if (list == NULL) goto failure;
- if (pr > 2) printList(list,n);
- if (n < 1) {
- (void) fprintf(stdout,"Empty .outputs list.\n");
- goto failure;
- }
- if (exdc) {
- for (i = 0; i < n; i++)
- FREE(list[i]);
- FREE(list);
- savestring = readString(fp);
- if (savestring == NULL) goto failure;
- continue;
- }
- if (net->noutputs) {
- net->outputs = REALLOC(char *, net->outputs,
- (net->noutputs + n) * sizeof(char *));
- for (i = 0; i < n; i++)
- net->outputs[net->noutputs + i] = list[i];
- } else {
- net->outputs = list;
- }
- net->npos += n;
- net->noutputs += n;
- } else if (strcmp(savestring,".wire_load_slope") == 0) {
- FREE(savestring);
- savestring = readString(fp);
- net->slope = savestring;
- } else if (strcmp(savestring,".latch") == 0) {
- FREE(savestring);
- newnode = ALLOC(BnetNode,1);
- if (newnode == NULL) goto failure;
- memset((char *) newnode, 0, sizeof(BnetNode));
- newnode->type = BNET_PRESENT_STATE_NODE;
- list = readList(fp,&n);
- if (list == NULL) goto failure;
- if (pr > 2) printList(list,n);
- /* Expect three names. */
- if (n != 3) {
- (void) fprintf(stdout,
- ".latch not followed by three tokens.\n");
- goto failure;
- }
- newnode->name = list[1];
- newnode->inputs = NULL;
- newnode->ninp = 0;
- newnode->f = NULL;
- newnode->active = FALSE;
- newnode->nfo = 0;
- newnode->polarity = 0;
- newnode->dd = NULL;
- newnode->next = NULL;
- if (lastnode == NULL) {
- net->nodes = newnode;
- } else {
- lastnode->next = newnode;
- }
- lastnode = newnode;
- /* Add next state variable to list. */
- if (maxlatches == 0) {
- maxlatches = 20;
- latches = ALLOC(char **,maxlatches);
- } else if (maxlatches <= net->nlatches) {
- maxlatches += 20;
- latches = REALLOC(char **,latches,maxlatches);
- }
- latches[net->nlatches] = list;
- net->nlatches++;
- savestring = readString(fp);
- if (savestring == NULL) goto failure;
- } else if (strcmp(savestring,".names") == 0) {
- FREE(savestring);
- newnode = ALLOC(BnetNode,1);
- memset((char *) newnode, 0, sizeof(BnetNode));
- if (newnode == NULL) goto failure;
- list = readList(fp,&n);
- if (list == NULL) goto failure;
- if (pr > 2) printList(list,n);
- /* Expect at least one name (the node output). */
- if (n < 1) {
- (void) fprintf(stdout,"Missing output name.\n");
- goto failure;
- }
- newnode->name = list[n-1];
- newnode->inputs = list;
- newnode->ninp = n-1;
- newnode->active = FALSE;
- newnode->nfo = 0;
- newnode->polarity = 0;
- if (newnode->ninp > 0) {
- newnode->type = BNET_INTERNAL_NODE;
- for (i = 0; i < net->noutputs; i++) {
- if (strcmp(net->outputs[i], newnode->name) == 0) {
- newnode->type = BNET_OUTPUT_NODE;
- break;
- }
- }
- } else {
- newnode->type = BNET_CONSTANT_NODE;
- }
- newnode->dd = NULL;
- newnode->next = NULL;
- if (lastnode == NULL) {
- net->nodes = newnode;
- } else {
- lastnode->next = newnode;
- }
- lastnode = newnode;
- /* Read node function. */
- newnode->f = NULL;
- if (exdc) {
- newnode->exdc_flag = 1;
- node = net->nodes;
- while (node) {
- if (node->type == BNET_OUTPUT_NODE &&
- strcmp(node->name, newnode->name) == 0) {
- node->exdc = newnode;
- break;
- }
- node = node->next;
- }
- }
- savestring = readString(fp);
- if (savestring == NULL) goto failure;
- lastline = NULL;
- while (savestring[0] != '.') {
- /* Reading a table line. */
- newline = ALLOC(BnetTabline,1);
- if (newline == NULL) goto failure;
- newline->next = NULL;
- if (lastline == NULL) {
- newnode->f = newline;
- } else {
- lastline->next = newline;
- }
- lastline = newline;
- if (newnode->type == BNET_INTERNAL_NODE ||
- newnode->type == BNET_OUTPUT_NODE) {
- newline->values = savestring;
- /* Read output 1 or 0. */
- savestring = readString(fp);
- if (savestring == NULL) goto failure;
- } else {
- newline->values = NULL;
- }
- if (savestring[0] == '0') newnode->polarity = 1;
- FREE(savestring);
- savestring = readString(fp);
- if (savestring == NULL) goto failure;
- }
- } else if (strcmp(savestring,".exdc") == 0) {
- FREE(savestring);
- exdc = 1;
- } else if (strcmp(savestring,".end") == 0) {
- FREE(savestring);
- break;
- }
- if ((!savestring) || savestring[0] != '.')
- savestring = readString(fp);
- if (savestring == NULL) goto failure;
- }
- /* Put nodes in symbol table. */
- newnode = net->nodes;
- while (newnode != NULL) {
- int retval = st_insert(net->hash,newnode->name,(char *) newnode);
- if (retval == ST_OUT_OF_MEM) {
- goto failure;
- } else if (retval == 1) {
- printf("Error: Multiple drivers for node %s\n", newnode->name);
- goto failure;
- } else {
- if (pr > 2) printf("Inserted %s\n",newnode->name);
- }
- newnode = newnode->next;
- }
- if (latches) {
- net->latches = latches;
- count = 0;
- net->outputs = REALLOC(char *, net->outputs,
- (net->noutputs + net->nlatches) * sizeof(char *));
- for (i = 0; i < net->nlatches; i++) {
- for (j = 0; j < net->noutputs; j++) {
- if (strcmp(latches[i][0], net->outputs[j]) == 0)
- break;
- }
- if (j < net->noutputs)
- continue;
- savestring = ALLOC(char, strlen(latches[i][0]) + 1);
- strcpy(savestring, latches[i][0]);
- net->outputs[net->noutputs + count] = savestring;
- count++;
- if (st_lookup(net->hash, savestring, (void **) &node)) {
- if (node->type == BNET_INTERNAL_NODE) {
- node->type = BNET_OUTPUT_NODE;
- }
- }
- }
- net->noutputs += count;
- net->inputs = REALLOC(char *, net->inputs,
- (net->ninputs + net->nlatches) * sizeof(char *));
- for (i = 0; i < net->nlatches; i++) {
- savestring = ALLOC(char, strlen(latches[i][1]) + 1);
- strcpy(savestring, latches[i][1]);
- net->inputs[net->ninputs + i] = savestring;
- }
- net->ninputs += net->nlatches;
- }
- /* Compute fanout counts. For each node in the linked list, fetch
- ** all its fanins using the symbol table, and increment the fanout of
- ** each fanin.
- */
- newnode = net->nodes;
- while (newnode != NULL) {
- BnetNode *auxnd;
- for (i = 0; i < newnode->ninp; i++) {
- if (!st_lookup(net->hash,newnode->inputs[i],(void **)&auxnd)) {
- (void) fprintf(stdout,"%s not driven\n", newnode->inputs[i]);
- goto failure;
- }
- auxnd->nfo++;
- }
- newnode = newnode->next;
- }
- if (!bnetSetLevel(net)) goto failure;
- return(net);
- failure:
- /* Here we should clean up the mess. */
- (void) fprintf(stdout,"Error in reading network from file.\n");
- return(NULL);
- } /* end of Bnet_ReadNetwork */
- /**
- @brief Prints to stdout a boolean network created by Bnet_ReadNetwork.
- @details Uses the blif format; this way, one can verify the
- equivalence of the input and the output with, say, sis.
- @sideeffect None
- @see Bnet_ReadNetwork
- */
- void
- Bnet_PrintNetwork(
- BnetNetwork * net /**< boolean network */)
- {
- BnetNode *nd;
- BnetTabline *tl;
- int i;
- if (net == NULL) return;
- (void) fprintf(stdout,".model %s\n", net->name);
- (void) fprintf(stdout,".inputs");
- printList(net->inputs,net->npis);
- (void) fprintf(stdout,".outputs");
- printList(net->outputs,net->npos);
- for (i = 0; i < net->nlatches; i++) {
- (void) fprintf(stdout,".latch");
- printList(net->latches[i],3);
- }
- nd = net->nodes;
- while (nd != NULL) {
- if (nd->type != BNET_INPUT_NODE && nd->type != BNET_PRESENT_STATE_NODE) {
- (void) fprintf(stdout,".names");
- for (i = 0; i < nd->ninp; i++) {
- (void) fprintf(stdout," %s",nd->inputs[i]);
- }
- (void) fprintf(stdout," %s\n",nd->name);
- tl = nd->f;
- while (tl != NULL) {
- if (tl->values != NULL) {
- (void) fprintf(stdout,"%s %d\n",tl->values,
- 1 - nd->polarity);
- } else {
- (void) fprintf(stdout,"%d\n", 1 - nd->polarity);
- }
- tl = tl->next;
- }
- }
- nd = nd->next;
- }
- (void) fprintf(stdout,".end\n");
- } /* end of Bnet_PrintNetwork */
- /**
- @brief Frees a boolean network created by Bnet_ReadNetwork.
- @sideeffect None
- @see Bnet_ReadNetwork
- */
- void
- Bnet_FreeNetwork(
- BnetNetwork * net)
- {
- BnetNode *node, *nextnode;
- BnetTabline *line, *nextline;
- int i;
- FREE(net->name);
- /* The input name strings are already pointed by the input nodes.
- ** Here we only need to free the latch names and the array that
- ** points to them.
- */
- for (i = 0; i < net->nlatches; i++) {
- FREE(net->inputs[net->npis + i]);
- }
- FREE(net->inputs);
- /* Free the output name strings and then the array pointing to them. */
- for (i = 0; i < net->noutputs; i++) {
- FREE(net->outputs[i]);
- }
- FREE(net->outputs);
- for (i = 0; i < net->nlatches; i++) {
- FREE(net->latches[i][0]);
- FREE(net->latches[i][1]);
- FREE(net->latches[i][2]);
- FREE(net->latches[i]);
- }
- if (net->nlatches) FREE(net->latches);
- node = net->nodes;
- while (node != NULL) {
- nextnode = node->next;
- if (node->type != BNET_PRESENT_STATE_NODE)
- FREE(node->name);
- for (i = 0; i < node->ninp; i++) {
- FREE(node->inputs[i]);
- }
- if (node->inputs != NULL) {
- FREE(node->inputs);
- }
- /* Free the function table. */
- line = node->f;
- while (line != NULL) {
- nextline = line->next;
- FREE(line->values);
- FREE(line);
- line = nextline;
- }
- FREE(node);
- node = nextnode;
- }
- st_free_table(net->hash);
- if (net->slope != NULL) FREE(net->slope);
- FREE(net);
- } /* end of Bnet_FreeNetwork */
- /**
- @brief Builds the %BDD for the function of a node.
- @details Builds the %BDD for the function of a node and stores a
- pointer to it in the dd field of the node itself. The reference count
- of the %BDD is incremented. If params is BNET_LOCAL_DD, then the %BDD is
- built in terms of the local inputs to the node; otherwise, if params
- is BNET_GLOBAL_DD, the %BDD is built in terms of the network primary
- inputs. To build the global %BDD of a node, the BDDs for its local
- inputs must exist. If that is not the case, Bnet_BuildNodeBDD
- recursively builds them. Likewise, to create the local %BDD for a node,
- the local inputs must have variables assigned to them. If that is not
- the case, Bnet_BuildNodeBDD recursively assigns variables to nodes.
- @return 1 in case of success; 0 otherwise.
- @sideeffect Sets the dd field of the node.
- */
- int
- Bnet_BuildNodeBDD(
- DdManager * dd /**< %DD manager */,
- BnetNode * nd /**< node of the boolean network */,
- st_table * hash /**< symbol table of the boolean network */,
- int params /**< type of %DD to be built */,
- int nodrop /**< retain the intermediate node DDs until the end */)
- {
- DdNode *func;
- BnetNode *auxnd;
- DdNode *tmp;
- DdNode *prod, *var;
- BnetTabline *line;
- int i;
- if (nd->dd != NULL) return(1);
- if (nd->type == BNET_CONSTANT_NODE) {
- if (nd->f == NULL) { /* constant 0 */
- func = Cudd_ReadLogicZero(dd);
- } else { /* either constant depending on the polarity */
- func = Cudd_ReadOne(dd);
- }
- Cudd_Ref(func);
- } else if (nd->type == BNET_INPUT_NODE ||
- nd->type == BNET_PRESENT_STATE_NODE) {
- if (nd->active == TRUE) { /* a variable is already associated: use it */
- func = Cudd_ReadVars(dd,nd->var);
- if (func == NULL) goto failure;
- } else { /* no variable associated: get a new one */
- func = Cudd_bddNewVar(dd);
- if (func == NULL) goto failure;
- nd->var = func->index;
- nd->active = TRUE;
- }
- Cudd_Ref(func);
- } else if (buildExorBDD(dd,nd,hash,params,nodrop)) {
- func = nd->dd;
- } else if (buildMuxBDD(dd,nd,hash,params,nodrop)) {
- func = nd->dd;
- } else { /* type == BNET_INTERNAL_NODE or BNET_OUTPUT_NODE */
- /* Initialize the sum to logical 0. */
- func = Cudd_ReadLogicZero(dd);
- Cudd_Ref(func);
- /* Build a term for each line of the table and add it to the
- ** accumulator (func).
- */
- line = nd->f;
- while (line != NULL) {
- #ifdef BNET_DEBUG
- (void) fprintf(stdout,"line = %s\n", line->values);
- #endif
- /* Initialize the product to logical 1. */
- prod = Cudd_ReadOne(dd);
- Cudd_Ref(prod);
- /* Scan the table line. */
- for (i = 0; i < nd->ninp; i++) {
- if (line->values[i] == '-') continue;
- if (!st_lookup(hash,nd->inputs[i],(void **)&auxnd)) {
- goto failure;
- }
- if (params == BNET_LOCAL_DD) {
- if (auxnd->active == FALSE) {
- if (!Bnet_BuildNodeBDD(dd,auxnd,hash,params,nodrop)) {
- goto failure;
- }
- }
- var = Cudd_ReadVars(dd,auxnd->var);
- if (var == NULL) goto failure;
- Cudd_Ref(var);
- if (line->values[i] == '0') {
- var = Cudd_Not(var);
- }
- } else { /* params == BNET_GLOBAL_DD */
- if (auxnd->dd == NULL) {
- if (!Bnet_BuildNodeBDD(dd,auxnd,hash,params,nodrop)) {
- goto failure;
- }
- }
- if (line->values[i] == '1') {
- var = auxnd->dd;
- } else { /* line->values[i] == '0' */
- var = Cudd_Not(auxnd->dd);
- }
- }
- tmp = Cudd_bddAnd(dd,prod,var);
- if (tmp == NULL) goto failure;
- Cudd_Ref(tmp);
- Cudd_IterDerefBdd(dd,prod);
- if (params == BNET_LOCAL_DD) {
- Cudd_IterDerefBdd(dd,var);
- }
- prod = tmp;
- }
- tmp = Cudd_bddOr(dd,func,prod);
- if (tmp == NULL) goto failure;
- Cudd_Ref(tmp);
- Cudd_IterDerefBdd(dd,func);
- Cudd_IterDerefBdd(dd,prod);
- func = tmp;
- line = line->next;
- }
- /* Associate a variable to this node if local BDDs are being
- ** built. This is done at the end, so that the primary inputs tend
- ** to get lower indices.
- */
- if (params == BNET_LOCAL_DD && nd->active == FALSE) {
- DdNode *auxfunc = Cudd_bddNewVar(dd);
- if (auxfunc == NULL) goto failure;
- Cudd_Ref(auxfunc);
- nd->var = auxfunc->index;
- nd->active = TRUE;
- Cudd_IterDerefBdd(dd,auxfunc);
- }
- }
- if (nd->polarity == 1) {
- nd->dd = Cudd_Not(func);
- } else {
- nd->dd = func;
- }
- if (params == BNET_GLOBAL_DD && nodrop == FALSE) {
- /* Decrease counters for all faninis.
- ** When count reaches 0, the DD is freed.
- */
- for (i = 0; i < nd->ninp; i++) {
- if (!st_lookup(hash,nd->inputs[i],(void **)&auxnd)) {
- goto failure;
- }
- auxnd->count--;
- if (auxnd->count == 0) {
- Cudd_IterDerefBdd(dd,auxnd->dd);
- if (auxnd->type == BNET_INTERNAL_NODE ||
- auxnd->type == BNET_CONSTANT_NODE) auxnd->dd = NULL;
- }
- }
- }
- return(1);
- failure:
- /* Here we should clean up the mess. */
- return(0);
- } /* end of Bnet_BuildNodeBDD */
- /**
- @brief Orders the %BDD variables by DFS.
- @return 1 in case of success; 0 otherwise.
- @sideeffect Uses the visited flags of the nodes.
- */
- int
- Bnet_DfsVariableOrder(
- DdManager * dd,
- BnetNetwork * net)
- {
- BnetNode **roots;
- BnetNode *node;
- int nroots;
- int i;
- roots = bnetOrderRoots(net,&nroots);
- if (roots == NULL) return(0);
- for (i = 0; i < nroots; i++) {
- if (!bnetDfsOrder(dd,net,roots[i])) {
- FREE(roots);
- return(0);
- }
- }
- /* Clear visited flags. */
- node = net->nodes;
- while (node != NULL) {
- node->visited = 0;
- node = node->next;
- }
- FREE(roots);
- return(1);
- } /* end of Bnet_DfsVariableOrder */
- /**
- @brief Writes the network BDDs to a file in dot, blif, or daVinci
- format.
- @details If "-" is passed as file name, the BDDs are dumped to the
- standard output.
- @return 1 in case of success; 0 otherwise.
- @sideeffect None
- */
- int
- Bnet_bddDump(
- DdManager * dd /**< %DD manager */,
- BnetNetwork * network /**< network whose BDDs should be dumped */,
- char * dfile /**< file name */,
- int dumpFmt /**< 0 -> dot */,
- int reencoded /**< whether variables have been reencoded */)
- {
- int noutputs;
- FILE *dfp = NULL;
- DdNode **outputs = NULL;
- char **inames = NULL;
- char **onames = NULL;
- char **altnames = NULL;
- BnetNode *node;
- int i;
- int retval = 0; /* 0 -> failure; 1 -> success */
- /* Open dump file. */
- if (strcmp(dfile, "-") == 0) {
- dfp = stdout;
- } else {
- dfp = fopen(dfile,"w");
- }
- if (dfp == NULL) goto endgame;
- /* Initialize data structures. */
- noutputs = network->noutputs;
- outputs = ALLOC(DdNode *,noutputs);
- if (outputs == NULL) goto endgame;
- onames = ALLOC(char *,noutputs);
- if (onames == NULL) goto endgame;
- inames = ALLOC(char *,Cudd_ReadSize(dd));
- if (inames == NULL) goto endgame;
- /* Find outputs and their names. */
- for (i = 0; i < network->nlatches; i++) {
- onames[i] = network->latches[i][0];
- if (!st_lookup(network->hash,network->latches[i][0],(void **)&node)) {
- goto endgame;
- }
- outputs[i] = node->dd;
- }
- for (i = 0; i < network->npos; i++) {
- onames[i + network->nlatches] = network->outputs[i];
- if (!st_lookup(network->hash,network->outputs[i],(void **)&node)) {
- goto endgame;
- }
- outputs[i + network->nlatches] = node->dd;
- }
- /* Find the input names. */
- for (i = 0; i < network->ninputs; i++) {
- if (!st_lookup(network->hash,network->inputs[i],(void **)&node)) {
- goto endgame;
- }
- inames[node->var] = network->inputs[i];
- }
- for (i = 0; i < network->nlatches; i++) {
- if (!st_lookup(network->hash,network->latches[i][1],(void **)&node)) {
- goto endgame;
- }
- inames[node->var] = network->latches[i][1];
- }
- if (reencoded == 1 && dumpFmt == 1) {
- altnames = bnetGenerateNewNames(network->hash,network->ninputs);
- if (altnames == NULL) {
- retval = 0;
- goto endgame;
- }
- retval = bnetDumpReencodingLogic(dd,network->name,noutputs,outputs,
- inames,altnames,onames,dfp);
- for (i = 0; i < network->ninputs; i++) {
- FREE(altnames[i]);
- }
- FREE(altnames);
- if (retval == 0) goto endgame;
- }
- /* Dump the BDDs. */
- if (dumpFmt == 1) {
- retval = Cudd_DumpBlif(dd,noutputs,outputs,
- (char const * const *) inames,
- (char const * const *) onames,
- network->name,dfp,0);
- } else if (dumpFmt == 2) {
- retval = Cudd_DumpDaVinci(dd,noutputs,outputs,
- (char const * const *) inames,
- (char const * const *) onames,dfp);
- } else if (dumpFmt == 3) {
- retval = Cudd_DumpDDcal(dd,noutputs,outputs,
- (char const * const *) inames,
- (char const * const *) onames,dfp);
- } else if (dumpFmt == 4) {
- retval = Cudd_DumpFactoredForm(dd,noutputs,outputs,
- (char const * const *) inames,
- (char const * const *) onames,dfp);
- } else if (dumpFmt == 5) {
- retval = Cudd_DumpBlif(dd,noutputs,outputs,
- (char const * const *) inames,
- (char const * const *) onames,
- network->name,dfp,1);
- } else {
- retval = Cudd_DumpDot(dd,noutputs,outputs,
- (char const * const *) inames,
- (char const * const *) onames,dfp);
- }
- endgame:
- if (dfp != stdout && dfp != NULL) {
- if (fclose(dfp) == EOF) retval = 0;
- }
- if (outputs != NULL) FREE(outputs);
- if (onames != NULL) FREE(onames);
- if (inames != NULL) FREE(inames);
- return(retval);
- } /* end of Bnet_bddDump */
- /**
- @brief Writes an array of BDDs to a file in dot, blif, DDcal,
- factored-form, daVinci, or blif-MV format.
- @details The BDDs and their names are passed as arguments. The
- inputs and their names are taken from the network. If "-" is passed
- as file name, the BDDs are dumped to the standard output. The encoding
- of the format is:
- <ul>
- <li>0: dot
- <li>1: blif
- <li>2: da Vinci
- <li>3: ddcal
- <li>4: factored form
- <li>5: blif-MV
- </ul>
- @return 1 in case of success; 0 otherwise.
- @sideeffect None
- */
- int
- Bnet_bddArrayDump(
- DdManager * dd /**< %DD manager */,
- BnetNetwork * network /**< network whose BDDs should be dumped */,
- char * dfile /**< file name */,
- DdNode ** outputs /**< BDDs to be dumped */,
- char ** onames /**< names of the BDDs to be dumped */,
- int noutputs /**< number of BDDs to be dumped */,
- int dumpFmt /**< 0 -> dot */)
- {
- FILE *dfp = NULL;
- char **inames = NULL;
- BnetNode *node;
- int i;
- int retval = 0; /* 0 -> failure; 1 -> success */
- /* Open dump file. */
- if (strcmp(dfile, "-") == 0) {
- dfp = stdout;
- } else {
- dfp = fopen(dfile,"w");
- }
- if (dfp == NULL) goto endgame;
- /* Initialize data structures. */
- inames = ALLOC(char *,Cudd_ReadSize(dd));
- if (inames == NULL) goto endgame;
- for (i = 0; i < Cudd_ReadSize(dd); i++) {
- inames[i] = NULL;
- }
- /* Find the input names. */
- for (i = 0; i < network->ninputs; i++) {
- if (!st_lookup(network->hash,network->inputs[i],(void **)&node)) {
- goto endgame;
- }
- inames[node->var] = network->inputs[i];
- }
- for (i = 0; i < network->nlatches; i++) {
- if (!st_lookup(network->hash,network->latches[i][1],(void **)&node)) {
- goto endgame;
- }
- inames[node->var] = network->latches[i][1];
- }
- /* Dump the BDDs. */
- if (dumpFmt == 1) {
- retval = Cudd_DumpBlif(dd,noutputs,outputs,
- (char const * const *) inames,
- (char const * const *) onames,
- network->name,dfp,0);
- } else if (dumpFmt == 2) {
- retval = Cudd_DumpDaVinci(dd,noutputs,outputs,
- (char const * const *) inames,
- (char const * const *) onames,dfp);
- } else if (dumpFmt == 3) {
- retval = Cudd_DumpDDcal(dd,noutputs,outputs,
- (char const * const *) inames,
- (char const * const *) onames,dfp);
- } else if (dumpFmt == 4) {
- retval = Cudd_DumpFactoredForm(dd,noutputs,outputs,
- (char const * const *) inames,
- (char const * const *) onames,dfp);
- } else if (dumpFmt == 5) {
- retval = Cudd_DumpBlif(dd,noutputs,outputs,
- (char const * const *) inames,
- (char const * const *) onames,
- network->name,dfp,1);
- } else {
- retval = Cudd_DumpDot(dd,noutputs,outputs,
- (char const * const *) inames,
- (char const * const *) onames,dfp);
- }
- endgame:
- if (dfp != stdout && dfp != NULL) {
- if (fclose(dfp) == EOF) retval = 0;
- }
- if (inames != NULL) FREE(inames);
- return(retval);
- } /* end of Bnet_bddArrayDump */
- /**
- @brief Reads the variable order from a file.
- @return 1 if successful; 0 otherwise.
- @sideeffect The BDDs for the primary inputs and present state variables
- are built.
- */
- int
- Bnet_ReadOrder(
- DdManager * dd,
- char * ordFile,
- BnetNetwork * net,
- int locGlob,
- int nodrop)
- {
- FILE *fp;
- st_table *dict;
- int result;
- BnetNode *node;
- char name[MAXLENGTH];
- if (ordFile == NULL) {
- return(0);
- }
- dict = st_init_table((st_compare_t) strcmp,st_strhash);
- if (dict == NULL) {
- return(0);
- }
- if ((fp = fopen(ordFile,"r")) == NULL) {
- (void) fprintf(stderr,"Unable to open %s\n",ordFile);
- st_free_table(dict);
- return(0);
- }
- while (!feof(fp)) {
- result = fscanf(fp, "%s", name);
- if (result == EOF) {
- break;
- } else if (result != 1) {
- st_free_table(dict);
- return(0);
- } else if (strlen(name) > MAXLENGTH) {
- st_free_table(dict);
- return(0);
- }
- /* There should be a node named "name" in the network. */
- if (!st_lookup(net->hash,name,(void **)&node)) {
- (void) fprintf(stderr,"Unknown name in order file (%s)\n", name);
- st_free_table(dict);
- return(0);
- }
- /* A name should not appear more than once in the order. */
- if (st_is_member(dict,name)) {
- (void) fprintf(stderr,"Duplicate name in order file (%s)\n", name);
- st_free_table(dict);
- return(0);
- }
- /* The name should correspond to a primary input or present state. */
- if (node->type != BNET_INPUT_NODE &&
- node->type != BNET_PRESENT_STATE_NODE) {
- (void) fprintf(stderr,"%s has the wrong type (%d)\n", name,
- node->type);
- st_free_table(dict);
- return(0);
- }
- /* Insert in table. Use node->name rather than name, because the
- ** latter gets overwritten.
- */
- if (st_insert(dict,node->name,NULL) == ST_OUT_OF_MEM) {
- (void) fprintf(stderr,"Out of memory in Bnet_ReadOrder\n");
- st_free_table(dict);
- return(0);
- }
- result = Bnet_BuildNodeBDD(dd,node,net->hash,locGlob,nodrop);
- if (result == 0) {
- (void) fprintf(stderr,"Construction of BDD failed\n");
- st_free_table(dict);
- return(0);
- }
- } /* while (!feof(fp)) */
- result = fclose(fp);
- if (result == EOF) {
- (void) fprintf(stderr,"Error closing order file %s\n", ordFile);
- st_free_table(dict);
- return(0);
- }
- /* The number of names in the order file should match exactly the
- ** number of primary inputs and present states.
- */
- if (st_count(dict) != net->ninputs) {
- (void) fprintf(stderr,"Order incomplete: %d names instead of %d\n",
- st_count(dict), net->ninputs);
- st_free_table(dict);
- return(0);
- }
- st_free_table(dict);
- return(1);
- } /* end of Bnet_ReadOrder */
- /**
- @brief Prints the order of the %DD variables of a network.
- @details Only primary inputs and present states are printed.
- @return 1 if successful; 0 otherwise.
- @sideeffect None
- */
- int
- Bnet_PrintOrder(
- BnetNetwork * net,
- DdManager *dd)
- {
- char **names; /* array used to print variable orders */
- int level; /* position of a variable in current order */
- BnetNode *node; /* auxiliary pointer to network node */
- int i,j;
- int retval;
- int nvars;
- nvars = Cudd_ReadSize(dd);
- names = ALLOC(char *, nvars);
- if (names == NULL) return(0);
- for (i = 0; i < nvars; i++) {
- names[i] = NULL;
- }
- for (i = 0; i < net->npis; i++) {
- if (!st_lookup(net->hash,net->inputs[i],(void **)&node)) {
- FREE(names);
- return(0);
- }
- if (node->dd == NULL) {
- FREE(names);
- return(0);
- }
- level = Cudd_ReadPerm(dd,node->var);
- names[level] = node->name;
- }
- for (i = 0; i < net->nlatches; i++) {
- if (!st_lookup(net->hash,net->latches[i][1],(void **)&node)) {
- FREE(names);
- return(0);
- }
- if (node->dd == NULL) {
- FREE(names);
- return(0);
- }
- level = Cudd_ReadPerm(dd,node->var);
- names[level] = node->name;
- }
- for (i = 0, j = 0; i < nvars; i++) {
- if (names[i] == NULL) continue;
- if ((j%8 == 0)&&j) {
- retval = printf("\n");
- if (retval == EOF) {
- FREE(names);
- return(0);
- }
- }
- retval = printf("%s ",names[i]);
- if (retval == EOF) {
- FREE(names);
- return(0);
- }
- j++;
- }
- FREE(names);
- retval = printf("\n");
- if (retval == EOF) {
- return(0);
- }
- return(1);
- } /* end of Bnet_PrintOrder */
- /*---------------------------------------------------------------------------*/
- /* Definition of internal functions */
- /*---------------------------------------------------------------------------*/
- /*---------------------------------------------------------------------------*/
- /* Definition of static functions */
- /*---------------------------------------------------------------------------*/
- /**
- @brief Reads a string from a file.
- @details The string can be MAXLENGTH-1 characters at
- most. readString allocates memory to hold the string.
- @return a pointer to the result string if successful. It returns
- NULL otherwise.
- @sideeffect None
- @see readList
- */
- static char *
- readString(
- FILE * fp /**< pointer to the file from which the string is read */)
- {
- char *savestring;
- int length;
- while (!CurPos) {
- if (!fgets(BuffLine, MAXLENGTH, fp))
- return(NULL);
- BuffLine[strlen(BuffLine) - 1] = '\0';
- CurPos = strtok(BuffLine, " \t");
- if (CurPos && CurPos[0] == '#') CurPos = (char *)NULL;
- }
- length = strlen(CurPos);
- savestring = ALLOC(char,length+1);
- if (savestring == NULL)
- return(NULL);
- strcpy(savestring,CurPos);
- CurPos = strtok(NULL, " \t");
- return(savestring);
- } /* end of readString */
- /**
- @brief Reads a list of strings from a line of a file.
- @details The strings are sequences of characters separated by spaces
- or tabs. The total length of the list, white space included, must
- not exceed MAXLENGTH-1 characters. readList allocates memory for
- the strings and creates an array of pointers to the individual
- lists. Only two pieces of memory are allocated by readList: One to
- hold all the strings, and one to hold the pointers to
- them. Therefore, when freeing the memory allocated by readList, only
- the pointer to the list of pointers, and the pointer to the
- beginning of the first string should be freed.
- @return the pointer to the list of pointers if successful; NULL
- otherwise.
- @sideeffect n is set to the number of strings in the list.
- @see readString printList
- */
- static char **
- readList(
- FILE * fp /**< pointer to the file from which the list is read */,
- int * n /**< on return, number of strings in the list */)
- {
- char *savestring;
- int length;
- char *stack[8192];
- char **list;
- int i, count = 0;
- while (CurPos) {
- if (strcmp(CurPos, "\\") == 0) {
- CurPos = (char *)NULL;
- while (!CurPos) {
- if (!fgets(BuffLine, MAXLENGTH, fp)) return(NULL);
- BuffLine[strlen(BuffLine) - 1] = '\0';
- CurPos = strtok(BuffLine, " \t");
- }
- }
- length = strlen(CurPos);
- savestring = ALLOC(char,length+1);
- if (savestring == NULL) return(NULL);
- strcpy(savestring,CurPos);
- stack[count] = savestring;
- count++;
- CurPos = strtok(NULL, " \t");
- }
- list = ALLOC(char *, count);
- for (i = 0; i < count; i++)
- list[i] = stack[i];
- *n = count;
- return(list);
- } /* end of readList */
- /**
- @brief Prints a list of strings to the standard output.
- @details The list is in the format created by readList.
- @sideeffect None
- @see readList Bnet_PrintNetwork
- */
- static void
- printList(
- char ** list /**< list of pointers to strings */,
- int n /**< length of the list */)
- {
- int i;
- for (i = 0; i < n; i++) {
- (void) fprintf(stdout," %s",list[i]);
- }
- (void) fprintf(stdout,"\n");
- } /* end of printList */
- /**
- @brief Generates n names not currently in a symbol table.
- @details The pointer to the symbol table may be NULL, in which case
- no test is made. The names generated by the procedure are
- unique. So, if there is no possibility of conflict with pre-existing
- names, NULL can be passed for the hash table.
- @return an array of names if succesful; NULL otherwise.
- @sideeffect None
- @see
- */
- static char **
- bnetGenerateNewNames(
- st_table * hash /* table of existing names (or NULL) */,
- int n /* number of names to be generated */)
- {
- char **list;
- char name[256];
- int i;
- if (n < 1) return(NULL);
- list = ALLOC(char *,n);
- if (list == NULL) return(NULL);
- for (i = 0; i < n; i++) {
- do {
- sprintf(name, "var%d", newNameNumber);
- newNameNumber++;
- } while (hash != NULL && st_is_member(hash,name));
- list[i] = util_strsav(name);
- }
- return(list);
- } /* bnetGenerateNewNames */
- /**
- @brief Writes blif for the reencoding logic.
- @sideeffect None
- */
- static int
- bnetDumpReencodingLogic(
- DdManager * dd /**< %DD manager */,
- char * mname /**< model name */,
- int noutputs /**< number of outputs */,
- DdNode ** outputs /**< array of network outputs */,
- char ** inames /**< array of network input names */,
- char ** altnames /**< array of names of reencoded inputs */,
- char ** onames /**< array of network output names */,
- FILE * fp /**< file pointer */)
- {
- int i;
- int retval;
- int nvars = Cudd_ReadSize(dd);
- int *support = NULL;
- support = bnetFindVectorSupport(dd,outputs,noutputs);
- if (support == NULL) return(0);
- /* Write the header (.model .inputs .outputs). */
- retval = fprintf(fp,".model %s.global\n.inputs",mname);
- if (retval == EOF) goto failure;
- for (i = 0; i < nvars; i++) {
- if ((i%8 == 0)&&i) {
- retval = fprintf(fp," \\\n");
- if (retval == EOF) goto failure;
- }
- retval = fprintf(fp," %s", inames[i]);
- if (retval == EOF) goto failure;
- }
- /* Write the .output line. */
- retval = fprintf(fp,"\n.outputs");
- if (retval == EOF) goto failure;
- for (i = 0; i < noutputs; i++) {
- if ((i%8 == 0)&&i) {
- retval = fprintf(fp," \\\n");
- if (retval == EOF) goto failure;
- }
- retval = fprintf(fp," %s", onames[i]);
- if (retval == EOF) goto failure;
- }
- retval = fprintf(fp,"\n");
- if (retval == EOF) goto failure;
- /* Instantiate main subcircuit. */
- retval = fprintf(fp,"\n.subckt %s", mname);
- if (retval == EOF) goto failure;
- for (i = 0; i < nvars; i++) {
- if ((i%8 == 0)&&i) {
- retval = fprintf(fp," \\\n");
- if (retval == EOF) goto failure;
- }
- if (support[i] == 1) {
- retval = fprintf(fp," %s=%s", inames[i], altnames[i]);
- if (retval == EOF) goto failure;
- }
- }
- for (i = 0; i < noutputs; i++) {
- if ((i%8 == 0)&&i) {
- retval = fprintf(fp," \\\n");
- if (retval == EOF) goto failure;
- }
- retval = fprintf(fp," %s=%s", onames[i], onames[i]);
- if (retval == EOF) goto failure;
- }
- retval = fprintf(fp,"\n");
- if (retval == EOF) goto failure;
- /* Instantiate reencoding subcircuit. */
- retval = fprintf(fp,"\n.subckt %s.reencode",mname);
- if (retval == EOF) goto failure;
- for (i = 0; i < nvars; i++) {
- if ((i%8 == 0)&&i) {
- retval = fprintf(fp," \\\n");
- if (retval == EOF) goto failure;
- }
- retval = fprintf(fp," %s=%s", inames[i], inames[i]);
- if (retval == EOF) goto failure;
- }
- retval = fprintf(fp," \\\n");
- if (retval == EOF) goto failure;
- for (i = 0; i < nvars; i++) {
- if ((i%8 == 0)&&i) {
- retval = fprintf(fp," \\\n");
- if (retval == EOF) goto failure;
- }
- if (support[i] == 1) {
- retval = fprintf(fp," %s=%s", altnames[i],altnames[i]);
- if (retval == EOF) goto failure;
- }
- }
- retval = fprintf(fp,"\n");
- if (retval == EOF) goto failure;
- /* Write trailer. */
- retval = fprintf(fp,".end\n\n");
- if (retval == EOF) goto failure;
- /* Write reencoding subcircuit. */
- retval = bnetBlifWriteReencode(dd,mname,inames,altnames,support,fp);
- if (retval == EOF) goto failure;
- FREE(support);
- return(1);
- failure:
- if (support != NULL) FREE(support);
- return(0);
- } /* end of bnetDumpReencodingLogic */
- /**
- @brief Writes blif for the truth table of an n-input xnor.
- @return 1 if successful; 0 otherwise.
- @sideeffect None
- */
- #if 0
- static int
- bnetBlifXnorTable(
- FILE * fp /**< file pointer */,
- int n /**< number of inputs */)
- {
- int power; /* 2 to the power n */
- int i,j,k;
- int nzeroes;
- int retval;
- char *line;
- line = ALLOC(char,n+1);
- if (line == NULL) return(0);
- line[n] = '\0';
- for (i = 0, power = 1; i < n; i++) {
- power *= 2;
- }
- for (i = 0; i < power; i++) {
- k = i;
- nzeroes = 0;
- for (j = 0; j < n; j++) {
- if (k & 1) {
- line[j] = '1';
- } else {
- line[j] = '0';
- nzeroes++;
- }
- k >>= 1;
- }
- if ((nzeroes & 1) == 0) {
- retval = fprintf(fp,"%s 1\n",line);
- if (retval == 0) return(0);
- }
- }
- return(1);
- } /* end of bnetBlifXnorTable */
- #endif
- /**
- @brief Writes blif for the reencoding logic.
- @details Exclusive NORs with more than two inputs are decomposed
- into cascaded two-input gates.
- @return 1 if successful; 0 otherwise.
- @sideeffect None
- */
- static int
- bnetBlifWriteReencode(
- DdManager * dd,
- char * mname,
- char ** inames,
- char ** altnames,
- int * support,
- FILE * fp)
- {
- int retval;
- int nvars = Cudd_ReadSize(dd);
- int i,j;
- int ninp;
- /* Write the header (.model .inputs .outputs). */
- retval = fprintf(fp,".model %s.reencode\n.inputs",mname);
- if (retval == EOF) return(0);
- for (i = 0; i < nvars; i++) {
- if ((i%8 == 0)&&i) {
- retval = fprintf(fp," \\\n");
- if (retval == EOF) goto failure;
- }
- retval = fprintf(fp," %s", inames[i]);
- if (retval == EOF) goto failure;
- }
- /* Write the .output line. */
- retval = fprintf(fp,"\n.outputs");
- if (retval == EOF) goto failure;
- for (i = 0; i < nvars; i++) {
- if ((i%8 == 0)&&i) {
- retval = fprintf(fp," \\\n");
- if (retval == EOF) goto failure;
- }
- if (support[i] == 1) {
- retval = fprintf(fp," %s", altnames[i]);
- if (retval == EOF) goto failure;
- }
- }
- retval = fprintf(fp,"\n");
- if (retval == EOF) goto failure;
- /* Instantiate exclusive nors. */
- for (i = 0; i < nvars; i++) {
- char *in1 = NULL;
- char *in2 = NULL;
- char **oname;
- if (support[i] == 0) continue;
- ninp = 0;
- for (j = 0; j < nvars; j++) {
- if (Cudd_ReadLinear(dd,i,j)) {
- switch (ninp) {
- case 0:
- in1 = inames[j];
- ninp++;
- break;
- case 1:
- in2 = inames[j];
- ninp++;
- break;
- case 2:
- oname = bnetGenerateNewNames(NULL,1);
- retval = fprintf(fp,".names %s %s %s\n11 1\n00 1\n",
- in1, in2, oname[0]);
- if (retval == EOF) goto failure;
- in1 = oname[0];
- in2 = inames[j];
- FREE(oname);
- break;
- default:
- goto failure;
- }
- }
- }
- switch (ninp) {
- case 1:
- retval = fprintf(fp,".names %s %s\n1 1\n", in1, altnames[i]);
- if (retval == EOF) goto failure;
- break;
- case 2:
- retval = fprintf(fp,".names %s %s %s\n11 1\n00 1\n",
- in1, in2, altnames[i]);
- if (retval == EOF) goto failure;
- break;
- default:
- goto failure;
- }
- }
- /* Write trailer. */
- retval = fprintf(fp,"\n.end\n\n");
- if (retval == EOF) goto failure;
- return(1);
- failure:
- return(0);
- } /* end of bnetBlifWriteReencode */
- /**
- @brief Finds the support of a list of DDs.
- @sideeffect None
- */
- static int *
- bnetFindVectorSupport(
- DdManager * dd,
- DdNode ** list,
- int n)
- {
- DdNode *support = NULL;
- DdNode *scan;
- int *array = NULL;
- int nvars = Cudd_ReadSize(dd);
- int i;
- /* Build an array with the support of the functions in list. */
- array = ALLOC(int,nvars);
- if (array == NULL) return(NULL);
- for (i = 0; i < nvars; i++) {
- array[i] = 0;
- }
- /* Take the union of the supports of each output function. */
- for (i = 0; i < n; i++) {
- support = Cudd_Support(dd,list[i]);
- if (support == NULL) {
- FREE(array);
- return(NULL);
- }
- Cudd_Ref(support);
- scan = support;
- while (!Cudd_IsConstant(scan)) {
- array[scan->index] = 1;
- scan = Cudd_T(scan);
- }
- Cudd_IterDerefBdd(dd,support);
- }
- return(array);
- } /* end of bnetFindVectorSupport */
- /**
- @brief Builds %BDD for a XOR function.
- @details Checks whether a function is a XOR with 2 or 3 inputs. If so,
- it builds the %BDD.
- @return 1 if the %BDD has been built; 0 otherwise.
- @sideeffect None
- */
- static int
- buildExorBDD(
- DdManager * dd,
- BnetNode * nd,
- st_table * hash,
- int params,
- int nodrop)
- {
- int check[8];
- int i;
- int nlines;
- BnetTabline *line;
- DdNode *func, *var, *tmp;
- BnetNode *auxnd;
- if (nd->ninp < 2 || nd->ninp > 3) return(0);
- nlines = 1 << (nd->ninp - 1);
- for (i = 0; i < 8; i++) check[i] = 0;
- line = nd->f;
- while (line != NULL) {
- int num = 0;
- int count = 0;
- nlines--;
- for (i = 0; i < nd->ninp; i++) {
- num <<= 1;
- if (line->values[i] == '-') {
- return(0);
- } else if (line->values[i] == '1') {
- count++;
- num++;
- }
- }
- if ((count & 1) == 0) return(0);
- if (check[num]) return(0);
- line = line->next;
- }
- if (nlines != 0) return(0);
- /* Initialize the exclusive sum to logical 0. */
- func = Cudd_ReadLogicZero(dd);
- Cudd_Ref(func);
- /* Scan the inputs. */
- for (i = 0; i < nd->ninp; i++) {
- if (!st_lookup(hash, nd->inputs[i], (void **) &auxnd)) {
- goto failure;
- }
- if (params == BNET_LOCAL_DD) {
- if (auxnd->active == FALSE) {
- if (!Bnet_BuildNodeBDD(dd,auxnd,hash,params,nodrop)) {
- goto failure;
- }
- }
- var = Cudd_ReadVars(dd,auxnd->var);
- if (var == NULL) goto failure;
- Cudd_Ref(var);
- } else { /* params == BNET_GLOBAL_DD */
- if (auxnd->dd == NULL) {
- if (!Bnet_BuildNodeBDD(dd,auxnd,hash,params,nodrop)) {
- goto failure;
- }
- }
- var = auxnd->dd;
- }
- tmp = Cudd_bddXor(dd,func,var);
- if (tmp == NULL) goto failure;
- Cudd_Ref(tmp);
- Cudd_IterDerefBdd(dd,func);
- if (params == BNET_LOCAL_DD) {
- Cudd_IterDerefBdd(dd,var);
- }
- func = tmp;
- }
- nd->dd = func;
- /* Associate a variable to this node if local BDDs are being
- ** built. This is done at the end, so that the primary inputs tend
- ** to get lower indices.
- */
- if (params == BNET_LOCAL_DD && nd->active == FALSE) {
- DdNode *auxfunc = Cudd_bddNewVar(dd);
- if (auxfunc == NULL) goto failure;
- Cudd_Ref(auxfunc);
- nd->var = auxfunc->index;
- nd->active = TRUE;
- Cudd_IterDerefBdd(dd,auxfunc);
- }
- return(1);
- failure:
- return(0);
- } /* end of buildExorBDD */
- /**
- @brief Builds %BDD for a multiplexer.
- @details Checks whether a function is a 2-to-1 multiplexer. If so,
- it builds the %BDD.
- @return 1 if the %BDD has been built; 0 otherwise.
- @sideeffect None
- */
- static int
- buildMuxBDD(
- DdManager * dd,
- BnetNode * nd,
- st_table * hash,
- int params,
- int nodrop)
- {
- BnetTabline *line;
- char *values[2];
- int mux[2] = {0, 0};
- int phase[2] = {0, 0};
- int j;
- int nlines = 0;
- int controlC = -1;
- int controlR = -1;
- DdNode *func, *f, *g, *h;
- BnetNode *auxnd;
- if (nd->ninp != 3 || nd->f == NULL) return(0);
- for (line = nd->f; line != NULL; line = line->next) {
- int dc = 0;
- if (nlines > 1) return(0);
- values[nlines] = line->values;
- for (j = 0; j < 3; j++) {
- if (values[nlines][j] == '-') {
- if (dc) return(0);
- dc = 1;
- }
- }
- if (!dc) return(0);
- nlines++;
- }
- if (nlines != 2) return(0);
- /* At this point we know we have:
- ** 3 inputs
- ** 2 lines
- ** 1 dash in each line
- ** If the two dashes are not in the same column, then there is
- ** exaclty one column without dashes: the control column.
- */
- for (j = 0; j < 3; j++) {
- if (values[0][j] == '-' && values[1][j] == '-') return(0);
- if (values[0][j] != '-' && values[1][j] != '-') {
- if (values[0][j] == values[1][j]) return(0);
- controlC = j;
- controlR = values[0][j] == '0';
- }
- }
- assert(controlC != -1 && controlR != -1);
- /* At this point we know that there is indeed no column with two
- ** dashes. The control column has been identified, and we know that
- ** its two elelments are different. */
- for (j = 0; j < 3; j++) {
- if (j == controlC) continue;
- if (values[controlR][j] == '1') {
- mux[0] = j;
- phase[0] = 0;
- } else if (values[controlR][j] == '0') {
- mux[0] = j;
- phase[0] = 1;
- } else if (values[1-controlR][j] == '1') {
- mux[1] = j;
- phase[1] = 0;
- } else if (values[1-controlR][j] == '0') {
- mux[1] = j;
- phase[1] = 1;
- }
- }
- /* Get the inputs. */
- if (!st_lookup(hash, nd->inputs[controlC], (void **) &auxnd)) {
- goto failure;
- }
- if (params == BNET_LOCAL_DD) {
- if (auxnd->active == FALSE) {
- if (!Bnet_BuildNodeBDD(dd,auxnd,hash,params,nodrop)) {
- goto failure;
- }
- }
- f = Cudd_ReadVars(dd,auxnd->var);
- if (f == NULL) goto failure;
- Cudd_Ref(f);
- } else { /* params == BNET_GLOBAL_DD */
- if (auxnd->dd == NULL) {
- if (!Bnet_BuildNodeBDD(dd,auxnd,hash,params,nodrop)) {
- goto failure;
- }
- }
- f = auxnd->dd;
- }
- if (!st_lookup(hash, nd->inputs[mux[0]], (void **) &auxnd)) {
- goto failure;
- }
- if (params == BNET_LOCAL_DD) {
- if (auxnd->active == FALSE) {
- if (!Bnet_BuildNodeBDD(dd,auxnd,hash,params,nodrop)) {
- goto failure;
- }
- }
- g = Cudd_ReadVars(dd,auxnd->var);
- if (g == NULL) goto failure;
- Cudd_Ref(g);
- } else { /* params == BNET_GLOBAL_DD */
- if (auxnd->dd == NULL) {
- if (!Bnet_BuildNodeBDD(dd,auxnd,hash,params,nodrop)) {
- goto failure;
- }
- }
- g = auxnd->dd;
- }
- g = Cudd_NotCond(g,phase[0]);
- if (!st_lookup(hash, nd->inputs[mux[1]], (void **) &auxnd)) {
- goto failure;
- }
- if (params == BNET_LOCAL_DD) {
- if (auxnd->active == FALSE) {
- if (!Bnet_BuildNodeBDD(dd,auxnd,hash,params,nodrop)) {
- goto failure;
- }
- }
- h = Cudd_ReadVars(dd,auxnd->var);
- if (h == NULL) goto failure;
- Cudd_Ref(h);
- } else { /* params == BNET_GLOBAL_DD */
- if (auxnd->dd == NULL) {
- if (!Bnet_BuildNodeBDD(dd,auxnd,hash,params,nodrop)) {
- goto failure;
- }
- }
- h = auxnd->dd;
- }
- h = Cudd_NotCond(h,phase[1]);
- func = Cudd_bddIte(dd,f,g,h);
- if (func == NULL) goto failure;
- Cudd_Ref(func);
- if (params == BNET_LOCAL_DD) {
- Cudd_IterDerefBdd(dd,f);
- Cudd_IterDerefBdd(dd,g);
- Cudd_IterDerefBdd(dd,h);
- }
- nd->dd = func;
- /* Associate a variable to this node if local BDDs are being
- ** built. This is done at the end, so that the primary inputs tend
- ** to get lower indices.
- */
- if (params == BNET_LOCAL_DD && nd->active == FALSE) {
- DdNode *auxfunc = Cudd_bddNewVar(dd);
- if (auxfunc == NULL) goto failure;
- Cudd_Ref(auxfunc);
- nd->var = auxfunc->index;
- nd->active = TRUE;
- Cudd_IterDerefBdd(dd,auxfunc);
- }
- return(1);
- failure:
- return(0);
- } /* end of buildExorBDD */
- /**
- @brief Sets the level of each node.
- @return 1 if successful; 0 otherwise.
- @sideeffect Changes the level and visited fields of the nodes it
- visits.
- @see bnetLevelDFS
- */
- static int
- bnetSetLevel(
- BnetNetwork * net)
- {
- BnetNode *node;
- /* Recursively visit nodes. This is pretty inefficient, because we
- ** visit all nodes in this loop, and most of them in the recursive
- ** calls to bnetLevelDFS. However, this approach guarantees that
- ** all nodes will be reached ven if there are dangling outputs. */
- node = net->nodes;
- while (node != NULL) {
- if (!bnetLevelDFS(net,node)) return(0);
- node = node->next;
- }
- /* Clear visited flags. */
- node = net->nodes;
- while (node != NULL) {
- node->visited = 0;
- node = node->next;
- }
- return(1);
- } /* end of bnetSetLevel */
- /**
- @brief Does a DFS from a node setting the level field.
- @return 1 if successful; 0 otherwise.
- @sideeffect Changes the level and visited fields of the nodes it
- visits.
- @see bnetSetLevel
- */
- static int
- bnetLevelDFS(
- BnetNetwork * net,
- BnetNode * node)
- {
- int i;
- BnetNode *auxnd;
- if (node->visited == 1) {
- return(1);
- }
- node->visited = 1;
- /* Graphical sources have level 0. This is the final value if the
- ** node has no fan-ins. Otherwise the successive loop will
- ** increase the level. */
- node->level = 0;
- for (i = 0; i < node->ninp; i++) {
- if (!st_lookup(net->hash, node->inputs[i], (void **) &auxnd)) {
- return(0);
- }
- if (!bnetLevelDFS(net,auxnd)) {
- return(0);
- }
- if (auxnd->level >= node->level) node->level = 1 + auxnd->level;
- }
- return(1);
- } /* end of bnetLevelDFS */
- /**
- @brief Orders network roots for variable ordering.
- @return an array with the ordered outputs and next state variables
- if successful; NULL otherwise.
- @sideeffect None
- */
- static BnetNode **
- bnetOrderRoots(
- BnetNetwork * net,
- int * nroots)
- {
- int i, noutputs;
- BnetNode *node;
- BnetNode **nodes = NULL;
- /* Initialize data structures. */
- noutputs = net->noutputs;
- nodes = ALLOC(BnetNode *, noutputs);
- if (nodes == NULL) goto endgame;
- /* Find output names and levels. */
- for (i = 0; i < net->noutputs; i++) {
- if (!st_lookup(net->hash,net->outputs[i],(void **)&node)) {
- goto endgame;
- }
- nodes[i] = node;
- }
- util_qsort(nodes, noutputs, sizeof(BnetNode *),
- (DD_QSFP)bnetLevelCompare);
- *nroots = noutputs;
- return(nodes);
- endgame:
- if (nodes != NULL) FREE(nodes);
- return(NULL);
- } /* end of bnetOrderRoots */
- /**
- @brief Comparison function used by qsort.
- @details Used to order the variables according to the number of keys
- in the subtables.
- @return the difference in number of keys between the two variables
- being compared.
- @sideeffect None
- */
- static int
- bnetLevelCompare(
- BnetNode ** x,
- BnetNode ** y)
- {
- return((*y)->level - (*x)->level);
- } /* end of bnetLevelCompare */
- /**
- @brief Does a DFS from a node ordering the inputs.
- @return 1 if successful; 0 otherwise.
- @sideeffect Changes visited fields of the nodes it visits.
- @see Bnet_DfsVariableOrder
- */
- static int
- bnetDfsOrder(
- DdManager * dd,
- BnetNetwork * net,
- BnetNode * node)
- {
- int i;
- BnetNode *auxnd;
- BnetNode **fanins;
- if (node->visited == 1) {
- return(1);
- }
- node->visited = 1;
- if (node->type == BNET_INPUT_NODE ||
- node->type == BNET_PRESENT_STATE_NODE) {
- node->dd = Cudd_bddNewVar(dd);
- if (node->dd == NULL) return(0);
- Cudd_Ref(node->dd);
- node->active = TRUE;
- node->var = node->dd->index;
- return(1);
- }
- fanins = ALLOC(BnetNode *, node->ninp);
- if (fanins == NULL) return(0);
- for (i = 0; i < node->ninp; i++) {
- if (!st_lookup(net->hash, node->inputs[i], (void **) &auxnd)) {
- FREE(fanins);
- return(0);
- }
- fanins[i] = auxnd;
- }
- util_qsort(fanins, node->ninp, sizeof(BnetNode *),
- (DD_QSFP)bnetLevelCompare);
- for (i = 0; i < node->ninp; i++) {
- /* for (i = node->ninp - 1; i >= 0; i--) { */
- int res = bnetDfsOrder(dd,net,fanins[i]);
- if (res == 0) {
- FREE(fanins);
- return(0);
- }
- }
- FREE(fanins);
- return(1);
- } /* end of bnetLevelDFS */
|