VIS

src/ntk/ntkNtk.c

Go to the documentation of this file.
00001 
00032 #include "ntkInt.h"
00033 #include "mdd.h"
00034 
00035 static char rcsid[] UNUSED = "$Id: ntkNtk.c,v 1.23 2010/04/09 23:44:05 fabio Exp $";
00036 
00037 /*---------------------------------------------------------------------------*/
00038 /* Structure declarations                                                    */
00039 /*---------------------------------------------------------------------------*/
00047 typedef struct ApplInfoStruct {
00048   Ntk_ApplInfoFreeFn  freeFn;  /* application function to free data */
00049   void               *data;    /* application data */
00050 } ApplInfo_t;
00051 
00052 
00055 /*---------------------------------------------------------------------------*/
00056 /* Static function prototypes                                                */
00057 /*---------------------------------------------------------------------------*/
00058 
00059 static char * NodeReadNameFromTable(Ntk_Node_t *node, st_table *name2ToName1);
00060 static Tbl_Table_t * DuplicateTableAndVars(Ntk_Node_t *node, char *name);
00061 
00065 /*---------------------------------------------------------------------------*/
00066 /* Definition of exported functions                                          */
00067 /*---------------------------------------------------------------------------*/
00068 
00081 char *
00082 Ntk_NetworkReadName(
00083   Ntk_Network_t * network)
00084 {
00085   return (network->name);
00086 }
00087 
00088 
00105 mdd_manager *
00106 Ntk_NetworkReadMddManager(
00107   Ntk_Network_t * network)
00108 {
00109   return (network->mddManager);
00110 }
00111 
00112 
00126 void
00127 Ntk_NetworkSetMddManager(
00128   Ntk_Network_t  * network,
00129   mdd_manager * mddManager)
00130 {
00131   network->mddManager = mddManager;
00132 }
00133 
00150 mAig_Manager_t *
00151 Ntk_NetworkReadMAigManager(
00152   Ntk_Network_t * network)
00153 {
00154   return (network->mAigManager);
00155 }
00156 
00157 
00172 void
00173 Ntk_NetworkSetMAigManager(
00174   Ntk_Network_t * network,
00175   mAig_Manager_t * mAigManager)
00176 {
00177   network->mAigManager = mAigManager;
00178 }
00179 
00193 mdd_manager *
00194 Ntk_NetworkInitializeMddManager(
00195   Ntk_Network_t * network)
00196 {
00197   network->mddManager = mdd_init_empty();
00198 
00199   return (network->mddManager);
00200 }
00201 
00202 
00217 bdd_reorder_type_t
00218 Ntk_NetworkReadDynamicVarOrderingMethod(
00219   Ntk_Network_t * network)
00220 {
00221   return (network->dynVarOrdMethod);
00222 }
00223 
00224 
00238 void
00239 Ntk_NetworkSetDynamicVarOrderingMethod(
00240   Ntk_Network_t * network,
00241   bdd_reorder_type_t dynVarOrdMethod,
00242   bdd_reorder_verbosity_t verbosity)
00243 {
00244   bdd_dynamic_reordering(network->mddManager, dynVarOrdMethod, verbosity);
00245   if (bdd_get_package_name() != CUDD) {
00246     if (dynVarOrdMethod == BDD_REORDER_SIFT ||
00247         dynVarOrdMethod == BDD_REORDER_WINDOW ||
00248         dynVarOrdMethod == BDD_REORDER_NONE) {
00249       network->dynVarOrdMethod = dynVarOrdMethod;
00250     } else
00251       network->dynVarOrdMethod = BDD_REORDER_SIFT;
00252   } else
00253     network->dynVarOrdMethod = dynVarOrdMethod;
00254 }
00255 
00256 
00270 void *
00271 Ntk_NetworkReadUndef(
00272   Ntk_Network_t * network)
00273 {
00274   return (network->undef);
00275 }
00276 
00277 
00291 void
00292 Ntk_NetworkSetUndef(
00293   Ntk_Network_t * network,
00294   void * value)
00295 {
00296   network->undef = value;
00297 }
00298 
00299 
00315 Ntk_Node_t *
00316 Ntk_NetworkFindNodeByMddId(
00317   Ntk_Network_t * network,
00318   int             mddId)
00319 {
00320   Ntk_Node_t *node = NIL(Ntk_Node_t);
00321 
00322   if (mddId != NTK_UNASSIGNED_MDD_ID) {
00323     st_lookup(network->mddIdToNode, (char *) (long) mddId, &node);
00324   }
00325 
00326   return (node);
00327 }
00328 
00329 
00344 Ntk_Node_t *
00345 Ntk_NetworkFindNodeByActualName(
00346   Ntk_Network_t * network,
00347   char * name)
00348 {
00349   Ntk_Node_t *node = NIL(Ntk_Node_t);
00350 
00351   st_lookup(network->actualNameToNode, name, &node);
00352 
00353   return (node);
00354 }
00355 
00356 
00375 Ntk_Node_t *
00376 Ntk_NetworkFindNodeByName(
00377   Ntk_Network_t * network,
00378   char * name)
00379 {
00380   Ntk_Node_t *node = NIL(Ntk_Node_t);
00381   char *actualName = Ntk_NetworkReadActualNameFromFormalName(network, name);
00382 
00383   /*
00384    * If there was no actual name corresponding to name in the formal to actual
00385    * table, then treat name as an actualName.
00386    */
00387   if (actualName == NIL(char)) {
00388     actualName = name;
00389   }
00390 
00391   st_lookup(network->actualNameToNode, actualName, &node);
00392 
00393   return (node);
00394 }
00395 
00396 
00412 char *
00413 Ntk_NetworkReadActualNameFromFormalName(
00414   Ntk_Network_t * network,
00415   char * formalName)
00416 {
00417   char *actualName = NIL(char);
00418 
00419   st_lookup(network->formalNameToActualName, formalName, &actualName);
00420 
00421   return (actualName);
00422 }
00423 
00424 
00437 void
00438 Ntk_NetworkInsertFormalNameToActualName(
00439   Ntk_Network_t * network,
00440   char * formalName,
00441   char * actualName)
00442 {
00443   char *formalNameCopy = util_strsav(formalName);
00444   char *actualNameCopy = util_strsav(actualName);
00445 
00446   st_insert(network->formalNameToActualName, formalNameCopy, actualNameCopy);
00447 }
00448 
00449 
00459 int
00460 Ntk_NetworkReadNumNodes(
00461   Ntk_Network_t * network)
00462 {
00463   return (lsLength(network->nodes));
00464 }
00465 
00466 
00476 int
00477 Ntk_NetworkReadNumLatches(
00478   Ntk_Network_t * network)
00479 {
00480   return (lsLength(network->latches));
00481 }
00482 
00483 
00493 int
00494 Ntk_NetworkReadNumCombInputs(
00495   Ntk_Network_t * network)
00496 {
00497   return (lsLength(network->combInputs));
00498 }
00499 
00500 
00511 int
00512 Ntk_NetworkReadNumCombOutputs(
00513   Ntk_Network_t * network)
00514 {
00515   return (lsLength(network->combOutputs));
00516 }
00517 
00518 
00528 int
00529 Ntk_NetworkReadNumPrimaryInputs(
00530   Ntk_Network_t * network)
00531 {
00532   return (lsLength(network->primaryInputs));
00533 }
00534 
00535 
00545 int
00546 Ntk_NetworkReadNumPseudoInputs(
00547   Ntk_Network_t * network)
00548 {
00549   return (lsLength(network->pseudoInputs));
00550 }
00551 
00552 
00562 int
00563 Ntk_NetworkReadNumInputs(
00564   Ntk_Network_t * network)
00565 {
00566   return (lsLength(network->inputs));
00567 }
00568 
00569 
00579 int
00580 Ntk_NetworkReadNumPrimaryOutputs(
00581   Ntk_Network_t * network)
00582 {
00583   return (lsLength(network->primaryOutputs));
00584 }
00585 
00586 
00599 lsList
00600 Ntk_NetworkReadNodes(
00601   Ntk_Network_t * network)
00602 {
00603   return (network->nodes);
00604 }
00605 
00606 
00619 lsList
00620 Ntk_NetworkReadCombInputs(
00621   Ntk_Network_t * network)
00622 {
00623   return (network->combInputs);
00624 }
00625 
00626 
00641 lsList
00642 Ntk_NetworkReadCombOutputs(
00643   Ntk_Network_t * network)
00644 {
00645   return (network->combOutputs);
00646 }
00647 
00648 
00661 lsList
00662 Ntk_NetworkReadLatches(
00663   Ntk_Network_t * network)
00664 {
00665   return (network->latches);
00666 }
00667 
00668 
00681 lsList
00682 Ntk_NetworkReadPrimaryInputs(
00683   Ntk_Network_t * network)
00684 {
00685   return (network->primaryInputs);
00686 }
00687 
00688 
00701 lsList
00702 Ntk_NetworkReadPseudoInputs(
00703   Ntk_Network_t * network)
00704 {
00705   return (network->pseudoInputs);
00706 }
00707 
00708 
00721 lsList
00722 Ntk_NetworkReadInputs(
00723   Ntk_Network_t * network)
00724 {
00725   return (network->inputs);
00726 }
00727 
00728 
00741 lsList
00742 Ntk_NetworkReadPrimaryOutputs(
00743   Ntk_Network_t * network)
00744 {
00745   return (network->primaryOutputs);
00746 }
00747 
00748 
00781 boolean
00782 Ntk_NetworkAddApplInfo(
00783   Ntk_Network_t * network,
00784   char * key,
00785   Ntk_ApplInfoFreeFn  freeFn,
00786   void * data)
00787 {
00788   ApplInfo_t *applInfo;
00789   boolean     status;
00790 
00791   if (st_lookup(network->applInfoTable, key, &applInfo)) {
00792     (*applInfo->freeFn)(applInfo->data);
00793     status = TRUE;
00794   }
00795   else {
00796     char *keyCopy = util_strsav(key);
00797 
00798     applInfo = ALLOC(ApplInfo_t, 1);
00799     st_insert(network->applInfoTable, keyCopy, (char *) applInfo);
00800     status = FALSE;
00801   }
00802 
00803   applInfo->freeFn = freeFn;
00804   applInfo->data   = data;
00805   return status;
00806 }
00807 
00821 boolean
00822 Ntk_NetworkSetApplInfo(
00823   Ntk_Network_t * network,
00824   char * key,
00825   Ntk_ApplInfoFreeFn  freeFn,
00826   void * data)
00827 {
00828   ApplInfo_t *applInfo;
00829   boolean     status;
00830 
00831   if (st_lookup(network->applInfoTable, key, &applInfo)) {
00832     status = TRUE;
00833   }
00834   else {
00835     char *keyCopy = util_strsav(key);
00836 
00837     applInfo = ALLOC(ApplInfo_t, 1);
00838     st_insert(network->applInfoTable, keyCopy, (char *) applInfo);
00839     status = FALSE;
00840   }
00841 
00842   applInfo->freeFn = freeFn;
00843   applInfo->data   = data;
00844   return status;
00845 }
00846 
00847 
00860 void *
00861 Ntk_NetworkReadApplInfo(
00862   Ntk_Network_t * network,
00863   char * key)
00864 {
00865   int         status;
00866   ApplInfo_t *applInfo;
00867 
00868   status = st_lookup(network->applInfoTable, key, &applInfo);
00869   if (status == 1) {
00870     return (applInfo->data);
00871   }
00872   else {
00873     return (NIL(void));
00874   }
00875 }
00876 
00877 
00895 boolean
00896 Ntk_NetworkFreeApplInfo(
00897   Ntk_Network_t * network,
00898   char * key)
00899 {
00900   int         status;
00901   ApplInfo_t *applInfo;
00902 
00903   status = st_lookup(network->applInfoTable, key, &applInfo);
00904 
00905   if (status == 1) {
00906     st_delete(network->applInfoTable, &key, &applInfo);
00907     (*applInfo->freeFn)(applInfo->data);
00908     FREE(key);  /* frees the string contained in the table */
00909     FREE(applInfo);
00910   }
00911 
00912   return ((status) ? TRUE : FALSE);
00913 }
00914 
00915 
00930 Ntk_Network_t *
00931 Ntk_NetworkAlloc(
00932   char * name)
00933 {
00934   Ntk_Network_t *network = ALLOC(Ntk_Network_t, 1);
00935 
00936   network->name                   = util_strsav(name);
00937   network->nodes                  = lsCreate();
00938   network->combInputs             = lsCreate();
00939   network->combOutputs            = lsCreate();
00940   network->latches                = lsCreate();
00941   network->primaryInputs          = lsCreate();
00942   network->pseudoInputs           = lsCreate();
00943   network->inputs                 = lsCreate();
00944   network->primaryOutputs         = lsCreate();
00945   network->combOutputsTable       = st_init_table(st_ptrcmp, st_ptrhash);
00946   network->mddIdToNode            = st_init_table(st_numcmp, st_numhash);
00947   network->actualNameToNode       = st_init_table(strcmp, st_strhash);
00948   network->formalNameToActualName = st_init_table(strcmp, st_strhash);
00949   network->applInfoTable          = st_init_table(strcmp, st_strhash);
00950   network->mddManager             = NIL(mdd_manager);
00951   network->mAigManager            = NIL(mAig_Manager_t);
00952   network->dynVarOrdMethod        = BDD_REORDER_NONE;
00953   network->undef                  = NIL(void);
00954 
00955   return network;
00956 }
00957 
00958 
00972 void
00973 Ntk_NetworkFree(
00974   Ntk_Network_t * network)
00975 {
00976   char *formal;
00977   char *actual;
00978   char *key;
00979   ApplInfo_t *applInfo;
00980   Ntk_Node_t *node;
00981   lsGen gen;
00982   st_generator *stGen;
00983 
00984 
00985   if (network == NIL(Ntk_Network_t)) {
00986     return;
00987   }
00988 
00989   FREE(network->name);
00990 
00991   Ntk_NetworkForEachNode(network, gen, node) {
00992     Ntk_NodeFree(node);
00993   }
00994 
00995   (void) lsDestroy(network->nodes,           (void (*) (lsGeneric)) NULL);
00996   (void) lsDestroy(network->combInputs,      (void (*) (lsGeneric)) NULL);
00997   (void) lsDestroy(network->combOutputs,     (void (*) (lsGeneric)) NULL);
00998   (void) lsDestroy(network->latches,         (void (*) (lsGeneric)) NULL);
00999   (void) lsDestroy(network->primaryInputs,   (void (*) (lsGeneric)) NULL);
01000   (void) lsDestroy(network->pseudoInputs,    (void (*) (lsGeneric)) NULL);
01001   (void) lsDestroy(network->inputs,          (void (*) (lsGeneric)) NULL);
01002   (void) lsDestroy(network->primaryOutputs,  (void (*) (lsGeneric)) NULL);
01003   st_free_table(network->combOutputsTable);
01004   st_free_table(network->mddIdToNode);
01005 
01006   /*
01007    * The keys in this table are strings representing node names.  The strings
01008    * are owned by the nodes, so we don't free them here.
01009    */
01010   st_free_table(network->actualNameToNode);
01011 
01012   /*
01013    * Free all the strings in the formalNameToActualName table before freeing
01014    * the table itself.
01015    */
01016   st_foreach_item(network->formalNameToActualName, stGen, &formal, &actual) {
01017     FREE(formal);
01018     FREE(actual);
01019   }
01020 
01021   st_free_table(network->formalNameToActualName);
01022 
01023   /*
01024    * Free all the key/applInfo pairs in the applInfoTable, and then free the
01025    * table itself.
01026    */
01027   st_foreach_item(network->applInfoTable, stGen, &key, &applInfo) {
01028     FREE(key);
01029     (*applInfo->freeFn)(applInfo->data);
01030     FREE(applInfo);
01031   }
01032   st_free_table(network->applInfoTable);
01033 
01034   if (network->mddManager != NIL(mdd_manager)) {
01035     mdd_quit(network->mddManager);
01036   }
01037 
01038   if (network->mAigManager != NIL(mAig_Manager_t)) {
01039     mAig_quit(network->mAigManager);
01040   }
01041 
01042   FREE(network);
01043 }
01044 
01045 
01060 void
01061 Ntk_NetworkFreeCallback(
01062   void * data /* an object of type Ntk_Network_t*  type casted to void* */)
01063 {
01064   Ntk_NetworkFree((Ntk_Network_t *) data);
01065 }
01066 
01067 
01080 void
01081 Ntk_NetworkWriteBlifMv(
01082   FILE *fp,
01083   Ntk_Network_t *network,
01084   boolean promotePseudo
01085   )
01086 {
01087   lsGen gen;
01088   Ntk_Node_t *node;
01089   int i;
01090 
01091   (void) fprintf(fp, ".model %s\n", Ntk_NetworkReadName(network));
01092 
01093   /* .inputs */
01094   if (Ntk_NetworkReadNumPrimaryInputs(network) != 0) {
01095     (void) fprintf(fp, ".inputs");
01096     Ntk_NetworkForEachPrimaryInput(network, gen, node) {
01097       (void) fprintf(fp, " %s", Ntk_NodeReadName(node));
01098     }
01099     (void) fprintf(fp, "\n");
01100   }
01101 
01102   if (promotePseudo && Ntk_NetworkReadNumPseudoInputs(network) != 0) {
01103     (void) fprintf(fp, "# pseudo inputs\n");
01104     (void) fprintf(fp, ".inputs");
01105     Ntk_NetworkForEachPseudoInput(network, gen, node) {
01106       (void) fprintf(fp, " %s", Ntk_NodeReadName(node));
01107     }
01108     (void) fprintf(fp, "\n");
01109   }
01110 
01111   /* .outputs */
01112   if (Ntk_NetworkReadNumPrimaryOutputs(network) != 0) {
01113     (void) fprintf(fp, ".outputs");
01114     Ntk_NetworkForEachPrimaryOutput(network, gen, node) {
01115       (void) fprintf(fp, " %s", Ntk_NodeReadName(node));
01116     }
01117     (void) fprintf(fp, "\n");
01118   }
01119 
01120   /* .mv .names .latch .reset */
01121   Ntk_NetworkForEachNode(network, gen, node) {
01122     Var_Variable_t *var = Ntk_NodeReadVariable(node);
01123     char *nodeName = Ntk_NodeReadName(node);
01124     boolean is_enum = Var_VariableTestIsEnumerative(var);
01125     int range = Var_VariableReadNumValues(var);
01126 
01127     if (Ntk_NodeTestIsShadow(node)) continue;
01128     if (Ntk_NodeTestIsCombinational(node) &&
01129         Ntk_NodeTestIsLatchInitialInput(node)) continue;
01130 
01131     if (is_enum) {
01132       if (range != 2) {
01133         /* Boolean enumerative variables need no .mv declaration. */
01134         (void) fprintf(fp, ".mv %s %d\n", nodeName, range);
01135       }
01136     } else {
01137       /* Variable is symbolic. */
01138       (void) fprintf(fp, ".mv %s %d", nodeName, range);
01139       for (i = 0; i < range; i++) {
01140         (void) fprintf(fp, " %s",
01141                        Var_VariableReadSymbolicValueFromIndex(var, i));
01142       }
01143       (void) fprintf(fp, "\n");
01144     }
01145   }
01146 
01147   if (!promotePseudo && Ntk_NetworkReadNumPseudoInputs(network) != 0) {
01148     (void) fprintf(fp, "# pseudo inputs start\n");
01149     Ntk_NetworkForEachPseudoInput(network, gen, node) {
01150       Tbl_Table_t *dupTable = DuplicateTableAndVars(node,
01151                                                     Ntk_NodeReadName(node));
01152       Tbl_TableWriteBlifMvToFile(dupTable, 0, fp);
01153       Tbl_TableFree(dupTable);
01154     }
01155     (void) fprintf(fp, "# pseudo inputs end\n");
01156   }
01157 
01158   Ntk_NetworkForEachNode(network, gen, node) {
01159 
01160     if (Ntk_NodeTestIsShadow(node)) continue;
01161     if (Ntk_NodeTestIsCombinational(node) &&
01162         Ntk_NodeTestIsLatchInitialInput(node)) continue;
01163 
01164     if (Ntk_NodeTestIsCombinational(node)) {
01165       Tbl_Table_t *dupTable = DuplicateTableAndVars(node,
01166                                                     Ntk_NodeReadName(node));
01167       Tbl_TableWriteBlifMvToFile(dupTable, 0, fp);
01168       Tbl_TableFree(dupTable);
01169     } else if (Ntk_NodeTestIsLatch(node)) {
01170       Ntk_Node_t *data = Ntk_LatchReadDataInput(node);
01171       Ntk_Node_t *reset = Ntk_LatchReadInitialInput(node);
01172       Tbl_Table_t *dupTable = DuplicateTableAndVars(reset,
01173                                                     Ntk_NodeReadName(node));
01174       (void) fprintf(fp, ".latch %s %s\n", Ntk_NodeReadName(data),
01175                      Ntk_NodeReadName(node));
01176       Tbl_TableWriteBlifMvToFile(dupTable, 1, fp);
01177       Tbl_TableFree(dupTable);
01178     }
01179   }
01180 
01181   (void) fprintf(fp, ".end\n");
01182 
01183 } /* Ntk_NetworkWriteBlifMv */
01184 
01185 
01198 void
01199 Ntk_NetworkPrint(
01200   FILE * fp,
01201   Ntk_Network_t * network,
01202   boolean printIo,
01203   boolean printTableStats)
01204 {
01205   Ntk_Node_t *node;
01206   lsGen       gen;
01207 
01208   (void) fprintf(fp, "Nodes of network %s:\n", Ntk_NetworkReadName(network));
01209 
01210   Ntk_NetworkForEachNode(network, gen, node) {
01211     Ntk_NodePrint(fp, node, printIo, printTableStats);
01212     /*
01213      * It's nice to have a line separating nodes when we print the fanins and
01214      * fanouts or table stats.
01215      */
01216     if (printIo || printTableStats) {
01217       (void) fprintf(fp, "\n");
01218     }
01219   }
01220 }
01221 
01222 
01234 void
01235 Ntk_NetworkPrintStats(
01236   FILE * fp,
01237   Ntk_Network_t * network)
01238 {
01239   lsGen          gen;
01240   Ntk_Node_t     *node;
01241   int            numConstants     = 0;
01242   int            numCombinational = 0;
01243   int            numEdges         = 0;
01244   mdd_manager  *mddMgr;
01245 
01246   /*
01247    * Count the number of constants and the number of combinational nodes.
01248    */
01249   Ntk_NetworkForEachNode(network, gen, node) {
01250     numEdges += Ntk_NodeReadNumFanouts(node);
01251     if (Ntk_NodeTestIsConstant(node)) {
01252       numConstants++;
01253     }
01254     if (Ntk_NodeTestIsCombinational(node)) {
01255       numCombinational++;
01256     }
01257   }
01258 
01259   mddMgr = Ntk_NetworkReadMddManager(network);
01260 
01261   if (mddMgr == NIL(mdd_manager)){
01262      (void) fprintf(fp, "%s  combinational=%d  pi=%d  po=%d  latches=%d  pseudo=%d  const=%d  edges=%d\n",
01263                  Ntk_NetworkReadName(network),
01264                  numCombinational,
01265                  Ntk_NetworkReadNumPrimaryInputs(network),
01266                  Ntk_NetworkReadNumPrimaryOutputs(network),
01267                  Ntk_NetworkReadNumLatches(network),
01268                  Ntk_NetworkReadNumPseudoInputs(network),
01269                  numConstants,
01270                  numEdges
01271                  );
01272   }else{
01273      array_t *bddIdArray;
01274      lsGen gen;
01275      Ntk_Node_t *latch;
01276      int n_boolean_latches;
01277      array_t *mddIdArray = array_alloc(int, 0);
01278 
01279      Ntk_NetworkForEachLatch(network, gen, latch){
01280        array_insert_last(int, mddIdArray, Ntk_NodeReadMddId(latch));
01281      }
01282 
01283      bddIdArray = mdd_id_array_to_bdd_id_array(mddMgr, mddIdArray);
01284      n_boolean_latches = array_n(bddIdArray);
01285      array_free(mddIdArray);
01286      array_free(bddIdArray);
01287 
01288      (void) fprintf(fp, "%s  combinational=%d  pi=%d  po=%d  latches=%d (boolean_latches=%d)  pseudo=%d  const=%d  edges=%d\n",
01289                  Ntk_NetworkReadName(network),
01290                  numCombinational,
01291                  Ntk_NetworkReadNumPrimaryInputs(network),
01292                  Ntk_NetworkReadNumPrimaryOutputs(network),
01293                  Ntk_NetworkReadNumLatches(network),
01294                  n_boolean_latches,
01295                  Ntk_NetworkReadNumPseudoInputs(network),
01296                  numConstants,
01297                  numEdges
01298                  );
01299   }
01300 }
01301 
01302 
01320 Ntk_Network_t *
01321 Ntk_NetworkDuplicate(
01322   Ntk_Network_t * oldNetwork)
01323 {
01324   int            i;
01325   lsGen          gen;
01326   Ntk_Node_t    *oldNode;
01327   Ntk_Node_t    *oldFaninNode;
01328   Ntk_Node_t    *oldOriginNode;
01329   Ntk_Node_t    *newOriginNode;
01330   array_t       *faninNameArray;
01331   Ntk_Network_t *newNetwork = Ntk_NetworkAlloc(Ntk_NetworkReadName(oldNetwork));
01332 
01333 
01334   /*
01335    * For each node in oldNetwork, create a node in newNetwork.
01336    */
01337   Ntk_NetworkForEachNode(oldNetwork, gen, oldNode) {
01338     (void) Ntk_NodeCreateInNetwork(newNetwork, Ntk_NodeReadName(oldNode),
01339                                    Ntk_NodeReadVariable(oldNode));
01340   }
01341 
01342   /*
01343    * For each node in oldNetwork, declare the corresponding node in newNetwork
01344    * using the type of the oldNode.
01345    */
01346   Ntk_NetworkForEachNode(oldNetwork, gen, oldNode) {
01347     char       *nodeName = Ntk_NodeReadName(oldNode);
01348     Ntk_Node_t *newNode  = Ntk_NetworkFindNodeByActualName(newNetwork, nodeName);
01349     assert(newNode != NIL(Ntk_Node_t));
01350 
01351     /*
01352      * Handle items that are independent of node type.
01353      */
01354     if (Ntk_NodeTestIsPrimaryOutput(oldNode)) {
01355       Ntk_NodeDeclareAsPrimaryOutput(newNode);
01356     }
01357 
01358     switch (oldNode->type) {
01359       case NtkPrimaryInput_c:
01360         Ntk_NodeDeclareAsPrimaryInput(newNode);
01361         break;
01362       case NtkPseudoInput_c:
01363         Ntk_NodeDeclareAsPseudoInput(newNode,
01364                                      Tbl_TableSoftDup(Ntk_NodeReadTable(oldNode)),
01365                                      Ntk_NodeReadOutputIndex(oldNode));
01366         break;
01367       case NtkLatch_c:
01368         Ntk_NodeDeclareAsLatch(newNode,
01369                                Ntk_NodeReadName(Ntk_LatchReadDataInput(oldNode)),
01370                                Ntk_NodeReadName(Ntk_LatchReadInitialInput(oldNode)));
01371         break;
01372       case NtkCombinational_c:
01373         /*
01374          * Create the array of names of the fanins of oldNode.
01375          */
01376         faninNameArray = array_alloc(char *, Ntk_NodeReadNumFanins(oldNode));
01377         Ntk_NodeForEachFanin(oldNode, i, oldFaninNode) {
01378           char *faninName = Ntk_NodeReadName(oldFaninNode);
01379           array_insert(char *, faninNameArray, i, faninName);
01380         }
01381 
01382         Ntk_NodeDeclareAsCombinational(newNode,
01383                                        Tbl_TableSoftDup(Ntk_NodeReadTable(oldNode)),
01384                                        faninNameArray,
01385                                        Ntk_NodeReadOutputIndex(oldNode));
01386         array_free(faninNameArray);
01387         break;
01388       case NtkShadow_c:
01389         oldOriginNode = Ntk_ShadowReadOrigin(oldNode);
01390         newOriginNode = Ntk_NetworkFindNodeByActualName(newNetwork,
01391                                                         Ntk_NodeReadName(oldOriginNode));
01392         Ntk_NodeDeclareAsShadow(newNode, newOriginNode);
01393         break;
01394       case NtkUnassigned_c:
01395         fail("Unexpected unassigned node type");
01396         break;
01397       default:
01398         fail("Unexpected type");
01399         break;
01400     }
01401   }
01402 
01403   return (newNetwork);
01404 }
01405 
01406 
01459 void
01460 Ntk_NetworkAppendNetwork(
01461   Ntk_Network_t * network1,
01462   Ntk_Network_t * network2,
01463   st_table *name2ToName1)
01464 {
01465   st_generator *stGen;
01466   lsGen         gen;
01467   Ntk_Node_t   *node1;
01468   Ntk_Node_t   *node2;
01469   char         *name1;
01470   char         *name2;
01471   st_table     *localName2ToName1 = st_init_table(strcmp, st_strhash);
01472 
01473 
01474   /*
01475    * For each node in network2, create a node in network1 as necessary. The
01476    * undef field of node2 is set to TRUE if a new node is created in network1
01477    * for it; else, it is set to FALSE. localName2ToName1 is a superset of
01478    * name2ToName1; in addition to the contents of name2ToName1, it contains
01479    * the new names (those appended with $NTK2) for those nodes being appended
01480    * to network2, and type II inputs.
01481    */
01482   Ntk_NetworkForEachNode(network2, gen, node2) {
01483     name1 = NIL(char);
01484     name2 = Ntk_NodeReadName(node2);
01485     st_lookup(name2ToName1, name2, &name1);
01486     if (name1 != NIL(char)) {
01487       /*
01488        * Name2 is in name2ToName1 table (type I input).  Hence, we will be
01489        * using the node in network1 corresponding to name1.  Assert that node2
01490        * is in fact an input, that name1 refers to an input node in network1, and
01491        * that node1 and node2 have the same variable domains.
01492        */
01493       Ntk_NodeSetUndef(node2, (void *) FALSE);
01494       st_insert(localName2ToName1, name2, util_strsav(name1));
01495 
01496       assert(Ntk_NodeTestIsInput(node2));
01497       node1 = Ntk_NetworkFindNodeByName(network1, name1);
01498       assert(node1 != NIL(Ntk_Node_t));
01499       assert(Var_VariablesTestHaveSameDomain(Ntk_NodeReadVariable(node1),
01500                                              Ntk_NodeReadVariable(node2)));
01501     }
01502     else {
01503       /*
01504        * Name2 is *not* in name2ToName1 table.  There are 2 possibilities: 1)
01505        * a node with name2 already exists in network1, and node2 is an input
01506        * (type II input); in this case, a) add map of name2 to name2 in the
01507        * localName2ToName1, b) assert that node1 is in fact an input, and c)
01508        * don't create a new node in network1; 2) a node with name2 doesn't
01509        * exist in network1, or node2 is not an input (type III inputs and
01510        * non-inputs); in this case, we unconditionally create a new node in
01511        * network1 using name2$NTK2.
01512        */
01513       node1 = Ntk_NetworkFindNodeByName(network1, name2);
01514 
01515       if ((node1 != NIL(Ntk_Node_t)) && Ntk_NodeTestIsInput(node2)) {
01516         Ntk_NodeSetUndef(node2, (void *) FALSE);
01517         st_insert(localName2ToName1, name2, util_strsav(name2));
01518       }
01519       else {
01520         char *newName = util_strcat3(name2, "$NTK2", "");
01521         Ntk_NodeSetUndef(node2, (void *) TRUE);
01522         st_insert(localName2ToName1, name2, newName);
01523         (void) Ntk_NodeCreateInNetwork(network1, newName,
01524                                        Ntk_NodeReadVariable(node2));
01525       }
01526     }
01527   }
01528 
01529   /*
01530    * For each node in network2 for which a new node was created in network1,
01531    * declare the corresponding node in network1 using the type of the node2.
01532    * (NOTE: this section shares a lot with Ntk_NetworkDuplicate, but is
01533    * sufficiently different that we don't share any code.)
01534    */
01535   Ntk_NetworkForEachNode(network2, gen, node2) {
01536     if (Ntk_NodeReadUndef(node2) == NIL(void)) {
01537       /*
01538        * node2 is superseded by a node in network1.
01539        */
01540       continue;
01541     }
01542 
01543     name2 = NodeReadNameFromTable(node2, localName2ToName1);
01544     node1 = Ntk_NetworkFindNodeByName(network1, name2);
01545     assert(node1 != NIL(Ntk_Node_t));
01546 
01547     /*
01548      * Handle items that are independent of node type.
01549      */
01550     if (Ntk_NodeTestIsPrimaryOutput(node2)) {
01551       Ntk_NodeDeclareAsPrimaryOutput(node1);
01552     }
01553 
01554     switch (node2->type) {
01555       case NtkPrimaryInput_c:
01556         Ntk_NodeDeclareAsPrimaryInput(node1);
01557         break;
01558 
01559       case NtkPseudoInput_c:
01560         Ntk_NodeDeclareAsPseudoInput(node1,
01561                                      Tbl_TableSoftDup(Ntk_NodeReadTable(node2)),
01562                                      Ntk_NodeReadOutputIndex(node2));
01563         break;
01564 
01565       case NtkLatch_c:
01566       {
01567         char *dataName = NodeReadNameFromTable(Ntk_LatchReadDataInput(node2),
01568                                                localName2ToName1);
01569         char *initName = NodeReadNameFromTable(Ntk_LatchReadInitialInput(node2),
01570                                                localName2ToName1);
01571 
01572         Ntk_NodeDeclareAsLatch(node1, dataName, initName);
01573         break;
01574       }
01575 
01576       case NtkCombinational_c:
01577       {
01578         int         i;
01579         Ntk_Node_t *faninNode2;
01580         array_t    *faninNameArray;
01581 
01582         /*
01583          * Create the array of names of the fanins of node2.
01584          */
01585         faninNameArray = array_alloc(char *, Ntk_NodeReadNumFanins(node2));
01586         Ntk_NodeForEachFanin(node2, i, faninNode2) {
01587           char *faninName = NodeReadNameFromTable(faninNode2, localName2ToName1);
01588           array_insert(char *, faninNameArray, i, faninName);
01589         }
01590 
01591         Ntk_NodeDeclareAsCombinational(node1,
01592                                        Tbl_TableSoftDup(Ntk_NodeReadTable(node2)),
01593                                        faninNameArray,
01594                                        Ntk_NodeReadOutputIndex(node2));
01595         array_free(faninNameArray);
01596         break;
01597       }
01598 
01599       case NtkShadow_c:
01600       {
01601         char       *originName;
01602         Ntk_Node_t *originNode2;
01603         Ntk_Node_t *originNode1;
01604 
01605         originNode2 = Ntk_ShadowReadOrigin(node2);
01606         /*
01607          * Currently, we don't allow a shadow node whose origin in a type I or
01608          * II input.  This is because, what if the corresponding node in
01609          * network1 (of the type I or II input), also has a shadow node?  Then
01610          * we would try to add a shadow node to a node already having a shadow;
01611          * this is illegal.
01612          */
01613         assert((boolean) (long) Ntk_NodeReadUndef(node2));
01614         originName = NodeReadNameFromTable(originNode2, localName2ToName1);
01615         originNode1 = Ntk_NetworkFindNodeByName(network1, originName);
01616 
01617         Ntk_NodeDeclareAsShadow(node1, originNode1);
01618         break;
01619       }
01620 
01621       case NtkUnassigned_c:
01622         fail("Unexpected unassigned node type");
01623         break;
01624       default:
01625         fail("Unexpected type");
01626         break;
01627     }
01628   }
01629 
01630   /*
01631    * Free all the values strings in the localName2ToName1, before freeing
01632    * the table itself.  The keys are not freed.
01633    */
01634   st_foreach_item(localName2ToName1, stGen, &name2, &name1) {
01635     FREE(name1);
01636   }
01637   st_free_table(localName2ToName1);
01638 }
01639 
01640 
01656 int
01657 Ntk_NetworkPrintDot(
01658   FILE *fp,
01659   Ntk_Network_t *network)
01660 {
01661   lsGen       gen;
01662   int i;
01663   Ntk_Node_t *nodePtr;
01664   Ntk_Node_t *fanoutPtr;
01665   time_t      now           = time(0);
01666   struct tm  *nowStructPtr  = localtime(& now);
01667   char       *nowTxt        = asctime(nowStructPtr);
01668   char       *networkName   = Ntk_NetworkReadName(network);
01669 
01670   /*
01671    * Write out the header for the output file.
01672    */
01673 
01674   (void) fprintf(fp, "# %s\n", Vm_VisReadVersion());
01675   (void) fprintf(fp, "# network name: %s\n", networkName);
01676   (void) fprintf(fp, "# generated: %s", nowTxt);
01677   (void) fprintf(fp, "#\n");
01678 
01679   (void) fprintf(fp, "# Network with %d nodes\n",
01680                  Ntk_NetworkReadNumNodes(network));
01681 
01682   (void) fprintf(fp, "digraph \"%s\" {\n  rotate=90;\n", networkName);
01683   (void) fprintf(fp, "  margin=0.5;\n  label=\"%s\";\n", networkName);
01684   (void) fprintf(fp, "  size=\"10,7.5\";\n  ratio=\"fill\";\n");
01685 
01686   /* Force the inputs and outputs to be printed at the same level in the graph */
01687   (void) fprintf(fp, "  { rank=same; ");
01688   Ntk_NetworkForEachCombInput(network,gen, nodePtr) {
01689     (void) fprintf(fp, "\"%s\"; ", Ntk_NodeReadName(nodePtr));
01690   }
01691   (void) fprintf(fp, "}\n");
01692   (void) fprintf(fp, "  { rank=same; ");
01693   Ntk_NetworkForEachCombOutput(network,gen, nodePtr) {
01694     (void) fprintf(fp, "\"%s\"; ", Ntk_NodeReadName(nodePtr));
01695   }
01696   (void) fprintf(fp, "}\n");
01697 
01698   /* Print all the edges */
01699   Ntk_NetworkForEachNode(network, gen, nodePtr) {
01700 
01701     if (Ntk_NodeReadNumFanouts(nodePtr) == 0 &&
01702         Ntk_NodeReadNumFanins(nodePtr) == 0) {
01703       /* Print the dot description for a node */
01704       (void) fprintf(fp, "  \"%s\";\n", Ntk_NodeReadName(nodePtr));
01705     } /* End of if */
01706 
01707     /* Print the edges comming out of that node */
01708     Ntk_NodeForEachFanout(nodePtr, i, fanoutPtr) {
01709       (void) fprintf(fp, "  \"%s\" -> \"%s\";\n", Ntk_NodeReadName(nodePtr),
01710                      Ntk_NodeReadName(fanoutPtr));
01711     }
01712   }
01713 
01714   (void) fprintf(fp, "}\n");
01715 
01716   return 1;
01717 }
01718 
01719 /*---------------------------------------------------------------------------*/
01720 /* Definition of internal functions                                          */
01721 /*---------------------------------------------------------------------------*/
01722 
01723 /*---------------------------------------------------------------------------*/
01724 /* Definition of static functions                                            */
01725 /*---------------------------------------------------------------------------*/
01726 
01738 static char *
01739 NodeReadNameFromTable(
01740   Ntk_Node_t *node,
01741   st_table *name2ToName1)
01742 {
01743   char    *name1  = NIL(char);
01744   char    *name2  = Ntk_NodeReadName(node);
01745   boolean  status UNUSED = st_lookup(name2ToName1, name2, &name1);
01746 
01747   assert(status);
01748   return name1;
01749 }
01750 
01751 
01763 static Tbl_Table_t *
01764 DuplicateTableAndVars(
01765   Ntk_Node_t *node,
01766   char *name
01767   )
01768 {
01769   Var_Variable_t *var, *newVar;
01770   Tbl_Table_t *dupTable, *tbl;
01771   int col;
01772   Tbl_Table_t *table = Ntk_NodeReadTable(node);
01773   array_t *split = Tbl_TableSplit(table);
01774   int outIndex = Ntk_NodeReadOutputIndex(node);
01775 
01776   arrayForEachItem(Tbl_Table_t *, split, col, tbl) {
01777     if (col == outIndex) {
01778       dupTable = tbl;
01779     } else {
01780       Tbl_TableFree(tbl);
01781     }
01782   }
01783   array_free(split);
01784 
01785   Tbl_TableForEachInputVar(dupTable, col, var) {
01786     Ntk_Node_t *fanin = Ntk_NodeReadFaninNode(node, col);
01787     char *newName = Ntk_NodeReadName(fanin);
01788     newVar = Var_VariableDup(var, NIL(Hrc_Node_t));
01789     Var_VariableChangeName(newVar, newName);
01790     Tbl_TableSetVar(dupTable, col, newVar, 0);
01791   }
01792 
01793   var = array_fetch(Var_Variable_t *,Tbl_TableReadOutputVars(dupTable), 0);
01794   newVar = Var_VariableDup(var, NIL(Hrc_Node_t));
01795   Var_VariableChangeName(newVar, name);
01796   Tbl_TableSetVar(dupTable, 0, newVar, 1);
01797 
01798   return dupTable;
01799 
01800 } /* DuplicateTableAndVars */