/**CFile*********************************************************************** FileName [rst.c] PackageName [rst] Synopsis [utilities for restructuring hierarchy ] Author [Sriram Rajamani , with many thanks to Yuji Kuimoto] Copyright [Copyright (c) 1994-1996 The Regents of the Univ. of California. All rights reserved. Permission is hereby granted, without written agreement and without license or royalty fees, to use, copy, modify, and distribute this software and its documentation for any purpose, provided that the above copyright notice and the following two paragraphs appear in all copies of this software. IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.] ******************************************************************************/ #include "rstInt.h" static char rcsid[] UNUSED = "$Id: rst.c,v 1.6 2005/04/16 07:33:12 fabio Exp $"; /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Structure declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ int verbose = 0; /* default value */ /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static int CommandCollapseChild(Hrc_Manager_t ** hmgr, int argc, char ** argv); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Initializes the test package.] SideEffects [] SeeAlso [Rst_End] ******************************************************************************/ void Rst_Init(void) { /* * Add a command to the global command table. By using the leading * underscore, the command will be listed under "help -a" but not "help". */ Cmd_CommandAdd("collapse_child", CommandCollapseChild, /* doesn't changes_network */ 0); Cmd_CommandAdd("decompose_child", Rst_CommandGroupComponents, /* doesn't changes_network */ 0); } /**Function******************************************************************** Synopsis [Ends the test package.] SideEffects [] SeeAlso [Rst_Init] ******************************************************************************/ void Rst_End(void) { /* * For example, free any global memory (if any) which the test package is * responsible for. */ } /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Implements the collapse_child command.] CommandName [collapse_child] CommandSynopsis [Collapses a parent (which is the current node) and a given child node into the parent] CommandArguments [\[-h\] \[-v\] <child_instance_name>] CommandDescription [This command collapses the given child into the current node. After this command, the number of children of the current node will decrease by one. The variables in the child node will be renamed to reflect their original name. For example, if the current node is named "foo" and it has two children, "bar1" and "bar2", then after

collapse_child bar1

is executed, the name of any variable occuring in bar1, say "xvar" will be renamed "bar1$xvar". The new parent will have only the single child "bar2" (which can be seen by typing "ls").

The user can use "cd" to traverse a hierarchy, go to a particular node. When the user uses "write_blif" from a particular node, vis will write the circuit in this node out. However, the user might want to do synthesis on the entire circuit in the hierarchy. In that case, the hierarchy can be collapsed into a single node, by repeatedly using this command.

Examples:

collapse_child P1

Collapse P1 into the current node.

Command options:

