VIS

src/ntm/ntm.c

Go to the documentation of this file.
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 }