VIS

src/io/ioCheck.c

Go to the documentation of this file.
00001 
00051 #include "ioInt.h"
00052 
00053 static char rcsid[] UNUSED = "$Id: ioCheck.c,v 1.11 2005/04/16 06:17:45 fabio Exp $";
00054 
00055 /*---------------------------------------------------------------------------*/
00056 /* Constant declarations                                                     */
00057 /*---------------------------------------------------------------------------*/
00058 
00059 
00060 /*---------------------------------------------------------------------------*/
00061 /* Type declarations                                                         */
00062 /*---------------------------------------------------------------------------*/
00063 
00064 
00065 /*---------------------------------------------------------------------------*/
00066 /* Stucture declarations                                                     */
00067 /*---------------------------------------------------------------------------*/
00068 
00069 
00070 /*---------------------------------------------------------------------------*/
00071 /* Variable declarations                                                     */
00072 /*---------------------------------------------------------------------------*/
00073 
00074 
00075 /*---------------------------------------------------------------------------*/
00076 /* Macro declarations                                                        */
00077 /*---------------------------------------------------------------------------*/
00078 
00079 
00082 /*---------------------------------------------------------------------------*/
00083 /* Static function prototypes                                                */
00084 /*---------------------------------------------------------------------------*/
00085 
00086 static boolean _IoModelTestMasterNodeConsistency(Hrc_Model_t *model, Hrc_Node_t *hnode);
00087 static boolean _IoModelTestConnectionConsistency(Hrc_Manager_t *hmgr, Hrc_Model_t *model, Hrc_Node_t *hnode, array_t *subcktArray);
00088 static boolean _IoModelTestLatchConsistency(Hrc_Node_t *hnode);
00089 static boolean _IoModelTestResetConsistency(Hrc_Manager_t *hmgr, Hrc_Model_t *model, Hrc_Node_t *hnode, array_t *resetArray);
00090 static boolean _IoModelTestInternalConnectionConsistency(Hrc_Model_t *model, Hrc_Node_t *hnode, boolean isVerbose);
00091 static boolean _IoModelTestIsAcyclic(Hrc_Model_t *model, Hrc_Node_t *hnode, st_table *varToTable, st_table *outputVarToSubckt, st_table *visitTable);
00092 static void _IoModelTestIsAcyclicError(Hrc_Model_t *model, Var_Variable_t *var);
00093 static int _IoModelTestIsAcyclicRecursive(Hrc_Model_t *model, Hrc_Node_t *hnode, Var_Variable_t *var, st_table *varToTable, st_table *outputVarToSubckt, st_table *visitTable, boolean isResetLogic);
00094 
00098 /*---------------------------------------------------------------------------*/
00099 /* Definition of exported functions                                          */
00100 /*---------------------------------------------------------------------------*/
00101 
00102 
00103 /*---------------------------------------------------------------------------*/
00104 /* Definition of internal functions                                          */
00105 /*---------------------------------------------------------------------------*/
00106 
00118 boolean
00119 IoNetworkTestConsistency(
00120   Hrc_Manager_t *hmgr, 
00121   array_t *modelArray,
00122   st_table *parserSubcktInfo,
00123   st_table *parserResetInfo,
00124   boolean isVerbose)
00125 {
00126   char *subcktArray, *resetArray;
00127   Hrc_Model_t *model;
00128   Hrc_Node_t *hnode;
00129   int i;
00130 
00131   for (i=0; i < array_n(modelArray); i++){
00132     model = array_fetch(Hrc_Model_t *,modelArray,i);
00133 
00134     hnode = Hrc_ModelReadMasterNode(model);
00135 
00136     if (_IoModelTestMasterNodeConsistency(model,hnode) == 0){
00137       return 0;
00138     }
00139     /* the following st_lookup should return 1 */
00140     (void)st_lookup(parserSubcktInfo,(char *)model,&subcktArray);
00141     if ((array_t *)subcktArray != NIL(array_t)){
00142       if (_IoModelTestConnectionConsistency(hmgr,model,hnode,(array_t *)subcktArray) == 0){
00143         return 0;
00144       }
00145     }
00146     /* the following st_lookup should return 1 */
00147     (void)st_lookup(parserResetInfo,(char *)model,&resetArray);
00148     if ((array_t *)resetArray != NIL(array_t)){
00149       if (_IoModelTestResetConsistency(hmgr,model,hnode,(array_t *)resetArray) == 0){
00150         return 0;
00151       }
00152     }
00153     if (_IoModelTestLatchConsistency(hnode) == 0){
00154       return 0;
00155     }
00156     if (_IoModelTestInternalConnectionConsistency(model,hnode,isVerbose) == 0){
00157       return 0;
00158     }
00159   }
00160   return 1;
00161 }
00162 
00163 /*---------------------------------------------------------------------------*/
00164 /* Definition of static functions                                            */
00165 /*---------------------------------------------------------------------------*/
00166 
00178 static boolean
00179 _IoModelTestMasterNodeConsistency(
00180   Hrc_Model_t *model,
00181   Hrc_Node_t *hnode)
00182 {
00183   char *varName;
00184   Var_Variable_t *var;
00185   st_generator *gen;
00186 
00187   Hrc_NodeForEachVariable(hnode,gen,varName,var){
00188     if (Var_VariableTestTypeConsistency(var) == 0){
00189       st_free_gen(gen);
00190       return 0;
00191     }
00192   }
00193   return 1;
00194 }
00195 
00207 static boolean
00208 _IoModelTestConnectionConsistency(
00209   Hrc_Manager_t *hmgr, 
00210   Hrc_Model_t *model, 
00211   Hrc_Node_t *hnode, 
00212   array_t *subcktArray)
00213 {
00214   int i, j;
00215   IoSubckt_t *subckt;
00216   char *nameOfSubcktModel, *instanceName, *formalName, *actualName, *actualPort;
00217   Hrc_Model_t *subcktModel;
00218   Hrc_Node_t *subcktHnode;
00219   st_table *tmpTable;
00220   st_table *outputCheckTable;
00221   array_t *formalNameArray, *actualNameArray, *actualInputArray, *actualOutputArray;
00222   Var_Variable_t *port, *var;
00223 
00224   for (i=0; i < array_n(subcktArray); i++){
00225     subckt = array_fetch(IoSubckt_t *,subcktArray,i);
00226     nameOfSubcktModel = subckt->modelName;
00227     if ((subcktModel = Hrc_ManagerFindModelByName(hmgr,nameOfSubcktModel)) == NIL(Hrc_Model_t)){
00228       error_append("Error: Model ");
00229       error_append(Hrc_ModelReadName(model));
00230       error_append(" has a subcircuit whose model ");
00231       error_append(nameOfSubcktModel);
00232       error_append(" is not defined.\n");
00233       return 0;
00234     }
00235 
00236     subcktHnode = Hrc_ModelReadMasterNode(subcktModel);
00237     instanceName = subckt->instanceName;
00238     formalNameArray = subckt->formalNameArray;
00239     actualNameArray = subckt->actualNameArray;
00240     assert(array_n(formalNameArray) == array_n(actualNameArray));
00241 
00242     if (array_n(formalNameArray) != 
00243         Hrc_NodeReadNumFormalInputs(subcktHnode) + Hrc_NodeReadNumFormalOutputs(subcktHnode)){
00244       error_append("Error: Subcircuit ");
00245       error_append(instanceName);
00246       error_append(" in model ");
00247       error_append(Hrc_ModelReadName(model));
00248       error_append(" and the corresponding model ");
00249       error_append(nameOfSubcktModel);
00250       error_append(" have different number of i/o ports.\n");
00251       return 0;
00252     }
00253 
00254     /* creating a temporary hash table from formal names to actual names */
00255     tmpTable = st_init_table(strcmp,st_strhash);
00256     for (j=0; j < array_n(formalNameArray); j++){
00257       formalName = array_fetch(char *,formalNameArray,j);
00258       actualName = array_fetch(char *,actualNameArray,j);
00259       if (st_insert(tmpTable,(char *)formalName,(char *)actualName)){
00260         error_append("Error: In subcircuit ");
00261         error_append(instanceName);
00262         error_append(" in model ");
00263         error_append(Hrc_ModelReadName(model));
00264         error_append(", formal variable ");
00265         error_append(formalName);
00266         error_append(" is used more than once.\n");
00267         st_free_table(tmpTable);
00268         return 0;
00269       }
00270     }
00271 
00272     /* create actualInputArray */
00273     actualInputArray = array_alloc(Var_Variable_t *,0);
00274     actualOutputArray = array_alloc(Var_Variable_t *,0);
00275     Hrc_NodeForEachFormalInput(subcktHnode,j,port){
00276       if (st_lookup(tmpTable,(char *)Var_VariableReadName(port),&actualPort) == 0){
00277         error_append("Error: Subcircuit ");
00278         error_append(instanceName);
00279         error_append(" in model ");
00280         error_append(Hrc_ModelReadName(model));
00281         error_append(" has no actual variable defined for variable ");
00282         error_append(Var_VariableReadName(port));
00283         error_append(".\n");
00284         return 0;
00285       }
00286       /* var should get a non-nil pointer */
00287       var = Hrc_NodeFindVariableByName(hnode,actualPort);
00288       if (Var_VariablesTestHaveSameDomain(var,port) == 0){
00289         error_append("Error: Formal variable ");
00290         error_append(Var_VariableReadName(port));
00291         error_append(" and actual variable ");
00292         error_append(actualPort);
00293         error_append(" have different types in subcircuit ");
00294         error_append(instanceName);
00295         error_append(" in model ");
00296         error_append(Hrc_ModelReadName(model));
00297         error_append(".\n");
00298         return 0;
00299       }
00300       if (Var_VariableSetSI(var) == -1){
00301         return 0;
00302       };
00303       array_insert_last(Var_Variable_t *,actualInputArray,var); 
00304     }
00305 
00306     /* create actualOutputArray */
00307     outputCheckTable = st_init_table(strcmp,st_strhash);
00308     Hrc_NodeForEachFormalOutput(subcktHnode,j,port){
00309 
00310       if (st_lookup(tmpTable,(char *)Var_VariableReadName(port),&actualPort) == 0){
00311         error_append("Error: Subcircuit ");
00312         error_append(instanceName);
00313         error_append(" in model ");
00314         error_append(Hrc_ModelReadName(model));
00315         error_append(" has no actual variable defined for variable ");
00316         error_append(Var_VariableReadName(port));
00317         error_append(".\n");
00318         return 0;
00319       }
00320       if (st_is_member(outputCheckTable,actualPort) == 1){
00321         error_append("Error: Subcircuit ");
00322         error_append(instanceName);
00323         error_append(" in model ");
00324         error_append(Hrc_ModelReadName(model));
00325         error_append(" has more than one output connected to the same variable ");
00326         error_append(actualPort);
00327         error_append(".\n");
00328         return 0;
00329       }
00330       (void)st_insert(outputCheckTable,actualPort,(char *)0);
00331       /* var should get a non-nil pointer */
00332       var = Hrc_NodeFindVariableByName(hnode,actualPort);
00333       if (Var_VariablesTestHaveSameDomain(var,port) == 0){
00334         error_append("Error: Formal variable ");
00335         error_append(Var_VariableReadName(port));
00336         error_append(" and actual variable ");
00337         error_append(actualPort);
00338         error_append(" have different types in subcircuit ");
00339         error_append(instanceName);
00340         error_append(" in model ");
00341         error_append(Hrc_ModelReadName(model));
00342         error_append(".\n");
00343         return 0;
00344       }
00345       if (Var_VariableSetSO(var) == -1){
00346         return 0;
00347       };
00348       array_insert_last(Var_Variable_t *,actualOutputArray,var); 
00349     }
00350     st_free_table(outputCheckTable);
00351     st_free_table(tmpTable);
00352     if (Hrc_ModelAddSubckt(model,subcktModel,instanceName,actualInputArray,actualOutputArray) == 0){
00353       error_append("Error: Model ");
00354       error_append(Hrc_ModelReadName(model));
00355       error_append(" has two subcircuits with the same instance name ");
00356       error_append(instanceName);
00357       error_append("\n");
00358       return 0;
00359     }
00360   }
00361   return 1;
00362 }
00363 
00364 
00376 static boolean
00377 _IoModelTestLatchConsistency(Hrc_Node_t *hnode)
00378 {
00379   Hrc_Latch_t *latch;
00380   Var_Variable_t *varIn, *varOut;
00381   st_generator *gen;
00382   char *latchName;
00383 
00384   Hrc_NodeForEachLatch(hnode,gen,latchName,latch){
00385     varIn = Hrc_LatchReadInput(latch);
00386     varOut = Hrc_LatchReadOutput(latch);
00387     if (Var_VariablesTestHaveSameDomain(varIn,varOut) == 0){
00388       error_append("Error: The input and the output of latch ");
00389       error_append(latchName);
00390       error_append(" have different domains.\n"); 
00391       return 0; 
00392     }
00393     if (Hrc_LatchReadResetTable(latch) == NIL(Tbl_Table_t)){
00394       error_append("Error: Latch ");
00395       error_append(Var_VariableReadName(varOut));
00396       error_append(" has no reset table.\n");
00397       return 0;
00398     }
00399   }
00400   return 1;
00401 }
00402 
00415 static boolean
00416 _IoModelTestResetConsistency(
00417   Hrc_Manager_t *hmgr,
00418   Hrc_Model_t *model,
00419   Hrc_Node_t *hnode,
00420   array_t *resetArray)
00421 {
00422   int i;
00423   Var_Variable_t *output;
00424   Tbl_Table_t *resetTable;
00425   Hrc_Latch_t *latch;
00426 
00427   for (i=0; i < array_n(resetArray); i++){
00428     resetTable = array_fetch(Tbl_Table_t *,resetArray,i);
00429     if (Tbl_TableReadNumOutputs(resetTable) != 1){
00430       error_append("Error: Reset table with output ");
00431       error_append(Var_VariableReadName(Tbl_TableReadIndexVar(resetTable,0,1)));
00432       error_append(" has to be a single output table.\n");
00433       return 0;
00434     }
00435     output = Tbl_TableReadIndexVar(resetTable,0,1);
00436     if (Var_VariableTestIsPS(output) == 0){
00437       error_append("Error: Reset table with output ");
00438       error_append(Var_VariableReadName(output));
00439       error_append(" is not attached to a latch.\n");
00440       return 0;
00441     }
00442     latch = Hrc_NodeFindLatchByName(hnode,Var_VariableReadName(output));
00443     if (Hrc_LatchSetResetTable(latch,resetTable) == 0){
00444       error_append("Error: You try to overwrite the reset table of ");
00445       error_append(Var_VariableReadName(output));
00446       error_append(".\n");
00447       return 0;
00448     }
00449     /* once a reset table is associated with a latch,
00450     we remove the table from resetArray */
00451     array_insert(Tbl_Table_t *,resetArray,i,NIL(Tbl_Table_t));
00452   }
00453   return 1;
00454 }
00455 
00456 
00469 static boolean
00470 _IoModelTestInternalConnectionConsistency(
00471   Hrc_Model_t *model,
00472   Hrc_Node_t *hnode,
00473   boolean isVerbose)
00474 {
00475   st_table *varToTable, *outputVarToSubckt, *inputVarToSubckt, *visitTable;
00476   st_generator *gen;
00477   int i, j, status, warningStatus;
00478   Var_Variable_t *var, *actualOutput;
00479   Tbl_Table_t *table;
00480   char *varName, *subcktName, *latchName;
00481   Hrc_Subckt_t *subckt, *anotherSubckt;
00482   Hrc_Latch_t *latch;
00483   
00484   /* creates a hash table from variables to tables */ 
00485   varToTable = st_init_table(st_ptrcmp,st_ptrhash);
00486   Hrc_NodeForEachNameTable(hnode,i,table){
00487     Tbl_TableForEachOutputVar(table,j,var){
00488       if (Var_VariableTestIsPI(var) == 1){
00489         error_append("Error: Primary input ");
00490         error_append(Var_VariableReadName(var));
00491         error_append(" is an output of a table in model ");
00492         error_append(Hrc_ModelReadName(model));
00493         error_append(".\n");
00494         st_free_table(varToTable);
00495         return 0; 
00496       }
00497       if (st_insert(varToTable,(char *)var,(char *)table) == 1){
00498         error_append("Error: Variable ");
00499         error_append(Var_VariableReadName(var));
00500         error_append(" is an output of more than one table in model ");
00501         error_append(Hrc_ModelReadName(model));
00502         error_append(".\n");
00503         st_free_table(varToTable);
00504         return 0;
00505       }
00506     }
00507   }
00508   Hrc_NodeForEachLatch(hnode,gen,latchName,latch){
00509     if (st_insert(varToTable,(char *)Hrc_LatchReadOutput(latch),(char *)Hrc_LatchReadResetTable(latch)) == 1){
00510       error_append("Error: Latch output ");
00511       error_append(Var_VariableReadName(Hrc_LatchReadOutput(latch)));
00512       error_append(" is an output of a table in model ");
00513       error_append(Hrc_ModelReadName(model));
00514       error_append(".\n");
00515       st_free_table(varToTable);
00516       return 0;
00517     }
00518   }
00519 
00520   /* creates two hash tables
00521      one from output variables of subckts to subckts
00522      the other one from input variables of subckts to subckts */
00523   outputVarToSubckt = st_init_table(st_ptrcmp,st_ptrhash);
00524   inputVarToSubckt = st_init_table(st_ptrcmp,st_ptrhash);
00525 
00526   Hrc_ModelForEachSubckt(model,gen,subcktName,subckt){
00527     array_t *actualOutputs = Hrc_SubcktReadActualOutputVars(subckt);
00528     array_t *actualInputs = Hrc_SubcktReadActualInputVars(subckt);
00529 
00530     for (i=0; i < array_n(actualOutputs); i++){
00531       actualOutput = array_fetch(Var_Variable_t *,actualOutputs,i);
00532       if (st_lookup(varToTable,(char *)actualOutput,&table) == 1){
00533         error_append("Error: Subckt output ");
00534         error_append(Var_VariableReadName(actualOutput));
00535         error_append(" in ");
00536         error_append(subcktName);
00537         error_append(" is an output of a table in model ");
00538         error_append(Hrc_ModelReadName(model));
00539         error_append(".\n");
00540         st_free_table(varToTable);
00541         st_free_table(outputVarToSubckt);
00542         st_free_gen(gen);
00543         return 0;
00544       }
00545       if (st_lookup(outputVarToSubckt,(char *)actualOutput,&anotherSubckt) == 1){
00546         error_append("Error: Subckt output ");
00547         error_append(Var_VariableReadName(actualOutput));
00548         error_append(" in ");
00549         error_append(subcktName);
00550         error_append(" is also a subckt output of ");
00551         error_append(Hrc_SubcktReadInstanceName(anotherSubckt));
00552         error_append(" in model ");
00553         error_append(Hrc_ModelReadName(model));
00554         error_append(".\n");
00555         st_free_table(varToTable);
00556         st_free_table(outputVarToSubckt);
00557         st_free_gen(gen);
00558         return 0;
00559       }
00560       (void)st_insert(outputVarToSubckt,(char *)actualOutput,(char *)subckt);
00561     }
00562     
00563     for (i=0; i < array_n(actualInputs); i++){
00564       Var_Variable_t *actualInput = array_fetch(Var_Variable_t *,actualInputs,i);
00565       (void)st_insert(inputVarToSubckt,(char *)actualInput,(char *)subckt);
00566     }
00567 
00568   }
00569 
00570   /* start checking the consistency of a hnode */
00571   Hrc_NodeForEachVariable(hnode,gen,varName,var) {
00572     if (st_lookup(varToTable,(char *)var,&table) == 0){
00573       if (Var_VariableTestIsPS(var) == 1 || Var_VariableTestIsPI(var) == 1){
00574         continue;
00575       }
00576       else {
00577        if (st_lookup(outputVarToSubckt,(char *)var,&subckt) == 0) { 
00578          error_append("Error: Variable "); 
00579          error_append(varName); 
00580          error_append(" is not defined as an output of a table in model "); 
00581          error_append(Hrc_ModelReadName(model)); 
00582          error_append(".\n"); 
00583          st_free_table(varToTable); 
00584          st_free_gen(gen); 
00585          return 0; 
00586        }
00587     }
00588     }
00589   }
00590 
00591   
00592   /* compute numFanoutTables */
00593   Hrc_NodeForEachNameTable(hnode,i,table){
00594     Tbl_TableForEachInputVar(table,j,var){
00595       Var_VariableIncrementNumFanoutTables(var);
00596     }
00597   }
00598 
00599   /* acyclic check */
00600   visitTable = st_init_table(st_ptrcmp,st_ptrhash);
00601   status = _IoModelTestIsAcyclic(model,hnode,varToTable,outputVarToSubckt,visitTable);
00602   warningStatus = 0;
00603   if (status == 1){
00604   /* as a by-product of the acyclic check, visitTable now contains
00605   all the variables reachable from either PO, NS, or reset tables.
00606   We use this to detect all the variables not used in the hnode */
00607     Hrc_NodeForEachVariable(hnode,gen,varName,var){
00608       if (st_is_member(visitTable,(char *)var) == 0 && 
00609           st_is_member(inputVarToSubckt,(char *)var) == 0 &&
00610           Var_VariableTestIsPO(var) == 0 &&
00611           Var_VariableTestIsNS(var) == 0 &&
00612           Var_VariableTestIsPS(var) == 0 ){
00613         warningStatus = 1;
00614         if (isVerbose){
00615           /* the following is just a warning. We do not return a failure status */
00616           error_append("Warning: Variable ");
00617           error_append(Var_VariableReadName(var));
00618           error_append(" is not used in ");
00619           error_append(Hrc_ModelReadName(model));
00620           error_append(".\n");
00621         }
00622       }
00623     }
00624   }
00625   if (isVerbose == 0 && warningStatus == 1){
00626     error_append("Warning: Some variables are unused in model ");
00627     error_append(Hrc_ModelReadName(model));
00628     error_append(".\n");
00629   }
00630   st_free_table(varToTable);
00631   st_free_table(outputVarToSubckt);
00632   st_free_table(inputVarToSubckt);
00633   st_free_table(visitTable);
00634 
00635   return 1;
00636 }
00637 
00638 
00650 static boolean
00651 _IoModelTestIsAcyclic(
00652   Hrc_Model_t *model,
00653   Hrc_Node_t *hnode,
00654   st_table *varToTable,
00655   st_table *outputVarToSubckt,
00656   st_table *visitTable)
00657 {
00658   int i;
00659   Var_Variable_t *var;
00660   st_generator *gen;
00661   char *latchName;
00662   Hrc_Latch_t *latch;
00663 
00664   Hrc_NodeForEachFormalOutput(hnode,i,var){
00665     if (_IoModelTestIsAcyclicRecursive(model,hnode,var,varToTable,outputVarToSubckt,visitTable,0) == 0){
00666       _IoModelTestIsAcyclicError(model,var);
00667       return 0;
00668     }
00669   }
00670   Hrc_NodeForEachLatch(hnode,gen,latchName,latch){
00671     Tbl_Table_t *resetTable;
00672 
00673     resetTable = Hrc_LatchReadResetTable(latch);
00674     Tbl_TableForEachInputVar(resetTable,i,var){
00675       int status;
00676       if ((status = _IoModelTestIsAcyclicRecursive(model,hnode,
00677           var,varToTable,outputVarToSubckt,visitTable,1)) == 0){
00678         _IoModelTestIsAcyclicError(model,var);
00679         st_free_gen(gen);
00680         return 0;
00681       }
00682       /* found a path from a PS to a reset table */
00683       if (status == -1){
00684         error_append(latchName);
00685         error_append(" in model ");
00686         error_append(Hrc_ModelReadName(model));
00687         error_append(".\n");
00688         st_free_gen(gen);
00689         return 0;
00690       }
00691     } 
00692   }
00693   Hrc_NodeForEachLatch(hnode,gen,latchName,latch){
00694     if (_IoModelTestIsAcyclicRecursive(model,hnode,
00695         (var = Hrc_LatchReadInput(latch)),varToTable,outputVarToSubckt,visitTable,0) == 0){
00696       _IoModelTestIsAcyclicError(model,var);
00697       st_free_gen(gen);
00698       return 0;
00699     } 
00700   }
00701   return 1;
00702 }
00703 
00715 static void
00716 _IoModelTestIsAcyclicError(
00717   Hrc_Model_t *model,
00718   Var_Variable_t *var)
00719 {
00720   error_append("Warning: Model ");
00721   error_append(Hrc_ModelReadName(model));
00722   error_append(" may have a cyclic connection which involves variable ");
00723   error_append(Var_VariableReadName(var));
00724   error_append("\n");
00725 }
00726 
00738 static int
00739 _IoModelTestIsAcyclicRecursive(
00740   Hrc_Model_t *model,
00741   Hrc_Node_t *hnode,
00742   Var_Variable_t *var,
00743   st_table *varToTable,
00744   st_table *outputVarToSubckt,
00745   st_table *visitTable,
00746   boolean isResetLogic)
00747 {
00748   int val, i;
00749   Var_Variable_t *input;
00750   Tbl_Table_t *table;
00751   Hrc_Subckt_t *subckt;
00752 
00753   if (st_lookup_int(visitTable,(char *)var, &val) == 1){
00754     return (!val);
00755   }
00756   else{
00757     (void)st_insert(visitTable,(char *)var,(char *)1);
00758     
00759     if (Var_VariableTestIsPI(var) == 0 &&
00760            (isResetLogic || Var_VariableTestIsPS(var) == 0)){
00761       if (isResetLogic && (Var_VariableTestIsPS(var) == 1)){
00762         error_append("Warning: There is a path from latch output ");
00763         error_append(Var_VariableReadName(var));
00764         error_append(" to reset table ");
00765 
00766         /* the error message is to be continued in _IoModelTestIsAcyclic() */
00767         return -1;  
00768       }
00769       if (st_lookup(varToTable,(char *)var,&table) == 1){
00770         Tbl_TableForEachInputVar(table,i,input){
00771           int status;
00772           if ((status = _IoModelTestIsAcyclicRecursive(model,hnode,input,
00773                            varToTable,outputVarToSubckt,visitTable,isResetLogic)) == 0){
00774             return 0;
00775           }
00776           if (status == -1){
00777             return -1;
00778           }
00779         }
00780       }
00781       else {
00782         array_t *actualInputs;
00783         /* the return value of the following st_lookup should be 1 */
00784         (void)st_lookup(outputVarToSubckt,(char *)var,&subckt);
00785         actualInputs = Hrc_SubcktReadActualInputVars(subckt);
00786         assert (actualInputs != NIL(array_t));
00787         for (i=0; i < array_n(actualInputs); i++){
00788           int status;
00789           input = array_fetch(Var_Variable_t *,actualInputs,i);
00790           if ((status = _IoModelTestIsAcyclicRecursive(model,hnode,input,
00791                          varToTable,outputVarToSubckt,visitTable,0)) == 0){
00792             return 0;
00793           }
00794           if (status == -1){
00795             return -1;
00796           }
00797         }
00798       }
00799     }
00800     (void)st_insert(visitTable,(char *)var,(char *)0);
00801     return 1;
00802   }
00803 }
00804 
00805 
00806 
00807 
00808 
00809 
00810 
00811 
00812 
00813 
00814 
00815 
00816 
00817