VIS
|
00001 00031 #include "ntmInt.h" 00032 00033 static char rcsid[] UNUSED = "$Id: ntm.c,v 1.11 2009/04/11 01:45:44 fabio Exp $"; 00034 00037 /*---------------------------------------------------------------------------*/ 00038 /* Static function prototypes */ 00039 /*---------------------------------------------------------------------------*/ 00040 00041 static Mvf_Function_t * NodeBuildMvfRecursively(Ntk_Node_t * node, st_table * leaves, st_table * nodeToMvfTable, mdd_manager *mddMgr, mdd_t *careSet); 00042 static Mvf_Function_t * NodeBuildInputMvf(Ntk_Node_t * node, mdd_manager *mddMgr); 00043 #if 0 00044 static Mvf_Function_t * NodeBuildPseudoInputMvf(Ntk_Node_t * node, mdd_manager * mddMgr); 00045 #endif 00046 static Mvf_Function_t * NodeBuildPseudoInputMvfNew(Ntk_Node_t * node, mdd_manager * mddMgr); 00047 static Mvf_Function_t * NodeBuildConstantMvf(Ntk_Node_t * node, int constantValue, mdd_manager *mddMgr); 00048 static Mvf_Function_t * NodeBuildInternalMvf(Ntk_Node_t * node, st_table * leaves, st_table * nodeToMvfTable, mdd_manager *mddMgr, mdd_t *careSet); 00049 static Mvf_Function_t * NodeReadMvf(Ntk_Node_t * node, st_table * nodeToMvfTable); 00050 static void NodeSetMvf(Ntk_Node_t * node, st_table * nodeToMvfTable, Mvf_Function_t * mvf); 00051 static int CommandNtmTest(Hrc_Manager_t ** hmgr, int argc, char ** argv); 00052 static void MvfSanityCheck(array_t *roots, array_t *mvfs); 00053 static void RegionInitializeReferenceCounts(array_t *roots, st_table *leaves); 00054 static void NodeDecrementRefCount(Ntk_Node_t *node, st_table *nodeToMvfTable); 00055 static boolean TableTestIsContainedInArray(st_table *table1, array_t *nodeArrary); 00056 00060 /*---------------------------------------------------------------------------*/ 00061 /* Definition of exported functions */ 00062 /*---------------------------------------------------------------------------*/ 00063 00073 void 00074 Ntm_Init(void) 00075 { 00076 Cmd_CommandAdd("_ntm_test", CommandNtmTest, /* doesn't changes_network */ 0); 00077 } 00078 00079 00089 void 00090 Ntm_End(void) 00091 { 00092 } 00093 00094 00134 array_t * 00135 Ntm_NetworkBuildMvfs( 00136 Ntk_Network_t * network, 00137 array_t * roots, 00138 st_table * leaves, 00139 mdd_t *careSet) 00140 { 00141 int i; 00142 st_generator *stGen; 00143 Mvf_Function_t *mvf; 00144 Ntk_Node_t *node; 00145 st_table *nodeToMvfTable; 00146 Mvf_Function_t *tmpMvf; 00147 int numRoots = array_n(roots); 00148 array_t *result = array_alloc(Mvf_Function_t *, numRoots); 00149 mdd_manager *mddMgr = Ntk_NetworkReadMddManager(network); 00150 00151 /* 00152 * Before initializing the reference counts, verify that the leaves form a 00153 * support set for the roots. 00154 */ 00155 if (!Ntk_NetworkTestLeavesCoverSupportOfRoots(network, roots, leaves)) { 00156 (void)fprintf(vis_stderr,"%s",error_string()); 00157 fflush(vis_stderr); 00158 fail("Leaves do not cover support of roots"); 00159 } 00160 00161 /* 00162 * Each node in the region defined by the roots and leaves is assigned a 00163 * reference count equaling the number of fanouts within the region. As a 00164 * special case, the roots are initialized to MAX_INT. 00165 */ 00166 RegionInitializeReferenceCounts(roots, leaves); 00167 00168 /* 00169 * For each root, compute its MVF and store a duplicate copy of it in the 00170 * result array. The nodeToMvfTable is used to keep track of intermediate 00171 * computations. Intermediate MVFs are freed as soon as possible by using 00172 * the reference count mechanism. 00173 */ 00174 nodeToMvfTable = st_init_table(st_ptrcmp, st_ptrhash); 00175 for (i = 0; i < numRoots; i++) { 00176 Ntk_Node_t *root = array_fetch(Ntk_Node_t *, roots, i); 00177 00178 tmpMvf = NodeBuildMvfRecursively(root, leaves, 00179 nodeToMvfTable, mddMgr, 00180 careSet); 00181 00182 mvf = Mvf_FunctionDuplicate(tmpMvf); 00183 array_insert(Mvf_Function_t *, result, i, mvf); 00184 } 00185 00186 /* 00187 * Because of the use of reference counting, the only nodes left in 00188 * nodeToMvfTable should be the roots. 00189 */ 00190 assert(TableTestIsContainedInArray(nodeToMvfTable, roots)); 00191 00192 /* 00193 * Free the remaining MVFs (corresponding to the roots) from the 00194 * nodeToMvfTable. 00195 */ 00196 st_foreach_item(nodeToMvfTable, stGen, &node, &mvf) { 00197 Mvf_FunctionFree(mvf); 00198 } 00199 st_free_table(nodeToMvfTable); 00200 00201 return result; 00202 } 00203 00204 /*---------------------------------------------------------------------------*/ 00205 /* Definition of internal functions */ 00206 /*---------------------------------------------------------------------------*/ 00207 00208 00209 /*---------------------------------------------------------------------------*/ 00210 /* Definition of static functions */ 00211 /*---------------------------------------------------------------------------*/ 00212 00213 00229 static Mvf_Function_t * 00230 NodeBuildMvfRecursively( 00231 Ntk_Node_t * node, 00232 st_table * leaves, 00233 st_table * nodeToMvfTable, 00234 mdd_manager *mddMgr, 00235 mdd_t *careSet) 00236 { 00237 Mvf_Function_t *mvf = NodeReadMvf(node, nodeToMvfTable); 00238 00239 00240 /* If the MVF for this node has already been computed, then just return it. */ 00241 if (mvf != NIL(Mvf_Function_t)) { 00242 return mvf; 00243 } 00244 00245 00246 if (Ntk_NodeTestIsConstant(node)) { 00247 /* Doesn't matter if constant is a leaf or not. */ 00248 mvf = NodeBuildConstantMvf(node, NTM_UNUSED, mddMgr); 00249 } 00250 00251 else { 00252 int constValue; 00253 if (st_lookup_int(leaves, (char *) node, &constValue)) { 00254 00255 if (constValue == NTM_UNUSED) { 00256 00257 /* Node is a leaf. */ 00258 if ((Ntk_NodeTestIsPrimaryInput(node)) || 00259 (Ntk_NodeTestIsLatch(node)) || 00260 (Ntk_NodeTestIsCombinational(node))) { 00261 /* Node can assume any value. */ 00262 mvf = NodeBuildInputMvf(node, mddMgr); 00263 } 00264 else if (Ntk_NodeTestIsPseudoInput(node)) { 00265 /* Node may assume only a subset of possible values. */ 00266 mvf = NodeBuildPseudoInputMvfNew(node, mddMgr); 00267 } 00268 else { 00269 fail("Encountered unknown type in MVF recursion\n"); 00270 } 00271 } 00272 else { 00273 /* treat the leaf node as being a constant taking the value constValue */ 00274 mvf = NodeBuildConstantMvf(node, constValue, mddMgr); 00275 } 00276 } 00277 else { 00278 00279 /* Node is not a leaf. If it is a combinational input, then fail. */ 00280 if (Ntk_NodeTestIsCombInput(node)) { 00281 fail("Encountered combinational input not in leaves table\n"); 00282 } 00283 else { 00284 mvf = NodeBuildInternalMvf(node, leaves, nodeToMvfTable, mddMgr, 00285 careSet); 00286 } 00287 } 00288 } 00289 00290 /* Minimize mvf wrt careSet, if careSet is not NULL. */ 00291 if (careSet != NIL(mdd_t)) { 00292 Mvf_Function_t *tempMvf = mvf; 00293 00294 mvf = Mvf_FunctionMinimize(tempMvf, careSet); 00295 Mvf_FunctionFree(tempMvf); 00296 } 00297 NodeSetMvf(node, nodeToMvfTable, mvf); 00298 return mvf; 00299 00300 } 00301 00302 00310 static Mvf_Function_t * 00311 NodeBuildInputMvf( 00312 Ntk_Node_t * node, 00313 mdd_manager *mddMgr) 00314 { 00315 int mddId = Ntk_NodeReadMddId(node); 00316 00317 assert(mddId != NTK_UNASSIGNED_MDD_ID); 00318 return Mvf_FunctionCreateFromVariable(mddMgr, mddId); 00319 } 00320 00321 00341 static Mvf_Function_t * 00342 NodeBuildPseudoInputMvfNew( 00343 Ntk_Node_t * node, 00344 mdd_manager * mddMgr) 00345 { 00346 mdd_t *vMdd, *tMdd, *rMdd; 00347 int lIndex, needProcess, i; 00348 Mvf_Function_t *mvf; 00349 int columnIndex = Ntk_NodeReadOutputIndex(node); 00350 Tbl_Table_t *table = Ntk_NodeReadTable(node); 00351 int mddId = Ntk_NodeReadMddId(node); 00352 00353 assert(mddId != NTK_UNASSIGNED_MDD_ID); 00354 mvf = Tbl_TableBuildNonDetConstantMvf(table, columnIndex, mddId, mddMgr); 00355 00356 rMdd = mdd_zero(mddMgr); 00357 needProcess = 0; 00358 lIndex = 0; 00359 for(i=0; i<mvf->num; i++) { 00360 vMdd = array_fetch(mdd_t *, mvf, i); 00361 if(mdd_equal(vMdd, rMdd)) { 00362 needProcess = 1; 00363 } 00364 else { 00365 lIndex = i; 00366 } 00367 } 00368 if(needProcess) { 00369 for(i=0; i<lIndex; i++) { 00370 vMdd = array_fetch(mdd_t *, mvf, i); 00371 tMdd = mdd_or(vMdd, rMdd, 1, 1); 00372 mdd_free(rMdd); 00373 rMdd = tMdd; 00374 } 00375 vMdd = array_fetch(mdd_t *, mvf, lIndex); 00376 mdd_free(vMdd); 00377 tMdd = mdd_not(rMdd); 00378 mdd_free(rMdd); 00379 array_insert(mdd_t *, mvf, lIndex, tMdd); 00380 } 00381 else { 00382 mdd_free(rMdd); 00383 } 00384 return mvf; 00385 } 00386 00387 #if 0 00388 static Mvf_Function_t * 00389 NodeBuildPseudoInputMvf( 00390 Ntk_Node_t * node, 00391 mdd_manager * mddMgr) 00392 { 00393 Mvf_Function_t *mvf; 00394 int columnIndex = Ntk_NodeReadOutputIndex(node); 00395 Tbl_Table_t *table = Ntk_NodeReadTable(node); 00396 int mddId = Ntk_NodeReadMddId(node); 00397 00398 assert(mddId != NTK_UNASSIGNED_MDD_ID); 00399 mvf = Tbl_TableBuildNonDetConstantMvf(table, columnIndex, mddId, mddMgr); 00400 00401 return mvf; 00402 } 00403 #endif 00404 00405 00424 static Mvf_Function_t * 00425 NodeBuildConstantMvf( 00426 Ntk_Node_t * node, 00427 int constantValue, 00428 mdd_manager *mddMgr) 00429 { 00430 int value = 0; /* initialized to stop lint complaining */ 00431 mdd_t *oneMdd = mdd_one(mddMgr); 00432 Var_Variable_t *variable = Ntk_NodeReadVariable(node); 00433 int numVarValues = Var_VariableReadNumValues(variable); 00434 Mvf_Function_t *mvf = Mvf_FunctionAlloc(mddMgr, numVarValues); 00435 00436 00437 if (constantValue != NTM_UNUSED) { 00438 /* Use the given value. */ 00439 assert((constantValue >= 0) && (constantValue < numVarValues)); 00440 value = constantValue; 00441 } 00442 else { 00443 int outputIndex = Ntk_NodeReadOutputIndex(node); 00444 Tbl_Table_t *table = Ntk_NodeReadTable(node); 00445 00446 assert(Ntk_NodeTestIsConstant(node)); 00447 value = Tbl_TableReadConstValue(table, outputIndex); 00448 assert(value != -1); 00449 } 00450 00451 Mvf_FunctionAddMintermsToComponent(mvf, value, oneMdd); 00452 mdd_free(oneMdd); 00453 return mvf; 00454 } 00455 00456 00468 static Mvf_Function_t * 00469 NodeBuildInternalMvf( 00470 Ntk_Node_t * node, 00471 st_table * leaves, 00472 st_table * nodeToMvfTable, 00473 mdd_manager *mddMgr, 00474 mdd_t *careSet) 00475 { 00476 int i; 00477 Mvf_Function_t *resultMvf; 00478 Ntk_Node_t *faninNode; 00479 array_t *faninMvfs = array_alloc(Mvf_Function_t *, Ntk_NodeReadNumFanins(node)); 00480 int outputIndex = Ntk_NodeReadOutputIndex(node); 00481 Tbl_Table_t *table = Ntk_NodeReadTable(node); 00482 00483 00484 Ntk_NodeForEachFanin(node, i, faninNode) { 00485 Mvf_Function_t *tmpMvf = NodeBuildMvfRecursively(faninNode, leaves, 00486 nodeToMvfTable, mddMgr, 00487 careSet); 00488 array_insert(Mvf_Function_t *, faninMvfs, i, tmpMvf); 00489 } 00490 resultMvf = Tbl_TableBuildMvfFromFanins(table, outputIndex, faninMvfs, mddMgr); 00491 00492 /* Mc_CheckValdityOfMvf(Ntk_NodeReadNetwork(node), mddMgr, node, resultMvf); */ 00493 00494 Ntk_NodeForEachFanin(node, i, faninNode) { 00495 NodeDecrementRefCount(faninNode, nodeToMvfTable); 00496 } 00497 00498 /* Don't free the MVFs themselves, but just free the array. */ 00499 array_free(faninMvfs); 00500 00501 return resultMvf; 00502 } 00503 00504 00513 static Mvf_Function_t * 00514 NodeReadMvf( 00515 Ntk_Node_t * node, 00516 st_table * nodeToMvfTable) 00517 { 00518 Mvf_Function_t *result = NIL(Mvf_Function_t); 00519 st_lookup(nodeToMvfTable, node, &result); 00520 00521 return result; 00522 } 00523 00524 00532 static void 00533 NodeSetMvf( 00534 Ntk_Node_t * node, 00535 st_table * nodeToMvfTable, 00536 Mvf_Function_t * mvf) 00537 { 00538 st_insert(nodeToMvfTable, (char *) node, (char *) mvf); 00539 } 00540 00541 00574 static int 00575 CommandNtmTest( 00576 Hrc_Manager_t ** hmgr, 00577 int argc, 00578 char ** argv) 00579 { 00580 int c; 00581 Ntk_Node_t *node; 00582 lsGen gen; 00583 array_t *result; /* array of Mvf_Function_t* */ 00584 array_t *roots; 00585 st_table *leaves; 00586 boolean verbose = FALSE; /* default */ 00587 Ntk_Network_t *network = Ntk_HrcManagerReadCurrentNetwork(*hmgr); 00588 00589 /* 00590 * Parse the command line. 00591 */ 00592 util_getopt_reset(); 00593 while ((c = util_getopt(argc, argv, "vh")) != EOF) { 00594 switch (c) { 00595 case 'v': 00596 verbose = 1; 00597 break; 00598 case 'h': 00599 goto usage; 00600 default: 00601 goto usage; 00602 } 00603 } 00604 00605 if (network == NIL(Ntk_Network_t)) { 00606 return 1; 00607 } 00608 00609 if (Ord_NetworkTestAreVariablesOrdered(network, Ord_InputAndLatch_c) == FALSE) { 00610 (void) fprintf(vis_stderr, "The MDD variables have not been ordered. "); 00611 (void) fprintf(vis_stderr, "Use static_order.\n"); 00612 return 1; 00613 } 00614 00615 roots = array_alloc(Ntk_Node_t *, 0); 00616 Ntk_NetworkForEachCombOutput(network, gen, node) { 00617 array_insert_last(Ntk_Node_t *, roots, node); 00618 } 00619 00620 leaves = st_init_table(st_ptrcmp, st_ptrhash); 00621 Ntk_NetworkForEachCombInput(network, gen, node) { 00622 st_insert(leaves, (char *) node, (char *) NTM_UNUSED); 00623 } 00624 00625 result = Ntm_NetworkBuildMvfs(network, roots, leaves, NIL(mdd_t)); 00626 00627 if (verbose) { 00628 MvfSanityCheck(roots, result); 00629 } 00630 00631 array_free(roots); 00632 st_free_table(leaves); 00633 00634 /* 00635 * Free the array of MVFs. 00636 */ 00637 Mvf_FunctionArrayFree(result); 00638 00639 return 0; 00640 00641 usage: 00642 (void) fprintf(vis_stderr, "usage: _ntm_test [-h] [-v]\n"); 00643 (void) fprintf(vis_stderr, " -h print the command usage\n"); 00644 (void) fprintf(vis_stderr, " -v verbose\n"); 00645 return 1; /* error exit */ 00646 } 00647 00648 00656 static void 00657 MvfSanityCheck( 00658 array_t *roots /* of Ntk_Node_t* */, 00659 array_t *mvfs /* of Mvf_Function_t* */) 00660 { 00661 int i; 00662 00663 assert(array_n(roots) == array_n(mvfs)); 00664 00665 for (i = 0; i < array_n(roots); i ++) { 00666 int value; 00667 mdd_t *valueMdd; 00668 Ntk_Node_t *root = array_fetch(Ntk_Node_t *, roots, i); 00669 Mvf_Function_t *mvf = array_fetch(Mvf_Function_t *, mvfs, i); 00670 00671 (void) fprintf(vis_stdout, "\nMDD stats for node %s:\n", Ntk_NodeReadName(root)); 00672 00673 Mvf_FunctionForEachComponent(mvf, value, valueMdd) { 00674 (void) fprintf(vis_stdout, "\tSize of MDD for value %d is %d\n", i, 00675 mdd_size(valueMdd)); 00676 } 00677 } 00678 } 00679 00680 00696 static void 00697 RegionInitializeReferenceCounts( 00698 array_t *roots, 00699 st_table *leaves) 00700 { 00701 int i; 00702 Ntk_Node_t *node; 00703 st_generator *stGen; 00704 st_table *regionNodes = Ntk_RegionFindNodes(roots, leaves); 00705 00706 st_foreach_item(regionNodes, stGen, &node, NULL) { 00707 Ntk_Node_t *fanoutNode; 00708 long refCount = 0; 00709 00710 Ntk_NodeForEachFanout(node, i, fanoutNode) { 00711 if (st_is_member(regionNodes, (char *) fanoutNode) 00712 && !st_is_member(leaves, (char *) fanoutNode) 00713 && !Ntk_NodeTestIsConstant(fanoutNode)) { 00714 refCount++; 00715 } 00716 } 00717 Ntk_NodeSetUndef(node, (void *) refCount); 00718 } 00719 00720 for(i = 0; i < array_n(roots); i++) { 00721 node = array_fetch(Ntk_Node_t *, roots, i); 00722 Ntk_NodeSetUndef(node, (void *) MAXINT); 00723 } 00724 00725 st_free_table(regionNodes); 00726 } 00727 00739 static void 00740 NodeDecrementRefCount( 00741 Ntk_Node_t *node, 00742 st_table *nodeToMvfTable) 00743 { 00744 Mvf_Function_t *mvf; 00745 long refCount = (long) Ntk_NodeReadUndef(node); 00746 00747 assert(refCount != 0); 00748 00749 refCount--; 00750 00751 if (refCount == 0) { 00752 st_delete(nodeToMvfTable, &node, &mvf); 00753 Mvf_FunctionFree(mvf); 00754 } 00755 00756 Ntk_NodeSetUndef(node, (void *) refCount); 00757 } 00758 00771 static boolean 00772 TableTestIsContainedInArray( 00773 st_table *table1, 00774 array_t *nodeArrary) 00775 { 00776 int i; 00777 st_generator *stGen; 00778 Ntk_Node_t *node; 00779 Mvf_Function_t *mvf; 00780 st_table *table2 = st_init_table(st_ptrcmp, st_ptrhash); 00781 00782 /* Create a hash table from the array. */ 00783 arrayForEachItem(Ntk_Node_t *, nodeArrary, i, node) { 00784 st_insert(table2, (char *) node, NIL(char)); 00785 } 00786 00787 st_foreach_item(table1, stGen, &node, &mvf) { 00788 if (!st_is_member(table2, node)) { 00789 st_free_table(table2); 00790 return FALSE; 00791 } 00792 } 00793 00794 st_free_table(table2); 00795 return TRUE; 00796 }