VIS
|
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 */