VIS

src/sim/simMain.c

Go to the documentation of this file.
00001 
00034 #include "simInt.h"
00035 
00036 static char rcsid[] UNUSED = "$Id: simMain.c,v 1.19 2005/04/23 14:31:51 jinh Exp $";
00037 
00040 /*---------------------------------------------------------------------------*/
00041 /* Static function prototypes                                                */
00042 /*---------------------------------------------------------------------------*/
00043 
00044 static int CommandSimulate(Hrc_Manager_t ** hmgr, int argc, char ** argv);
00045 static int EvaluateBinaryFunction(mdd_t * functionMdd, mdd_t * vectorMdd);
00046 static int NodeLexCmp(const void *node1, const void *node2);
00047 static mdd_t * StatesMddFromVector(Sim_Sim_t * sim, mdd_manager *mddManager);
00048 static void GenerateInitState(Sim_Sim_t * sim, boolean random);
00049 
00053 /*---------------------------------------------------------------------------*/
00054 /* Definition of exported functions                                          */
00055 /*---------------------------------------------------------------------------*/
00056 
00066 void
00067 Sim_Init(void)
00068 {
00069   Cmd_CommandAdd("simulate", CommandSimulate, /* doesn't changes_network */ 0);
00070 }
00071 
00072 
00082 void
00083 Sim_End(void)
00084 {
00085 }
00086 
00112 Sim_Sim_t *
00113 Sim_SimCreate(
00114   Ntk_Network_t * network,
00115   st_table      * nodeToMvfTable,
00116   char          * inputFile,
00117   int             lineNumber,
00118   array_t       * nodesArray,
00119   int             currentStateHead,
00120   int             internalPartitionHead,
00121   int             nextStateHead,
00122   int             outputHead,
00123   array_t       * initState,
00124   array_t       * vectorArray,
00125   boolean         verbose)
00126 {
00127   Sim_Sim_t *sim         = ALLOC(Sim_Sim_t, 1);
00128   
00129   sim->network           = network;
00130   sim->nodeToMvfTable    = nodeToMvfTable;
00131   sim->inputFile         = inputFile;
00132   sim->lineNumber        = lineNumber;
00133   sim->nodesArray        = nodesArray;
00134   sim->currentStateHead  = currentStateHead;
00135   sim->internalPartitionHead  = internalPartitionHead,
00136   sim->nextStateHead     = nextStateHead;
00137   sim->outputHead        = outputHead;
00138   sim->initState         = initState;
00139   sim->vectorArray       = vectorArray;
00140   sim->verbose           = verbose;
00141   
00142   return(sim);
00143 }
00144 
00156 void
00157 Sim_SimReset(
00158   Sim_Sim_t * sim)
00159 {
00160   int       i, value;
00161   array_t  *lastVector;
00162 
00163   assert(sim->initState != NIL(array_t));
00164   
00165   /* Reset initState */
00166 
00167   if (sim->initState != NIL(array_t)) {
00168     array_free(sim->initState);
00169   }
00170   
00171   sim->initState = array_alloc(int, 0);
00172   lastVector = array_fetch_last(array_t *,sim->vectorArray);
00173   for (i = sim->nextStateHead; i < sim->outputHead; i++) {
00174     value = array_fetch(int, lastVector, i);
00175     array_insert_last(int, sim->initState, value);
00176   }
00177 
00178   /* Free vectorArray */
00179   for (i = 0; i < array_n(sim->vectorArray); i++) {/* Free Vectors */
00180     array_t *vector = array_fetch(array_t *, sim->vectorArray, i);
00181     array_free(vector);
00182   }
00183   array_free(sim->vectorArray);
00184   sim->vectorArray = NIL(array_t);
00185 }
00186 
00194 void
00195 Sim_SimFree(
00196   Sim_Sim_t * sim)
00197 {
00198   int             i;
00199   array_t        *vector;
00200   Ntk_Node_t     *node;
00201   Mvf_Function_t *mvFunction;
00202   st_generator   *stGen;
00203 
00204   if (sim->nodesArray != NULL) {
00205     array_free(sim->nodesArray);
00206   }
00207   if (sim->initState != NIL(array_t)) {
00208     array_free(sim->initState);
00209   }
00210 
00211   if (sim->vectorArray != NIL(array_t)) {
00212     for (i = 0; i < array_n(sim->vectorArray); i++) {
00213       vector = array_fetch(array_t *, sim->vectorArray, i);
00214       array_free(vector);
00215     }
00216     array_free(sim->vectorArray);
00217   }
00218   if(sim->nodeToMvfTable != NIL(st_table)) {
00219     st_foreach_item(sim->nodeToMvfTable, stGen, &node, &mvFunction) {
00220       Mvf_FunctionFree(mvFunction);
00221     }
00222   }
00223   st_free_table(sim->nodeToMvfTable);
00224   FREE(sim);
00225 }
00226 
00235 array_t *
00236 Sim_NetworkCreateNodesArray(
00237   Ntk_Network_t * network,
00238   int           * currentStateHead,
00239   int           * internalPartitionHead,
00240   int           * nextStateHead,
00241   int           * outputHead)
00242 {
00243   int            i;
00244   lsGen          inputGen;
00245   lsGen          latchGen;
00246   lsGen          outputGen;  
00247   Ntk_Node_t    *node;
00248   array_t       *nodesArray = array_alloc(Ntk_Node_t *, 0);
00249   graph_t       *partition;
00250   vertex_t      *vertex;
00251   array_t *dfsarray;
00252 
00253   /* Input Nodes */
00254 
00255   { 
00256         array_t *tmpArray= array_alloc(Ntk_Node_t *, 0);
00257     Ntk_NetworkForEachInput(network, inputGen, node) {
00258           array_insert_last(Ntk_Node_t *, tmpArray, node);
00259         }
00260         array_sort(tmpArray, NodeLexCmp);
00261         array_append(nodesArray, tmpArray);
00262         array_free(tmpArray);
00263   }
00264   
00265   
00266   *currentStateHead = array_n(nodesArray);  /* Initialize currentStateHead */
00267 
00268   /* Adding latches */
00269   
00270   {
00271         array_t *tmpArray= array_alloc(Ntk_Node_t *, 0);
00272     Ntk_NetworkForEachLatch(network, latchGen, node) {
00273           array_insert_last(Ntk_Node_t *, tmpArray, node);
00274         }
00275         array_sort(tmpArray, NodeLexCmp);
00276         array_append(nodesArray, tmpArray);
00277         array_free(tmpArray);
00278   }
00279   
00280   *internalPartitionHead = array_n(nodesArray);  /* Initialize internalPartitionHead */
00281 
00282   /* Add internal partition nodes */
00283 
00284   partition = Part_NetworkReadPartition(network);
00285   dfsarray = g_dfs(partition);
00286   for(i=0; i< array_n(dfsarray); i++){
00287     vertex = array_fetch(vertex_t *, dfsarray, i);
00288     node = Ntk_NetworkFindNodeByName(network, Part_VertexReadName(vertex));
00289     if(!(Ntk_NodeTestIsCombInput(node) || Ntk_NodeTestIsCombOutput(node))){
00290       array_insert_last(Ntk_Node_t *, nodesArray, node);
00291     }
00292   }
00293   array_free(dfsarray);
00294   
00295   *nextStateHead = array_n(nodesArray);  /* Initialize nextStateHead */
00296 
00297   /* Add data-input of latches as next state node */
00298 
00299   for (i = *currentStateHead; i < *internalPartitionHead; i++) {
00300     node = array_fetch(Ntk_Node_t *, nodesArray, i);
00301     node = Ntk_LatchReadDataInput(node);
00302     array_insert_last(Ntk_Node_t *, nodesArray, node);
00303   }
00304   
00305   *outputHead = array_n(nodesArray);  /* Initialize outputHead */
00306   
00307           
00308   /* Adding outputs */
00309   
00310   {
00311         array_t *tmpArray= array_alloc(Ntk_Node_t *, 0);
00312     Ntk_NetworkForEachPrimaryOutput(network, outputGen, node) {
00313       array_insert_last(Ntk_Node_t *, tmpArray, node);
00314         }
00315         array_sort(tmpArray, NodeLexCmp);
00316         array_append(nodesArray, tmpArray);
00317         array_free(tmpArray);
00318   }
00319 
00320   return(nodesArray);
00321 }  
00322 
00334 void
00335 Sim_SimGenerateRandomVectors(
00336   Sim_Sim_t    * sim,
00337   int            numberVector,
00338   Sim_PseudoSrc  pseudoInputSource)
00339 {
00340   int            i;
00341   int            j;
00342   array_t       *vector;
00343   array_t       *vectorArray = array_alloc(array_t *, 0);
00344   array_t       *nodesArray  = sim->nodesArray;
00345 
00346 
00347   /* Initialization with empty vectors */
00348   for (j = 0; j < numberVector; j++) {
00349     vector = array_alloc(int, 0);
00350     array_insert_last(array_t *, vectorArray, vector);
00351   } 
00352 
00353   /* For every input node */
00354   for (i = 0; i < sim->currentStateHead; i++) {
00355     Ntk_Node_t *node = array_fetch(Ntk_Node_t *, nodesArray, i);
00356 
00357     /* For every vector */
00358     for (j = 0; j < numberVector; j++) {
00359       int value = SimNodeComputeRandomValue(node, pseudoInputSource);
00360       
00361       vector = array_fetch(array_t *, vectorArray, j);
00362       /* vector is empty => array_insert_last is convenient */
00363       array_insert_last(int, vector, value);
00364     }
00365   }
00366 
00367   sim->vectorArray = vectorArray;
00368 }
00369 
00381 void
00382 Sim_SimGenerateRandomInitState(
00383   Sim_Sim_t * sim)
00384 {
00385   GenerateInitState(sim, TRUE);
00386 }
00387 
00388 
00405 void
00406 Sim_SimSimulate(
00407   Sim_Sim_t * sim)
00408 {
00409   Ntk_Node_t    *node;
00410   array_t       *vector;
00411   array_t       *partitionVector;
00412   int            i, j;
00413   int            value;
00414   mdd_t         *vectorMdd;
00415   int            numberVector = array_n(sim->vectorArray);
00416   
00417   if(sim->verbose) {
00418     (void) fprintf(vis_stdout, "Simulating %d vectors ...\n", numberVector);
00419     fflush(vis_stdout);
00420   }
00421 
00422   /* Initialization with initState */
00423   SimSimInitializeCurrentState(sim);
00424 
00425   /*
00426   for (j = sim->internalPartitionHead; j < sim->nextStateHead; j++) {
00427     node =  array_fetch(Ntk_Node_t *, sim->nodesArray, j);
00428     fprintf(stdout, "%s \t", Ntk_NodeReadName(node));
00429   }
00430   if(sim->internalPartitionHead < sim->nextStateHead){
00431     fprintf(stdout, "\n");
00432   }
00433   */
00434   
00435   for (i = 0; i < numberVector; i++) { /* For every vector */
00436     if (i > 0) {         /* Put the current-state = last-next-state */
00437       SimSimVectorFillCurrentState(sim, i);
00438     }
00439     else {
00440       SimSimInitializeCurrentState(sim);
00441     }
00442 
00443     vector = array_fetch(array_t *, sim->vectorArray, i);
00444 
00445     /* partitionVector represents the values of the internal nodes
00446        of the partition, induced by the values of the vector array.
00447     */
00448 
00449     partitionVector = array_alloc(int, 0);
00450     
00451     /* simulate internal nodes first. As these internal nodes are 
00452        simulated, the vectorMdd is updated to reflect the newly computed
00453        values
00454     */
00455 
00456     for (j = sim->internalPartitionHead; j < sim->nextStateHead; j++) {
00457       vectorMdd = SimSimVectorBuildMdd(sim, vector, partitionVector);
00458       node =  array_fetch(Ntk_Node_t *, sim->nodesArray, j);
00459       value = Sim_nodeToMvfTableEvaluateNode(sim->nodeToMvfTable, node, vectorMdd);
00460       array_insert(int, partitionVector, j - sim->internalPartitionHead, value);
00461       mdd_free(vectorMdd);
00462     }
00463     /*
00464     if(sim->internalPartitionHead < sim->nextStateHead){
00465       fprintf(stdout, "\n");
00466     }
00467     */
00468     /* simulate the rest of the nodes */
00469     vectorMdd = SimSimVectorBuildMdd(sim, vector, partitionVector);
00470     array_free(partitionVector);
00471 
00472     for (j = sim->nextStateHead; j < array_n(sim->nodesArray); j++) {
00473       node =  array_fetch(Ntk_Node_t *, sim->nodesArray, j);
00474       value = Sim_nodeToMvfTableEvaluateNode(sim->nodeToMvfTable, node, vectorMdd);
00475       array_insert(int, vector, j, value);
00476     }
00477 
00478     mdd_free(vectorMdd);
00479   }
00480 }
00481 
00501 int
00502 Sim_nodeToMvfTableEvaluateNode(
00503   st_table   * nodeToMvfTable,
00504   Ntk_Node_t * node,
00505   mdd_t      * vectorMdd)
00506 {
00507   int             i;
00508   Mvf_Function_t *mvFunction = NIL(Mvf_Function_t);
00509 
00510   (void) st_lookup(nodeToMvfTable, (char *) node,  &mvFunction);
00511 
00512   /*
00513    * For a binary function the array contains 2 MDDs for off-set and
00514    * on-set, with the indices 0 or 1.
00515    */
00516 
00517   for (i = 0; i < Mvf_FunctionReadNumComponents(mvFunction) - 1; i++) {
00518     if (EvaluateBinaryFunction(Mvf_FunctionReadComponent(mvFunction, i),
00519                                vectorMdd) == 1) {
00520       return(i);
00521     }
00522   }
00523   /* Return last value without evaluation */
00524   return(i);
00525 }
00526 
00547 array_t *
00548 Sim_nodeToMvfTableEvaluateNodesArray(
00549   st_table  * nodeToMvfTable,
00550   array_t   * nodesArray,
00551   mdd_t     * vectorMdd)
00552 {
00553   int          i, value;
00554   Ntk_Node_t  *node;
00555   array_t     *resultArray = array_alloc(int, 0);
00556 
00557   for (i = 0; i < array_n(nodesArray); i++) {
00558     node  = array_fetch(Ntk_Node_t *, nodesArray, i);
00559     value = Sim_nodeToMvfTableEvaluateNode(nodeToMvfTable, node, vectorMdd);
00560     array_insert(int, resultArray, i, value);
00561   }
00562   return(resultArray);
00563 }
00564   
00576 mdd_t *
00577 Sim_RandomSimulate(
00578   Ntk_Network_t * network,
00579   int             num,
00580   boolean         verbose)
00581 {
00582   int        numRemainingVector;
00583   st_table  *nodeToMvfTable;
00584   Sim_Sim_t *sim;
00585   int        currentStateHead    = 0;
00586   int        internalPartitionHead    = 0;
00587   int        nextStateHead       = 0;  
00588   int        outputHead          = 0;
00589   int firstTime = 1;
00590   mdd_t *states, *simStates;
00591   mdd_manager *mddManager = Ntk_NetworkReadMddManager(network);
00592   Sim_PseudoSrc pseudoInputSource = Sim_Random_c;
00593   array_t   *nodesArray          = Sim_NetworkCreateNodesArray(network,
00594                                              &currentStateHead, &internalPartitionHead, 
00595                                              &nextStateHead, &outputHead); 
00596 
00597   /* Building nodeToMvfTable */
00598   nodeToMvfTable = Sim_NetworkBuildNodeToMvfTable(network, nodesArray,
00599                                                   internalPartitionHead,
00600                                                   nextStateHead);
00601     
00602   sim = Sim_SimCreate(network, nodeToMvfTable, NULL, 0, nodesArray,
00603                       currentStateHead, internalPartitionHead, nextStateHead, outputHead, 
00604                       NULL, NULL, verbose);
00605 
00606   /* If partition method was partial/boundary, and -i was used, then dont simulate*/
00607   if(SimTestPartInTermsOfCI(sim)){
00608     fprintf(stdout, "The partition contains internal nodes, and all partition functions are \n");
00609     fprintf(stdout, "in terms of combinational inputs - quitting. Re-create the partition \n");
00610     fprintf(stdout, "without the -i option and then re-run simulatate.\n");
00611     Sim_SimFree(sim);
00612     return(0);
00613   }
00614   
00615   /* Simulation by packet */  
00616   simStates = mdd_zero(mddManager);
00617   numRemainingVector = num;
00618   do {
00619     mdd_t *tmp;
00620     /* Number of vectors to be simulated in current pass. */
00621     num = (numRemainingVector > SIMPACKET_SIZE)
00622         ? SIMPACKET_SIZE
00623         :  numRemainingVector;
00624 
00625     Sim_SimGenerateRandomVectors(sim, num, pseudoInputSource);
00626 
00627     /*
00628      * Random init state generation. This must follow generation of input
00629      * vectors, because init state depends on inputs.
00630      */
00631     if (firstTime) {
00632       GenerateInitState(sim, FALSE);
00633     }
00634     
00635     /* SIMULATION */
00636     Sim_SimSimulate(sim);
00637     
00638     /* Print simulation vectors. On first pass, file must be created. */
00639     states = StatesMddFromVector(sim, mddManager);
00640     tmp = mdd_or(states, simStates, 1, 1);
00641     mdd_free(states);
00642     mdd_free(simStates);
00643     simStates = tmp;
00644     firstTime = 0;
00645     
00646     /* Reset Vectors */
00647     Sim_SimReset(sim);
00648 
00649     numRemainingVector -= num;
00650   } while(numRemainingVector > 0);
00651 
00652   Sim_SimFree(sim);
00653   return(simStates);
00654 } /* end of Sim_RandomSimulate */
00655 
00656 
00657 
00658 /*---------------------------------------------------------------------------*/
00659 /* Definition of internal functions                                          */
00660 /*---------------------------------------------------------------------------*/
00661 
00675 void
00676 SimSimInitializeCurrentState(
00677   Sim_Sim_t * sim)
00678 {
00679   int       i, value;
00680   
00681   /* Get the first vector from vectorArray */
00682   array_t  *vector = array_fetch(array_t *, sim->vectorArray, 0);
00683   
00684   for (i = 0; i < array_n(sim->initState); i++) {
00685     value = array_fetch(int, sim->initState, i);
00686     array_insert_last(int, vector, value);
00687   }
00688 }
00689 
00703 boolean
00704 SimRandomSimulateAndPrint(
00705   Ntk_Network_t * network,
00706   int             num,
00707   char          * outputFile,
00708   Sim_PseudoSrc   pseudoInputSource,
00709   int             printInputsFlag,
00710   int             printOutputsFlag,
00711   int             printPseudoInputsFlag,
00712   int             printStatesFlag,
00713   boolean         verbose)
00714 {
00715   int        numRemainingVector;
00716   FILE      *outFile;
00717   st_table  *nodeToMvfTable;
00718   Sim_Sim_t *sim;
00719   int        firstTime           = 1;
00720   int        currentStateHead    = 0;
00721   int        internalPartitionHead    = 0;
00722   int        nextStateHead       = 0;  
00723   int        outputHead          = 0;  
00724   array_t   *nodesArray          = Sim_NetworkCreateNodesArray(network,
00725                                              &currentStateHead, &internalPartitionHead, 
00726                                              &nextStateHead, &outputHead); 
00727 
00728   /* Building nodeToMvfTable */
00729   nodeToMvfTable = Sim_NetworkBuildNodeToMvfTable(network, nodesArray,
00730                                                   internalPartitionHead,
00731                                                   nextStateHead);
00732     
00733   sim = Sim_SimCreate(network, nodeToMvfTable, NULL, 0, nodesArray,
00734                       currentStateHead, internalPartitionHead, nextStateHead, outputHead, 
00735                       NULL, NULL, verbose);
00736 
00737   /* If partition method was partial/boundary, and -i was used, then dont simulate*/
00738   if(SimTestPartInTermsOfCI(sim)){
00739     fprintf(stdout, "The partition contains internal nodes, and all partition functions are \n");
00740     fprintf(stdout, "in terms of combinational inputs - quitting. Re-create the partition \n");
00741     fprintf(stdout, "without the -i option and then re-run simulatate.\n");
00742     Sim_SimFree(sim);
00743     return(0);
00744   }
00745   
00746   if (outputFile == NIL(char)) {
00747     outFile = vis_stdout;
00748   }
00749   else {
00750     outFile = Cmd_FileOpen(outputFile, "w", NIL(char *), 0);
00751     if (outFile == NIL(FILE)){
00752       return(0);
00753     }
00754   }
00755 
00756   /* Simulation by packet */  
00757   numRemainingVector = num;
00758   do {
00759 
00760     /* Number of vectors to be simulated in current pass. */
00761     num = (numRemainingVector > SIMPACKET_SIZE)
00762         ? SIMPACKET_SIZE
00763         :  numRemainingVector;
00764 
00765     Sim_SimGenerateRandomVectors(sim, num, pseudoInputSource);
00766 
00767     /*
00768      * Random init state generation. This must follow generation of input
00769      * vectors, because init state depends on inputs.
00770      */
00771     if (firstTime) {
00772       Sim_SimGenerateRandomInitState(sim);
00773     }
00774     
00775     /* SIMULATION */
00776     Sim_SimSimulate(sim);
00777     
00778     /* Print simulation vectors. On first pass, file must be created. */
00779     Sim_SimPrint(sim, outFile, firstTime, printInputsFlag,
00780                  printOutputsFlag, printPseudoInputsFlag,
00781                  printStatesFlag);
00782     firstTime = 0;
00783 
00784     /* Reset Vectors */
00785     Sim_SimReset(sim);
00786 
00787     numRemainingVector -= num;
00788   } while(numRemainingVector > 0);
00789 
00790   if (outputFile != NIL(char)) {
00791     fclose(outFile);
00792   }
00793   Sim_SimFree(sim);
00794   return(1);
00795 }
00796 
00821 boolean
00822 SimFileSimulateAndPrint(
00823   Ntk_Network_t * network,
00824   int             num,
00825   char          * inputFile,
00826   char          * outputFile,
00827   Sim_PseudoSrc   pseudoInputSource,
00828   int             printInputsFlag,
00829   int             printOutputsFlag,
00830   int             printPseudoInputsFlag,
00831   int             printStatesFlag,
00832   boolean         verbose)
00833 {
00834   int        numRemainingVector, packet;
00835   int        ioStatus;
00836   FILE      *outFile;
00837   int        printFlag  = 1;
00838   FILE      *inFile     = Cmd_FileOpen(inputFile, "r", NIL(char *), 0);
00839   Sim_Sim_t *sim        = Sim_FileParseDeclaration(network, inFile, inputFile, verbose);
00840 
00841   if (sim == NIL(Sim_Sim_t)) {
00842     return(0);
00843   }
00844 
00845   /* If partition method was partial/boundary, and -i was used, then dont simulate*/
00846   if(SimTestPartInTermsOfCI(sim)){
00847     fprintf(stdout, "The partition contains internal nodes, and all partition functions are \n");
00848     fprintf(stdout, "in terms of combinational inputs - quitting. Re-create the partition \n");
00849     fprintf(stdout, "without the -i option and then re-run simulatate.\n");
00850     Sim_SimFree(sim);
00851     return(0);
00852   }
00853 
00854   if (outputFile == NIL(char)) {
00855     outFile    = vis_stdout;
00856   }
00857   else {
00858     outFile    = Cmd_FileOpen(outputFile, "w", NIL(char *), 0);
00859     if (outFile == NIL(FILE)){
00860       return(0);
00861     }
00862   }
00863   
00864   /* Simulation by packet */  
00865   numRemainingVector = num;
00866   do {
00867 
00868     /********** Number of vectors to be simulated in current pass **********/
00869     /* num == 0 => simulate all vectors of the file => packet = SIMPACKET_SIZE */
00870     if (numRemainingVector > SIMPACKET_SIZE || num == 0) {
00871       packet = SIMPACKET_SIZE;
00872     }
00873     else {
00874       packet = numRemainingVector;
00875     }
00876 
00877     ioStatus = Sim_FileParseVectors(inFile, sim, numRemainingVector);
00878     if (ioStatus == 0) { /* Error case */
00879       Sim_SimFree(sim);
00880       fclose(inFile);
00881       if (outputFile != NIL(char)) {
00882         fclose(outFile);
00883       }
00884       return(0);
00885     }
00886       
00887 
00888     /*************************** SIMULATION  ****************************/
00889 
00890     Sim_SimSimulate(sim);
00891     
00892     /******************* Print Simulation Vectors **********************/
00893 
00894     Sim_SimPrint(sim, outFile, printFlag, printInputsFlag,
00895                  printOutputsFlag, printPseudoInputsFlag,
00896                  printStatesFlag);
00897     printFlag = 0;
00898 
00899     Sim_SimReset(sim);
00900     numRemainingVector -= packet;
00901   } while(ioStatus != 2 && (num == 0 || numRemainingVector > 0));
00902 
00903   Sim_SimFree(sim);
00904   fclose(inFile);
00905   if (outputFile != NIL(char)) {
00906     fclose(outFile);
00907   }
00908   return(1);
00909 }
00910 
00911 /*---------------------------------------------------------------------------*/
00912 /* Definition of static functions                                            */
00913 /*---------------------------------------------------------------------------*/
00914 
01078 static int
01079 CommandSimulate(
01080   Hrc_Manager_t ** hmgr,
01081   int              argc,
01082   char          ** argv)
01083 {
01084   int            c;
01085   unsigned int   i;
01086   long           startTime        = 0;
01087   long           endTime          = 0;
01088   long           cpuTime          = 0;
01089   int            numberVector      = 0;
01090   FILE          *inputFp           = NIL(FILE);
01091   Sim_PseudoSrc  pseudoInputSource = Sim_Undef_c;          /* default */
01092   boolean        verbose           = FALSE;                /* default */
01093   char          *inputFile         = NIL(char);
01094   char          *outputFile        = NIL(char);
01095   Ntk_Network_t *network           = Ntk_HrcManagerReadCurrentNetwork(*hmgr);
01096   int printInputsFlag = 1; /*default*/
01097   int printOutputsFlag = 1;/*default*/
01098   int printPseudoInputsFlag = 1;/*default*/
01099   int printStatesFlag = 1;/*default*/
01100   
01101   /*
01102    * Parse command line options.
01103    */
01104 
01105   util_getopt_reset();
01106   while ((c = util_getopt(argc, argv, "I:O:P:S:hvi:o:n:p:s")) != EOF) {
01107     switch(c) {
01108       case 'I':
01109         printInputsFlag = atoi(util_optarg);
01110         break;
01111       case 'O':
01112         printOutputsFlag = atoi(util_optarg);
01113         break;
01114       case 'P':
01115         printPseudoInputsFlag = atoi(util_optarg);
01116         break;
01117       case 'S':
01118         printStatesFlag = atoi(util_optarg);
01119         break;
01120       case 'h':
01121         goto usage;
01122       case 'i':
01123         inputFile = util_optarg;
01124         break;
01125       case 'n':
01126         for (i = 0; i < strlen(util_optarg); i++) {
01127           if (!isdigit((int)util_optarg[i])) {
01128             goto usage;
01129           }
01130         }
01131         numberVector = atoi(util_optarg);
01132         break;
01133       case 'o':
01134         outputFile = util_optarg;        
01135         break;
01136       case 'p':
01137         if (!strcmp("0", util_optarg)) {
01138           pseudoInputSource = Sim_User_c;
01139         }
01140         else if (!strcmp("1", util_optarg)) {
01141           pseudoInputSource = Sim_Random_c;
01142         }
01143         else if (!strcmp("2", util_optarg)) {
01144           pseudoInputSource = Sim_First_c;
01145         }
01146         else {
01147           goto usage;
01148         }
01149         break;
01150       case 'v':
01151         verbose = 1;
01152         break;
01153       default:
01154         goto usage;
01155     }
01156   }
01157 
01158   if (network == NIL(Ntk_Network_t)) {
01159     return 1;
01160   }
01161 
01162   if (Ord_NetworkTestAreVariablesOrdered(network,Ord_InputAndLatch_c) == FALSE){
01163     (void) fprintf(vis_stdout, "The MDD variables have not been ordered. Use static_order.\n");
01164     return 1;
01165   }
01166 
01167   if (Part_NetworkReadPartition(network) == NIL(graph_t)) {
01168     (void) fprintf(vis_stderr, "Network has not been partitioned. Use build_partition_mdds.\n");
01169     return 1;
01170   }
01171   
01173   util_srandom(SimComputeRandomInteger());
01174 
01175   /* Parameters verification */
01176 
01177   if (numberVector <= 0 && inputFile == NIL(char)) {
01178     (void) fprintf(vis_stderr, "Simulate: specify an input file with -i or use -n option to set\n");
01179     (void) fprintf(vis_stderr, "the number of vectors randomly generated\n");
01180     return(1);
01181   }
01182   if (pseudoInputSource == Sim_User_c && inputFile == NIL(char)) {
01183     (void) fprintf(vis_stderr, "Simulate: '-p 0' option and random vectors\n");
01184     (void) fprintf(vis_stderr, "           generation are incompatible\n");
01185     return(1);
01186   }
01187   if ((pseudoInputSource != Sim_Undef_c) && inputFile != NIL(char)) {
01188     (void) fprintf(vis_stderr, "Simulate: '-p' option is available only if vectors\n");
01189     (void) fprintf(vis_stderr, "           are generated randomly.\n");
01190     return(1);
01191   }
01192 
01193   if (numberVector == 0 && inputFile == NIL(char)) {
01194     (void) fprintf(vis_stderr, "Simulate: number of vectors not specified.\nUsing 10 random vectors\n");
01195     numberVector = 10;
01196   }
01197   if (inputFile != NIL(char)) {
01198     inputFp = Cmd_FileOpen(inputFile, "r", NIL(char *), 0);
01199     if (inputFp == NIL(FILE)) {
01200       return (1);
01201     }
01202   }
01203 
01204   /* CPU-Time print with verbose option */
01205   if (verbose) {
01206     startTime = util_cpu_time();
01207   }
01208 
01209   
01210   /************** Random Vectors generation **************/
01211   error_init();
01212 
01213   if (inputFile == NIL(char)) {
01214     if (SimRandomSimulateAndPrint(network, numberVector, outputFile,
01215                                   pseudoInputSource, printInputsFlag,
01216                                   printOutputsFlag,
01217                                   printPseudoInputsFlag, 
01218                                   printStatesFlag,
01219                                   verbose) == 0) {
01220       (void) fprintf(vis_stdout, "%s", error_string());      
01221       return (1);
01222     }
01223   }
01224   
01225 /************* Read vectors from a file ***************/
01226   
01227   else {
01228     if (SimFileSimulateAndPrint(network, numberVector, inputFile, outputFile,
01229                                 pseudoInputSource, printInputsFlag,
01230                                 printOutputsFlag, printPseudoInputsFlag,
01231                                 printStatesFlag, verbose) == 0) {
01232       (void) fprintf(vis_stdout, "%s", error_string());      
01233       return(1);
01234     }
01235   }
01236   
01237   if (verbose) {
01238     endTime = util_cpu_time();
01239     cpuTime = endTime - startTime;    
01240     (void) fprintf(vis_stdout, "====> Simulation time: %d ms\n", (int)cpuTime);
01241   }
01242 
01243   return 0;             /* normal exit */
01244 
01245   usage:
01246   (void) fprintf(vis_stderr, "usage: simulate [-I <0/1>][-O <0/1>][-P <0/1>][-S <0/1>][-h][-i vectors_file]\n");
01247   (void) fprintf(vis_stderr, "                [-n number-vectors][-o output_file][-p <0/1/2>] [-v]\n");
01248 
01249   (void) fprintf(vis_stderr, "    -I <0/1>\t\tControls printing of primary input variables\n");
01250   (void) fprintf(vis_stderr, "            \t\t(0:no print, 1:print, default is 1)\n");
01251   (void) fprintf(vis_stderr, "    -O <0/1>\t\tControls printing of output variables\n");
01252   (void) fprintf(vis_stderr, "            \t\t(0:no print, 1:print, default is 1)\n");
01253   (void) fprintf(vis_stderr, "    -P <0/1>\t\tControls printing of pseudo input variables\n");
01254   (void) fprintf(vis_stderr, "            \t\t(0:no print, 1:print, default is 1)\n");
01255   (void) fprintf(vis_stderr, "    -S <0/1>\t\tControls printing of state variables\n");
01256   (void) fprintf(vis_stderr, "            \t\t(0:no print, 1:print, default is 1)\n");
01257   (void) fprintf(vis_stderr, "    -h \tPrints this usage message.\n");
01258   (void) fprintf(vis_stderr, "    -i <vectors_file>\tThe input file containing simulation vectors.\n");
01259   (void) fprintf(vis_stderr, "                   \tIf not specified, N vectors are generated randomly.\n");
01260   (void) fprintf(vis_stderr, "                   \tN is given by the option '-n'.\n");
01261   (void) fprintf(vis_stderr, "    -n <N>\t\tWith this option, only the first N vectors\n");
01262   (void) fprintf(vis_stderr, "          \t\twill be simulated. If '-i' option is not used,\n");
01263   (void) fprintf(vis_stderr, "           \t\tN is the number of random vectors.\n");
01264   (void) fprintf(vis_stderr, "    -o <output_file>\tThe output file. If not specified, the output\n");
01265   (void) fprintf(vis_stderr, "                    \twill be directed to stdout.\n");
01266   (void) fprintf(vis_stderr, "    -p <0|1|2>\t\tIf 0 : non-deterministic cases are treated\n");
01267   (void) fprintf(vis_stderr, "              \t\tas specified by user.\n");
01268   (void) fprintf(vis_stderr, "              \t\tIf 1: non-deterministic cases are treated randomly.\n");
01269   (void) fprintf(vis_stderr, "              \t\tIf 2: non-deterministic cases are treated by\n");
01270   (void) fprintf(vis_stderr, "              \t\tchoosing the first possibility.\n");
01271   (void) fprintf(vis_stderr, "    -v \tVerbose. Print CPU time usage.\n");
01272 
01273   return 1;             /* error exit */
01274 }
01275 
01276 
01290 static int
01291 EvaluateBinaryFunction(
01292   mdd_t * functionMdd,
01293   mdd_t * vectorMdd)
01294 {
01295   mdd_t       * result = mdd_cofactor_minterm(functionMdd, vectorMdd);
01296 
01297   if (mdd_is_tautology(result, 1)) {
01298     mdd_free(result);
01299     return (1);
01300   }
01301   else if (mdd_is_tautology(result, 0)) {
01302     mdd_free(result);
01303     return (0);
01304   }
01305   else {
01306     mdd_free(result);
01307     return (-1);
01308   }
01309 }
01310 
01311 
01321 static int
01322 NodeLexCmp(
01323   const void *node1,
01324   const void *node2)
01325 {
01326   char *name1 = Ntk_NodeReadName(*(Ntk_Node_t **)node1);
01327   char *name2 = Ntk_NodeReadName(*(Ntk_Node_t **)node2);
01328 
01329   return strcmp(name1, name2);
01330 }
01331 
01341 static mdd_t *
01342 StatesMddFromVector(
01343   Sim_Sim_t       * sim,
01344   mdd_manager *mddManager
01345   )
01346 
01347 {
01348   int             i, j;
01349   array_t        *vector;
01350   Ntk_Node_t     *node;
01351   mdd_t *state, *simStates, *tmp, *mddLiteral;
01352   int value;
01353   array_t *valueArray;
01354   int mddId;
01355 
01356   /* start with zero */
01357   simStates = mdd_zero(mddManager);
01358   valueArray = array_alloc(int, 1);
01359   for (i = 0; i < array_n(sim->vectorArray); i++) {
01360       /* add every state in the vector */
01361     vector = array_fetch(array_t *, sim->vectorArray, i);
01362     state = mdd_one(mddManager);
01363     for (j = sim->currentStateHead; j < sim->internalPartitionHead; j++){
01364       /* Build the state */
01365       node = array_fetch(Ntk_Node_t *, sim->nodesArray, j);
01366       mddId = Ntk_NodeReadMddId(node);
01367       value = array_fetch(int, vector, j);
01368       array_insert(int, valueArray, 0, value);
01369       mddLiteral = mdd_literal(mddManager, mddId, valueArray);
01370       
01371       tmp = mdd_and(state, mddLiteral, 1, 1);
01372       mdd_free(state);
01373       mdd_free(mddLiteral);
01374       state = tmp;
01375     }
01376 
01377     tmp = mdd_or(simStates, state, 1, 1);
01378     mdd_free(simStates);
01379     mdd_free(state);
01380     simStates = tmp;
01381 
01382   }
01383   array_free(valueArray);
01384   return simStates;
01385 } /* end of StatesMddFromVector */
01386 
01387 
01399 static void
01400 GenerateInitState(
01401   Sim_Sim_t * sim, boolean random)
01402 {
01403   int            i;
01404   array_t       *mvfArray;
01405   array_t       *initState   = array_alloc(int, 0);
01406   array_t       *nodesArray  = sim->nodesArray;
01407   array_t       *vectorArray = sim->vectorArray;
01408   array_t       *firstVector = array_fetch(array_t *, vectorArray, 0);
01409   st_table      *leaves      = st_init_table(st_ptrcmp, st_ptrhash);
01410   int            numLatches  = sim->internalPartitionHead - sim->currentStateHead;
01411   array_t       *rootArray   = array_alloc(Ntk_Node_t *, numLatches);
01412   
01413   /* Free old initState */
01414   if (sim->initState != NIL(array_t)) {
01415     array_free(sim->initState);
01416   }
01417   sim->initState = initState;
01418 
01419   /*
01420    * Load a symbol table with the initial values of the primary and pseudo
01421    * inputs.
01422    */
01423   for (i = 0; i < sim->currentStateHead; i++) {
01424     Ntk_Node_t *node  = array_fetch(Ntk_Node_t *, nodesArray, i);
01425     if (random) {
01426       int         value = array_fetch(int, firstVector, i); 
01427       st_insert(leaves, (char *) node, (char *) (long) value);
01428     } else {
01429       st_insert(leaves, (char *) node, (char *) (long) NTM_UNUSED);
01430     }
01431   }
01432   
01433   /*
01434    * Create an array containing the initialization function for all the
01435    * latches. This array has the same order as the simulation vector.
01436    */
01437   for (i = sim->currentStateHead; i < sim->internalPartitionHead; i++) {
01438     Ntk_Node_t     *latch      = array_fetch(Ntk_Node_t *, nodesArray, i);
01439     Ntk_Node_t     *initNode   = Ntk_LatchReadInitialInput(latch);
01440     
01441     array_insert_last(Ntk_Node_t *, rootArray, initNode);
01442   }
01443 
01444   /*
01445    * Build the MVFs for the initialization functions, using the initial input
01446    * values.
01447    */
01448   mvfArray = Ntm_NetworkBuildMvfs(sim->network, rootArray, leaves, NIL(mdd_t));
01449   array_free(rootArray);
01450   st_free_table(leaves);
01451 
01452   /*
01453    * Get the initial value of each latch from the MVF of the corresponding
01454    * initialization function.  Since the initialization functions are in terms
01455    * of primary and pseudo input values, and we have completely specified
01456    * values for all inputs, each initialization function should have evaluated
01457    * to a constant (i.e. exactly one non-zero component, and that component is
01458    * the tautology.
01459    */
01460   for (i = 0; i < numLatches; i++) {
01461     int             j;
01462     int             value = 0;  /* initialized to avoid lint complaint */
01463     Mvf_Function_t *initMvf;
01464     mdd_t          *component;
01465     int             numNonZero = 0;
01466     
01467     initMvf = array_fetch(Mvf_Function_t *, mvfArray, i);
01468     Mvf_FunctionForEachComponent(initMvf, j, component) { 
01469       if (!mdd_is_tautology(component, 0)) {
01470         assert(mdd_is_tautology(component, 1));
01471         numNonZero++;
01472         value = j;
01473       }
01474     }
01475 
01476     assert(numNonZero == 1);
01477     array_insert_last(int, initState, value);
01478   }
01479 
01480   Mvf_FunctionArrayFree(mvfArray);
01481   return;
01482 } /* end of GenerateInitState */
01483