-h
Print the command usage.
-v
Verbose mode. ] SideEffects [] ******************************************************************************/ static int CommandCollapseChild( Hrc_Manager_t ** hmgr, int argc, char ** argv) { int c; Hrc_Node_t *parent, *child; boolean retVal; verbose = 0; /* * Parse command line options. */ util_getopt_reset(); while ((c = util_getopt(argc, argv, "vh")) != EOF) { switch(c) { case 'v': verbose = 1; break; case 'h': goto usage; default: goto usage; } } if(argc < 2){ goto usage; } parent = Hrc_ManagerReadCurrentNode(*hmgr); if (parent == NULL) { fprintf(vis_stderr, "Can't find parent node \n"); return(1); } if (argc - util_optind == 0) { (void) fprintf(vis_stderr, "Child node name not provided\n"); goto usage; } else if (argc - util_optind > 1) { (void) fprintf(vis_stderr, "too many arguments\n"); goto usage; } if(verbose) (void)fprintf(vis_stdout, "Collapsing child : %s\n", argv[util_optind]); child = Hrc_ManagerFindNodeByPathName(*hmgr, argv[util_optind],TRUE); if (child == NULL) { fprintf(vis_stderr, "Can't find child node %s\n", argv[util_optind]); return(1); } retVal = RstCollapseNode( *hmgr, parent, child); return(retVal); usage: (void) fprintf(vis_stdout, "The collapse_child command collapses the child node into the current node.\n"); (void) fprintf(vis_stderr, "usage: collapse_child [-h] [-v] \n"); (void) fprintf(vis_stderr, " -h\t\tprint the command usage\n"); (void) fprintf(vis_stderr, " -v\t\tverbose\n"); return 1; /* error exit */ } /**Function******************************************************************** Synopsis [Given node1 and node2 where node1 is a parent of node2, this function collapses node2 into node1] Description [optional] SideEffects [node2 will be deleted from the hierarchy and banished into thin air. Current node will be set to new parent] SeeAlso [optional] ******************************************************************************/ int RstCollapseNode( Hrc_Manager_t *hmgr, Hrc_Node_t *parent, Hrc_Node_t *child ) { boolean foundChild; st_generator *gen; /*XXX - Do I need to initialize this */ char *curChildName, *newModelName, *parentModelName, *parentInstanceName, *suffixModelName; Hrc_Node_t *curChild, *newNode, *root; Hrc_Model_t *parentModelPtr, *childModelPtr, *newModelPtr; array_t *actualInputArray, *actualOutputArray, *formalInputArray, *formalOutputArray; st_table *parentVarTable, *childVarTable; int i; Var_Variable_t *var, *newVar; boolean retVal; /* set current node to parent */ Hrc_ManagerSetCurrentNode(hmgr, parent); /* get root node */ root = Hrc_ManagerReadRootNode(hmgr); /* check if the child is really our child */ foundChild = FALSE; Hrc_NodeForEachChild ( parent, gen, curChildName, curChild){ if(curChild == child) foundChild = TRUE; } if(!foundChild) { fprintf(vis_stdout, "Collapse called with bad child\n"); return(-1); } /* get masternodes for parent and child */ parentModelPtr = Hrc_ManagerFindModelByName(hmgr,Hrc_NodeReadModelName(parent)); assert(parentModelPtr != NULL); childModelPtr = Hrc_ManagerFindModelByName(hmgr,Hrc_NodeReadModelName(child)); assert(childModelPtr != NULL); /* create a new model by concatenating names of parent and child */ suffixModelName = util_strcat3( Hrc_ModelReadName(parentModelPtr), "#",Hrc_ModelReadName(childModelPtr)); newModelName = util_strcat3( Hrc_NodeReadInstanceName(child), "#",suffixModelName); FREE(suffixModelName); assert(newModelName != 0); newModelPtr = Hrc_ManagerFindModelByName(hmgr, newModelName); if(newModelPtr != NULL){ fprintf(vis_stdout, "Warning: rst has detected an existing model with name %s\n", newModelName); fprintf(vis_stdout, "If you have collapsed another instance of this child model\n"); fprintf(vis_stdout, "into another instance of this parent previously this is \n"); fprintf(vis_stdout, "normal and collapse_child will function correctly.\n"); fprintf(vis_stdout, "Otherwise, you have a name conflict that rst cannot handle\n"); } else { newModelPtr = Hrc_ModelAlloc(hmgr, newModelName); if(verbose){ fprintf(vis_stdout, "Adding child components to new model\n"); } childVarTable = RstAddChildComponentsToNewModel(hmgr,child, parent, newModelPtr); actualInputArray = Hrc_NodeReadActualInputs(child); actualOutputArray = Hrc_NodeReadActualOutputs(child); formalInputArray = Hrc_NodeReadFormalInputs(child); formalOutputArray = Hrc_NodeReadFormalOutputs(child); assert(array_n(actualInputArray) == array_n(formalInputArray)); assert(array_n(actualOutputArray) == array_n(formalOutputArray)); parentVarTable = st_init_table(st_ptrcmp,st_ptrhash); for ( i = 0; i < array_n(formalInputArray); i++) { /* get the modified child var */ var = array_fetch(Var_Variable_t *, formalInputArray, i); retVal = st_lookup(childVarTable, (char *)var, &newVar); assert(retVal); var = array_fetch(Var_Variable_t *, actualInputArray, i); st_insert(parentVarTable, (char *) var, (char *) newVar); } for ( i = 0; i < array_n(formalOutputArray); i++) { /* get the modified child var */ var = array_fetch(Var_Variable_t *, formalOutputArray, i); retVal = st_lookup(childVarTable, (char *)var, &newVar); assert(retVal); var = array_fetch(Var_Variable_t *, actualOutputArray, i); st_insert(parentVarTable, (char *) var, (char *) newVar); } if(verbose){ fprintf(vis_stdout, "Adding parent components to new model\n"); } RstAddParentComponentsToNewModel(hmgr, parent, newModelPtr, parentVarTable, child); st_free_table(childVarTable); st_free_table(parentVarTable); } if(verbose) fprintf(vis_stdout, "Creating new model hierarchy.\n"); parentInstanceName = Hrc_NodeReadInstanceName(parent); if(verbose) fprintf(vis_stdout, "Retaining old parent's instance name %s\n", parentInstanceName); newNode = Hrc_ModelCreateHierarchy(hmgr, newModelPtr,parentInstanceName); if(verbose) fprintf(vis_stdout, "Replacing old hierarchy tree with new tree.\n"); retVal = Hrc_TreeReplace(parent,newNode); assert(retVal); Hrc_ManagerSetCurrentNode(hmgr,newNode); if(root == parent){ if(verbose){ fprintf(vis_stdout, "Current parent IS the root...\n"); fprintf(vis_stdout, "Deleting old root model\n"); } parentModelName = util_strsav(Hrc_ModelReadName(parentModelPtr)); Hrc_ModelDelete(hmgr, parentModelName); FREE(parentModelName); } FREE(newModelName); return(0); } /**Function******************************************************************** Synopsis [Add Child's components - latches,tables,vars to new model] Description [optional] SideEffects [none] SeeAlso [optional] ******************************************************************************/ st_table * RstAddChildComponentsToNewModel( Hrc_Manager_t *hmgr, Hrc_Node_t *child, Hrc_Node_t *parent, Hrc_Model_t *newModelPtr ) { Hrc_Node_t *newMaster, *grandChild; st_generator *gen; int i,index; Tbl_Table_t *tbl,*newTbl, *resetTbl, *newResetTbl; Var_Variable_t *var, *newVar , *newLatchInput, *newLatchOutput, *parentVar; char *latchName, *varName, *newVarName, *grandChildInstName, *newSubcktName; Hrc_Latch_t *latch, *newLatch; st_table *childVarToNewVar; array_t *actualInputArray, *newActualInputArray; array_t *actualOutputArray, *newActualOutputArray; boolean retVal; newMaster = Hrc_ModelReadMasterNode(newModelPtr); childVarToNewVar = st_init_table(st_ptrcmp,st_ptrhash); /* Add all Child's variables to the new model after prefixing child name */ Hrc_NodeForEachVariable(child, gen, varName, var){ if( Var_VariableTestIsPI(var) || Var_VariableTestIsPO(var)){ parentVar = Hrc_VariableFindActualFromFormal(child, var, parent); assert(parentVar != NULL); newVarName = util_strsav(Var_VariableReadName(parentVar)); assert(newVarName != NULL); } else{ newVarName = util_strcat3(Hrc_NodeReadInstanceName(child), "$", Var_VariableReadName(var)); assert(newVarName != NULL); } newVar = Hrc_NodeFindVariableByName(newMaster, newVarName); if (newVar != NULL){ assert (Var_VariableTestIsPI(var) || Var_VariableTestIsPO(var)); } if(newVar == NULL) { newVar = Var_VariableDup(var,newMaster); retVal = Var_VariableChangeName(newVar,newVarName); assert(retVal); Var_VariableResetAllTypes(newVar); } FREE(newVarName); st_insert(childVarToNewVar, (char *)var, (char *)newVar); } /* Add all Child's tables to new model */ Hrc_NodeForEachNameTable(child, i, tbl){ /* copy the table */ newTbl = Tbl_TableHardDup(tbl); /* Muck with its vars */ Tbl_TableForEachInputVar(newTbl, index, var){ retVal = st_lookup(childVarToNewVar, (char *)var, &newVar); assert(retVal); Tbl_TableSubstituteVar(newTbl,var,newVar); } Tbl_TableForEachOutputVar(newTbl, index, var){ retVal = st_lookup(childVarToNewVar, (char *)var, &newVar); assert(retVal); Tbl_TableSubstituteVar(newTbl,var,newVar); } /* add it in! */ Hrc_NodeAddNameTable(newMaster, newTbl); } /* Add all Child's latches to the new model */ Hrc_NodeForEachLatch( child, gen, latchName, latch){ /* muck with the variables */ retVal = st_lookup(childVarToNewVar, (char *)Hrc_LatchReadInput(latch), &(newLatchInput)); assert(retVal); Var_VariableSetNS(newLatchInput); retVal = st_lookup(childVarToNewVar, (char *)Hrc_LatchReadOutput(latch), &(newLatchOutput)); Var_VariableSetPS(newLatchOutput); assert(retVal); /* get new latch */ newLatch = Hrc_LatchCreate(newModelPtr, newLatchInput, newLatchOutput); assert(newLatch != NULL); /* copy reset table */ resetTbl = Hrc_LatchReadResetTable(latch); assert(resetTbl != NULL); newResetTbl = Tbl_TableSoftDup(resetTbl); /* muck with reset table vars */ Tbl_TableForEachInputVar(newResetTbl, index, var){ retVal = st_lookup(childVarToNewVar, (char *)var, &newVar); assert(retVal); Tbl_TableSubstituteVar(newResetTbl,var,newVar); } Tbl_TableForEachOutputVar(newResetTbl, index, var){ retVal = st_lookup(childVarToNewVar, (char *)var, &newVar); assert(retVal); Tbl_TableSubstituteVar(newResetTbl,var,newVar); } /* Add table to latch */ retVal = Hrc_LatchSetResetTable(newLatch,newResetTbl); assert(retVal); /* add it in! */ Hrc_NodeAddLatch(newMaster, newLatch); } /* add all Child's sub circuits to master */ Hrc_NodeForEachChild(child, gen, grandChildInstName, grandChild) { actualInputArray = Hrc_NodeReadActualInputs(grandChild); actualOutputArray = Hrc_NodeReadActualOutputs(grandChild); newActualInputArray = array_alloc(Var_Variable_t *, 0); newActualOutputArray = array_alloc(Var_Variable_t *, 0); /* same story - var mucking */ for ( i = 0; i < array_n(actualInputArray); i++){ var = array_fetch(Var_Variable_t *, actualInputArray, i); assert(var != NULL); retVal = st_lookup(childVarToNewVar, (char *)var, &newVar); assert(retVal); Var_VariableSetSI(newVar); array_insert_last(Var_Variable_t *, newActualInputArray, newVar); } for ( i = 0; i < array_n(actualOutputArray); i++){ var = array_fetch(Var_Variable_t *, actualOutputArray, i); assert(var != NULL); retVal = st_lookup(childVarToNewVar, (char *)var, &newVar); assert(retVal); Var_VariableSetSO(newVar); array_insert_last(Var_Variable_t *, newActualOutputArray, newVar); } /* add subcircuit to model */ newSubcktName = util_strcat3(Hrc_NodeReadInstanceName(child), "$", Hrc_NodeReadInstanceName(grandChild)); Hrc_ModelAddSubckt(newModelPtr, Hrc_ManagerFindModelByName(hmgr,Hrc_NodeReadModelName(grandChild)), newSubcktName, newActualInputArray, newActualOutputArray); FREE(newSubcktName); } return(childVarToNewVar); } /**Function******************************************************************** Synopsis [Add parents componets to new model] Description [optional] SideEffects [none] SeeAlso [optional] ******************************************************************************/ int RstAddParentComponentsToNewModel( Hrc_Manager_t *hmgr, Hrc_Node_t *parent, Hrc_Model_t *newModelPtr, st_table *parentVarTable, Hrc_Node_t *child ) { Hrc_Node_t *newMaster, *curChild; st_generator *gen; int i,index; Tbl_Table_t *tbl,*newTbl, *resetTbl, *newResetTbl; Var_Variable_t *var, *newVar , *newLatchInput, *newLatchOutput ; char *latchName, *varName, *curChildInstName; Hrc_Latch_t *latch, *newLatch; array_t *actualInputArray, *newActualInputArray; array_t *actualOutputArray, *newActualOutputArray; int pFanout; boolean retVal; newMaster = Hrc_ModelReadMasterNode(newModelPtr); /* Add all Parent's variables to the new model. If a parent variable is an interface to the child, it will change and get merged with the child's correspoinding interface variable */ Hrc_NodeForEachVariable(parent, gen, varName, var){ if(st_lookup(parentVarTable, (char *) var, &newVar) == 0){ /* not an interface to child - copy it */ newVar = Var_VariableDup(var,newMaster); assert(newVar != NULL); Var_VariableResetAllTypes(newVar); st_insert(parentVarTable, (char *)var, (char *)newVar); } else { /* interface variable. Have to increment the number of fanouts */ pFanout = Var_VariableReadNumFanoutTables(var); while(pFanout){ Var_VariableIncrementNumFanoutTables(newVar); pFanout--; } } } /* Add all Parent's tables to new model */ Hrc_NodeForEachNameTable(parent, i, tbl){ /* copy the table */ newTbl = Tbl_TableHardDup(tbl); /* Muck with its vars */ Tbl_TableForEachInputVar(newTbl, index, var){ retVal = st_lookup(parentVarTable, (char *)var, &newVar); assert(retVal); Tbl_TableSubstituteVar(newTbl,var,newVar); } Tbl_TableForEachOutputVar(newTbl, index, var){ retVal = st_lookup(parentVarTable, (char *)var, &newVar); assert(retVal); Tbl_TableSubstituteVar(newTbl,var,newVar); } /* add it in! */ Hrc_NodeAddNameTable(newMaster, newTbl); } /* Add all Parent's latches to the new model */ Hrc_NodeForEachLatch( parent, gen, latchName, latch){ /* muck with the variables */ retVal = st_lookup(parentVarTable, (char *)Hrc_LatchReadInput(latch), &(newLatchInput)); assert(retVal); Var_VariableSetNS(newLatchInput); retVal = st_lookup(parentVarTable, (char *)Hrc_LatchReadOutput(latch), &(newLatchOutput)); assert(retVal); Var_VariableSetPS(newLatchOutput); /* get new latch */ newLatch = Hrc_LatchCreate(newModelPtr, newLatchInput, newLatchOutput); assert(newLatch != NULL); /* copy reset table */ resetTbl = Hrc_LatchReadResetTable(latch); assert(resetTbl != NULL); newResetTbl = Tbl_TableSoftDup(resetTbl); /* muck with reset table vars */ Tbl_TableForEachInputVar(newResetTbl, index, var){ retVal = st_lookup(parentVarTable, (char *)var, &newVar); assert(retVal); Tbl_TableSubstituteVar(newResetTbl,var,newVar); } Tbl_TableForEachOutputVar(newResetTbl, index, var){ retVal = st_lookup(parentVarTable, (char *)var, &newVar); assert(retVal); Tbl_TableSubstituteVar(newResetTbl,var,newVar); } /* add table to latch */ retVal = Hrc_LatchSetResetTable(newLatch,newResetTbl); assert(retVal); /* add it in! */ Hrc_NodeAddLatch(newMaster, newLatch); } /* add all Parent's sub circuits to master except "the" child's */ Hrc_NodeForEachChild(parent, gen, curChildInstName, curChild) { /* do nothing for "the" child */ if(curChild == child){ continue; } actualInputArray = Hrc_NodeReadActualInputs(curChild); actualOutputArray = Hrc_NodeReadActualOutputs(curChild); newActualInputArray = array_alloc(Var_Variable_t *, 0); newActualOutputArray = array_alloc(Var_Variable_t *, 0); /* same story - var mucking */ for ( i = 0; i < array_n(actualInputArray); i++){ var = array_fetch(Var_Variable_t *, actualInputArray, i); retVal = st_lookup(parentVarTable, (char *)var, &newVar); assert(retVal); Var_VariableSetSI(newVar); array_insert_last(Var_Variable_t *, newActualInputArray, newVar); } for ( i = 0; i < array_n(actualOutputArray); i++){ var = array_fetch(Var_Variable_t *, actualOutputArray, i); retVal = st_lookup(parentVarTable, (char *)var, &newVar); assert(retVal); Var_VariableSetSO(newVar); array_insert_last(Var_Variable_t *, newActualOutputArray, newVar); } /* add subcircuit to model */ Hrc_ModelAddSubckt(newModelPtr, Hrc_ManagerFindModelByName(hmgr,Hrc_NodeReadModelName(curChild)), Hrc_NodeReadInstanceName(curChild), newActualInputArray, newActualOutputArray); } /* add all formal inputs */ Hrc_NodeForEachFormalInput( parent, i, var){ retVal = st_lookup(parentVarTable, (char *)var, &newVar); assert(retVal); retVal = Hrc_NodeAddFormalInput(newMaster, newVar); Var_VariableSetPI(newVar); assert(retVal); } /* add all formal outputs */ Hrc_NodeForEachFormalOutput( parent, i, var){ retVal = st_lookup(parentVarTable, (char *)var, &newVar); assert(retVal); retVal = Hrc_NodeAddFormalOutput(newMaster, newVar); Var_VariableSetPO(newVar); assert(retVal); } return(0); } #ifdef COLLAPSE_DEBUG int printVarTable( st_table *varTable) { st_generator *gen; Var_Variable_t *var, *newVar; st_foreach_item( varTable, gen, (char **) &var, (char **)&newVar){ printf("address: %u : %15s -> %15s \n", (unsigned)var, Var_VariableReadName(var), Var_VariableReadName(newVar)); } return(0); } #endif