VIS

src/rst/rstGroup.c

Go to the documentation of this file.
00001 
00032 #include <stdio.h>
00033 #include "rstInt.h"
00034 #include "cmd.h"
00035 #include "varInt.h"
00036 
00037 static char rcsid[] UNUSED = "$Id: rstGroup.c,v 1.9 2005/05/16 06:22:35 fabio Exp $";
00038 
00039 /*---------------------------------------------------------------------------*/
00040 /* Constant declarations                                                     */
00041 /*---------------------------------------------------------------------------*/
00042 
00043 /*
00044 #define RST_GROUP_DEBUG 1
00045 */
00046 
00047 /*---------------------------------------------------------------------------*/
00048 /* Structure declarations                                                    */
00049 /*---------------------------------------------------------------------------*/
00050 
00051 /*---------------------------------------------------------------------------*/
00052 /* Type declarations                                                         */
00053 /*---------------------------------------------------------------------------*/
00054 /*---------------------------------------------------------------------------*/
00055 /* Variable declarations                                                     */
00056 /*---------------------------------------------------------------------------*/
00057 
00058 /*---------------------------------------------------------------------------*/
00059 /* Macro declarations                                                        */
00060 /*---------------------------------------------------------------------------*/
00061 
00062 #define Rst_VarForEachVarInArray( \
00063   /* array_t* */          array,  \
00064   /* int, local */        i,      \
00065   /* Var_Variable_t* */   var     \
00066 )                                 \
00067 arrayForEachItem(Var_Variable_t*, array, i, var)
00068 
00071 /*---------------------------------------------------------------------------*/
00072 /* Static function prototypes                                                */
00073 /*---------------------------------------------------------------------------*/
00074 
00075 
00079 /*---------------------------------------------------------------------------*/
00080 /* Definition of exported functions                                          */
00081 /*---------------------------------------------------------------------------*/
00082 
00083 
00084 
00096 /*
00097   This was moved to VAR package by Yuji on 11/8 and renamed to
00098   Var_VariableResetNumFanoutTables()
00099   
00100   void
00101 Var_VariableResetNumFanout(
00102   Var_Variable_t* var)
00103 {
00104   var->numFanoutTables = 0;
00105 }
00106 */
00107 
00108 
00127 Tbl_Table_t*
00128 Tbl_TableDupAndSubstVars(
00129   Tbl_Table_t* Table,
00130   st_table* VartoVar)
00131 {
00132   int tblIndx, retVal;
00133   Var_Variable_t *var, *newVar;
00134   Tbl_Table_t* newTbl = Tbl_TableHardDup(Table);
00135   
00136   Tbl_TableForEachInputVar(newTbl, tblIndx, var) {
00137     retVal = st_lookup(VartoVar, (char*) var, &newVar);
00138     assert(retVal);
00139     Tbl_TableSubstituteVar(newTbl, var, newVar);
00140     Var_VariableIncrementNumFanoutTables(newVar);
00141   }
00142   Tbl_TableForEachOutputVar(newTbl, tblIndx, var) {
00143     retVal = st_lookup(VartoVar, (char*) var,&newVar);
00144     assert(retVal);
00145     Tbl_TableSubstituteVar(newTbl, var, newVar);
00146   }
00147   return newTbl;
00148 }
00149 
00166 array_t*
00167 Rst_VartoVarLookup(
00168   array_t* VarArray,
00169   st_table* VartoVarOne,
00170   st_table* VartoVarTwo)
00171 {
00172   int i, retVal;
00173   Var_Variable_t *var, *newVar, *tmpVar;
00174   array_t* newVarArray = array_alloc(Var_Variable_t*, array_n(VarArray));
00175 
00176   Rst_VarForEachVarInArray(VarArray, i, var) {
00177     retVal = st_lookup(VartoVarOne, (char*) var, &newVar);
00178     assert(retVal);
00179     if (VartoVarTwo) {
00180       tmpVar = newVar;
00181       retVal = st_lookup(VartoVarTwo, (char*) tmpVar, &newVar);
00182     }
00183     assert(retVal);
00184     array_insert(Var_Variable_t*, newVarArray, i, newVar);
00185   }
00186   return newVarArray;
00187 }
00188 
00207 array_t*
00208 Rst_GetNamesUntilNextOption(
00209   array_t* nameArray,
00210   int argc,
00211   char **argv)
00212 {
00213   char* name;
00214 
00215   while ((util_optind < argc) && (*argv[util_optind] != '-')) {
00216     name = util_strcat3(argv[util_optind], "", "");
00217     array_insert_last(char*, nameArray, name);
00218     util_optind++;
00219   }
00220   return nameArray;
00221 }
00222 
00235 array_t*
00236 Rst_LoadNameArrayFromFile(
00237   array_t* nameArray,
00238   FILE* fp)
00239 {
00240   char* name;
00241   char buffer[1024];
00242 
00243   while (fscanf(fp, "%s", buffer) != EOF) {
00244     name = util_strcat3(buffer, "", "");
00245     array_insert_last(char*, nameArray, name);
00246   }
00247   return nameArray;
00248 }
00249 
00273 Rst_Group_t*
00274 RstGroupComponents(
00275   Hrc_Model_t* CurModel,
00276   char* NewName,
00277   array_t* VarGroup,
00278   array_t* Subcircuits)
00279 {
00280   int i, j, tblIndx;
00281   long inGroup;  
00282   char* latchName, *subcktName;
00283   Hrc_Latch_t* latch;
00284   Hrc_Subckt_t* subckt;
00285   Hrc_Node_t* curMaster;
00286   st_generator* sgen;
00287   Tbl_Table_t* tbl;
00288   Var_Variable_t* var = NIL(Var_Variable_t);
00289   array_t* subOutputs;
00290   Rst_Group_t* group = RstGroupAlloc(NewName);
00291 
00292   curMaster = Hrc_ModelReadMasterNode(CurModel);
00293 
00294   /* Make sure there is something to group */
00295   i=0;
00296   if (VarGroup) {
00297     i += array_n(VarGroup);
00298   }
00299   if (Subcircuits) {
00300     i += array_n(Subcircuits);
00301   }
00302   if (i == 0) {
00303     return 0;
00304   }
00305 
00306   /* Determine Input/Output Formal list from implied partitioning */
00307 
00308   if (VarGroup) {
00309     /* Store group variables (ie outputs of tables/latches) in hash
00310        table */
00311     Rst_VarForEachVarInArray(VarGroup, i, var) {
00312       if ((var) && (! Var_VariableTestIsPI(var))) {
00313         st_insert(group->Vars, (char*) var, (char*) (long) 1);
00314       } else if ((var) && (Var_VariableTestIsPI(var))) {
00315         (void) fprintf(vis_stderr,
00316                        "Warning: can't group a PI: %s\n",
00317                        Var_VariableReadName(var));
00318       }
00319     }
00320   }
00321 
00322   if (Subcircuits) {
00323     /* Store Subckt in group Subcircuits hashtable.
00324        Store output vars of all group Subckts in var hash table */
00325     for (i = 0; i < array_n(Subcircuits); i++) {
00326       subckt = array_fetch(Hrc_Subckt_t*, Subcircuits, i);
00327       st_insert(group->Subcircuits, (char*) subckt, (char*) (long) 1);
00328       Rst_VarForEachVarInArray(Hrc_SubcktReadActualOutputVars(subckt),
00329                                j, var) {
00330         if (! st_lookup(group->Vars, (char*) var, &inGroup)) {
00331           st_insert(group->Vars, (char*) var, (char*) (long) 1);
00332         }
00333       }
00334     }
00335   }
00336 
00337   /* Table and Latch outputs which are group vars become members of the group
00338    */
00339   
00340   Hrc_NodeForEachLatch(curMaster, sgen, latchName, latch) {
00341     if (st_lookup(group->Vars, (char*) Hrc_LatchReadOutput(latch), &inGroup)) {
00342       st_insert(group->Latches, (char*) latch, (char*) (long) 1);
00343     }
00344   }
00345   
00346   Hrc_NodeForEachNameTable(curMaster, tblIndx, tbl) {
00347     Tbl_TableForEachOutputVar(tbl, j, var) {
00348       inGroup = 0;
00349       if (st_lookup(group->Vars, (char*) var, &inGroup)) {
00350         st_insert(group->Tables, (char*) tbl, (char*) (long) 1);
00351         break;
00352       }
00353     }
00354     /* FIXME: Table Splitting here */
00355     
00356     if ((inGroup)  && (Tbl_TableReadNumOutputs(tbl) > 1)) {
00357       (void) fprintf(vis_stderr,
00358                      "WARNING: multi-output table %s moved to group %s\n",
00359                      Var_VariableReadName(var), group->name);
00360     }
00361   }
00362   /* If outputs of a subckt are in a group, the subckt moves
00363      into the group */
00364   
00365   Hrc_ModelForEachSubckt(CurModel, sgen, subcktName, subckt) {
00366     Var_Variable_t* outVar = NIL(Var_Variable_t); /* initialize to pacify */
00367     if (! st_lookup(group->Subcircuits, (char*) subckt, &inGroup)) {
00368       subOutputs = Hrc_SubcktReadActualOutputVars(subckt);
00369       Rst_VarForEachVarInArray(subOutputs, i, outVar) {
00370         if (st_lookup(group->Vars, (char*) outVar, &inGroup)) {
00371           break;
00372         }
00373       }
00374       if (i < array_n(subOutputs)) {
00375         Rst_VarForEachVarInArray(subOutputs, j, var) {
00376           if (! st_lookup(group->Vars, (char*) var, &inGroup)) {
00377             st_insert(group->Vars, (char*) var, (char*) (long) 1);
00378           }
00379         }
00380         st_insert(group->Subcircuits, (char*) subckt, (char*) (long) 1);
00381         (void) fprintf(vis_stderr,
00382                        "Warning: instance %s becomes member of group %s",
00383                        subcktName, group->name);
00384         (void) fprintf(vis_stderr, " because of output variable %s\n",
00385                        Var_VariableReadName(outVar));
00386       }
00387     }
00388   }
00389   
00390   /* Group Outputs: Scan parent outputs for group vars. Scan non-group
00391      component (Subcircuits/Latches/Tables) inputs for group vars */
00392 
00393   Hrc_NodeForEachFormalOutput(curMaster, i, var) {
00394     if ((st_lookup(group->Vars, (char*) var, &inGroup)) &&
00395         (! st_lookup(group->Outputs, (char*) var, &inGroup))) {
00396       st_insert(group->Outputs, (char*) var, (char*) (long) 1);
00397     }
00398   }
00399 
00400   Hrc_ModelForEachSubckt(CurModel, sgen, subcktName, subckt) {
00401     if (! st_lookup(group->Subcircuits, (char*) subckt, &inGroup)) {
00402       Rst_VarForEachVarInArray(Hrc_SubcktReadActualInputVars(subckt), i, var) {
00403         if ((st_lookup(group->Vars, (char*) var, &inGroup)) &&
00404             (! st_lookup(group->Outputs, (char*) var, &inGroup))) {
00405             st_insert(group->Outputs, (char*) var, (char*) (long) 1);
00406         }
00407       }
00408     }
00409   }
00410   Hrc_NodeForEachLatch(curMaster, sgen, latchName, latch) {
00411     if (! st_lookup(group->Latches, (char*) latch, &inGroup)) {
00412       var = Hrc_LatchReadInput(latch);
00413       if ((st_lookup(group->Vars, (char*) var, &inGroup)) &&
00414           (! st_lookup(group->Outputs, (char*) var, &inGroup))) {
00415         st_insert(group->Outputs, (char*) var, (char*) (long) 1);
00416       }
00417     }
00418   }
00419   Hrc_NodeForEachNameTable(curMaster, i, tbl) {
00420     if (! st_lookup(group->Tables, (char*) tbl, &inGroup)) {
00421       Tbl_TableForEachInputVar(tbl, j, var) {
00422         if ((st_lookup(group->Vars, (char*) var, &inGroup)) &&
00423             (! st_lookup(group->Outputs, (char*) var, &inGroup))) {
00424           st_insert(group->Outputs, (char*) var, (char*) (long) 1);
00425         }
00426       }
00427     }
00428   }
00429   
00430   /* Group Inputs:  Scan group subcomponent inputs for non-group vars */
00431 
00432   /* Formal inputs are never vars of a group.  Thus, they are always
00433      non-group vars when are inputs to group subcomponents, and are
00434      caught by the code below*/
00435   
00436   Hrc_ModelForEachSubckt(CurModel, sgen, subcktName, subckt) {
00437     if (st_lookup(group->Subcircuits, (char*) subckt, &inGroup)) {
00438       Rst_VarForEachVarInArray(Hrc_SubcktReadActualInputVars(subckt), i, var) {
00439         if ((! st_lookup(group->Vars, (char*) var, &inGroup)) &&
00440             (! st_lookup(group->Inputs, (char*) var, &inGroup))) {
00441           st_insert(group->Inputs, (char*) var, (char*) (long) 1);
00442         }
00443       }
00444     }
00445   }
00446   Hrc_NodeForEachLatch(curMaster, sgen, latchName, latch) {
00447     if (st_lookup(group->Latches, (char*) latch, &inGroup)) {
00448       var = Hrc_LatchReadInput(latch);
00449       if ((! st_lookup(group->Vars, (char*) var, &inGroup)) &&
00450           (! st_lookup(group->Inputs, (char*) var, &inGroup))) {
00451         st_insert(group->Inputs, (char*) var, (char*) (long) 1);
00452       }
00453       /* Reset table here */
00454       tbl = Hrc_LatchReadResetTable(latch);
00455       Tbl_TableForEachInputVar(tbl, j, var) {
00456         if (! st_lookup(group->Vars, (char*) var, &inGroup))
00457           st_insert(group->Vars, (char*) var, (char*) (long) 1);
00458       }
00459     }
00460   }
00461   Hrc_NodeForEachNameTable(curMaster, tblIndx, tbl) {
00462     if (st_lookup(group->Tables, (char*) tbl, &inGroup)) {
00463       Tbl_TableForEachInputVar(tbl, j, var) {
00464         if ((! st_lookup(group->Vars, (char*) var, &inGroup)) &&
00465             (! st_lookup(group->Inputs, (char*) var, &inGroup))) {
00466           st_insert(group->Inputs, (char*) var, (char*) (long) 1);
00467         }
00468       }
00469     }
00470   }
00471 
00472   return group;
00473 }
00474 
00491 Hrc_Model_t*
00492 Rst_GroupRestructureModel(
00493   Hrc_Manager_t* Hmgr,
00494   Hrc_Model_t* ParentModel,
00495   array_t* GroupArray)
00496 {
00497   int i, j;
00498   char *newModelName;
00499   st_generator *sgen;
00500   Var_Variable_t *var, *newVar;
00501   Hrc_Model_t *newModel, *newParentModel;
00502   Hrc_Node_t *newMaster;
00503   Rst_Group_t *group, *parentGroup;
00504   st_table *varForwPtr;
00505   array_t *newModelArray, *newMasterArray, *newNodeArray;
00506 
00507   for (i = 0; i < array_n(GroupArray); i++) {
00508     group = array_fetch(Rst_Group_t*, GroupArray, i);
00509 #ifdef RST_GROUP_DEBUG
00510     RstGroupPrint(group);
00511 #endif
00512   }
00513   /* Check group components for disjointness */
00514 
00515   if (RstGroupDisjointCheck(GroupArray))
00516     return 0;
00517 
00518   /* Construct a level of hierarchy for each group */
00519 
00520   newModelArray = array_alloc(Hrc_Model_t*, array_n(GroupArray));
00521   newMasterArray = array_alloc(Hrc_Node_t*, array_n(GroupArray));
00522   newNodeArray = array_alloc(Hrc_Node_t*, array_n(GroupArray));
00523   
00524   for (i = 0; i < array_n(GroupArray); i++) {
00525     group = array_fetch(Rst_Group_t*, GroupArray, i);
00526     newModel = RstGroupBuildModel(Hmgr, group);
00527     if (! newModel) {
00528       return 0;
00529     }
00530     newMaster = Hrc_ModelReadMasterNode(newModel);
00531     array_insert(Hrc_Model_t*, newModelArray, i, newModel);
00532     array_insert(Hrc_Node_t*, newMasterArray, i, newMaster);
00533   }
00534 
00535   /* Build the new parent hierarchy */
00536   
00537   newModelName = RstGroupNewParentName(Hrc_ModelReadName(ParentModel));
00538   parentGroup = RstCreateParentGroup(Hmgr, ParentModel, newModelName,
00539                                       GroupArray);
00540   FREE(newModelName);
00541   if (! parentGroup) {
00542     return 0;
00543   }
00544 #ifdef RST_GROUP_DEBUG
00545   RstGroupPrint(parentGroup);
00546 #endif
00547   newParentModel = RstGroupBuildModel(Hmgr, parentGroup);
00548 
00549   /* Computing actuals:  Group IO vars USED to be in the old parent.
00550      1) lookup what the new IO vars used to be in the old parent
00551      2) In the old parent, find the correspond new parent vars
00552      */
00553   
00554   /* Build Table: Parent to New Parent Vars, by reversing back pointers */
00555 
00556   varForwPtr = st_init_table(st_ptrcmp, st_ptrhash);
00557   st_foreach_item(parentGroup->VarBackPtr, sgen, &newVar, &var) {
00558     st_insert(varForwPtr, (char*) var, (char*) newVar);
00559   }
00560 
00561   /* Free parent group now */
00562   RstGroupFree(parentGroup); parentGroup = 0;
00563   
00564   /* Instantiate groups as subckts */
00565 
00566   for (i = 0; i < array_n(GroupArray); i++) {
00567     array_t* actualInputArray, *actualOutputArray;
00568 
00569     group = array_fetch(Rst_Group_t*, GroupArray, i);
00570     newModel = array_fetch(Hrc_Model_t*, newModelArray, i);
00571     newMaster = Hrc_ModelReadMasterNode(newModel);
00572 
00573     actualInputArray =
00574       Rst_VartoVarLookup(Hrc_NodeReadFormalInputs(newMaster),
00575                          group->VarBackPtr, varForwPtr);
00576     actualOutputArray =
00577       Rst_VartoVarLookup(Hrc_NodeReadFormalOutputs(newMaster),
00578                          group->VarBackPtr, varForwPtr);
00579 
00580     Hrc_ModelAddSubckt(newParentModel, newModel, group->name, 
00581                        actualInputArray, actualOutputArray);
00582     Rst_VarForEachVarInArray(actualInputArray, j, var) {
00583       Var_VariableSetSI(var);
00584     }
00585     Rst_VarForEachVarInArray(actualOutputArray, j, var) {
00586       Var_VariableSetSO(var);
00587     }
00588   }
00589   array_free(newModelArray);
00590   array_free(newMasterArray);
00591   array_free(newNodeArray);
00592 
00593   st_free_table(varForwPtr);
00594   return newParentModel;
00595 }
00596 
00613 Hrc_Node_t*
00614 Rst_GroupRestructureNode(
00615   Hrc_Manager_t* Hmgr,
00616   Hrc_Node_t* CurNode,
00617   array_t* GroupArray)
00618 {
00619   int retVal;
00620 #ifdef RST_GROUP_DEBUG
00621   st_generator* sgen;
00622   char* childName;
00623   Hrc_Node_t *child;
00624 #endif  
00625   Hrc_Model_t *newParentModel;
00626   Hrc_Node_t *newNode = 0;
00627   Hrc_Model_t* CurModel=
00628     Hrc_ManagerFindModelByName(Hmgr, Hrc_NodeReadModelName(CurNode));
00629 
00630   newParentModel = Rst_GroupRestructureModel(Hmgr, CurModel, GroupArray);
00631   if (newParentModel) {
00632 
00633     newNode = Hrc_ModelCreateHierarchy(Hmgr, newParentModel,
00634                                        Hrc_NodeReadInstanceName(CurNode));
00635 
00636 #ifdef RST_GROUP_DEBUG
00637     (void) fprintf(vis_stderr, "Checking New Node\n");
00638     assert(Hrc_NodeCheckVariableConsistency(newNode));
00639     (void) fprintf(vis_stderr, "Checking Subcircuits\n");
00640     Hrc_NodeForEachChild(newNode, sgen, childName, child) {
00641       assert(Hrc_NodeCheckVariableConsistency(child));
00642     }
00643 #endif
00644   
00645     retVal = Hrc_TreeReplace(CurNode, newNode);
00646     assert(retVal);
00647     Hrc_ManagerSetCurrentNode(Hmgr, newNode);
00648   }
00649   return newNode;
00650 }
00651 
00664 Hrc_Model_t*
00665 Rst_GroupGroupCombLogic(
00666   Hrc_Manager_t* Hmgr,
00667   Hrc_Model_t* CurModel)
00668 {
00669   long inGroup;
00670   int tblIndx, varIndx;
00671   Var_Variable_t *var;
00672   Tbl_Table_t* tbl;
00673   array_t* varArray = array_alloc(Var_Variable_t*, 0);
00674   Rst_Group_t *group;
00675   st_table *tableOutputs = st_init_table(st_ptrcmp, st_ptrhash);
00676   Hrc_Node_t *curMaster;
00677   Hrc_Model_t* newModel;
00678 
00679   /* Perhaps this is better done with the NameTables so that we drop
00680      subckts from inclusion */
00681 
00682   curMaster = Hrc_ModelReadMasterNode(CurModel);
00683 
00684   Hrc_NodeForEachNameTable(curMaster, tblIndx, tbl) {
00685     Tbl_TableForEachOutputVar(tbl, varIndx, var) {
00686       if (! st_lookup(tableOutputs, (char*) var, &inGroup)) {
00687         st_insert(tableOutputs, (char*) var, (char*) (long) 1);
00688         array_insert_last(Var_Variable_t*, varArray, var);
00689       }
00690     }
00691   }
00692   st_free_table(tableOutputs);
00693   group = RstGroupComponents(CurModel,
00694                               util_strcat3(Hrc_ModelReadName(CurModel),
00695                                            "_comb", ""),
00696                               varArray, NULL);
00697   array_free(varArray);
00698 
00699   if (group) {
00700     array_t *groupArray = array_alloc(Rst_Group_t*, 1);
00701     array_insert_last(Rst_Group_t*, groupArray, group);
00702     newModel = Rst_GroupRestructureModel(Hmgr, CurModel, groupArray);
00703     array_free(groupArray);
00704     return newModel;
00705   }
00706   return 0;
00707 }
00708 
00720 Hrc_Model_t*
00721 Rst_GroupGroupLatches(
00722   Hrc_Manager_t* Hmgr,
00723   Hrc_Model_t* CurModel)
00724 {
00725   char *latchName;
00726   st_generator *sgen;
00727   Hrc_Latch_t *latch;
00728   array_t* varArray = array_alloc(Var_Variable_t*, 0);
00729   Rst_Group_t *group;
00730   Hrc_Node_t* curMaster = Hrc_ModelReadMasterNode(CurModel);
00731   Hrc_Model_t* newModel;
00732 
00733   Hrc_NodeForEachLatch(curMaster, sgen, latchName, latch) {
00734     array_insert_last(Var_Variable_t*, varArray, Hrc_LatchReadOutput(latch));
00735   }
00736   
00737   group = RstGroupComponents(CurModel,
00738                               util_strcat3(Hrc_ModelReadName(CurModel),
00739                                            "_latch", ""),
00740                               varArray, NULL);
00741   array_free(varArray);
00742 
00743   if (group) {
00744     array_t *groupArray = array_alloc(Rst_Group_t*, 1);
00745     array_insert_last(Rst_Group_t*, groupArray, group);
00746     newModel = Rst_GroupRestructureModel(Hmgr, CurModel, groupArray);
00747     array_free(groupArray);
00748     return newModel;
00749   }
00750   return 0;
00751 }
00752 
00827 int
00828 Rst_CommandGroupComponents(
00829   Hrc_Manager_t** Hmgr,
00830   int  argc,
00831   char ** argv)
00832 {
00833   enum { SUBCKT_GROUP, VAR_GROUP } readType = SUBCKT_GROUP;
00834   int c, i, retVal, tblIndx;
00835   st_generator *sgen;
00836   Rst_Group_t* group;
00837   Var_Variable_t* var;
00838   Hrc_Subckt_t* child;
00839   char *fileName, *varName, *childName, *latchName;
00840   char* groupName = 0;
00841   array_t *vars = 0, *children = 0;
00842   Hrc_Latch_t* latch;
00843   Tbl_Table_t* tbl;
00844   array_t* nameArray = 0;
00845   array_t* groupArray = array_alloc(Rst_Group_t*, 1);
00846   Hrc_Node_t* curNode = Hrc_ManagerReadCurrentNode(*Hmgr);
00847   Hrc_Node_t* curMaster;
00848   FILE* fp;
00849   Hrc_Model_t* CurModel;
00850   
00851   if (! curNode) {
00852     /* No node has been read in. The only sane thing we
00853        support is the -h option */
00854     array_free(groupArray); groupArray = 0;
00855     util_getopt_reset();
00856     if ((c = util_getopt(argc,argv,"h")) !=  EOF) {
00857       goto usage;
00858     }
00859     (void) fprintf(vis_stderr, "ERROR: no current Node\n");
00860     return 1;
00861   }
00862 
00863   CurModel=
00864       Hrc_ManagerFindModelByName(Hrc_NodeReadManager(curNode),
00865                                  Hrc_NodeReadModelName(curNode));
00866   curMaster = Hrc_ModelReadMasterNode(CurModel);
00867 
00868   /* This command processing loop is conceptually simple, but almost
00869     'goto' like and needs explanation.  The command line is a sequence
00870     of groups between which are specified component names to group.
00871 
00872     A group is started with a Naming operation '-n'. We get a list of
00873     component names to group either from the command line or from a
00874     file.  Names can be anywhere on the command line (except between
00875     -n/-f and their argument).  The names are interpreted as Variables
00876     or Children depending on the last -v or -c flag.  Children is the
00877     default setting on entry.
00878 
00879     After every option, we can read more names off command line, so we
00880     drop into this mode after completing a -n <name> or -f <file>
00881     operation.  This means we always drop into the outer 'default'.
00882 
00883      The goal is to collect a set of Variable and Child names for each
00884      Group Name specified.  */
00885   
00886   util_getopt_reset();
00887   while ((c = util_getopt(argc, argv, "n:f:cvtlh")) != EOF) {
00888     switch(c) {
00889         case 'n':               /* expects a Name arg */
00890         case 'f':               /* expects a filename arg */
00891           switch(c) {
00892               case 'n':         /* Name a new group */
00893                 if (groupName != NULL) {
00894                   group = RstGroupComponents(CurModel, groupName,
00895                                               vars, children);
00896                   array_free(vars); vars = 0;
00897                   array_free(children); children = 0;
00898                   FREE(groupName);
00899                   if (group) {
00900                     array_insert_last(Rst_Group_t*, groupArray, group);
00901                   } else {
00902                     (void) fprintf(vis_stderr,
00903                                    "Warning: Incomplete group %s -- ignored\n",
00904                                    groupName);
00905                     RstGroupFree(group); group = 0;
00906                   }
00907                 }
00908                 vars = array_alloc(Var_Variable_t*, 0);
00909                 children = array_alloc(Hrc_Subckt_t*, 0);
00910                 groupName = util_strcat3(argv[util_optind -1], "","");
00911                 break;
00912               case 'f':         /* Read component names from file */
00913                 fileName = argv[util_optind - 1];
00914                 fp = Cmd_FileOpen(util_optarg, "r", &fileName, 1);
00915                 if (fp == NIL(FILE)) {
00916                   (void) fprintf(vis_stderr,
00917                                  "Could not open file %s\n", fileName);
00918                   return 1;
00919                 }
00920                 nameArray = array_alloc(char*, 0);
00921                 Rst_LoadNameArrayFromFile(nameArray, fp);
00922                 fclose(fp);
00923                 break;
00924           }
00925           /* WE ALWAYS DROP IN HERE ON EVERY FLAG */
00926         default:
00927           if (! groupName && (c != 'h')) {
00928             (void) fprintf(vis_stderr, "ERROR: Group not defined yet\n");
00929             goto usage;
00930           }
00931           if (! nameArray) nameArray = array_alloc(char*, 0);
00932           switch(c) {
00933               case 'n':
00934               case 'f':
00935                 break;
00936               case 'c': readType = SUBCKT_GROUP; break;
00937               case 'v': readType = VAR_GROUP; break;
00938               case 'l':
00939                 /* Put latch ouput vars into group*/
00940                 Hrc_NodeForEachLatch(curMaster, sgen, latchName, latch) {
00941                   var = Hrc_LatchReadOutput(latch);
00942                   array_insert_last(Var_Variable_t*, vars, var);
00943                 }
00944                 break;
00945               case 't':
00946                 /* Put table ouput vars into group*/
00947                 Hrc_NodeForEachNameTable(curMaster, tblIndx, tbl) {
00948                   Tbl_TableForEachOutputVar(tbl, i, var) {
00949                       array_insert_last(Var_Variable_t*, vars, var);
00950                   }
00951                 }
00952                 break;
00953               default: goto usage;
00954           }
00955           /* Grab any more names off the command line, appending if
00956              possible to nameArray */
00957           
00958           Rst_GetNamesUntilNextOption(nameArray, argc, argv);
00959 
00960           /* We store names read as either variable names or child names */
00961           
00962           switch(readType) {
00963               case VAR_GROUP:
00964                 for (i=0; i < array_n(nameArray); i++) {
00965                   varName = array_fetch(char*, nameArray, i);
00966                   var = Hrc_NodeFindVariableByName(curMaster, varName);
00967                   if (var) {
00968                     array_insert_last(Var_Variable_t*, vars, var);
00969                   } else {
00970                     (void) fprintf(vis_stderr, "Could not find variable %s\n",
00971                                    varName);
00972                   }
00973                 }
00974                 break;
00975               case SUBCKT_GROUP:
00976                 for (i=0; i < array_n(nameArray); i++) {
00977                   childName = array_fetch(char*, nameArray, i);
00978                   retVal = st_lookup(Hrc_ModelReadSubcktTable(CurModel),
00979                                      childName, &child);
00980                   if (retVal) {
00981                     array_insert_last(Hrc_Subckt_t*, children, child);
00982                   } else {
00983                     (void) fprintf(vis_stderr, "Could not find instance %s\n",
00984                                    childName);
00985                   }
00986                 }
00987                 break;
00988               default:          /* Unreached */
00989                 break;
00990           }
00991           break;
00992     }
00993     for (i=0; i < array_n(nameArray); i++) {
00994       varName = array_fetch(char*, nameArray, i);
00995       FREE(varName);
00996     }
00997     array_free(nameArray); nameArray = 0;
00998   }
00999   if (groupName) {
01000     group = RstGroupComponents(CurModel, groupName, vars, children);
01001     if (group) 
01002       array_insert_last(Rst_Group_t*, groupArray, group);
01003     else
01004       (void) fprintf(vis_stderr, "Incomplete group %s\n", groupName);
01005     array_free(vars); vars = 0;
01006     array_free(children); children = 0;
01007     FREE(groupName);
01008   }
01009 
01010   if (array_n(groupArray) > 0) {
01011     Rst_GroupRestructureNode(*Hmgr, curNode, groupArray);
01012     for (i=0; i < array_n(groupArray); i++) {
01013       group = array_fetch(Rst_Group_t*, groupArray, i);
01014       RstGroupFree(group);
01015     }
01016     array_free(groupArray); groupArray = 0;
01017   } else {
01018     (void) fprintf(vis_stderr, "ERROR: no groups defined\n");
01019     array_free(groupArray);
01020     return 1;
01021   }
01022   return 0;                     /* normal exit */
01023 
01024 usage:
01025    if (vars) array_free(vars); vars = 0;
01026    if (children) array_free(children); children = 0;
01027   FREE(groupName); groupName = 0;
01028   array_free(nameArray); nameArray = 0;
01029   array_free(groupArray);
01030   (void) fprintf(vis_stderr, "usage: decompose_child -n <groupname>");
01031   (void) fprintf(vis_stderr, " [-f <filename>] [-c] [-v] [<names>] [-t] [-l] [-h] \n");
01032   (void) fprintf(vis_stderr, "   -n\t\tName of new child group \n");
01033   (void) fprintf(vis_stderr, "   -f\t\tLoad names from file \n");
01034   (void) fprintf(vis_stderr, "   -c\t\tGroup by children toggle (default)\n");
01035   (void) fprintf(vis_stderr, "   -v\t\tGroup by variable toggle \n");
01036   (void) fprintf(vis_stderr, "   -l\t\tGroup latches\n");
01037   (void) fprintf(vis_stderr, "   -t\t\tGroup combinational logic tables \n");
01038   (void) fprintf(vis_stderr, "   -h\t\thelp \n");
01039   return 1;                     /* error exit */
01040 
01041 }
01042 
01043 /*---------------------------------------------------------------------------*/
01044 /* Definition of internal functions                                          */
01045 /*---------------------------------------------------------------------------*/
01046 
01047 
01048 /*---------------------------------------------------------------------------*/
01049 /* Definition of static functions                                            */
01050 /*---------------------------------------------------------------------------*/
01051 
01066 Rst_Group_t*
01067 RstGroupAlloc(char* Name)
01068 {
01069   Rst_Group_t* group = ALLOC(Rst_Group_t, 1);
01070 
01071   group->Vars = st_init_table(st_ptrcmp, st_ptrhash);
01072   group->Latches = st_init_table(st_ptrcmp, st_ptrhash);
01073   group->Tables = st_init_table(st_ptrcmp, st_ptrhash);
01074   group->Subcircuits = st_init_table(st_ptrcmp, st_ptrhash);
01075   group->Inputs = st_init_table(st_ptrcmp, st_ptrhash);
01076   group->Outputs = st_init_table(st_ptrcmp, st_ptrhash);
01077   group->VarBackPtr = st_init_table(st_ptrcmp, st_ptrhash);
01078   group->name = ALLOC(char, strlen(Name) + 1);
01079   strcpy(group->name, Name);
01080   return group;
01081 }
01082 
01095 void
01096 RstGroupFree(Rst_Group_t* Group)
01097 {
01098   st_free_table(Group->Vars);
01099   st_free_table(Group->Latches);
01100   st_free_table(Group->Tables);
01101   st_free_table(Group->Subcircuits);
01102   st_free_table(Group->Inputs);
01103   st_free_table(Group->Outputs);
01104   st_free_table(Group->VarBackPtr);
01105   FREE(Group->name);
01106   FREE(Group);                  /* Watch for dangling references  */
01107 }
01108 
01120 char*
01121 RstGroupNewParentName(
01122   char* Name)
01123 {
01124   char* newName = util_strcat3(Name, "_N", "");
01125   return newName;
01126 }
01127 
01139 void
01140 RstGroupPrint(
01141   Rst_Group_t* group)
01142 {
01143   st_generator* sgen;
01144   Var_Variable_t* var;
01145   Hrc_Subckt_t* subckt;
01146   Hrc_Latch_t* latch;
01147   
01148   printf("GROUP: %s\n\tInputs:\t", group->name);
01149   st_foreach_item(group->Inputs, sgen, &var, NIL(char *)) {
01150     printf("%s ", Var_VariableReadName(var));
01151   }
01152   printf("\n\tOutputs:\t");
01153   st_foreach_item(group->Outputs, sgen, &var, NIL(char *)) {
01154     printf("%s ", Var_VariableReadName(var));
01155   }
01156   printf("\n\tSubcircuits:\t");
01157   st_foreach_item(group->Subcircuits, sgen, &subckt, NIL(char *)) {
01158     printf("%s ", Hrc_SubcktReadInstanceName(subckt));
01159   }
01160   printf("\n\tLatches:\t");
01161   st_foreach_item(group->Latches, sgen, &latch, NIL(char *)) {
01162     printf("%s ", Var_VariableReadName(Hrc_LatchReadOutput(latch)));
01163   }
01164   printf("\n\tVars:\t");
01165   st_foreach_item(group->Vars, sgen, &var, NIL(char *)) {
01166     printf("%s ", Var_VariableReadName(var));
01167   }
01168   printf("\n");
01169 }
01170 
01183 int
01184 RstGroupDisjointCheck(
01185   array_t* GroupArray)
01186 {
01187   int i, j, retVal;
01188   st_generator *sgen;
01189   Hrc_Subckt_t* subckt;
01190   Rst_Group_t* group1, *group2;
01191   Hrc_Latch_t* latch;
01192   Tbl_Table_t* tbl;
01193   Var_Variable_t* var;
01194 
01195   for (i = 0; i < array_n(GroupArray); i++) {
01196       group1 = array_fetch(Rst_Group_t*, GroupArray, i);
01197     for (j = i + 1; j < array_n(GroupArray); j++) {
01198       group2 = array_fetch(Rst_Group_t*, GroupArray, j);
01199       
01200       st_foreach_item(group1->Subcircuits, sgen, &subckt, NULL) {
01201         retVal = st_lookup(group2->Subcircuits, (char*) subckt, NIL(char *));
01202         if (retVal) {
01203           (void) fprintf(vis_stderr,
01204                          "ERROR: component %s assigned to groups %s and %s\n",
01205                          Hrc_SubcktReadInstanceName(subckt),
01206                          group1->name, group2->name);
01207           return 1;
01208         }
01209       }
01210       st_foreach_item(group1->Vars, sgen, &var, NULL) {
01211         retVal = st_lookup(group2->Vars, (char*) var, NIL(char *));
01212         if (retVal) {
01213           (void) fprintf(vis_stderr,
01214                          "ERROR: var %s assigned to groups %s and %s\n",
01215                          Var_VariableReadName(var),
01216                          group1->name, group2->name);
01217           return 1;
01218         }
01219       }
01220       st_foreach_item(group1->Tables, sgen, &tbl, NULL) {
01221         retVal = st_lookup(group2->Tables, (char*) tbl, NIL(char *));
01222         if (retVal) {
01223           (void) fprintf(vis_stderr,
01224                          "ERROR: table assigned to groups %s and %s\n",
01225                          group1->name, group2->name);
01226           return 1;
01227         }
01228       }
01229       st_foreach_item(group1->Latches, sgen, &latch, NULL) {
01230         retVal = st_lookup(group2->Latches, (char*) latch, NIL(char *));
01231         if (retVal) {
01232           (void) fprintf(vis_stderr,
01233                          "ERROR: latch %s assigned to groups %s and %s\n",
01234                          Var_VariableReadName(Hrc_LatchReadOutput(latch)),
01235                          group1->name, group2->name);
01236           return 1;
01237         }
01238       }
01239     }
01240   }
01241   return 0;
01242 } 
01243 
01259 Rst_Group_t*
01260 RstCreateParentGroup(
01261   Hrc_Manager_t* Hmgr,
01262   Hrc_Model_t* ParentModel,
01263   char* NewModelName,
01264   array_t* GroupArray)
01265 {
01266   int i, j, tblIndx, varIndx;
01267   long inGroup;  
01268   char *latchName, *subcktName, *varName;
01269   st_generator* sgen;
01270   Var_Variable_t* var;
01271   Tbl_Table_t* tbl;
01272   Hrc_Latch_t* latch;
01273   Hrc_Subckt_t *subckt;
01274   Hrc_Node_t *parentMaster;
01275   Rst_Group_t *group, *parentGroup;
01276   array_t* subOutputs;
01277 
01278   /* Build a parent group */
01279 
01280   parentGroup = RstGroupAlloc(NewModelName);
01281   parentMaster = Hrc_ModelReadMasterNode(ParentModel);
01282 
01283   /* IO of latches of parent group are parent group vars */
01284   
01285   Hrc_NodeForEachLatch(parentMaster, sgen, latchName, latch) {
01286     for (i = 0; i < array_n(GroupArray); i++) {
01287       group = array_fetch(Rst_Group_t*, GroupArray, i);
01288       if (st_lookup(group->Latches, (char*) latch, &inGroup)) {
01289         break;
01290       }
01291     }
01292     if (i >= array_n(GroupArray)) {
01293       st_insert(parentGroup->Latches, (char*) latch, (char*) (long) 1);
01294       var = Hrc_LatchReadInput(latch);
01295       if (! st_lookup(parentGroup->Vars, (char*) var, &inGroup)) {
01296         st_insert(parentGroup->Vars, (char*) var, (char*) (long) 1);
01297       }
01298       var = Hrc_LatchReadOutput(latch);
01299       if (! st_lookup(parentGroup->Vars, (char*) var, &inGroup)) {
01300         st_insert(parentGroup->Vars, (char*) var, (char*) (long) 1);
01301       }
01302     }
01303   }
01304 
01305   /* IO of parent group tables (that stay in parent) are parent group vars */
01306   
01307   Hrc_NodeForEachNameTable(parentMaster, tblIndx, tbl) {
01308     for (i = 0; i < array_n(GroupArray); i++) {
01309       group = array_fetch(Rst_Group_t*, GroupArray, i);
01310       if (st_lookup(group->Tables, (char*) tbl, &inGroup)) {
01311         break;
01312       }
01313     }
01314     if (i >= array_n(GroupArray)) {
01315       /* Table stays in parent */
01316       st_insert(parentGroup->Tables, (char*) tbl, (char*) (long) 1);
01317       Tbl_TableForEachInputVar(tbl, varIndx, var) {
01318         if (! st_lookup(parentGroup->Vars, (char*) var, &inGroup)) {
01319           st_insert(parentGroup->Vars, (char*) var, (char*) (long) 1);
01320         }
01321       }
01322       Tbl_TableForEachOutputVar(tbl, varIndx, var) {
01323         if (! st_lookup(parentGroup->Vars, (char*) var, &inGroup)) {
01324           st_insert(parentGroup->Vars, (char*) var, (char*) (long) 1);
01325         }
01326       }
01327     }
01328   }
01329   
01330   /* IO of groups are group Vars of the parent.  Note that inputs are
01331    never group vars of a group EXCEPT in the case of the parent group */
01332   
01333   Hrc_NodeForEachVariable(parentMaster, sgen, varName, var) {
01334     if (! st_lookup(parentGroup->Vars, (char*) var, &inGroup)) {
01335       for (i = 0; i < array_n(GroupArray); i++) {
01336         group = array_fetch(Rst_Group_t*, GroupArray, i);
01337         if ((st_lookup(group->Inputs, (char*) var, &inGroup)) ||
01338             (st_lookup(group->Outputs, (char*) var, &inGroup))) {
01339           break;
01340         }
01341       }
01342       if (i < array_n(GroupArray)) {
01343         st_insert(parentGroup->Vars, (char*) var, (char*) (long) 1);
01344       }
01345     }
01346   }
01347 
01348   /* All formal IO of old parent remains part of the parent group */
01349   
01350   Hrc_NodeForEachFormalInput(parentMaster, i, var)
01351     st_insert(parentGroup->Inputs, (char*) var, (char*) (long) 1);
01352 
01353   Hrc_NodeForEachFormalOutput(parentMaster, i, var)
01354     st_insert(parentGroup->Outputs, (char*) var, (char*) (long) 1);
01355 
01356   /* Outputs of subckts of parent group are parent group vars
01357    We do this last to catch this possible dangling input scenario*/
01358   
01359   Hrc_ModelForEachSubckt(ParentModel, sgen, subcktName, subckt) {
01360     for (i = 0; i < array_n(GroupArray); i++) {
01361       group = array_fetch(Rst_Group_t*, GroupArray, i);
01362       if (st_lookup(group->Subcircuits, (char*) subckt, &inGroup)) {
01363         break;
01364       }
01365     }
01366     if (i >= array_n(GroupArray)) {
01367       st_insert(parentGroup->Subcircuits, (char*) subckt, (char*) (long) 1);
01368       subOutputs = Hrc_SubcktReadActualOutputVars(subckt);
01369       Rst_VarForEachVarInArray(subOutputs, j, var) {
01370         if (! st_lookup(parentGroup->Vars, (char*) var, &inGroup)) {
01371           st_insert(parentGroup->Vars, (char*) var, (char*) (long) 1);
01372         }
01373       }
01374       /* FIXME: Possible bug: inputs are caught because they are
01375          outputs of other components.  But a dangling input (ie, one
01376          with no connection to anything) might get dropped. But adding
01377          an input var might cause it's driving component to be
01378          incorporated!  We opt for a warning here.  */
01379       /* FIXME: Hack-using same array */
01380       subOutputs = Hrc_SubcktReadActualInputVars(subckt); 
01381       Rst_VarForEachVarInArray(subOutputs, j, var) {
01382         if ((! st_lookup(parentGroup->Vars, (char*) var, &inGroup)) &&
01383             (! st_lookup(parentGroup->Inputs, (char*) var, &inGroup))) {
01384           (void) fprintf(vis_stderr,
01385                          "Warning: subcircuit %s has input variable %s ",
01386                          subcktName, Var_VariableReadName(var));
01387           (void) fprintf(vis_stderr, "that has no driver in parent %s\n",
01388                          parentGroup->name);
01389         }
01390       }
01391     }
01392   }
01393   return parentGroup;
01394 }
01395 
01407 void
01408 RstModelPrint(
01409   Hrc_Model_t* newModel)
01410 {
01411   Hrc_Node_t* newMaster;
01412   int i;
01413   st_generator* sgen;
01414   char* varName;
01415   Var_Variable_t* var;
01416 
01417   /* Print out new model  */
01418   printf("Model %s\n", Hrc_ModelReadName(newModel));
01419   newMaster = Hrc_ModelReadMasterNode(newModel);
01420   printf("\tInputs :\t");
01421   Rst_VarForEachVarInArray(Hrc_NodeReadFormalInputs(newMaster), i, var) {
01422     printf("%s ", Var_VariableReadName(var));
01423   }
01424   printf("\n\tOutputs:\t");
01425   Rst_VarForEachVarInArray(Hrc_NodeReadFormalOutputs(newMaster), i, var) {
01426     printf("%s ", Var_VariableReadName(var));
01427   }
01428   printf("\n\tVars:\t");
01429   Hrc_NodeForEachVariable(Hrc_ModelReadMasterNode(newModel),
01430                           sgen, varName, var) {
01431     printf("%s ", Var_VariableReadName(var));
01432   }
01433   printf("\n");
01434 }
01435 
01451 Hrc_Model_t*
01452 RstGroupBuildModel(
01453   Hrc_Manager_t* Hmgr,
01454   Rst_Group_t* Group)
01455 {
01456   long inGroup;  
01457   int retVal, i;
01458   st_generator* sgen;
01459   Var_Variable_t* var, *newVar, *newLatchInput, *newLatchOutput;
01460   Tbl_Table_t* tbl, *newTbl;
01461   Hrc_Latch_t* latch, *newLatch;
01462   st_table* varForwPtr;
01463   Hrc_Node_t* newMaster;
01464   Hrc_Subckt_t *subckt;
01465   Hrc_Model_t* subcktModel;
01466   Hrc_Model_t* newModel = Hrc_ModelAlloc(Hmgr, Group->name);
01467   array_t* actualInputArray, *actualOutputArray;
01468 
01469   if (! newModel) {
01470     (void) fprintf(vis_stderr, "ERROR: could not create Model %s\n",
01471                    Group->name);
01472     return 0;
01473   }
01474   
01475   newMaster = Hrc_ModelReadMasterNode(newModel);
01476   assert(newMaster);
01477 
01478   varForwPtr = st_init_table(st_ptrcmp, st_ptrhash);
01479   /* Add group's Variables: Inputs, Outputs */
01480   st_foreach_item(Group->Inputs, sgen, &var, &inGroup) {
01481     if (! st_lookup(varForwPtr, (char*) var, &newVar)) {
01482       newVar = Var_VariableDup(var, newMaster);
01483       Var_VariableResetAllTypes(newVar);
01484       Var_VariableResetNumFanoutTables(newVar);
01485       Hrc_NodeAddFormalInput(newMaster, newVar);
01486       Var_VariableSetPI(newVar);
01487       st_insert(Group->VarBackPtr, (char*) newVar, (char*) var);
01488       st_insert(varForwPtr, (char*) var, (char*) newVar);
01489     }
01490   }
01491   st_foreach_item(Group->Outputs, sgen, &var, &inGroup) {
01492     if (! st_lookup(varForwPtr, (char*) var, &newVar)) {
01493       newVar = Var_VariableDup(var, newMaster);
01494       Var_VariableResetAllTypes(newVar);
01495       Var_VariableResetNumFanoutTables(newVar);
01496       Hrc_NodeAddFormalOutput(newMaster, newVar);
01497       Var_VariableSetPO(newVar);
01498       st_insert(Group->VarBackPtr, (char*) newVar, (char*) var);
01499       st_insert(varForwPtr, (char*) var, (char*) newVar);
01500     }
01501   }
01502   st_foreach_item(Group->Vars, sgen, &var, &inGroup) {
01503     if (! st_lookup(varForwPtr, (char*) var, &newVar)) {
01504       newVar = Var_VariableDup(var, newMaster);
01505       Var_VariableResetAllTypes(newVar);
01506       Var_VariableResetNumFanoutTables(newVar);
01507       st_insert(Group->VarBackPtr, (char*) newVar, (char*) var);
01508       st_insert(varForwPtr, (char*) var, (char*) newVar);
01509     }
01510   }
01511       
01512   /* Add group's Tables */
01513   st_foreach_item(Group->Tables, sgen, &tbl, &inGroup) {
01514     Hrc_NodeAddNameTable(newMaster, Tbl_TableDupAndSubstVars(tbl, varForwPtr));
01515   }
01516 
01517   /* Add group's Latches */
01518   st_foreach_item(Group->Latches, sgen, &latch, &inGroup) {
01519     retVal = st_lookup(varForwPtr, (char*) Hrc_LatchReadInput(latch),
01520                        &newLatchInput);
01521     assert(retVal);
01522     retVal = st_lookup(varForwPtr, (char*) Hrc_LatchReadOutput(latch),
01523                        &newLatchOutput);
01524     assert(retVal);
01525     
01526     newLatch = Hrc_LatchCreate(newModel, newLatchInput, newLatchOutput);
01527     assert(newLatch != NULL);
01528     Var_VariableSetNS(newLatchInput);
01529     Var_VariableSetPS(newLatchOutput);
01530     
01531     /* Duplicate and attach Reset Table */
01532     tbl = Hrc_LatchReadResetTable(latch);
01533     newTbl = Tbl_TableDupAndSubstVars(tbl, varForwPtr);
01534     /* HACK: For some reason, we don't count latches in fanout count  */
01535     retVal = Hrc_LatchSetResetTable(newLatch, newTbl);
01536 /*    newTbl = Hrc_LatchReadResetTable(latch); */
01537     assert(retVal);
01538     Tbl_TableForEachInputVar(tbl, i, var) {
01539       retVal = st_lookup(varForwPtr, (char*) var, &newVar);
01540       assert(retVal);
01541       Var_VariableResetAllTypes(newVar);
01542       Var_VariableResetNumFanoutTables(newVar);
01543     }
01544     Hrc_NodeAddLatch(newMaster, newLatch);
01545   }
01546 
01547   /* Add group's Subckts */
01548   
01549   st_foreach_item(Group->Subcircuits, sgen, &subckt, &inGroup) {
01550     actualInputArray =
01551       Rst_VartoVarLookup(Hrc_SubcktReadActualInputVars(subckt),
01552                          varForwPtr, 0);
01553     actualOutputArray =
01554       Rst_VartoVarLookup(Hrc_SubcktReadActualOutputVars(subckt),
01555                          varForwPtr, 0);
01556     subcktModel = Hrc_SubcktReadModel(subckt);
01557     Hrc_ModelAddSubckt(newModel, subcktModel,
01558                        Hrc_SubcktReadInstanceName(subckt),
01559                        actualInputArray, actualOutputArray);
01560     Rst_VarForEachVarInArray(actualInputArray, i, var) {
01561       Var_VariableSetSI(var);
01562     }
01563     Rst_VarForEachVarInArray(actualOutputArray, i, var) {
01564       Var_VariableSetSO(var);
01565     }
01566   }
01567 
01568   st_free_table(varForwPtr);
01569 
01570 #ifdef RST_GROUP_DEBUG
01571   RstModelPrint(newModel);
01572 #endif
01573   return newModel;
01574 }
01575 
01576 /* Overrides for Emacs so that we follow VIS tabbing style.
01577  * Must remain at end of file.
01578  * ---------------------------------------------------------------------------
01579  * Local variables:
01580  * c-basic-offset: 2
01581  * c-indent-level: 2
01582  * c-brace-imaginary-offset: 0
01583  * c-brace-offset: -2
01584  * c-argdecl-indent: 2
01585  * c-comment-only-line-offset: 0
01586  * c-label-offset: -4
01587  * c-continued-statement-offset: 2
01588  * c-continued-brace-offset: 0
01589  * End: */