source: vis_dev/vis-2.3/src/rst/rstGroup.c @ 25

Last change on this file since 25 was 14, checked in by cecile, 13 years ago

vis2.3

File size: 53.4 KB
RevLine 
[14]1/**CFile***********************************************************************
2
3  FileName    [rstGroup.c]
4
5  PackageName [rst]
6
7  Synopsis    [rst package partitioning code with user interface.]
8
9  Author      [Desmond A. Kirkpatrick]
10
11  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
12  All rights reserved.
13
14  Permission is hereby granted, without written agreement and without license
15  or royalty fees, to use, copy, modify, and distribute this software and its
16  documentation for any purpose, provided that the above copyright notice and
17  the following two paragraphs appear in all copies of this software.
18
19  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
20  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
21  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
22  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
24  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
25  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
26  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
27  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
28  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
29
30******************************************************************************/
31
32#include <stdio.h>
33#include "rstInt.h"
34#include "cmd.h"
35#include "varInt.h"
36
37static char rcsid[] UNUSED = "$Id: rstGroup.c,v 1.9 2005/05/16 06:22:35 fabio Exp $";
38
39/*---------------------------------------------------------------------------*/
40/* Constant declarations                                                     */
41/*---------------------------------------------------------------------------*/
42
43/*
44#define RST_GROUP_DEBUG 1
45*/
46
47/*---------------------------------------------------------------------------*/
48/* Structure declarations                                                    */
49/*---------------------------------------------------------------------------*/
50
51/*---------------------------------------------------------------------------*/
52/* Type declarations                                                         */
53/*---------------------------------------------------------------------------*/
54/*---------------------------------------------------------------------------*/
55/* Variable declarations                                                     */
56/*---------------------------------------------------------------------------*/
57
58/*---------------------------------------------------------------------------*/
59/* Macro declarations                                                        */
60/*---------------------------------------------------------------------------*/
61
62#define Rst_VarForEachVarInArray( \
63  /* array_t* */          array,  \
64  /* int, local */        i,      \
65  /* Var_Variable_t* */   var     \
66)                                 \
67arrayForEachItem(Var_Variable_t*, array, i, var)
68
69/**AutomaticStart*************************************************************/
70
71/*---------------------------------------------------------------------------*/
72/* Static function prototypes                                                */
73/*---------------------------------------------------------------------------*/
74
75
76/**AutomaticEnd***************************************************************/
77
78
79/*---------------------------------------------------------------------------*/
80/* Definition of exported functions                                          */
81/*---------------------------------------------------------------------------*/
82
83
84
85/**Function********************************************************************
86
87  Synopsis    [Resets number of fanout tables.]
88
89  Description [This should be moved to the Var package.]
90
91  SideEffects []
92
93  SeeAlso     []
94
95******************************************************************************/
96/*
97  This was moved to VAR package by Yuji on 11/8 and renamed to
98  Var_VariableResetNumFanoutTables()
99 
100  void
101Var_VariableResetNumFanout(
102  Var_Variable_t* var)
103{
104  var->numFanoutTables = 0;
105}
106*/
107
108
109/**Function********************************************************************
110
111  Synopsis    [Duplicates a table and substitutes its variables.]
112
113  Description [Duplicates a table and substitutes its input and output
114  variables with variables given in an st_table.  This is a common
115  operation when copying tables to new Nodes during hierarchy
116  restructuring operations.  VartoVar table MUST contain new variables
117  for each variable in Table.  Returns a pointer to new table.
118
119  This should be moved to the Tbl package. ]
120
121  SideEffects [Creates new table and potentially modifies variable
122  types of variables in st_table.]
123
124  SeeAlso     []
125
126******************************************************************************/
127Tbl_Table_t*
128Tbl_TableDupAndSubstVars(
129  Tbl_Table_t* Table,
130  st_table* VartoVar)
131{
132  int tblIndx, retVal;
133  Var_Variable_t *var, *newVar;
134  Tbl_Table_t* newTbl = Tbl_TableHardDup(Table);
135 
136  Tbl_TableForEachInputVar(newTbl, tblIndx, var) {
137    retVal = st_lookup(VartoVar, (char*) var, &newVar);
138    assert(retVal);
139    Tbl_TableSubstituteVar(newTbl, var, newVar);
140    Var_VariableIncrementNumFanoutTables(newVar);
141  }
142  Tbl_TableForEachOutputVar(newTbl, tblIndx, var) {
143    retVal = st_lookup(VartoVar, (char*) var,&newVar);
144    assert(retVal);
145    Tbl_TableSubstituteVar(newTbl, var, newVar);
146  }
147  return newTbl;
148}
149
150/**Function********************************************************************
151
152  Synopsis    [Translates a set of variables given one or two st_tables.]
153
154  Description [Given an array of variables, this function looks up the
155  variable in table VartoVarOne and finds a new variable to translate
156  to.  If VartoVarTwo exist, it repeats this operation.  It returns an
157  array of new (translated) variables.
158
159  Is this a good Var package utility? ]
160
161  SideEffects [Creates new array_t of variables.]
162
163  SeeAlso     []
164
165******************************************************************************/
166array_t*
167Rst_VartoVarLookup(
168  array_t* VarArray,
169  st_table* VartoVarOne,
170  st_table* VartoVarTwo)
171{
172  int i, retVal;
173  Var_Variable_t *var, *newVar, *tmpVar;
174  array_t* newVarArray = array_alloc(Var_Variable_t*, array_n(VarArray));
175
176  Rst_VarForEachVarInArray(VarArray, i, var) {
177    retVal = st_lookup(VartoVarOne, (char*) var, &newVar);
178    assert(retVal);
179    if (VartoVarTwo) {
180      tmpVar = newVar;
181      retVal = st_lookup(VartoVarTwo, (char*) tmpVar, &newVar);
182    }
183    assert(retVal);
184    array_insert(Var_Variable_t*, newVarArray, i, newVar);
185  }
186  return newVarArray;
187}
188
189/**Function********************************************************************
190
191  Synopsis    [Grabs non-option strings off command line.]
192
193  Description [While running getopt, this function can be used to
194  parse strings between options off the command line.  This is useful
195  for options with multiple arguments or arguments that can be
196  specified anywhere with respect to option flags.
197
198  Perhaps this belongs in the Cmd package. ]
199
200  SideEffects [Creates new array_t of allocated char*s.
201               Presumes that getopt has been reset and is running.
202               MODIFIES util_optind!!!]
203
204  SeeAlso     [util_getopt, Rst_CommandGroupComponents]
205
206******************************************************************************/
207array_t*
208Rst_GetNamesUntilNextOption(
209  array_t* nameArray,
210  int argc,
211  char **argv)
212{
213  char* name;
214
215  while ((util_optind < argc) && (*argv[util_optind] != '-')) {
216    name = util_strcat3(argv[util_optind], "", "");
217    array_insert_last(char*, nameArray, name);
218    util_optind++;
219  }
220  return nameArray;
221}
222
223/**Function********************************************************************
224
225  Synopsis    [Reads an array of strings from a file.]
226
227  Description [Returns an array of strings read from an open file.]
228
229  SideEffects [Returns allocated char*s in nameArray which must be
230  preallocated.  fp must have been opened.]
231
232  SeeAlso     []
233
234******************************************************************************/
235array_t*
236Rst_LoadNameArrayFromFile(
237  array_t* nameArray,
238  FILE* fp)
239{
240  char* name;
241  char buffer[1024];
242
243  while (fscanf(fp, "%s", buffer) != EOF) {
244    name = util_strcat3(buffer, "", "");
245    array_insert_last(char*, nameArray, name);
246  }
247  return nameArray;
248}
249
250/**Function********************************************************************
251
252  Synopsis    [Creates a Group from user specified components]
253
254  Description [Treating all components which PRODUCE variables (ie,
255  outputs of Tables, Latches, Subcircuits) as in the group specified by a
256  list of variables, this function builds a group and all the tables
257  associated.  Specifically, it derives the input and output
258  variables, as well as simple tables to list the contained
259  components.  A Group can then be transformed into a model via
260  RstGroupBuildModel.  Note that a special kind of group for the
261  remainder of the Node being partitioned is created using
262  RstCreateParentGroup.  This routine is called by
263  Rst_GroupRestructureNode.
264
265  NUMBER ONE RULE OF GROUPS: GROUP COMPONENTS are tracked by their
266  OUTPUT VARS ]
267
268  SideEffects [Allocates a Rst_Group_t.]
269
270  SeeAlso     [RstGroupBuildModel, RstCreateParentGroup, Rst_GroupRestructureNode]
271
272******************************************************************************/
273Rst_Group_t*
274RstGroupComponents(
275  Hrc_Model_t* CurModel,
276  char* NewName,
277  array_t* VarGroup,
278  array_t* Subcircuits)
279{
280  int i, j, tblIndx;
281  long inGroup; 
282  char* latchName, *subcktName;
283  Hrc_Latch_t* latch;
284  Hrc_Subckt_t* subckt;
285  Hrc_Node_t* curMaster;
286  st_generator* sgen;
287  Tbl_Table_t* tbl;
288  Var_Variable_t* var = NIL(Var_Variable_t);
289  array_t* subOutputs;
290  Rst_Group_t* group = RstGroupAlloc(NewName);
291
292  curMaster = Hrc_ModelReadMasterNode(CurModel);
293
294  /* Make sure there is something to group */
295  i=0;
296  if (VarGroup) {
297    i += array_n(VarGroup);
298  }
299  if (Subcircuits) {
300    i += array_n(Subcircuits);
301  }
302  if (i == 0) {
303    return 0;
304  }
305
306  /* Determine Input/Output Formal list from implied partitioning */
307
308  if (VarGroup) {
309    /* Store group variables (ie outputs of tables/latches) in hash
310       table */
311    Rst_VarForEachVarInArray(VarGroup, i, var) {
312      if ((var) && (! Var_VariableTestIsPI(var))) {
313        st_insert(group->Vars, (char*) var, (char*) (long) 1);
314      } else if ((var) && (Var_VariableTestIsPI(var))) {
315        (void) fprintf(vis_stderr,
316                       "Warning: can't group a PI: %s\n",
317                       Var_VariableReadName(var));
318      }
319    }
320  }
321
322  if (Subcircuits) {
323    /* Store Subckt in group Subcircuits hashtable.
324       Store output vars of all group Subckts in var hash table */
325    for (i = 0; i < array_n(Subcircuits); i++) {
326      subckt = array_fetch(Hrc_Subckt_t*, Subcircuits, i);
327      st_insert(group->Subcircuits, (char*) subckt, (char*) (long) 1);
328      Rst_VarForEachVarInArray(Hrc_SubcktReadActualOutputVars(subckt),
329                               j, var) {
330        if (! st_lookup(group->Vars, (char*) var, &inGroup)) {
331          st_insert(group->Vars, (char*) var, (char*) (long) 1);
332        }
333      }
334    }
335  }
336
337  /* Table and Latch outputs which are group vars become members of the group
338   */
339 
340  Hrc_NodeForEachLatch(curMaster, sgen, latchName, latch) {
341    if (st_lookup(group->Vars, (char*) Hrc_LatchReadOutput(latch), &inGroup)) {
342      st_insert(group->Latches, (char*) latch, (char*) (long) 1);
343    }
344  }
345 
346  Hrc_NodeForEachNameTable(curMaster, tblIndx, tbl) {
347    Tbl_TableForEachOutputVar(tbl, j, var) {
348      inGroup = 0;
349      if (st_lookup(group->Vars, (char*) var, &inGroup)) {
350        st_insert(group->Tables, (char*) tbl, (char*) (long) 1);
351        break;
352      }
353    }
354    /* FIXME: Table Splitting here */
355   
356    if ((inGroup)  && (Tbl_TableReadNumOutputs(tbl) > 1)) {
357      (void) fprintf(vis_stderr,
358                     "WARNING: multi-output table %s moved to group %s\n",
359                     Var_VariableReadName(var), group->name);
360    }
361  }
362  /* If outputs of a subckt are in a group, the subckt moves
363     into the group */
364 
365  Hrc_ModelForEachSubckt(CurModel, sgen, subcktName, subckt) {
366    Var_Variable_t* outVar = NIL(Var_Variable_t); /* initialize to pacify */
367    if (! st_lookup(group->Subcircuits, (char*) subckt, &inGroup)) {
368      subOutputs = Hrc_SubcktReadActualOutputVars(subckt);
369      Rst_VarForEachVarInArray(subOutputs, i, outVar) {
370        if (st_lookup(group->Vars, (char*) outVar, &inGroup)) {
371          break;
372        }
373      }
374      if (i < array_n(subOutputs)) {
375        Rst_VarForEachVarInArray(subOutputs, j, var) {
376          if (! st_lookup(group->Vars, (char*) var, &inGroup)) {
377            st_insert(group->Vars, (char*) var, (char*) (long) 1);
378          }
379        }
380        st_insert(group->Subcircuits, (char*) subckt, (char*) (long) 1);
381        (void) fprintf(vis_stderr,
382                       "Warning: instance %s becomes member of group %s",
383                       subcktName, group->name);
384        (void) fprintf(vis_stderr, " because of output variable %s\n",
385                       Var_VariableReadName(outVar));
386      }
387    }
388  }
389 
390  /* Group Outputs: Scan parent outputs for group vars. Scan non-group
391     component (Subcircuits/Latches/Tables) inputs for group vars */
392
393  Hrc_NodeForEachFormalOutput(curMaster, i, var) {
394    if ((st_lookup(group->Vars, (char*) var, &inGroup)) &&
395        (! st_lookup(group->Outputs, (char*) var, &inGroup))) {
396      st_insert(group->Outputs, (char*) var, (char*) (long) 1);
397    }
398  }
399
400  Hrc_ModelForEachSubckt(CurModel, sgen, subcktName, subckt) {
401    if (! st_lookup(group->Subcircuits, (char*) subckt, &inGroup)) {
402      Rst_VarForEachVarInArray(Hrc_SubcktReadActualInputVars(subckt), i, var) {
403        if ((st_lookup(group->Vars, (char*) var, &inGroup)) &&
404            (! st_lookup(group->Outputs, (char*) var, &inGroup))) {
405            st_insert(group->Outputs, (char*) var, (char*) (long) 1);
406        }
407      }
408    }
409  }
410  Hrc_NodeForEachLatch(curMaster, sgen, latchName, latch) {
411    if (! st_lookup(group->Latches, (char*) latch, &inGroup)) {
412      var = Hrc_LatchReadInput(latch);
413      if ((st_lookup(group->Vars, (char*) var, &inGroup)) &&
414          (! st_lookup(group->Outputs, (char*) var, &inGroup))) {
415        st_insert(group->Outputs, (char*) var, (char*) (long) 1);
416      }
417    }
418  }
419  Hrc_NodeForEachNameTable(curMaster, i, tbl) {
420    if (! st_lookup(group->Tables, (char*) tbl, &inGroup)) {
421      Tbl_TableForEachInputVar(tbl, j, var) {
422        if ((st_lookup(group->Vars, (char*) var, &inGroup)) &&
423            (! st_lookup(group->Outputs, (char*) var, &inGroup))) {
424          st_insert(group->Outputs, (char*) var, (char*) (long) 1);
425        }
426      }
427    }
428  }
429 
430  /* Group Inputs:  Scan group subcomponent inputs for non-group vars */
431
432  /* Formal inputs are never vars of a group.  Thus, they are always
433     non-group vars when are inputs to group subcomponents, and are
434     caught by the code below*/
435 
436  Hrc_ModelForEachSubckt(CurModel, sgen, subcktName, subckt) {
437    if (st_lookup(group->Subcircuits, (char*) subckt, &inGroup)) {
438      Rst_VarForEachVarInArray(Hrc_SubcktReadActualInputVars(subckt), i, var) {
439        if ((! st_lookup(group->Vars, (char*) var, &inGroup)) &&
440            (! st_lookup(group->Inputs, (char*) var, &inGroup))) {
441          st_insert(group->Inputs, (char*) var, (char*) (long) 1);
442        }
443      }
444    }
445  }
446  Hrc_NodeForEachLatch(curMaster, sgen, latchName, latch) {
447    if (st_lookup(group->Latches, (char*) latch, &inGroup)) {
448      var = Hrc_LatchReadInput(latch);
449      if ((! st_lookup(group->Vars, (char*) var, &inGroup)) &&
450          (! st_lookup(group->Inputs, (char*) var, &inGroup))) {
451        st_insert(group->Inputs, (char*) var, (char*) (long) 1);
452      }
453      /* Reset table here */
454      tbl = Hrc_LatchReadResetTable(latch);
455      Tbl_TableForEachInputVar(tbl, j, var) {
456        if (! st_lookup(group->Vars, (char*) var, &inGroup))
457          st_insert(group->Vars, (char*) var, (char*) (long) 1);
458      }
459    }
460  }
461  Hrc_NodeForEachNameTable(curMaster, tblIndx, tbl) {
462    if (st_lookup(group->Tables, (char*) tbl, &inGroup)) {
463      Tbl_TableForEachInputVar(tbl, j, var) {
464        if ((! st_lookup(group->Vars, (char*) var, &inGroup)) &&
465            (! st_lookup(group->Inputs, (char*) var, &inGroup))) {
466          st_insert(group->Inputs, (char*) var, (char*) (long) 1);
467        }
468      }
469    }
470  }
471
472  return group;
473}
474
475/**Function********************************************************************
476
477  Synopsis [Takes a Group partitioning of a Node and builds a new
478  Model reflecting that partition.]
479
480  Description [Called by the main routine Rst_CommandGroupComponents,
481  this routine builds the models corresponding to each group in
482  GroupArray, builds a new Node instantiating these models as
483  subckts.  Note that one can build a Group using RstGroupComponents]
484
485  SideEffects [Allocates a new Hrc_Model_t.]
486
487  SeeAlso     [RstGroupComponents, RstGroupBuildModel, RstCreateParentGroup,
488  Rst_CommandGroupComponents, Rst_GroupRestructureNode]
489
490******************************************************************************/
491Hrc_Model_t*
492Rst_GroupRestructureModel(
493  Hrc_Manager_t* Hmgr,
494  Hrc_Model_t* ParentModel,
495  array_t* GroupArray)
496{
497  int i, j;
498  char *newModelName;
499  st_generator *sgen;
500  Var_Variable_t *var, *newVar;
501  Hrc_Model_t *newModel, *newParentModel;
502  Hrc_Node_t *newMaster;
503  Rst_Group_t *group, *parentGroup;
504  st_table *varForwPtr;
505  array_t *newModelArray, *newMasterArray, *newNodeArray;
506
507  for (i = 0; i < array_n(GroupArray); i++) {
508    group = array_fetch(Rst_Group_t*, GroupArray, i);
509#ifdef RST_GROUP_DEBUG
510    RstGroupPrint(group);
511#endif
512  }
513  /* Check group components for disjointness */
514
515  if (RstGroupDisjointCheck(GroupArray))
516    return 0;
517
518  /* Construct a level of hierarchy for each group */
519
520  newModelArray = array_alloc(Hrc_Model_t*, array_n(GroupArray));
521  newMasterArray = array_alloc(Hrc_Node_t*, array_n(GroupArray));
522  newNodeArray = array_alloc(Hrc_Node_t*, array_n(GroupArray));
523 
524  for (i = 0; i < array_n(GroupArray); i++) {
525    group = array_fetch(Rst_Group_t*, GroupArray, i);
526    newModel = RstGroupBuildModel(Hmgr, group);
527    if (! newModel) {
528      return 0;
529    }
530    newMaster = Hrc_ModelReadMasterNode(newModel);
531    array_insert(Hrc_Model_t*, newModelArray, i, newModel);
532    array_insert(Hrc_Node_t*, newMasterArray, i, newMaster);
533  }
534
535  /* Build the new parent hierarchy */
536 
537  newModelName = RstGroupNewParentName(Hrc_ModelReadName(ParentModel));
538  parentGroup = RstCreateParentGroup(Hmgr, ParentModel, newModelName,
539                                      GroupArray);
540  FREE(newModelName);
541  if (! parentGroup) {
542    return 0;
543  }
544#ifdef RST_GROUP_DEBUG
545  RstGroupPrint(parentGroup);
546#endif
547  newParentModel = RstGroupBuildModel(Hmgr, parentGroup);
548
549  /* Computing actuals:  Group IO vars USED to be in the old parent.
550     1) lookup what the new IO vars used to be in the old parent
551     2) In the old parent, find the correspond new parent vars
552     */
553 
554  /* Build Table: Parent to New Parent Vars, by reversing back pointers */
555
556  varForwPtr = st_init_table(st_ptrcmp, st_ptrhash);
557  st_foreach_item(parentGroup->VarBackPtr, sgen, &newVar, &var) {
558    st_insert(varForwPtr, (char*) var, (char*) newVar);
559  }
560
561  /* Free parent group now */
562  RstGroupFree(parentGroup); parentGroup = 0;
563 
564  /* Instantiate groups as subckts */
565
566  for (i = 0; i < array_n(GroupArray); i++) {
567    array_t* actualInputArray, *actualOutputArray;
568
569    group = array_fetch(Rst_Group_t*, GroupArray, i);
570    newModel = array_fetch(Hrc_Model_t*, newModelArray, i);
571    newMaster = Hrc_ModelReadMasterNode(newModel);
572
573    actualInputArray =
574      Rst_VartoVarLookup(Hrc_NodeReadFormalInputs(newMaster),
575                         group->VarBackPtr, varForwPtr);
576    actualOutputArray =
577      Rst_VartoVarLookup(Hrc_NodeReadFormalOutputs(newMaster),
578                         group->VarBackPtr, varForwPtr);
579
580    Hrc_ModelAddSubckt(newParentModel, newModel, group->name, 
581                       actualInputArray, actualOutputArray);
582    Rst_VarForEachVarInArray(actualInputArray, j, var) {
583      Var_VariableSetSI(var);
584    }
585    Rst_VarForEachVarInArray(actualOutputArray, j, var) {
586      Var_VariableSetSO(var);
587    }
588  }
589  array_free(newModelArray);
590  array_free(newMasterArray);
591  array_free(newNodeArray);
592
593  st_free_table(varForwPtr);
594  return newParentModel;
595}
596
597/**Function********************************************************************
598
599  Synopsis [Takes a Group partitioning of a Node and replaces Node
600  with the partitioned Node.]
601
602  Description [Called by the main routine Rst_CommandGroupComponents,
603  this routine builds the models corresponding to each group in
604  GroupArray, builds a new Node instantiating these models as
605  subckts.  Note that one can build a Group using RstGroupComponents]
606
607  SideEffects [Allocates a new Hrc_Node_t and replaces the CurNode with it.]
608
609  SeeAlso     [RstGroupComponents, RstGroupBuildModel, RstCreateParentGroup,
610  Rst_CommandGroupComponents]
611
612******************************************************************************/
613Hrc_Node_t*
614Rst_GroupRestructureNode(
615  Hrc_Manager_t* Hmgr,
616  Hrc_Node_t* CurNode,
617  array_t* GroupArray)
618{
619  int retVal;
620#ifdef RST_GROUP_DEBUG
621  st_generator* sgen;
622  char* childName;
623  Hrc_Node_t *child;
624#endif 
625  Hrc_Model_t *newParentModel;
626  Hrc_Node_t *newNode = 0;
627  Hrc_Model_t* CurModel=
628    Hrc_ManagerFindModelByName(Hmgr, Hrc_NodeReadModelName(CurNode));
629
630  newParentModel = Rst_GroupRestructureModel(Hmgr, CurModel, GroupArray);
631  if (newParentModel) {
632
633    newNode = Hrc_ModelCreateHierarchy(Hmgr, newParentModel,
634                                       Hrc_NodeReadInstanceName(CurNode));
635
636#ifdef RST_GROUP_DEBUG
637    (void) fprintf(vis_stderr, "Checking New Node\n");
638    assert(Hrc_NodeCheckVariableConsistency(newNode));
639    (void) fprintf(vis_stderr, "Checking Subcircuits\n");
640    Hrc_NodeForEachChild(newNode, sgen, childName, child) {
641      assert(Hrc_NodeCheckVariableConsistency(child));
642    }
643#endif
644 
645    retVal = Hrc_TreeReplace(CurNode, newNode);
646    assert(retVal);
647    Hrc_ManagerSetCurrentNode(Hmgr, newNode);
648  }
649  return newNode;
650}
651
652/**Function********************************************************************
653
654  Synopsis    [Creates a model of the combinational portion of a Node.]
655
656  Description [Finds the combinational logic of a Model and groups it into
657  a new Model.]
658
659  SideEffects [Allocates a new Hrc_Model_t.]
660
661  SeeAlso     [RstGroupComponents, Rst_GroupRestructureNode]
662
663******************************************************************************/
664Hrc_Model_t*
665Rst_GroupGroupCombLogic(
666  Hrc_Manager_t* Hmgr,
667  Hrc_Model_t* CurModel)
668{
669  long inGroup;
670  int tblIndx, varIndx;
671  Var_Variable_t *var;
672  Tbl_Table_t* tbl;
673  array_t* varArray = array_alloc(Var_Variable_t*, 0);
674  Rst_Group_t *group;
675  st_table *tableOutputs = st_init_table(st_ptrcmp, st_ptrhash);
676  Hrc_Node_t *curMaster;
677  Hrc_Model_t* newModel;
678
679  /* Perhaps this is better done with the NameTables so that we drop
680     subckts from inclusion */
681
682  curMaster = Hrc_ModelReadMasterNode(CurModel);
683
684  Hrc_NodeForEachNameTable(curMaster, tblIndx, tbl) {
685    Tbl_TableForEachOutputVar(tbl, varIndx, var) {
686      if (! st_lookup(tableOutputs, (char*) var, &inGroup)) {
687        st_insert(tableOutputs, (char*) var, (char*) (long) 1);
688        array_insert_last(Var_Variable_t*, varArray, var);
689      }
690    }
691  }
692  st_free_table(tableOutputs);
693  group = RstGroupComponents(CurModel,
694                              util_strcat3(Hrc_ModelReadName(CurModel),
695                                           "_comb", ""),
696                              varArray, NULL);
697  array_free(varArray);
698
699  if (group) {
700    array_t *groupArray = array_alloc(Rst_Group_t*, 1);
701    array_insert_last(Rst_Group_t*, groupArray, group);
702    newModel = Rst_GroupRestructureModel(Hmgr, CurModel, groupArray);
703    array_free(groupArray);
704    return newModel;
705  }
706  return 0;
707}
708
709/**Function********************************************************************
710
711  Synopsis    [Creates a model of the latch portion of a Node.]
712
713  Description [Finds the latches of a Model and groups them into a new Model.]
714
715  SideEffects [Allocates a new Hrc_Model_t.]
716
717  SeeAlso     [RstGroupComponents, Rst_GroupRestructureNode]
718
719******************************************************************************/
720Hrc_Model_t*
721Rst_GroupGroupLatches(
722  Hrc_Manager_t* Hmgr,
723  Hrc_Model_t* CurModel)
724{
725  char *latchName;
726  st_generator *sgen;
727  Hrc_Latch_t *latch;
728  array_t* varArray = array_alloc(Var_Variable_t*, 0);
729  Rst_Group_t *group;
730  Hrc_Node_t* curMaster = Hrc_ModelReadMasterNode(CurModel);
731  Hrc_Model_t* newModel;
732
733  Hrc_NodeForEachLatch(curMaster, sgen, latchName, latch) {
734    array_insert_last(Var_Variable_t*, varArray, Hrc_LatchReadOutput(latch));
735  }
736 
737  group = RstGroupComponents(CurModel,
738                              util_strcat3(Hrc_ModelReadName(CurModel),
739                                           "_latch", ""),
740                              varArray, NULL);
741  array_free(varArray);
742
743  if (group) {
744    array_t *groupArray = array_alloc(Rst_Group_t*, 1);
745    array_insert_last(Rst_Group_t*, groupArray, group);
746    newModel = Rst_GroupRestructureModel(Hmgr, CurModel, groupArray);
747    array_free(groupArray);
748    return newModel;
749  }
750  return 0;
751}
752
753/**Function********************************************************************
754
755  Synopsis [This function is the command-line interface for the user
756  to specify groups into which to partition the components of the
757  current level of hierarchy.]
758
759  CommandName [decompose_child]
760
761  CommandSynopsis [Partitions Node components into child nodes. ]
762
763  CommandArguments[-n  &lt;groupname&gt; \[-f &lt;filename&gt;\]
764  \[-c\] \[-v\] \[-t\] \[-l\] \[&lt;components&gt;\]]
765 
766  CommandDescription [This command partitions the current Node into
767  several new children nodes according to user-specified groups.
768
769  The user may specify several groups by name \[-n\] sequentially on
770  the command line.  Within each group a list of components (either
771  variables or child nodes) can be placed.  The flags \[-c\] \[-v\]
772  toggle whether element names are interpreted as child instances or
773  variables (default is instances \[-c\]).  Element names can be
774  loaded from a file as well using the \[-f\] flag. <p>
775
776  By specifying a variable to be grouped, any object (e.g., Table,
777  Latch, Child) that PRODUCES that variable is included in the newly
778  created child node for that group.<p>
779
780
781  Command options:<p> 
782
783  <dl>
784  <dt> -n &lt;groupname&gt;
785  <dd> Define new group
786  </dl>
787
788  <dl>
789  <dt> -f &lt;filename&gt;
790  <dd> Load names from file
791  </dl>
792  <dl>
793
794  <dt> -c
795  <dd> Interpret names that follow as child instances to group
796  </dl>
797
798  <dt> -v
799  <dd> Interpret names that follow as variables
800  </dl>
801
802  <dt> -l
803  <dd> Include all latch output nodes (and therefore latches) in group
804  </dl>
805
806  <dt> -t
807  <dd> Include all combinational tables in group.
808  </dl>
809
810  Examples:<p>
811             decompose_child -n c1 -v G1 G2 -n c2 IA IB<p>
812
813             Place variables G1 and G2 into a new child node c1 and
814             child nodes IA and IB into a new child node c2.<p>
815
816  Example:<p>
817  decompose_child -n ckt_inst child1 -f myinstances -v var1 -n latch_inst -l <p>
818
819  This groups the subckts child1 and those listed in the file myinstances,
820  as well as the variable var1 into a subckt called 'ckt_inst'. It
821  also groups all the latches into a subckt called 'latch_inst'.]
822
823  SideEffects [Replaces current Node with a new Node containing
824  children representing the partition.]
825
826******************************************************************************/
827int
828Rst_CommandGroupComponents(
829  Hrc_Manager_t** Hmgr,
830  int  argc,
831  char ** argv)
832{
833  enum { SUBCKT_GROUP, VAR_GROUP } readType = SUBCKT_GROUP;
834  int c, i, retVal, tblIndx;
835  st_generator *sgen;
836  Rst_Group_t* group;
837  Var_Variable_t* var;
838  Hrc_Subckt_t* child;
839  char *fileName, *varName, *childName, *latchName;
840  char* groupName = 0;
841  array_t *vars = 0, *children = 0;
842  Hrc_Latch_t* latch;
843  Tbl_Table_t* tbl;
844  array_t* nameArray = 0;
845  array_t* groupArray = array_alloc(Rst_Group_t*, 1);
846  Hrc_Node_t* curNode = Hrc_ManagerReadCurrentNode(*Hmgr);
847  Hrc_Node_t* curMaster;
848  FILE* fp;
849  Hrc_Model_t* CurModel;
850 
851  if (! curNode) {
852    /* No node has been read in. The only sane thing we
853       support is the -h option */
854    array_free(groupArray); groupArray = 0;
855    util_getopt_reset();
856    if ((c = util_getopt(argc,argv,"h")) !=  EOF) {
857      goto usage;
858    }
859    (void) fprintf(vis_stderr, "ERROR: no current Node\n");
860    return 1;
861  }
862
863  CurModel=
864      Hrc_ManagerFindModelByName(Hrc_NodeReadManager(curNode),
865                                 Hrc_NodeReadModelName(curNode));
866  curMaster = Hrc_ModelReadMasterNode(CurModel);
867
868  /* This command processing loop is conceptually simple, but almost
869    'goto' like and needs explanation.  The command line is a sequence
870    of groups between which are specified component names to group.
871
872    A group is started with a Naming operation '-n'. We get a list of
873    component names to group either from the command line or from a
874    file.  Names can be anywhere on the command line (except between
875    -n/-f and their argument).  The names are interpreted as Variables
876    or Children depending on the last -v or -c flag.  Children is the
877    default setting on entry.
878
879    After every option, we can read more names off command line, so we
880    drop into this mode after completing a -n <name> or -f <file>
881    operation.  This means we always drop into the outer 'default'.
882
883     The goal is to collect a set of Variable and Child names for each
884     Group Name specified.  */
885 
886  util_getopt_reset();
887  while ((c = util_getopt(argc, argv, "n:f:cvtlh")) != EOF) {
888    switch(c) {
889        case 'n':               /* expects a Name arg */
890        case 'f':               /* expects a filename arg */
891          switch(c) {
892              case 'n':         /* Name a new group */
893                if (groupName != NULL) {
894                  group = RstGroupComponents(CurModel, groupName,
895                                              vars, children);
896                  array_free(vars); vars = 0;
897                  array_free(children); children = 0;
898                  FREE(groupName);
899                  if (group) {
900                    array_insert_last(Rst_Group_t*, groupArray, group);
901                  } else {
902                    (void) fprintf(vis_stderr,
903                                   "Warning: Incomplete group %s -- ignored\n",
904                                   groupName);
905                    RstGroupFree(group); group = 0;
906                  }
907                }
908                vars = array_alloc(Var_Variable_t*, 0);
909                children = array_alloc(Hrc_Subckt_t*, 0);
910                groupName = util_strcat3(argv[util_optind -1], "","");
911                break;
912              case 'f':         /* Read component names from file */
913                fileName = argv[util_optind - 1];
914                fp = Cmd_FileOpen(util_optarg, "r", &fileName, 1);
915                if (fp == NIL(FILE)) {
916                  (void) fprintf(vis_stderr,
917                                 "Could not open file %s\n", fileName);
918                  return 1;
919                }
920                nameArray = array_alloc(char*, 0);
921                Rst_LoadNameArrayFromFile(nameArray, fp);
922                fclose(fp);
923                break;
924          }
925          /* WE ALWAYS DROP IN HERE ON EVERY FLAG */
926        default:
927          if (! groupName && (c != 'h')) {
928            (void) fprintf(vis_stderr, "ERROR: Group not defined yet\n");
929            goto usage;
930          }
931          if (! nameArray) nameArray = array_alloc(char*, 0);
932          switch(c) {
933              case 'n':
934              case 'f':
935                break;
936              case 'c': readType = SUBCKT_GROUP; break;
937              case 'v': readType = VAR_GROUP; break;
938              case 'l':
939                /* Put latch ouput vars into group*/
940                Hrc_NodeForEachLatch(curMaster, sgen, latchName, latch) {
941                  var = Hrc_LatchReadOutput(latch);
942                  array_insert_last(Var_Variable_t*, vars, var);
943                }
944                break;
945              case 't':
946                /* Put table ouput vars into group*/
947                Hrc_NodeForEachNameTable(curMaster, tblIndx, tbl) {
948                  Tbl_TableForEachOutputVar(tbl, i, var) {
949                      array_insert_last(Var_Variable_t*, vars, var);
950                  }
951                }
952                break;
953              default: goto usage;
954          }
955          /* Grab any more names off the command line, appending if
956             possible to nameArray */
957         
958          Rst_GetNamesUntilNextOption(nameArray, argc, argv);
959
960          /* We store names read as either variable names or child names */
961         
962          switch(readType) {
963              case VAR_GROUP:
964                for (i=0; i < array_n(nameArray); i++) {
965                  varName = array_fetch(char*, nameArray, i);
966                  var = Hrc_NodeFindVariableByName(curMaster, varName);
967                  if (var) {
968                    array_insert_last(Var_Variable_t*, vars, var);
969                  } else {
970                    (void) fprintf(vis_stderr, "Could not find variable %s\n",
971                                   varName);
972                  }
973                }
974                break;
975              case SUBCKT_GROUP:
976                for (i=0; i < array_n(nameArray); i++) {
977                  childName = array_fetch(char*, nameArray, i);
978                  retVal = st_lookup(Hrc_ModelReadSubcktTable(CurModel),
979                                     childName, &child);
980                  if (retVal) {
981                    array_insert_last(Hrc_Subckt_t*, children, child);
982                  } else {
983                    (void) fprintf(vis_stderr, "Could not find instance %s\n",
984                                   childName);
985                  }
986                }
987                break;
988              default:          /* Unreached */
989                break;
990          }
991          break;
992    }
993    for (i=0; i < array_n(nameArray); i++) {
994      varName = array_fetch(char*, nameArray, i);
995      FREE(varName);
996    }
997    array_free(nameArray); nameArray = 0;
998  }
999  if (groupName) {
1000    group = RstGroupComponents(CurModel, groupName, vars, children);
1001    if (group) 
1002      array_insert_last(Rst_Group_t*, groupArray, group);
1003    else
1004      (void) fprintf(vis_stderr, "Incomplete group %s\n", groupName);
1005    array_free(vars); vars = 0;
1006    array_free(children); children = 0;
1007    FREE(groupName);
1008  }
1009
1010  if (array_n(groupArray) > 0) {
1011    Rst_GroupRestructureNode(*Hmgr, curNode, groupArray);
1012    for (i=0; i < array_n(groupArray); i++) {
1013      group = array_fetch(Rst_Group_t*, groupArray, i);
1014      RstGroupFree(group);
1015    }
1016    array_free(groupArray); groupArray = 0;
1017  } else {
1018    (void) fprintf(vis_stderr, "ERROR: no groups defined\n");
1019    array_free(groupArray);
1020    return 1;
1021  }
1022  return 0;                     /* normal exit */
1023
1024usage:
1025   if (vars) array_free(vars); vars = 0;
1026   if (children) array_free(children); children = 0;
1027  FREE(groupName); groupName = 0;
1028  array_free(nameArray); nameArray = 0;
1029  array_free(groupArray);
1030  (void) fprintf(vis_stderr, "usage: decompose_child -n <groupname>");
1031  (void) fprintf(vis_stderr, " [-f <filename>] [-c] [-v] [<names>] [-t] [-l] [-h] \n");
1032  (void) fprintf(vis_stderr, "   -n\t\tName of new child group \n");
1033  (void) fprintf(vis_stderr, "   -f\t\tLoad names from file \n");
1034  (void) fprintf(vis_stderr, "   -c\t\tGroup by children toggle (default)\n");
1035  (void) fprintf(vis_stderr, "   -v\t\tGroup by variable toggle \n");
1036  (void) fprintf(vis_stderr, "   -l\t\tGroup latches\n");
1037  (void) fprintf(vis_stderr, "   -t\t\tGroup combinational logic tables \n");
1038  (void) fprintf(vis_stderr, "   -h\t\thelp \n");
1039  return 1;                     /* error exit */
1040
1041}
1042
1043/*---------------------------------------------------------------------------*/
1044/* Definition of internal functions                                          */
1045/*---------------------------------------------------------------------------*/
1046
1047
1048/*---------------------------------------------------------------------------*/
1049/* Definition of static functions                                            */
1050/*---------------------------------------------------------------------------*/
1051
1052/**Function********************************************************************
1053
1054  Synopsis    [Allocates a group.]
1055
1056  Description [Initializes all tables for collecting components of a
1057  group for node partitioning.  The VarBackPtr table stores pointers
1058  from newly allocated variables to their original variables in the
1059  Node being partitioned.]
1060
1061  SideEffects [Creates a new Rst_Group_t.]
1062
1063  SeeAlso     [RstGroupFree, RstGroupPrint]
1064
1065******************************************************************************/
1066Rst_Group_t*
1067RstGroupAlloc(char* Name)
1068{
1069  Rst_Group_t* group = ALLOC(Rst_Group_t, 1);
1070
1071  group->Vars = st_init_table(st_ptrcmp, st_ptrhash);
1072  group->Latches = st_init_table(st_ptrcmp, st_ptrhash);
1073  group->Tables = st_init_table(st_ptrcmp, st_ptrhash);
1074  group->Subcircuits = st_init_table(st_ptrcmp, st_ptrhash);
1075  group->Inputs = st_init_table(st_ptrcmp, st_ptrhash);
1076  group->Outputs = st_init_table(st_ptrcmp, st_ptrhash);
1077  group->VarBackPtr = st_init_table(st_ptrcmp, st_ptrhash);
1078  group->name = ALLOC(char, strlen(Name) + 1);
1079  strcpy(group->name, Name);
1080  return group;
1081}
1082
1083/**Function********************************************************************
1084
1085  Synopsis    [Frees a group.]
1086
1087  Description [Frees all tables associated with a group.
1088  Frees the name stored with the group.]
1089
1090  SideEffects []
1091
1092  SeeAlso     [RstGroupAlloc, RstGroupPrint]
1093
1094******************************************************************************/
1095void
1096RstGroupFree(Rst_Group_t* Group)
1097{
1098  st_free_table(Group->Vars);
1099  st_free_table(Group->Latches);
1100  st_free_table(Group->Tables);
1101  st_free_table(Group->Subcircuits);
1102  st_free_table(Group->Inputs);
1103  st_free_table(Group->Outputs);
1104  st_free_table(Group->VarBackPtr);
1105  FREE(Group->name);
1106  FREE(Group);                  /* Watch for dangling references  */
1107}
1108
1109/**Function********************************************************************
1110
1111  Synopsis    [Creates a new name for the node being partitioned.]
1112
1113  Description []
1114
1115  SideEffects []
1116
1117  SeeAlso     []
1118
1119******************************************************************************/
1120char*
1121RstGroupNewParentName(
1122  char* Name)
1123{
1124  char* newName = util_strcat3(Name, "_N", "");
1125  return newName;
1126}
1127
1128/**Function********************************************************************
1129
1130  Synopsis    [Prints the tables of a group for debug purposes.]
1131
1132  Description []
1133
1134  SideEffects []
1135
1136  SeeAlso     []
1137
1138******************************************************************************/
1139void
1140RstGroupPrint(
1141  Rst_Group_t* group)
1142{
1143  st_generator* sgen;
1144  Var_Variable_t* var;
1145  Hrc_Subckt_t* subckt;
1146  Hrc_Latch_t* latch;
1147 
1148  printf("GROUP: %s\n\tInputs:\t", group->name);
1149  st_foreach_item(group->Inputs, sgen, &var, NIL(char *)) {
1150    printf("%s ", Var_VariableReadName(var));
1151  }
1152  printf("\n\tOutputs:\t");
1153  st_foreach_item(group->Outputs, sgen, &var, NIL(char *)) {
1154    printf("%s ", Var_VariableReadName(var));
1155  }
1156  printf("\n\tSubcircuits:\t");
1157  st_foreach_item(group->Subcircuits, sgen, &subckt, NIL(char *)) {
1158    printf("%s ", Hrc_SubcktReadInstanceName(subckt));
1159  }
1160  printf("\n\tLatches:\t");
1161  st_foreach_item(group->Latches, sgen, &latch, NIL(char *)) {
1162    printf("%s ", Var_VariableReadName(Hrc_LatchReadOutput(latch)));
1163  }
1164  printf("\n\tVars:\t");
1165  st_foreach_item(group->Vars, sgen, &var, NIL(char *)) {
1166    printf("%s ", Var_VariableReadName(var));
1167  }
1168  printf("\n");
1169}
1170
1171/**Function********************************************************************
1172
1173  Synopsis    [Makes sure groups are disjoint.]
1174
1175  Description [Checks that each Variable, Table, Latch, and Subcircuit
1176  is assigned to one and only one group.]
1177
1178  SideEffects []
1179
1180  SeeAlso     [Rst_GroupBuildModel]
1181
1182******************************************************************************/
1183int
1184RstGroupDisjointCheck(
1185  array_t* GroupArray)
1186{
1187  int i, j, retVal;
1188  st_generator *sgen;
1189  Hrc_Subckt_t* subckt;
1190  Rst_Group_t* group1, *group2;
1191  Hrc_Latch_t* latch;
1192  Tbl_Table_t* tbl;
1193  Var_Variable_t* var;
1194
1195  for (i = 0; i < array_n(GroupArray); i++) {
1196      group1 = array_fetch(Rst_Group_t*, GroupArray, i);
1197    for (j = i + 1; j < array_n(GroupArray); j++) {
1198      group2 = array_fetch(Rst_Group_t*, GroupArray, j);
1199     
1200      st_foreach_item(group1->Subcircuits, sgen, &subckt, NULL) {
1201        retVal = st_lookup(group2->Subcircuits, (char*) subckt, NIL(char *));
1202        if (retVal) {
1203          (void) fprintf(vis_stderr,
1204                         "ERROR: component %s assigned to groups %s and %s\n",
1205                         Hrc_SubcktReadInstanceName(subckt),
1206                         group1->name, group2->name);
1207          return 1;
1208        }
1209      }
1210      st_foreach_item(group1->Vars, sgen, &var, NULL) {
1211        retVal = st_lookup(group2->Vars, (char*) var, NIL(char *));
1212        if (retVal) {
1213          (void) fprintf(vis_stderr,
1214                         "ERROR: var %s assigned to groups %s and %s\n",
1215                         Var_VariableReadName(var),
1216                         group1->name, group2->name);
1217          return 1;
1218        }
1219      }
1220      st_foreach_item(group1->Tables, sgen, &tbl, NULL) {
1221        retVal = st_lookup(group2->Tables, (char*) tbl, NIL(char *));
1222        if (retVal) {
1223          (void) fprintf(vis_stderr,
1224                         "ERROR: table assigned to groups %s and %s\n",
1225                         group1->name, group2->name);
1226          return 1;
1227        }
1228      }
1229      st_foreach_item(group1->Latches, sgen, &latch, NULL) {
1230        retVal = st_lookup(group2->Latches, (char*) latch, NIL(char *));
1231        if (retVal) {
1232          (void) fprintf(vis_stderr,
1233                         "ERROR: latch %s assigned to groups %s and %s\n",
1234                         Var_VariableReadName(Hrc_LatchReadOutput(latch)),
1235                         group1->name, group2->name);
1236          return 1;
1237        }
1238      }
1239    }
1240  }
1241  return 0;
1242} 
1243
1244/**Function********************************************************************
1245
1246  Synopsis    [Creates the Parent Group.]
1247
1248  Description [Creates a special Group representing components of a
1249  Node "left behind" by a partitioning of it's components into groups.
1250  This takes special care because Vars have to remain in the parent if
1251  they are on the interface of a Group or connect remaining components
1252  of the Parent.]
1253
1254  SideEffects [Allocates a new Rst_Group_t]
1255
1256  SeeAlso     [RstGroupComponents, RstGroupBuildModel, Rst_GroupRestructureNode]
1257
1258******************************************************************************/
1259Rst_Group_t*
1260RstCreateParentGroup(
1261  Hrc_Manager_t* Hmgr,
1262  Hrc_Model_t* ParentModel,
1263  char* NewModelName,
1264  array_t* GroupArray)
1265{
1266  int i, j, tblIndx, varIndx;
1267  long inGroup; 
1268  char *latchName, *subcktName, *varName;
1269  st_generator* sgen;
1270  Var_Variable_t* var;
1271  Tbl_Table_t* tbl;
1272  Hrc_Latch_t* latch;
1273  Hrc_Subckt_t *subckt;
1274  Hrc_Node_t *parentMaster;
1275  Rst_Group_t *group, *parentGroup;
1276  array_t* subOutputs;
1277
1278  /* Build a parent group */
1279
1280  parentGroup = RstGroupAlloc(NewModelName);
1281  parentMaster = Hrc_ModelReadMasterNode(ParentModel);
1282
1283  /* IO of latches of parent group are parent group vars */
1284 
1285  Hrc_NodeForEachLatch(parentMaster, sgen, latchName, latch) {
1286    for (i = 0; i < array_n(GroupArray); i++) {
1287      group = array_fetch(Rst_Group_t*, GroupArray, i);
1288      if (st_lookup(group->Latches, (char*) latch, &inGroup)) {
1289        break;
1290      }
1291    }
1292    if (i >= array_n(GroupArray)) {
1293      st_insert(parentGroup->Latches, (char*) latch, (char*) (long) 1);
1294      var = Hrc_LatchReadInput(latch);
1295      if (! st_lookup(parentGroup->Vars, (char*) var, &inGroup)) {
1296        st_insert(parentGroup->Vars, (char*) var, (char*) (long) 1);
1297      }
1298      var = Hrc_LatchReadOutput(latch);
1299      if (! st_lookup(parentGroup->Vars, (char*) var, &inGroup)) {
1300        st_insert(parentGroup->Vars, (char*) var, (char*) (long) 1);
1301      }
1302    }
1303  }
1304
1305  /* IO of parent group tables (that stay in parent) are parent group vars */
1306 
1307  Hrc_NodeForEachNameTable(parentMaster, tblIndx, tbl) {
1308    for (i = 0; i < array_n(GroupArray); i++) {
1309      group = array_fetch(Rst_Group_t*, GroupArray, i);
1310      if (st_lookup(group->Tables, (char*) tbl, &inGroup)) {
1311        break;
1312      }
1313    }
1314    if (i >= array_n(GroupArray)) {
1315      /* Table stays in parent */
1316      st_insert(parentGroup->Tables, (char*) tbl, (char*) (long) 1);
1317      Tbl_TableForEachInputVar(tbl, varIndx, var) {
1318        if (! st_lookup(parentGroup->Vars, (char*) var, &inGroup)) {
1319          st_insert(parentGroup->Vars, (char*) var, (char*) (long) 1);
1320        }
1321      }
1322      Tbl_TableForEachOutputVar(tbl, varIndx, var) {
1323        if (! st_lookup(parentGroup->Vars, (char*) var, &inGroup)) {
1324          st_insert(parentGroup->Vars, (char*) var, (char*) (long) 1);
1325        }
1326      }
1327    }
1328  }
1329 
1330  /* IO of groups are group Vars of the parent.  Note that inputs are
1331   never group vars of a group EXCEPT in the case of the parent group */
1332 
1333  Hrc_NodeForEachVariable(parentMaster, sgen, varName, var) {
1334    if (! st_lookup(parentGroup->Vars, (char*) var, &inGroup)) {
1335      for (i = 0; i < array_n(GroupArray); i++) {
1336        group = array_fetch(Rst_Group_t*, GroupArray, i);
1337        if ((st_lookup(group->Inputs, (char*) var, &inGroup)) ||
1338            (st_lookup(group->Outputs, (char*) var, &inGroup))) {
1339          break;
1340        }
1341      }
1342      if (i < array_n(GroupArray)) {
1343        st_insert(parentGroup->Vars, (char*) var, (char*) (long) 1);
1344      }
1345    }
1346  }
1347
1348  /* All formal IO of old parent remains part of the parent group */
1349 
1350  Hrc_NodeForEachFormalInput(parentMaster, i, var)
1351    st_insert(parentGroup->Inputs, (char*) var, (char*) (long) 1);
1352
1353  Hrc_NodeForEachFormalOutput(parentMaster, i, var)
1354    st_insert(parentGroup->Outputs, (char*) var, (char*) (long) 1);
1355
1356  /* Outputs of subckts of parent group are parent group vars
1357   We do this last to catch this possible dangling input scenario*/
1358 
1359  Hrc_ModelForEachSubckt(ParentModel, sgen, subcktName, subckt) {
1360    for (i = 0; i < array_n(GroupArray); i++) {
1361      group = array_fetch(Rst_Group_t*, GroupArray, i);
1362      if (st_lookup(group->Subcircuits, (char*) subckt, &inGroup)) {
1363        break;
1364      }
1365    }
1366    if (i >= array_n(GroupArray)) {
1367      st_insert(parentGroup->Subcircuits, (char*) subckt, (char*) (long) 1);
1368      subOutputs = Hrc_SubcktReadActualOutputVars(subckt);
1369      Rst_VarForEachVarInArray(subOutputs, j, var) {
1370        if (! st_lookup(parentGroup->Vars, (char*) var, &inGroup)) {
1371          st_insert(parentGroup->Vars, (char*) var, (char*) (long) 1);
1372        }
1373      }
1374      /* FIXME: Possible bug: inputs are caught because they are
1375         outputs of other components.  But a dangling input (ie, one
1376         with no connection to anything) might get dropped. But adding
1377         an input var might cause it's driving component to be
1378         incorporated!  We opt for a warning here.  */
1379      /* FIXME: Hack-using same array */
1380      subOutputs = Hrc_SubcktReadActualInputVars(subckt); 
1381      Rst_VarForEachVarInArray(subOutputs, j, var) {
1382        if ((! st_lookup(parentGroup->Vars, (char*) var, &inGroup)) &&
1383            (! st_lookup(parentGroup->Inputs, (char*) var, &inGroup))) {
1384          (void) fprintf(vis_stderr,
1385                         "Warning: subcircuit %s has input variable %s ",
1386                         subcktName, Var_VariableReadName(var));
1387          (void) fprintf(vis_stderr, "that has no driver in parent %s\n",
1388                         parentGroup->name);
1389        }
1390      }
1391    }
1392  }
1393  return parentGroup;
1394}
1395
1396/**Function********************************************************************
1397
1398  Synopsis    [Debug routine for printing a Model.]
1399
1400  Description [Prints the IO and Vars of a new Model]
1401
1402  SideEffects []
1403
1404  SeeAlso     [RstGroupBuildModel]
1405
1406******************************************************************************/
1407void
1408RstModelPrint(
1409  Hrc_Model_t* newModel)
1410{
1411  Hrc_Node_t* newMaster;
1412  int i;
1413  st_generator* sgen;
1414  char* varName;
1415  Var_Variable_t* var;
1416
1417  /* Print out new model  */
1418  printf("Model %s\n", Hrc_ModelReadName(newModel));
1419  newMaster = Hrc_ModelReadMasterNode(newModel);
1420  printf("\tInputs :\t");
1421  Rst_VarForEachVarInArray(Hrc_NodeReadFormalInputs(newMaster), i, var) {
1422    printf("%s ", Var_VariableReadName(var));
1423  }
1424  printf("\n\tOutputs:\t");
1425  Rst_VarForEachVarInArray(Hrc_NodeReadFormalOutputs(newMaster), i, var) {
1426    printf("%s ", Var_VariableReadName(var));
1427  }
1428  printf("\n\tVars:\t");
1429  Hrc_NodeForEachVariable(Hrc_ModelReadMasterNode(newModel),
1430                          sgen, varName, var) {
1431    printf("%s ", Var_VariableReadName(var));
1432  }
1433  printf("\n");
1434}
1435
1436/**Function********************************************************************
1437
1438  Synopsis    [Builds a Model from a Group.]
1439
1440  Description [Uses the tables of a group to replicate the portion of
1441  a Node' structure contained by a Groups.  Duplicates Variables,
1442  Tables, Latches, and Subcircuit Instances to create a Model reflecting
1443  the structure of the Group.]
1444
1445  SideEffects [Allocates a new Hrc_Model_t.]
1446
1447  SeeAlso     [RstGroupComponents, Rst_GroupRestructureNode,
1448  Rst_CommandGroupComponents]
1449
1450******************************************************************************/
1451Hrc_Model_t*
1452RstGroupBuildModel(
1453  Hrc_Manager_t* Hmgr,
1454  Rst_Group_t* Group)
1455{
1456  long inGroup; 
1457  int retVal, i;
1458  st_generator* sgen;
1459  Var_Variable_t* var, *newVar, *newLatchInput, *newLatchOutput;
1460  Tbl_Table_t* tbl, *newTbl;
1461  Hrc_Latch_t* latch, *newLatch;
1462  st_table* varForwPtr;
1463  Hrc_Node_t* newMaster;
1464  Hrc_Subckt_t *subckt;
1465  Hrc_Model_t* subcktModel;
1466  Hrc_Model_t* newModel = Hrc_ModelAlloc(Hmgr, Group->name);
1467  array_t* actualInputArray, *actualOutputArray;
1468
1469  if (! newModel) {
1470    (void) fprintf(vis_stderr, "ERROR: could not create Model %s\n",
1471                   Group->name);
1472    return 0;
1473  }
1474 
1475  newMaster = Hrc_ModelReadMasterNode(newModel);
1476  assert(newMaster);
1477
1478  varForwPtr = st_init_table(st_ptrcmp, st_ptrhash);
1479  /* Add group's Variables: Inputs, Outputs */
1480  st_foreach_item(Group->Inputs, sgen, &var, &inGroup) {
1481    if (! st_lookup(varForwPtr, (char*) var, &newVar)) {
1482      newVar = Var_VariableDup(var, newMaster);
1483      Var_VariableResetAllTypes(newVar);
1484      Var_VariableResetNumFanoutTables(newVar);
1485      Hrc_NodeAddFormalInput(newMaster, newVar);
1486      Var_VariableSetPI(newVar);
1487      st_insert(Group->VarBackPtr, (char*) newVar, (char*) var);
1488      st_insert(varForwPtr, (char*) var, (char*) newVar);
1489    }
1490  }
1491  st_foreach_item(Group->Outputs, sgen, &var, &inGroup) {
1492    if (! st_lookup(varForwPtr, (char*) var, &newVar)) {
1493      newVar = Var_VariableDup(var, newMaster);
1494      Var_VariableResetAllTypes(newVar);
1495      Var_VariableResetNumFanoutTables(newVar);
1496      Hrc_NodeAddFormalOutput(newMaster, newVar);
1497      Var_VariableSetPO(newVar);
1498      st_insert(Group->VarBackPtr, (char*) newVar, (char*) var);
1499      st_insert(varForwPtr, (char*) var, (char*) newVar);
1500    }
1501  }
1502  st_foreach_item(Group->Vars, sgen, &var, &inGroup) {
1503    if (! st_lookup(varForwPtr, (char*) var, &newVar)) {
1504      newVar = Var_VariableDup(var, newMaster);
1505      Var_VariableResetAllTypes(newVar);
1506      Var_VariableResetNumFanoutTables(newVar);
1507      st_insert(Group->VarBackPtr, (char*) newVar, (char*) var);
1508      st_insert(varForwPtr, (char*) var, (char*) newVar);
1509    }
1510  }
1511     
1512  /* Add group's Tables */
1513  st_foreach_item(Group->Tables, sgen, &tbl, &inGroup) {
1514    Hrc_NodeAddNameTable(newMaster, Tbl_TableDupAndSubstVars(tbl, varForwPtr));
1515  }
1516
1517  /* Add group's Latches */
1518  st_foreach_item(Group->Latches, sgen, &latch, &inGroup) {
1519    retVal = st_lookup(varForwPtr, (char*) Hrc_LatchReadInput(latch),
1520                       &newLatchInput);
1521    assert(retVal);
1522    retVal = st_lookup(varForwPtr, (char*) Hrc_LatchReadOutput(latch),
1523                       &newLatchOutput);
1524    assert(retVal);
1525   
1526    newLatch = Hrc_LatchCreate(newModel, newLatchInput, newLatchOutput);
1527    assert(newLatch != NULL);
1528    Var_VariableSetNS(newLatchInput);
1529    Var_VariableSetPS(newLatchOutput);
1530   
1531    /* Duplicate and attach Reset Table */
1532    tbl = Hrc_LatchReadResetTable(latch);
1533    newTbl = Tbl_TableDupAndSubstVars(tbl, varForwPtr);
1534    /* HACK: For some reason, we don't count latches in fanout count  */
1535    retVal = Hrc_LatchSetResetTable(newLatch, newTbl);
1536/*    newTbl = Hrc_LatchReadResetTable(latch); */
1537    assert(retVal);
1538    Tbl_TableForEachInputVar(tbl, i, var) {
1539      retVal = st_lookup(varForwPtr, (char*) var, &newVar);
1540      assert(retVal);
1541      Var_VariableResetAllTypes(newVar);
1542      Var_VariableResetNumFanoutTables(newVar);
1543    }
1544    Hrc_NodeAddLatch(newMaster, newLatch);
1545  }
1546
1547  /* Add group's Subckts */
1548 
1549  st_foreach_item(Group->Subcircuits, sgen, &subckt, &inGroup) {
1550    actualInputArray =
1551      Rst_VartoVarLookup(Hrc_SubcktReadActualInputVars(subckt),
1552                         varForwPtr, 0);
1553    actualOutputArray =
1554      Rst_VartoVarLookup(Hrc_SubcktReadActualOutputVars(subckt),
1555                         varForwPtr, 0);
1556    subcktModel = Hrc_SubcktReadModel(subckt);
1557    Hrc_ModelAddSubckt(newModel, subcktModel,
1558                       Hrc_SubcktReadInstanceName(subckt),
1559                       actualInputArray, actualOutputArray);
1560    Rst_VarForEachVarInArray(actualInputArray, i, var) {
1561      Var_VariableSetSI(var);
1562    }
1563    Rst_VarForEachVarInArray(actualOutputArray, i, var) {
1564      Var_VariableSetSO(var);
1565    }
1566  }
1567
1568  st_free_table(varForwPtr);
1569
1570#ifdef RST_GROUP_DEBUG
1571  RstModelPrint(newModel);
1572#endif
1573  return newModel;
1574}
1575
1576/* Overrides for Emacs so that we follow VIS tabbing style.
1577 * Must remain at end of file.
1578 * ---------------------------------------------------------------------------
1579 * Local variables:
1580 * c-basic-offset: 2
1581 * c-indent-level: 2
1582 * c-brace-imaginary-offset: 0
1583 * c-brace-offset: -2
1584 * c-argdecl-indent: 2
1585 * c-comment-only-line-offset: 0
1586 * c-label-offset: -4
1587 * c-continued-statement-offset: 2
1588 * c-continued-brace-offset: 0
1589 * End: */
Note: See TracBrowser for help on using the repository browser.