/**CFile*********************************************************************** FileName [simUtil.c] PackageName [sim] Synopsis [Basic useful functions for the sim package.] Author [Shaker Sarwary and Tom Shiple] 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 "simInt.h" #include static char rcsid[] UNUSED = "$Id: simUtil.c,v 1.8 2005/04/26 19:10:09 jinh Exp $"; /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Builds a table mapping a node to a Mvf_Function.] Description [Builds a table mapping a node to a Mvf_Function. nodesArray should contain every nodes for which a Mvf_Function is requested. Returns an empty table if nodesArray doesn't contain any node.] SideEffects [] ******************************************************************************/ st_table * Sim_NetworkBuildNodeToMvfTable( Ntk_Network_t *network, array_t *nodesArray, int internalPartitionHead, int nextStateHead) { array_t *rootsName; array_t *leavesMddId; array_t *mvfArray; st_table *nodeToMvfTable; SimNodesArrayBuildRootsAndLeaves(network, nodesArray, internalPartitionHead, nextStateHead, &rootsName, &leavesMddId); mvfArray = Part_PartitionBuildFunctions(Part_NetworkReadPartition(network), rootsName, leavesMddId, NIL(mdd_t)); array_free(leavesMddId); array_free(rootsName); nodeToMvfTable = SimNodesArrayBuildNodeToMvfTable(nodesArray, internalPartitionHead, mvfArray); array_free(mvfArray); return(nodeToMvfTable); } /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Returns the integer code of the value of a variable associated to a node.] Description [Returns the integer code of the value of a variable associated to a node. If the value does not belong to the domain of the variable, then -1 is returned. It is an error to call this function with a NULL node.] SideEffects [] ******************************************************************************/ int SimNodeReadValueCode( Ntk_Node_t * node, char * value) { int index; Var_Variable_t *var = Ntk_NodeReadVariable(node); if (Var_VariableTestIsSymbolic(var)) { return(Var_VariableReadIndexFromSymbolicValue(var, value)); } /* Enumerative or binary variable */ else { index = atoi(value); if (index >= Var_VariableReadNumValues(var) || index < 0) { return(-1); } else { return(index); } } } /**Function******************************************************************** Synopsis [Tests if the partition is in terms of CIs alone, in case internal partition nodes are present.] Description [ Returns 1 if internal nodes are present and the partition is in terms of only combinational inputs (and constants)] SideEffects [] ******************************************************************************/ boolean SimTestPartInTermsOfCI( Sim_Sim_t *sim ) { int j, k, value, mddId; Ntk_Node_t *node, *supportNode; Mvf_Function_t *mvFunction; array_t *mddIdArray; /* if there are no internal nodes, return FALSE. This allows simulation to proceed when partition method inout is used. */ if(sim->internalPartitionHead == sim->nextStateHead){ return FALSE; } for (j = sim->nextStateHead; j < array_n(sim->nodesArray); j++) { node = array_fetch(Ntk_Node_t *, sim->nodesArray, j); (void) st_lookup(sim->nodeToMvfTable, (char *) node, &mvFunction); mddIdArray = Mvf_FunctionComputeSupport(mvFunction, Ntk_NetworkReadMddManager(sim->network), &value); if(mddIdArray != NIL(array_t)){ for(k = 0; k < array_n(mddIdArray); k++){ mddId = array_fetch(int, mddIdArray, k); supportNode = Ntk_NetworkFindNodeByMddId(sim->network, mddId); if(!Ntk_NodeTestIsCombInput(supportNode)){ array_free(mddIdArray); return FALSE; } } array_free(mddIdArray); }/* if array not nil */ }/* for all nodes */ return TRUE; } /**Function******************************************************************** Synopsis [Converts integer to string of ASCII characters.] Description [Converts integer to string of ASCII characters. It is the responsibility of the user to free the returned string.] SideEffects [] ******************************************************************************/ char * SimInteger2ASCII( int number) { char * str = ALLOC(char, 21); (void) sprintf(str, "%d", number); return(str); } /**Function******************************************************************** Synopsis [Print a string according to a given format.] Description [Print a string according to a given format. The output file must be valid. The string is formated according to len. If len > strlen(string), then blanks are added] SideEffects [] ******************************************************************************/ void SimStringPrint( FILE * fp, char * string, int len) { int i; fprintf(fp, "%s", string); for(i = strlen(string); i < len; i++) { fprintf(fp, " "); } fprintf(fp, " "); } /**Function******************************************************************** Synopsis [Returns an integer array that will contain the size of the largest value of a node in the nodesArray.] Description [Returns an integer array that will contain the size of the largest value of a node in the nodesArray. It is the responsibility of the user to free the returned array.] SideEffects [] ******************************************************************************/ array_t * SimSimInitDataFormat( Sim_Sim_t * sim) { int i, j; int size; int maxSize; int numValue; boolean symbolic; Ntk_Node_t *node; Var_Variable_t *var; array_t *formatArray = array_alloc(int, 0); for (j = 0; j < array_n(sim->nodesArray); j++) { node = array_fetch(Ntk_Node_t *, sim->nodesArray, j); var = Ntk_NodeReadVariable(node); symbolic = Var_VariableTestIsSymbolic(var); numValue = Var_VariableReadNumValues(var); maxSize = 0; if (symbolic) { for (i = 0; i < numValue; i++) { size = strlen(Var_VariableReadSymbolicValueFromIndex(var, i)); if (size > maxSize) { maxSize = size; } } } else { /* Binary or enumertive type */ while(numValue != 0) { maxSize++; numValue = numValue/10; } } array_insert_last(int, formatArray, maxSize); } return(formatArray); } /**Function******************************************************************** Synopsis [Does a copy of the nextState values to the currentState of the next simulation vector.] Description [Does a copy of the nextState values to the currentState of the next simulation vector. The current vector must contain the nextState values. The next vector must not contain already a currentState value.] SideEffects [] ******************************************************************************/ void SimSimVectorFillCurrentState( Sim_Sim_t * sim /* sim data-structure */, int n /* index of nextState in the vectorArray */) { int i; array_t *currentVector = array_fetch(array_t *, sim->vectorArray, n-1); array_t *nextVector = array_fetch(array_t *, sim->vectorArray, n); for (i = sim->nextStateHead; i < sim->outputHead; i++) { /* We assume nextVector contains only the inputs : insert_last is convenient */ int value = array_fetch(int, currentVector, i); array_insert_last(int, nextVector, value); } } /**Function******************************************************************** Synopsis [Returns a random value for a multi-valued variable.] Description [Returns a random value for a multi-valued variable. If the node is of type pseudo-input, then 1) if pseudoInputSource is Sim_First_c, then the first value of the first row is used, else 2) a random row of the table is chosen, and within this row, a random value in the output entry is chosen (this is not exactly random, because a value could appear in more than one row). If the node in not a pseudo-input, then a random value from the domain of the node's variable is chosen. The encoded value is returned.] SideEffects [] ******************************************************************************/ int SimNodeComputeRandomValue( Ntk_Node_t * node, Sim_PseudoSrc pseudoInputSource) { int value = 0; /* initialize so that lint doesn't complain */ if (Ntk_NodeTestIsPseudoInput(node)) { Tbl_Entry_t *entry; int rowNum; int colNum; int rowChoice; Tbl_Table_t *table = Ntk_NodeReadTable(node); int outIndex = Ntk_NodeReadOutputIndex(node); /* Decide which row to take value from. */ if (pseudoInputSource == Sim_First_c) { rowChoice = 0; } else { int numRows = Tbl_TableReadNumRows(table); rowChoice = ((int) util_random()) % numRows; } Tbl_TableForEachOutputEntry(table, rowNum, colNum, entry) { if ((colNum == outIndex) && (rowNum == rowChoice)) { Tbl_Range_t *range; lsGen lsGen; int tempValue; int entryChoice; int i = 0; /* We are now in rowChoice. Decide which value of entry to take. */ if (pseudoInputSource == Sim_First_c) { entryChoice = 0; } else { int numValues = Tbl_EntryReadNumValues(entry); entryChoice = ((int) util_random()) % numValues; } Tbl_EntryForEachValue(entry, tempValue, lsGen, range) { if(entryChoice == i) { value = tempValue; /* * We could break out of the two FOR loops to avoid unnecessary * work. However, the inner loop has an lsGen that must be freed * if the loop is broken early, and I couldn't get lsFinish to be * called correctly. Also, the table shouldn't be big to worry * about it. */ } i++; } } } } else { Var_Variable_t *var = Ntk_NodeReadVariable(node); value = ((int) util_random()) % Var_VariableReadNumValues(var); } return value; } /**Function******************************************************************** Synopsis [Builds the mdd of a simulation vector.] Description [Builds the mdd of a simulation vector from an array of integers. The length of this array should be equal to the number of combinational inputs in the sim structure. The ith integer of this array gives the value of the ith node in the sim structure's nodesArray.] SideEffects [] ******************************************************************************/ mdd_t * SimSimVectorBuildMdd( Sim_Sim_t * sim, array_t * vector, array_t * partitionVector) { int i; int value; mdd_t *mddMinterm; Ntk_Node_t *node; mdd_t *literalMdd; mdd_t *tmpMdd; Ntk_Network_t *network = sim->network; mdd_manager *mddManager = Ntk_NetworkReadMddManager(network); mddMinterm = mdd_one(mddManager); for(i = 0; i < sim->internalPartitionHead; i++) { /* For every combinational input */ node = array_fetch(Ntk_Node_t *, sim->nodesArray, i); value = array_fetch(int, vector, i); /* LiteralMdd will represent the mdd of "Node-variable = value" */ literalMdd = mdd_eq_c(mddManager, Ntk_NodeReadMddId(node), value); tmpMdd = mdd_and(literalMdd, mddMinterm, 1, 1); mdd_free(mddMinterm); mdd_free(literalMdd); mddMinterm = tmpMdd; } for(i = 0; i < array_n(partitionVector); i++) { /* For every internal Partition node */ node = array_fetch(Ntk_Node_t *, sim->nodesArray, i + sim->internalPartitionHead); value = array_fetch(int, partitionVector, i); /* LiteralMdd will represent the mdd of "Node-variable = value" */ literalMdd = mdd_eq_c(mddManager, Ntk_NodeReadMddId(node), value); tmpMdd = mdd_and(literalMdd, mddMinterm, 1, 1); mdd_free(mddMinterm); mdd_free(literalMdd); mddMinterm = tmpMdd; } return(mddMinterm); } /**Function******************************************************************** Synopsis [Write an error message to error_string.] Description [Write an error message to error_string. The message will be written as ("%s%s%s", str1, str2, str3).] SideEffects [] ******************************************************************************/ void SimAppendErrorMsg( char * str1, char * str2, char * str3) { error_append(str1); error_append(str2); error_append(str3); } /**Function******************************************************************** Synopsis [Returns a random value.] Description [Returns a random value. Uses gettimeofday system function.] SideEffects [] ******************************************************************************/ int SimComputeRandomInteger(void) { struct timeval tp; struct timezone tzp; if ((int) gettimeofday(&tp,&tzp) == -1) { fprintf (vis_stderr, "sim : Error while calling gettimeofday.\n"); exit(-1); } return((int) (tp.tv_sec)); } /**Function******************************************************************** Synopsis [Builds an array of MddId of primary inputs, pseudo inputs, and current states, and an array of name of next states and outputs.] Description [Builds an array of MddId of leaves of a network : primary inputs, pseudo inputs, and current states, and an array of name of roots: next states and outputs. These arrays are returned through the parameteres leaves and roots. We suppose that every primary inputs, pseudo inputs, and current states has an MDD Id.] SideEffects [] ******************************************************************************/ void SimNodesArrayBuildRootsAndLeaves( Ntk_Network_t *network, array_t * nodesArray, int internalPartitionHead, int nextStateHead, array_t ** roots, array_t ** leaves) { int i; Ntk_Node_t *node; *roots = array_alloc(char *, 0); *leaves = array_alloc(int, 0); for(i = 0; i < nextStateHead; i++) { node = array_fetch(Ntk_Node_t *, nodesArray, i); array_insert_last(int, *leaves, Ntk_NodeReadMddId(node)); } for(i = internalPartitionHead; i < array_n(nodesArray); i++) { node = array_fetch(Ntk_Node_t *, nodesArray, i); array_insert_last(char *, *roots, Ntk_NodeReadName(node)); } } /**Function******************************************************************** Synopsis [Builds a table mapping a node to its Mvf_Function.] Description [Builds a table mapping a node to its Mvf_Function. mvfArray is an array of Mvf_Function.] SideEffects [] ******************************************************************************/ st_table * SimNodesArrayBuildNodeToMvfTable( array_t * nodesArray, int internalPartitionHead, array_t * mvfArray) { int i; Ntk_Node_t *node; array_t *mvf; st_table *nodeToMvfTable = st_init_table(st_ptrcmp, st_ptrhash); for(i = internalPartitionHead; i < array_n(nodesArray); i++) { node = array_fetch(Ntk_Node_t *, nodesArray, i); mvf = array_fetch(Mvf_Function_t *, mvfArray, i - internalPartitionHead); st_insert(nodeToMvfTable, (char *) node, (char *) mvf); } return(nodeToMvfTable); } /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/