/**CFile*********************************************************************** FileName [hrcMemUtil.c] PackageName [hrc] Synopsis [This file deals with the memory utilities for the hrc package.] Description [] SeeAlso [] Author [Shaz Qadeer] 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 "hrcInt.h" static char rcsid[] UNUSED = "$Id: hrcMemUtil.c,v 1.3 2005/04/16 04:23:47 fabio Exp $"; /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static void ModelFree(Hrc_Model_t *model); static void SubcktFree(Hrc_Subckt_t *subckt); static void LatchFree(Hrc_Latch_t *latch); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Allocates a hierarchy manager.] Description [The function allocates memory for a hierarchy manager. It initializes the model table of the manager and sets rootNode and currentNode to NULL.] SideEffects [] SeeAlso [] ******************************************************************************/ Hrc_Manager_t * Hrc_ManagerAlloc( void) { Hrc_Manager_t *manager = ALLOC(Hrc_Manager_t, 1); manager->rootNode = NIL(Hrc_Node_t); manager->currentNode = NIL(Hrc_Node_t); manager->modelTable = st_init_table(strcmp, st_strhash); return manager; } /**Function******************************************************************** Synopsis [Allocates a model with a given name.] Description [The function checks if a model by the name modelName already exists. If it does NULL is returned otherwise memory for a new model is allocated. A copy of modelName is made and stored in the model. Therefore, the string modelName should be freed by the user. The subcircuit table and the master node of the model are initialized. The model is registered with the manager.] SideEffects [] SeeAlso [] ******************************************************************************/ Hrc_Model_t * Hrc_ModelAlloc( Hrc_Manager_t *manager, char *modelName) { Hrc_Model_t *model; if(!st_is_member(manager->modelTable,modelName)){ model = ALLOC(Hrc_Model_t, 1); model->modelName = util_strsav(modelName); st_insert(manager->modelTable, model->modelName, (char *) model); model->subcktTable = st_init_table(strcmp, st_strhash); model->masterNode = Hrc_NodeAlloc(manager, model->modelName, NIL(char), NIL(Hrc_Node_t)); return model; } else { return NIL(Hrc_Model_t); } } /**Function******************************************************************** Synopsis [Allocates a node for a particular instantiation of a model.] Description [The function allocates memory for a node and initializes all the arrays and hash tables inside the node. Note that the user must free the strings modelName and instanceName because copies of these strings are made and stored. The undef field is set to NULL.] SideEffects [] SeeAlso [] ******************************************************************************/ Hrc_Node_t * Hrc_NodeAlloc( Hrc_Manager_t *manager, char *modelName, char *instanceName, Hrc_Node_t *parentNode) { Hrc_Node_t *node = ALLOC(Hrc_Node_t, 1); /* The manager field is needed only for allocating the parent node. For allocating any other node in the hierarchy, the manager can be obtained from the parent node. */ node->manager = manager; node->modelName = util_strsav(modelName); node->instanceName = util_strsav(instanceName); node->parentNode = parentNode; node->formalInputs = array_alloc(Var_Variable_t *, 0); node->formalOutputs = array_alloc(Var_Variable_t *, 0); /* The arrays actualInputs and actualOutputs do not need to be allocated because 1) they are never needed for the master node of a model, and 2) they are written over whenever a new node is added to the hierarchy by using Hrc_NodeAddChild() */ node->actualInputs = NIL(array_t); node->actualOutputs = NIL(array_t); node->nameTables = array_alloc(Tbl_Table_t *, 0); node->childTable = st_init_table(strcmp, st_strhash); node->latchTable = st_init_table(strcmp, st_strhash); node->varTable = st_init_table(strcmp, st_strhash); node->applInfoTable = st_init_table(strcmp, st_strhash); node->undef = NIL(void); return node; } /**Function******************************************************************** Synopsis [Duplicates a node with a new instance name.] Description [The function duplicates a node. The manager, parentNode, and undef fields are simply copied into the duplicated node. All the other fields viz. hash tables and arrays are allocated anew. All the variables and tables are duplicated. Note that actualInputs and actualOutputs are not copied. They are initialized to NULL. The latches are also duplicated (the reset table is duplicated and the undef field is copied). The applInfoTable is duplicated along with its keys. The user should free instanceName because it is copied.] SideEffects [] SeeAlso [] ******************************************************************************/ Hrc_Node_t * Hrc_NodeDup( Hrc_Node_t *node, char *instanceName) { Hrc_Node_t *dupNode = ALLOC(Hrc_Node_t, 1); st_generator *gen; int i, index; Var_Variable_t *var, *dupVar; Tbl_Table_t *table, *dupTable; Hrc_Latch_t *latch, *dupLatch; st_table *varToDupVar; char *name, *dupName; char *key, *dupKey; ApplInfo_t *applInfo; dupNode->manager = node->manager; dupNode->modelName = util_strsav(node->modelName); dupNode->instanceName = util_strsav(instanceName); dupNode->parentNode = node->parentNode; dupNode->formalInputs = array_alloc(Var_Variable_t *, 0); dupNode->formalOutputs = array_alloc(Var_Variable_t *, 0); dupNode->actualInputs = NIL(array_t); dupNode->actualOutputs = NIL(array_t); /* dupNode->actualInputs = array_alloc(Var_Variable_t *, 0); Hrc_NodeForEachActualInput(node, i, var) { dupVar = Var_VariableDup(var, dupNode); array_insert_last(Var_Variable_t *, dupNode->actualInputs, dupVar); } dupNode->actualOutputs = array_alloc(Var_Variable_t *, 0); Hrc_NodeForEachActualOutput(node, i, var) { dupVar = Var_VariableDup(var, dupNode); array_insert_last(Var_Variable_t *, dupNode->actualOutputs, dupVar); } */ dupNode->varTable = st_init_table(strcmp, st_strhash); varToDupVar = st_init_table(st_ptrcmp, st_ptrhash); Hrc_NodeForEachVariable(node, gen, name, var) { dupVar = Var_VariableDup(var, dupNode); dupName = Var_VariableReadName(dupVar); st_insert(dupNode->varTable, dupName, dupVar); st_insert(varToDupVar, var, dupVar); } Hrc_NodeForEachFormalInput(node, i, var) { st_lookup(varToDupVar, var, &dupVar); array_insert_last(Var_Variable_t *, dupNode->formalInputs, dupVar); } Hrc_NodeForEachFormalOutput(node, i, var) { st_lookup(varToDupVar, var, &dupVar); array_insert_last(Var_Variable_t *, dupNode->formalOutputs, dupVar); } dupNode->nameTables = array_alloc(Tbl_Table_t *, 0); Hrc_NodeForEachNameTable(node, i, table) { dupTable = Tbl_TableSoftDup(table); /*dupTable = Tbl_TableHardDup(table);*/ Tbl_TableForEachInputVar(dupTable, index, var) { st_lookup(varToDupVar, var, &dupVar); Tbl_TableSubstituteVar(dupTable, var, dupVar); } Tbl_TableForEachOutputVar(dupTable, index, var) { st_lookup(varToDupVar, var, &dupVar); Tbl_TableSubstituteVar(dupTable, var, dupVar); } array_insert_last(Tbl_Table_t *, dupNode->nameTables, dupTable); } dupNode->latchTable = st_init_table(strcmp, st_strhash); Hrc_NodeForEachLatch(node, gen, name, latch) { dupLatch = ALLOC(Hrc_Latch_t, 1); st_lookup(varToDupVar, latch->latchInput, &(dupLatch->latchInput)); st_lookup(varToDupVar, latch->latchOutput, &(dupLatch->latchOutput)); dupLatch->resetTable = Tbl_TableSoftDup(latch->resetTable); /*dupLatch->resetTable = Tbl_TableHardDup(latch->resetTable);*/ Tbl_TableForEachInputVar(dupLatch->resetTable, index, var) { st_lookup(varToDupVar, var, &dupVar); Tbl_TableSubstituteVar(dupLatch->resetTable, var, dupVar); } Tbl_TableForEachOutputVar(dupLatch->resetTable, index, var) { st_lookup(varToDupVar, var, &dupVar); Tbl_TableSubstituteVar(dupLatch->resetTable, var, dupVar); } dupLatch->undef = latch->undef; st_insert(dupNode->latchTable, Var_VariableReadName(dupLatch->latchOutput), dupLatch); } dupNode->childTable = st_copy(node->childTable); dupNode->applInfoTable = st_init_table(strcmp, st_strhash); st_foreach_item(node->applInfoTable, gen, &key, &applInfo) { dupKey = util_strsav(key); st_insert(dupNode->applInfoTable, dupKey, applInfo); } dupNode->undef = node->undef; st_free_table(varToDupVar); return dupNode; } /**Function******************************************************************** Synopsis [Creates a latch and registers it with a model.] Description [The function looks up the latch in the hash table of latches in the master node of model. If a latch with the same output variable name is not present in the table memory for a new latch is allocated. The resetTable and undef fields of the latch are initialized to NULL and the latch is returned. Otherwise, NULL is returned.] SideEffects [] SeeAlso [] ******************************************************************************/ Hrc_Latch_t * Hrc_LatchCreate( Hrc_Model_t *model, Var_Variable_t *latchInput, Var_Variable_t *latchOutput) { Hrc_Latch_t *latch; char *outputName = Var_VariableReadName(latchOutput); if(!st_is_member(model->masterNode->latchTable, outputName)) { latch = ALLOC(Hrc_Latch_t, 1); latch->latchInput = latchInput; latch->latchOutput = latchOutput; latch->resetTable = NIL(Tbl_Table_t); latch->undef = NIL(void); st_insert(model->masterNode->latchTable, outputName, (char *) latch); return latch; } else { return NIL(Hrc_Latch_t); } } /**Function******************************************************************** Synopsis [Frees a hierarchy manager.] Description [The function frees every node in the hierarchy recursively starting from the root node if it is not NULL. All models in the model table are freed and model table itself is freed.] SideEffects [] SeeAlso [] ******************************************************************************/ void Hrc_ManagerFree( Hrc_Manager_t *manager) { st_generator *gen; char *name; Hrc_Model_t *model; if(manager->rootNode != NIL(Hrc_Node_t)) { HrcNodeFreeRecursively(manager->rootNode); } Hrc_ManagerForEachModel(manager, gen, name, model){ ModelFree(model); } st_free_table(manager->modelTable); FREE(manager); } /**Function******************************************************************** Synopsis [Deletes a model from the manager.] Description [The function looks up the entry for model in the hash table of models in the manager. If the entry is not found, FALSE is returned otherwise it is removed, model is freed, and TRUE is returned. Note that the corresponding master node is freed too.] SideEffects [] SeeAlso [ModelFree()] ******************************************************************************/ boolean Hrc_ModelDelete( Hrc_Manager_t *manager, char *modelName) { Hrc_Model_t *model; if(st_delete(manager->modelTable, &(modelName), &model)) { ModelFree(model); return TRUE; } else { return FALSE; } } /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Frees a tree hanging from a node.] Description [The subtree hanging down from node is freed recursively node by node. In each node, all tables, latches and formal variables are freed and the freeFn is called for all the entries in applInfoTable. The function also frees the memory allocated to the internal fields of all the nodes it frees.] SideEffects [The rootNode and currentNode fields in the hierarchy manager are set to NULL if either of these are freed.] SeeAlso [HrcNodeFreeInternalMemory(), Hrc_TreeReplace()] ******************************************************************************/ void HrcNodeFreeRecursively( Hrc_Node_t *node) { st_generator *gen; char *name; Hrc_Node_t *childNode; if(node == node->manager->rootNode) { node->manager->rootNode = NIL(Hrc_Node_t); } if(node == node->manager->currentNode) { node->manager->currentNode = NIL(Hrc_Node_t); } HrcNodeFreeInternalMemory(node); Hrc_NodeForEachChild(node, gen, name, childNode) { HrcNodeFreeRecursively(childNode); } st_free_table(node->childTable); FREE(node); } /**Function******************************************************************** Synopsis [Frees the memory allocated to the internal fields of a node.] Description [The function frees all tables, latches and formal variables in the node. The keys in applInfoTable and the applInfoTable itself are also freed.] SideEffects [] SeeAlso [HrcNodeFreeRecursively()] ******************************************************************************/ void HrcNodeFreeInternalMemory( Hrc_Node_t *node) { char *name; st_generator *gen; int i; Tbl_Table_t *table; Hrc_Latch_t *latch; Var_Variable_t *var; ApplInfo_t *applInfo; char *key; FREE(node->modelName); FREE(node->instanceName); array_free(node->formalInputs); array_free(node->formalOutputs); /* In a master node of a model, actualInputs and actualOutputs are NULL. That is why the following two checks are needed. */ if(node->actualInputs != NIL(array_t)) { array_free(node->actualInputs); } if(node->actualOutputs != NIL(array_t)) { array_free(node->actualOutputs); } Hrc_NodeForEachNameTable(node, i, table) { Tbl_TableFree(table); } array_free(node->nameTables); Hrc_NodeForEachLatch(node, gen, name, latch) { LatchFree(latch); } st_free_table(node->latchTable); Hrc_NodeForEachVariable(node, gen, name, var) { Var_VariableFree(var); } st_free_table(node->varTable); if(node->applInfoTable) { st_foreach_item(node->applInfoTable, gen, &key, &applInfo) { FREE(key); (*applInfo->freeFn)(applInfo->data); FREE(applInfo); } st_free_table(node->applInfoTable); } } /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Frees the memory allocated to a model and its master node.] Description [The function frees model. It also frees the master node and all the sub-circuits of the model.] SideEffects [] SeeAlso [Hrc_ModelDelete(), Hrc_ManagerFree()] ******************************************************************************/ static void ModelFree( Hrc_Model_t *model) { st_generator *gen; char *name; Hrc_Subckt_t *subckt; FREE(model->modelName); HrcNodeFreeInternalMemory(model->masterNode); st_free_table(model->masterNode->childTable); FREE(model->masterNode); st_foreach_item(model->subcktTable, gen, &name, &subckt) { SubcktFree(subckt); } st_free_table(model->subcktTable); FREE(model); } /**Function******************************************************************** Synopsis [Frees a sub-circuit.] Description [This function frees a sub-circuit. Note that all the variables inside a sub-circuit are freed.] SideEffects [] SeeAlso [ModelFree()] ******************************************************************************/ static void SubcktFree( Hrc_Subckt_t *subckt) { FREE(subckt->instanceName); array_free(subckt->actualInputVars); array_free(subckt->actualOutputVars); FREE(subckt); } /**Function******************************************************************** Synopsis [Frees a latch.] Description [The function frees the latch. If resetTable is not NULL, it is freed. Note that the input and output variables of latch are not freed.] SideEffects [] SeeAlso [HrcNodeFreeInternalMemory()] ******************************************************************************/ static void LatchFree( Hrc_Latch_t *latch) { if(latch->resetTable != NIL(Tbl_Table_t)){ Tbl_TableFree(latch->resetTable); } FREE(latch); }