/**CFile*********************************************************************** FileName [simIo.c] PackageName [sim] Synopsis [Routines to read and write simulation vectors.] Author [Shaker Sarwary, Tom Shiple and Rajeev Ranjan] 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" static char rcsid[] UNUSED = "$Id: simIo.c,v 1.5 2005/05/10 15:50:43 hhkim Exp $"; /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /* * Maximum permissible length of a line in the simulation file. */ #define MAX_LINE_LENGTH 500000 /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static array_t * SimObtainInputsArray(Sim_Sim_t * sim); static void FreeArrays(array_t *array1, array_t *array2, array_t *array3, array_t *array4); static array_t * BufferBuildInputsNodeArray(char * buffer, Ntk_Network_t * network); static array_t * BufferBuildLatchesNodeArray(char * buffer, Ntk_Network_t * network); static array_t * BufferBuildOutputsNodeArray(char * buffer, Ntk_Network_t * network); static array_t * BufferBuildValuesArray(char * buffer, array_t * nodesArray); static void SimAddVector(Sim_Sim_t * sim, array_t * vector); static void BufferSkipWhiteSpace(char * buffer, int * position); static char * BufferObtainStringAtPosition(char * buffer, int * position); static void PrintValue(array_t *nodesArray, array_t *vector, int vectorIndex, int strSize, FILE *file); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Print the simulation vectors contained in a SimSimStruct.] Description [Print the simulation vectors contained in a SimSimStruct. If printMode is 0, then only vectors are printed, else the header is also printed(.inputs, .outputs ...). printInputsFlag, printPseudoInputsFlag, printOutputsFlag, and printStatesFlag control the printing of primary inputs, pseudo inputs, primary outputs and state variables respectively. A value of 1 of these flags indicate printing is enabled, and value 0 indicates otherwise. This function writes warnings into error_string. The printed file is accepted as input file in sim.] SideEffects [] ******************************************************************************/ void Sim_SimPrint( Sim_Sim_t * sim, FILE * of, boolean printMode, int printInputsFlag, int printOutputsFlag, int printPseudoInputsFlag, int printStatesFlag ) { int i, j; char *str; array_t *vector = NIL(array_t); array_t *formatArray; Ntk_Node_t *node; Var_Variable_t *var; int index; int strSize = 0; int numNodes = array_n(sim->nodesArray); int inputWidth = sim->currentStateHead; if(sim->verbose) { (void) printf("Printing %d vectors...\n", array_n(sim->vectorArray)); } formatArray = SimSimInitDataFormat(sim); if (printMode) { (void) fprintf(of, "# %s\n", Vm_VisReadVersion()); (void) fprintf(of, "# Network: %s\n", Ntk_NetworkReadName(sim->network)); if (sim->inputFile != NIL(char)) { (void) fprintf(of, "# Input Vectors File: %s\n", sim->inputFile); } else { (void) fprintf(of, "# Simulation vectors have been randomly generated\n"); } (void) fprintf(of, "\n\n"); (void) fprintf(of, ".inputs "); for (i = 0; i < inputWidth; i++) { node = array_fetch(Ntk_Node_t *, sim->nodesArray, i); (void) fprintf(of, "%s ", Ntk_NodeReadName(node)); } (void) fprintf(of, "\n"); (void) fprintf(of, ".latches "); for (i = sim->currentStateHead; i < sim->internalPartitionHead; i++) { node = array_fetch(Ntk_Node_t *, sim->nodesArray, i); (void) fprintf(of, "%s ", Ntk_NodeReadName(node)); } (void) fprintf(of, "\n"); (void) fprintf(of, ".outputs "); for (i = sim->outputHead; i < numNodes; i++) { node = array_fetch(Ntk_Node_t *, sim->nodesArray, i); (void) fprintf(of, "%s ", Ntk_NodeReadName(node)); } (void) fprintf(of, "\n"); /* Reset State is the current state of the first vector */ (void) fprintf(of, ".initial "); vector = array_fetch(array_t *, sim->vectorArray, 0); for (i = sim->currentStateHead; i < sim->internalPartitionHead; i++) { if(i >= array_n(vector)) {/* If currentState is not specified '*' is printed */ (void) fprintf(of, "* "); } else { node = array_fetch(Ntk_Node_t *, sim->nodesArray, i); var = Ntk_NodeReadVariable(node); index = array_fetch(int, vector, i); if (Var_VariableTestIsSymbolic(var)) { (void) fprintf(of, "%s ", Var_VariableReadSymbolicValueFromIndex(var, index)); } else { /* Binary or enumerative type */ str = SimInteger2ASCII(index); (void) fprintf(of, "%s ", str); FREE(str); } } } (void) fprintf(of, "\n\n.start_vectors"); (void) fprintf(of, "\n\n"); /* * Print the order of variables for which values * are printed in the next lines. */ (void) fprintf(of, "# "); /* * If either printInputsFlag or printPseudoInputsFlag is zero, we * cannot use the output as the input for simulation. Print a * warning message regarding that. */ if ((printInputsFlag == 0) || (printPseudoInputsFlag == 0)){ (void) fprintf(vis_stderr,"Warning - print flag of some inputs is set to zero.\n"); (void) fprintf(vis_stderr,"Hence the output file you specified cannot be used as an input\n"); (void) fprintf(vis_stderr,"file for a subsequent simulation run.\n"); } if (printInputsFlag || printPseudoInputsFlag){ for (i = 0; i < inputWidth; i++) { node = array_fetch(Ntk_Node_t *, sim->nodesArray, i); if (Ntk_NodeTestIsPrimaryInput(node)){ if (printInputsFlag){ (void) fprintf(of, "%s ", Ntk_NodeReadName(node)); } } else{ if (printPseudoInputsFlag){ (void) fprintf(of, "%s ", Ntk_NodeReadName(node)); } } } (void) fprintf(of, "; "); } if (printStatesFlag) { for (i = sim->currentStateHead; i < sim->internalPartitionHead; i++) { node = array_fetch(Ntk_Node_t *, sim->nodesArray, i); (void) fprintf(of, "%s ", Ntk_NodeReadName(node)); } (void) fprintf(of, "; "); } if (printOutputsFlag){ for (i = sim->outputHead; i < numNodes; i++) { node = array_fetch(Ntk_Node_t *, sim->nodesArray, i); (void) fprintf(of, "%s ", Ntk_NodeReadName(node)); } (void) fprintf(of, "\n\n"); } } for (i = 0; i < array_n(sim->vectorArray); i++) { vector = array_fetch(array_t *, sim->vectorArray, i); if ((printInputsFlag) || (printPseudoInputsFlag)){ for (j = 0; j < sim->currentStateHead; j++) { strSize = array_fetch(int, formatArray, j); node = array_fetch(Ntk_Node_t *, sim->nodesArray, j); if (Ntk_NodeTestIsPrimaryInput(node)){ if(printInputsFlag){ PrintValue(sim->nodesArray, vector, j, strSize, of); } } else { if (printPseudoInputsFlag){ PrintValue(sim->nodesArray, vector, j, strSize, of); } } } } if (printStatesFlag){ (void) fprintf(of,"; "); for (j = sim->currentStateHead; j < sim->internalPartitionHead; j++){ strSize = array_fetch(int, formatArray, j); node = array_fetch(Ntk_Node_t *, sim->nodesArray, j); PrintValue(sim->nodesArray, vector, j, strSize, of); } } if (printOutputsFlag){ (void) fprintf(of,"; "); for (j = sim->outputHead; j < numNodes; j++){ strSize = array_fetch(int, formatArray, j); node = array_fetch(Ntk_Node_t *, sim->nodesArray, j); PrintValue(sim->nodesArray, vector, j, strSize, of); } } (void) fprintf(of, "\n"); } if (printStatesFlag){ /* * Need to print the final state on a separate line. */ (void) fprintf(of,"# Final State : "); for (j = sim->currentStateHead; j < sim->internalPartitionHead; j++){ strSize = array_fetch(int, formatArray, j); node = array_fetch(Ntk_Node_t *, sim->nodesArray, j); PrintValue(sim->nodesArray, vector, j, strSize, of); } (void) fprintf(of, "\n"); } array_free(formatArray); } /**Function******************************************************************** Synopsis [Parses the header of the simulation vectors file containing declarations, and builds a SimSimStruct.] Description [Parses the header of the simulation vectors file containing declarations, and builds a SimSimStruct. nodeToMvfTable providing MDDs of primary outputs and next-state functions is also built. verbose is here for initialization of sim structure. The header of a simulation-vectors file contains .inputs, .latches, .outputs, and .initial fields. If a variable is found for which there doesn't exist a corresponding node in the network, or a value is found that does not belong to the domain of its specific variable, then an error message is written in error_string, the allocated memory is freed, and the function returns NULL. The simulation file must contain each category of declaration in a line(Two ".inputs" is not allowed in the same file). initial-state declaration must be written after the latches declaration. The function returns the initialized sim structure.] SideEffects [] ******************************************************************************/ Sim_Sim_t * Sim_FileParseDeclaration( Ntk_Network_t * network, FILE * fp, char * inputFile, boolean verbose) { int i; Ntk_Node_t *node; char buffer[MAX_LINE_LENGTH]; char *buffer2; int currentStateHead; int internalPartitionHead; int nextStateHead; int outputHead; st_table *nodeToMvfTable; array_t *nodesArray; int lineNumber = 0; array_t *inputsArray = NIL(array_t); array_t *latchesArray = NIL(array_t); array_t *internalPartitionArray = NIL(array_t); array_t *outputsArray = NIL(array_t); array_t *initState = NIL(array_t); Sim_Sim_t *sim = NIL(Sim_Sim_t); graph_t *partition; vertex_t *vertex; array_t *dfsarray; internalPartitionArray = array_alloc(Ntk_Node_t *, 0); /* Add internal partition nodes */ partition = Part_NetworkReadPartition(network); dfsarray = g_dfs(partition); for(i=0; i< array_n(dfsarray); i++){ vertex = array_fetch(vertex_t *, dfsarray, i); node = Ntk_NetworkFindNodeByName(network, Part_VertexReadName(vertex)); if(!(Ntk_NodeTestIsCombInput(node) || Ntk_NodeTestIsCombOutput(node))){ array_insert_last(Ntk_Node_t *, internalPartitionArray, node); } } array_free(dfsarray); while (fgets(buffer, MAX_LINE_LENGTH -1, fp) != NULL) { int position = 0; lineNumber++; /* Every line must end by '\n' */ if (buffer[strlen(buffer) -1] != '\n') { SimAppendErrorMsg("Simulate: Line ", SimInteger2ASCII(lineNumber), "istoolong!\n"); FreeArrays(inputsArray, latchesArray, outputsArray, internalPartitionArray); return(sim); } /* Eliminate spaces */ BufferSkipWhiteSpace(buffer, &position); /* buffer2 will contain buffer without space in the begining */ buffer2 = buffer + position; /* Avoid comment and empty lines */ if (buffer[position] != '#' && buffer[position] != '\n') { if (!strncmp(buffer2, ".inputs", 7)) { inputsArray = BufferBuildInputsNodeArray(buffer2 + 7, network); if (inputsArray == NIL(array_t)) { SimAppendErrorMsg("Simulate: Error line ", SimInteger2ASCII(lineNumber), ".\n"); FreeArrays(inputsArray, latchesArray, outputsArray, internalPartitionArray); return(sim); } } else if (!strncmp(buffer2, ".latches", 8)) { latchesArray = BufferBuildLatchesNodeArray(buffer2 + 8, network); if (latchesArray == NIL(array_t)) { SimAppendErrorMsg("Simulate: Error line ", SimInteger2ASCII(lineNumber), ".\n"); FreeArrays(inputsArray, latchesArray, outputsArray, internalPartitionArray); return(sim); } } else if (!strncmp(buffer2, ".outputs", 8)) { outputsArray = BufferBuildOutputsNodeArray(buffer2 + 8, network); if (outputsArray == NIL(array_t)) { SimAppendErrorMsg("Simulate: Error line ", SimInteger2ASCII(lineNumber), ".\n"); FreeArrays(inputsArray, latchesArray, outputsArray, internalPartitionArray); return(sim); } } else if (!strncmp(buffer2, ".initial", 8)) { /* Error if latches are not already read before initial-state */ if (latchesArray == NIL(array_t)) { error_append("Simulate: Latches must be declared before initial state declaration.\n"); FreeArrays(inputsArray, latchesArray, outputsArray, internalPartitionArray); return(sim); } initState = BufferBuildValuesArray(buffer2 + 8, latchesArray); if (initState == NIL(array_t)) { SimAppendErrorMsg("Simulate: Error line ", SimInteger2ASCII(lineNumber), ".\n"); FreeArrays(inputsArray, latchesArray, outputsArray, internalPartitionArray); return(sim); } } else if (!strncmp(buffer2, ".start_vectors", 14)) { /* Verification of the declarations */ if (inputsArray == NIL(array_t)) { error_append("Simulate: Input file is missing inputs declaration.\n"); FreeArrays(inputsArray, latchesArray, outputsArray, internalPartitionArray); return(sim); } currentStateHead = array_n(inputsArray); nodesArray = array_dup(inputsArray); array_free(inputsArray); inputsArray = NIL(array_t); if(latchesArray == NIL(array_t)) { /* Verify if actually there is no latch in the network */ if (Ntk_NetworkReadNumLatches(network) > 0) { error_append("Simulate: Input file is missing latches declaration.\n"); FreeArrays(inputsArray, latchesArray, outputsArray, internalPartitionArray); return(0); } else { internalPartitionHead = currentStateHead; nextStateHead = internalPartitionHead + array_n(internalPartitionArray); outputHead = nextStateHead; } } else { internalPartitionHead = currentStateHead + array_n(latchesArray); nextStateHead = internalPartitionHead + array_n(internalPartitionArray); outputHead = nextStateHead + array_n(latchesArray); /* Add current states node */ array_append(nodesArray, latchesArray); array_append(nodesArray, internalPartitionArray); array_free(internalPartitionArray); /* Add next state node as data-input of current-state node */ for(i = 0; i < array_n(latchesArray); i++) { node = array_fetch(Ntk_Node_t *, latchesArray, i); node = Ntk_LatchReadDataInput(node); array_insert_last(Ntk_Node_t *, nodesArray, node); } array_free(latchesArray); } if (outputsArray != NIL(array_t)) { array_append(nodesArray, outputsArray); array_free(outputsArray); } /* Building nodeToMvfTable */ nodeToMvfTable = Sim_NetworkBuildNodeToMvfTable(network, nodesArray, internalPartitionHead, nextStateHead); sim = Sim_SimCreate(network, nodeToMvfTable, inputFile, lineNumber, nodesArray, currentStateHead, internalPartitionHead, nextStateHead, outputHead, initState, NULL, verbose); return(sim); /* Normal end */ } /* Unknown string in the declaration part */ else { SimAppendErrorMsg("Simulate: Syntax error in the declaration line: ", SimInteger2ASCII(lineNumber), " or missing .start_vectors statement.\n") ; FreeArrays(inputsArray, latchesArray, outputsArray, internalPartitionArray); return(sim); } } } array_free(internalPartitionArray); return(sim); } /**Function******************************************************************** Synopsis [Parses the vectors of a simulation vectors file.] Description [Parses the vectors of a simulation vectors file. This function should be called after Sim_FileParseDeclaration. Reads lines from first line after ".start_vectors" statement. Fills the vectorArray field of sim. If this field is already set, it will be lost. Only "num" vectors are read(even if the number of vectors in the file is greater than this number). If num is 0, then all vectors in the file are read. If value is found that does not belong to the domain of its specific variable, then an error message is written in error_string, and the function returns 0. The function returns 1 if it normally ends and no EOF is detected. It returns 2 otherwise(normal end and EOF).] SideEffects [] SeeAlso [Sim_FileParseDeclaration, Sim_SimReset] ******************************************************************************/ int Sim_FileParseVectors( FILE * fp, Sim_Sim_t * sim, int num) { char buffer[MAX_LINE_LENGTH]; char *buffer2; array_t *vectorArray; int numberVector = 0; array_t *inputsArray = SimObtainInputsArray(sim); sim->vectorArray = array_alloc(array_t *, 0); while (fgets(buffer, MAX_LINE_LENGTH -1, fp) != NULL) { int position = 0; (sim->lineNumber)++; /* Every line must end by '\n' */ if (buffer[strlen(buffer) -1] != '\n') { SimAppendErrorMsg("Simulate: Line ", SimInteger2ASCII(sim->lineNumber), " is too long!\n"); array_free(inputsArray); return(0); } /* Eliminate spaces */ BufferSkipWhiteSpace(buffer, &position); /* buffer2 will contain buffer without space in the begining */ buffer2 = buffer + position; /* Avoid comment and empty lines */ if (buffer[position] != '#' && buffer[position] != '\n') { /* Read only "num" vectors */ if (numberVector >= num && num != 0) { array_free(inputsArray); return(1); /* Normal end before EOF */ } vectorArray = BufferBuildValuesArray(buffer2, inputsArray); if (vectorArray == NIL(array_t)) { SimAppendErrorMsg("Simulate: Error line ", SimInteger2ASCII(sim->lineNumber), ".\n"); array_free(inputsArray); return(0); } numberVector++; SimAddVector(sim, vectorArray); } } array_free(inputsArray); return(2); /* End of file */ } /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Returns a new array containing the input nodes.] Description [Returns a new array containing the input nodes. If there is no inputs node in sim structure, then an empty array is returned.] SideEffects [] ******************************************************************************/ static array_t * SimObtainInputsArray( Sim_Sim_t * sim) { int i; Ntk_Node_t * node; array_t * inputsArray = array_alloc(Ntk_Node_t *, 0); for (i = 0; i < sim->currentStateHead; i++) { node = array_fetch(Ntk_Node_t *, sim->nodesArray, i); array_insert_last(Ntk_Node_t *, inputsArray, node); } return(inputsArray); } /**Function******************************************************************** Synopsis [Frees arrays.] Description [Frees array. Verifies if array is non NULL.] SideEffects [] ******************************************************************************/ static void FreeArrays( array_t *array1, array_t *array2, array_t *array3, array_t *array4) { if (array1 != NIL(array_t)) { array_free(array1); } if (array2 != NIL(array_t)) { array_free(array2); } if (array3 != NIL(array_t)) { array_free(array3); } if (array4 != NIL(array_t)) { array_free(array4); } } /**Function******************************************************************** Synopsis [Builds an array of nodes corresponding to the name of inputs read in the buffer.] Description [Builds an array of nodes corresponding to the name of inputs read in the buffer. If the name does not correspond to any input node in the network, or the number of values is not correct, then an error message is written in error_string, and NULL is returned.] SideEffects [] ******************************************************************************/ static array_t * BufferBuildInputsNodeArray( char * buffer, Ntk_Network_t * network) { char *str; Ntk_Node_t *node; int position = 0; array_t *array = array_alloc(Ntk_Node_t *, 0); while((str = BufferObtainStringAtPosition(buffer, &position)) != NULL) { node = Ntk_NetworkFindNodeByActualName(network, str); if (node == NIL(Ntk_Node_t) || !Ntk_NodeTestIsInput(node)) { SimAppendErrorMsg("Simulate: ", str, " is not a valid input name.\n"); array_free(array); FREE(str); return(NIL(array_t)); } FREE(str); array_insert_last(Ntk_Node_t *, array, node); } /* Verification of number of values */ if (array_n(array) != Ntk_NetworkReadNumInputs(network)) { error_append("Simulate: All inputs and pseudo-inputs must be specified.\n"); array_free(array); return(NIL(array_t)); } return(array); } /**Function******************************************************************** Synopsis [Builds an array of nodes corresponding to the name of latches read in the buffer.] Description [Builds an array of nodes corresponding to the name of latches read in the buffer. If the name does not correspond to any latch node in the network, or the number of values is not correct, then an error message is written in error_string, and NULL is returned.] SideEffects [] ******************************************************************************/ static array_t * BufferBuildLatchesNodeArray( char * buffer, Ntk_Network_t * network) { char *str; Ntk_Node_t *node; int position = 0; array_t *array = array_alloc(Ntk_Node_t *, 0); while ((str = BufferObtainStringAtPosition(buffer, &position)) != NULL) { node = Ntk_NetworkFindNodeByActualName(network, str); if (node == NIL(Ntk_Node_t) || !Ntk_NodeTestIsLatch(node)) { SimAppendErrorMsg("Simulate: ", str, " is not a valid latch name\n"); array_free(array); FREE(str); return(NIL(array_t)); } FREE(str); array_insert_last(Ntk_Node_t *, array, node); } /* Verification of number of items */ if (array_n(array) != Ntk_NetworkReadNumLatches(network)) { error_append("Simulate: All latches must be specified.\n"); array_free(array); return(NIL(array_t)); } return(array); } /**Function******************************************************************** Synopsis [Builds an array of nodes corresponding to the name of outputs read in the buffer.] Description [Builds an array of nodes corresponding to the name of outputs read in the buffer. If the name does not correspond to any output node in the network, then an error message is written in error_string, and NULL is returned. The number of outputs may be incomplete.] SideEffects [] ******************************************************************************/ static array_t * BufferBuildOutputsNodeArray( char * buffer, Ntk_Network_t * network) { char *str; Ntk_Node_t *node; int position = 0; array_t *array = array_alloc(Ntk_Node_t *, 0); while((str = BufferObtainStringAtPosition(buffer, &position)) != NULL) { node = Ntk_NetworkFindNodeByActualName(network, str); if (node == NIL(Ntk_Node_t) || !Ntk_NodeTestIsPrimaryOutput(node)) { SimAppendErrorMsg("Simulate: ", str, " is not a valid output name\n"); FREE(str); array_free(array); return(NIL(array_t)); } FREE(str); array_insert_last(Ntk_Node_t *, array, node); } return(array); } /**Function******************************************************************** Synopsis [Builds an array of integers representing the code of strings contained in the buffer.] Description [Builds an array of integers representing the code of strings contained in the buffer. The code is 1 or 0, if the value is equal "1" or "0" and the variable is a binary variable. For a symbolic variable it is equal to the index of the value of the variable. The code is equal to the value of a variable if the variable has an enumerative type. If a wrong value is detected, then an error message is written in error_string and NULL is returned. This function verifies also if the number of values is equal to the number of nodes in the nodesArray. If it is not, it returns NULL.] SideEffects [] ******************************************************************************/ static array_t * BufferBuildValuesArray( char * buffer, array_t * nodesArray) { char *str; Ntk_Node_t *node; int index; int i = 0; int arraySize = array_n(nodesArray); int position = 0; array_t *array = array_alloc(int, 0); while((str = BufferObtainStringAtPosition(buffer, &position)) != NULL) { if (i >= arraySize) { SimAppendErrorMsg("Simulate: Too many values(", str, " invalid value).\n"); array_free(array); FREE(str); return(NIL(array_t)); } node = array_fetch(Ntk_Node_t *, nodesArray, i); i++; index = SimNodeReadValueCode(node, str); if (index == -1) { SimAppendErrorMsg("Simulate: ", str, ": invalid value.\n"); array_free(array); FREE(str); return(NIL(array_t)); } FREE(str); array_insert_last(int, array, index); } /* Verification of number of items */ if (array_n(array) != array_n(nodesArray)) { error_append("Simulate: incomplete number of values.\n"); array_free(array); return(NIL(array_t)); } return(array); } /**Function******************************************************************** Synopsis [Add a vector to the array of vectors of a sim.] Description [Add a vector to the array of vectors of a sim. It is an error to call this function with a NULL sim or a sim that does not have a vectors array.] SideEffects [] ******************************************************************************/ static void SimAddVector( Sim_Sim_t * sim, array_t * vector) { array_insert_last(array_t *, sim->vectorArray, vector); } /**Function******************************************************************** Synopsis [skip over white space in a string.] Description [skip over white space in a string. set position to the first character different from ' ' and '\t'.] SideEffects [] ******************************************************************************/ static void BufferSkipWhiteSpace( char * buffer, int * position) { for (; buffer[*position] == ' ' || buffer[*position] == '\t'; (*position)++); } /**Function******************************************************************** Synopsis [Returns a string read in a buffer at the given position.] Description [Returns a string read in a buffer at the given position. The end of string is detected by ' ', '\t', ';' or '\n'. Eliminates the Space in the begining of the buffer. Returns NULL if an empty string has been found before ';' or '\n'.] SideEffects [] ******************************************************************************/ static char * BufferObtainStringAtPosition( char * buffer, int * position) { char *str; int strPosition; int len; /* Traverse Space */ BufferSkipWhiteSpace(buffer, position); strPosition = *position; for (;buffer[*position] != ' ' && buffer[*position] != '\t' && buffer[*position] != ';' && buffer[*position] != '\n'; (*position)++); if (strPosition == *position) { return(NIL(char)); } len = *position - strPosition + 1; str = ALLOC(char, len); strncpy(str, buffer + strPosition, len - 1); str[len-1] = '\0'; return(str); } /**Function******************************************************************** Synopsis [Prints the value of a particular variable for a given simulation vector.] Description [Prints the value of a particular variable for a given simulation vector. The variable is obtained from the node at the vectorIndex position of the nodesArray. The value is obtained from the vectorIndex position of the vector. strSize is used for formatting. If the number of elements in the vector is less than the vectorIndex, a * is printed instead.] SideEffects [] ******************************************************************************/ static void PrintValue(array_t *nodesArray, array_t *vector, int vectorIndex, int strSize, FILE *file) { int index; Var_Variable_t *var; char *str; Ntk_Node_t *node; if (array_n(vector) > vectorIndex) { node = array_fetch(Ntk_Node_t *, nodesArray, vectorIndex); var = Ntk_NodeReadVariable(node); index = array_fetch(int, vector, vectorIndex); if (Var_VariableTestIsSymbolic(var)) { SimStringPrint(file, Var_VariableReadSymbolicValueFromIndex(var, index), strSize); } else { /* Binary or enumerative type */ str = SimInteger2ASCII(index); SimStringPrint(file, str, strSize); FREE(str); } } else { error_append("Warning: Value is missing in vector.\n"); SimStringPrint(file, "*", strSize); } }