1 | /**CFile*********************************************************************** |
---|
2 | |
---|
3 | FileName [simIo.c] |
---|
4 | |
---|
5 | PackageName [sim] |
---|
6 | |
---|
7 | Synopsis [Routines to read and write simulation vectors.] |
---|
8 | |
---|
9 | Author [Shaker Sarwary, Tom Shiple and Rajeev Ranjan] |
---|
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 | #include "simInt.h" |
---|
32 | |
---|
33 | static char rcsid[] UNUSED = "$Id: simIo.c,v 1.5 2005/05/10 15:50:43 hhkim Exp $"; |
---|
34 | |
---|
35 | /*---------------------------------------------------------------------------*/ |
---|
36 | /* Constant declarations */ |
---|
37 | /*---------------------------------------------------------------------------*/ |
---|
38 | |
---|
39 | /* |
---|
40 | * Maximum permissible length of a line in the simulation file. |
---|
41 | */ |
---|
42 | #define MAX_LINE_LENGTH 500000 |
---|
43 | |
---|
44 | |
---|
45 | /**AutomaticStart*************************************************************/ |
---|
46 | |
---|
47 | /*---------------------------------------------------------------------------*/ |
---|
48 | /* Static function prototypes */ |
---|
49 | /*---------------------------------------------------------------------------*/ |
---|
50 | |
---|
51 | static array_t * SimObtainInputsArray(Sim_Sim_t * sim); |
---|
52 | static void FreeArrays(array_t *array1, array_t *array2, array_t *array3, array_t *array4); |
---|
53 | static array_t * BufferBuildInputsNodeArray(char * buffer, Ntk_Network_t * network); |
---|
54 | static array_t * BufferBuildLatchesNodeArray(char * buffer, Ntk_Network_t * network); |
---|
55 | static array_t * BufferBuildOutputsNodeArray(char * buffer, Ntk_Network_t * network); |
---|
56 | static array_t * BufferBuildValuesArray(char * buffer, array_t * nodesArray); |
---|
57 | static void SimAddVector(Sim_Sim_t * sim, array_t * vector); |
---|
58 | static void BufferSkipWhiteSpace(char * buffer, int * position); |
---|
59 | static char * BufferObtainStringAtPosition(char * buffer, int * position); |
---|
60 | static void PrintValue(array_t *nodesArray, array_t *vector, int vectorIndex, int strSize, FILE *file); |
---|
61 | |
---|
62 | /**AutomaticEnd***************************************************************/ |
---|
63 | |
---|
64 | |
---|
65 | /*---------------------------------------------------------------------------*/ |
---|
66 | /* Definition of exported functions */ |
---|
67 | /*---------------------------------------------------------------------------*/ |
---|
68 | |
---|
69 | /**Function******************************************************************** |
---|
70 | |
---|
71 | Synopsis [Print the simulation vectors contained in a SimSimStruct.] |
---|
72 | |
---|
73 | Description [Print the simulation vectors contained in a SimSimStruct. If |
---|
74 | printMode is 0, then only vectors are printed, else the header is also |
---|
75 | printed(.inputs, .outputs ...). printInputsFlag, |
---|
76 | printPseudoInputsFlag, printOutputsFlag, and printStatesFlag control |
---|
77 | the printing of primary inputs, pseudo inputs, primary outputs and |
---|
78 | state variables respectively. A value of 1 of these flags indicate |
---|
79 | printing is enabled, and value 0 indicates otherwise. This function writes |
---|
80 | warnings into error_string. The printed file is accepted as input file in sim.] |
---|
81 | |
---|
82 | SideEffects [] |
---|
83 | |
---|
84 | ******************************************************************************/ |
---|
85 | void |
---|
86 | Sim_SimPrint( |
---|
87 | Sim_Sim_t * sim, |
---|
88 | FILE * of, |
---|
89 | boolean printMode, |
---|
90 | int printInputsFlag, |
---|
91 | int printOutputsFlag, |
---|
92 | int printPseudoInputsFlag, |
---|
93 | int printStatesFlag |
---|
94 | ) |
---|
95 | |
---|
96 | { |
---|
97 | int i, j; |
---|
98 | char *str; |
---|
99 | array_t *vector = NIL(array_t); |
---|
100 | array_t *formatArray; |
---|
101 | Ntk_Node_t *node; |
---|
102 | Var_Variable_t *var; |
---|
103 | int index; |
---|
104 | int strSize = 0; |
---|
105 | int numNodes = array_n(sim->nodesArray); |
---|
106 | int inputWidth = sim->currentStateHead; |
---|
107 | |
---|
108 | if(sim->verbose) { |
---|
109 | (void) printf("Printing %d vectors...\n", array_n(sim->vectorArray)); |
---|
110 | } |
---|
111 | |
---|
112 | formatArray = SimSimInitDataFormat(sim); |
---|
113 | |
---|
114 | if (printMode) { |
---|
115 | (void) fprintf(of, "# %s\n", Vm_VisReadVersion()); |
---|
116 | (void) fprintf(of, "# Network: %s\n", Ntk_NetworkReadName(sim->network)); |
---|
117 | |
---|
118 | if (sim->inputFile != NIL(char)) { |
---|
119 | (void) fprintf(of, "# Input Vectors File: %s\n", sim->inputFile); |
---|
120 | } |
---|
121 | else { |
---|
122 | (void) fprintf(of, "# Simulation vectors have been randomly generated\n"); |
---|
123 | } |
---|
124 | (void) fprintf(of, "\n\n"); |
---|
125 | (void) fprintf(of, ".inputs "); |
---|
126 | for (i = 0; i < inputWidth; i++) { |
---|
127 | node = array_fetch(Ntk_Node_t *, sim->nodesArray, i); |
---|
128 | (void) fprintf(of, "%s ", Ntk_NodeReadName(node)); |
---|
129 | } |
---|
130 | (void) fprintf(of, "\n"); |
---|
131 | (void) fprintf(of, ".latches "); |
---|
132 | for (i = sim->currentStateHead; i < sim->internalPartitionHead; i++) { |
---|
133 | node = array_fetch(Ntk_Node_t *, sim->nodesArray, i); |
---|
134 | (void) fprintf(of, "%s ", Ntk_NodeReadName(node)); |
---|
135 | } |
---|
136 | (void) fprintf(of, "\n"); |
---|
137 | |
---|
138 | (void) fprintf(of, ".outputs "); |
---|
139 | for (i = sim->outputHead; i < numNodes; i++) { |
---|
140 | node = array_fetch(Ntk_Node_t *, sim->nodesArray, i); |
---|
141 | (void) fprintf(of, "%s ", Ntk_NodeReadName(node)); |
---|
142 | } |
---|
143 | (void) fprintf(of, "\n"); |
---|
144 | |
---|
145 | /* Reset State is the current state of the first vector */ |
---|
146 | (void) fprintf(of, ".initial "); |
---|
147 | vector = array_fetch(array_t *, sim->vectorArray, 0); |
---|
148 | for (i = sim->currentStateHead; i < sim->internalPartitionHead; i++) { |
---|
149 | if(i >= array_n(vector)) {/* If currentState is not specified '*' is printed */ |
---|
150 | (void) fprintf(of, "* "); |
---|
151 | } |
---|
152 | else { |
---|
153 | node = array_fetch(Ntk_Node_t *, sim->nodesArray, i); |
---|
154 | var = Ntk_NodeReadVariable(node); |
---|
155 | index = array_fetch(int, vector, i); |
---|
156 | if (Var_VariableTestIsSymbolic(var)) { |
---|
157 | (void) fprintf(of, "%s ", Var_VariableReadSymbolicValueFromIndex(var, index)); |
---|
158 | } |
---|
159 | else { /* Binary or enumerative type */ |
---|
160 | str = SimInteger2ASCII(index); |
---|
161 | (void) fprintf(of, "%s ", str); |
---|
162 | FREE(str); |
---|
163 | } |
---|
164 | } |
---|
165 | } |
---|
166 | |
---|
167 | (void) fprintf(of, "\n\n.start_vectors"); |
---|
168 | |
---|
169 | (void) fprintf(of, "\n\n"); |
---|
170 | |
---|
171 | /* |
---|
172 | * Print the order of variables for which values |
---|
173 | * are printed in the next lines. |
---|
174 | */ |
---|
175 | |
---|
176 | (void) fprintf(of, "# "); |
---|
177 | /* |
---|
178 | * If either printInputsFlag or printPseudoInputsFlag is zero, we |
---|
179 | * cannot use the output as the input for simulation. Print a |
---|
180 | * warning message regarding that. |
---|
181 | */ |
---|
182 | if ((printInputsFlag == 0) || (printPseudoInputsFlag == 0)){ |
---|
183 | (void) fprintf(vis_stderr,"Warning - print flag of some inputs is set to zero.\n"); |
---|
184 | (void) fprintf(vis_stderr,"Hence the output file you specified cannot be used as an input\n"); |
---|
185 | (void) fprintf(vis_stderr,"file for a subsequent simulation run.\n"); |
---|
186 | } |
---|
187 | |
---|
188 | if (printInputsFlag || printPseudoInputsFlag){ |
---|
189 | for (i = 0; i < inputWidth; i++) { |
---|
190 | node = array_fetch(Ntk_Node_t *, sim->nodesArray, i); |
---|
191 | if (Ntk_NodeTestIsPrimaryInput(node)){ |
---|
192 | if (printInputsFlag){ |
---|
193 | (void) fprintf(of, "%s ", Ntk_NodeReadName(node)); |
---|
194 | } |
---|
195 | } |
---|
196 | else{ |
---|
197 | if (printPseudoInputsFlag){ |
---|
198 | (void) fprintf(of, "%s ", Ntk_NodeReadName(node)); |
---|
199 | } |
---|
200 | } |
---|
201 | } |
---|
202 | (void) fprintf(of, "; "); |
---|
203 | } |
---|
204 | |
---|
205 | if (printStatesFlag) { |
---|
206 | for (i = sim->currentStateHead; i < sim->internalPartitionHead; i++) { |
---|
207 | node = array_fetch(Ntk_Node_t *, sim->nodesArray, i); |
---|
208 | (void) fprintf(of, "%s ", Ntk_NodeReadName(node)); |
---|
209 | } |
---|
210 | (void) fprintf(of, "; "); |
---|
211 | } |
---|
212 | if (printOutputsFlag){ |
---|
213 | for (i = sim->outputHead; i < numNodes; i++) { |
---|
214 | node = array_fetch(Ntk_Node_t *, sim->nodesArray, i); |
---|
215 | (void) fprintf(of, "%s ", Ntk_NodeReadName(node)); |
---|
216 | } |
---|
217 | (void) fprintf(of, "\n\n"); |
---|
218 | } |
---|
219 | } |
---|
220 | |
---|
221 | for (i = 0; i < array_n(sim->vectorArray); i++) { |
---|
222 | vector = array_fetch(array_t *, sim->vectorArray, i); |
---|
223 | if ((printInputsFlag) || (printPseudoInputsFlag)){ |
---|
224 | for (j = 0; j < sim->currentStateHead; j++) { |
---|
225 | strSize = array_fetch(int, formatArray, j); |
---|
226 | node = array_fetch(Ntk_Node_t *, sim->nodesArray, j); |
---|
227 | if (Ntk_NodeTestIsPrimaryInput(node)){ |
---|
228 | if(printInputsFlag){ |
---|
229 | PrintValue(sim->nodesArray, vector, j, strSize, of); |
---|
230 | } |
---|
231 | } |
---|
232 | else { |
---|
233 | if (printPseudoInputsFlag){ |
---|
234 | PrintValue(sim->nodesArray, vector, j, strSize, of); |
---|
235 | } |
---|
236 | } |
---|
237 | } |
---|
238 | } |
---|
239 | if (printStatesFlag){ |
---|
240 | (void) fprintf(of,"; "); |
---|
241 | for (j = sim->currentStateHead; j < sim->internalPartitionHead; j++){ |
---|
242 | strSize = array_fetch(int, formatArray, j); |
---|
243 | node = array_fetch(Ntk_Node_t *, sim->nodesArray, j); |
---|
244 | PrintValue(sim->nodesArray, vector, j, strSize, of); |
---|
245 | } |
---|
246 | } |
---|
247 | if (printOutputsFlag){ |
---|
248 | (void) fprintf(of,"; "); |
---|
249 | for (j = sim->outputHead; j < numNodes; j++){ |
---|
250 | strSize = array_fetch(int, formatArray, j); |
---|
251 | node = array_fetch(Ntk_Node_t *, sim->nodesArray, j); |
---|
252 | PrintValue(sim->nodesArray, vector, j, strSize, of); |
---|
253 | } |
---|
254 | } |
---|
255 | (void) fprintf(of, "\n"); |
---|
256 | } |
---|
257 | if (printStatesFlag){ |
---|
258 | /* |
---|
259 | * Need to print the final state on a separate line. |
---|
260 | */ |
---|
261 | (void) fprintf(of,"# Final State : "); |
---|
262 | for (j = sim->currentStateHead; j < sim->internalPartitionHead; j++){ |
---|
263 | strSize = array_fetch(int, formatArray, j); |
---|
264 | node = array_fetch(Ntk_Node_t *, sim->nodesArray, j); |
---|
265 | PrintValue(sim->nodesArray, vector, j, strSize, of); |
---|
266 | } |
---|
267 | (void) fprintf(of, "\n"); |
---|
268 | } |
---|
269 | array_free(formatArray); |
---|
270 | } |
---|
271 | |
---|
272 | |
---|
273 | |
---|
274 | /**Function******************************************************************** |
---|
275 | |
---|
276 | Synopsis [Parses the header of the simulation vectors file containing |
---|
277 | declarations, and builds a SimSimStruct.] |
---|
278 | |
---|
279 | Description [Parses the header of the simulation vectors file containing |
---|
280 | declarations, and builds a SimSimStruct. nodeToMvfTable providing MDDs of |
---|
281 | primary outputs and next-state functions is also built. verbose is here for |
---|
282 | initialization of sim structure. The header of a simulation-vectors file |
---|
283 | contains .inputs, .latches, .outputs, and .initial fields. If a variable is |
---|
284 | found for which there doesn't exist a corresponding node in the network, or |
---|
285 | a value is found that does not belong to the domain of its specific |
---|
286 | variable, then an error message is written in error_string, the allocated |
---|
287 | memory is freed, and the function returns NULL. The simulation file must |
---|
288 | contain each category of declaration in a line(Two ".inputs" is not allowed |
---|
289 | in the same file). initial-state declaration must be written after the |
---|
290 | latches declaration. The function returns the initialized sim structure.] |
---|
291 | |
---|
292 | SideEffects [] |
---|
293 | |
---|
294 | ******************************************************************************/ |
---|
295 | Sim_Sim_t * |
---|
296 | Sim_FileParseDeclaration( |
---|
297 | Ntk_Network_t * network, |
---|
298 | FILE * fp, |
---|
299 | char * inputFile, |
---|
300 | boolean verbose) |
---|
301 | { |
---|
302 | int i; |
---|
303 | Ntk_Node_t *node; |
---|
304 | char buffer[MAX_LINE_LENGTH]; |
---|
305 | char *buffer2; |
---|
306 | int currentStateHead; |
---|
307 | int internalPartitionHead; |
---|
308 | int nextStateHead; |
---|
309 | int outputHead; |
---|
310 | st_table *nodeToMvfTable; |
---|
311 | array_t *nodesArray; |
---|
312 | int lineNumber = 0; |
---|
313 | array_t *inputsArray = NIL(array_t); |
---|
314 | array_t *latchesArray = NIL(array_t); |
---|
315 | array_t *internalPartitionArray = NIL(array_t); |
---|
316 | array_t *outputsArray = NIL(array_t); |
---|
317 | array_t *initState = NIL(array_t); |
---|
318 | Sim_Sim_t *sim = NIL(Sim_Sim_t); |
---|
319 | graph_t *partition; |
---|
320 | vertex_t *vertex; |
---|
321 | array_t *dfsarray; |
---|
322 | |
---|
323 | internalPartitionArray = array_alloc(Ntk_Node_t *, 0); |
---|
324 | |
---|
325 | /* Add internal partition nodes */ |
---|
326 | partition = Part_NetworkReadPartition(network); |
---|
327 | dfsarray = g_dfs(partition); |
---|
328 | for(i=0; i< array_n(dfsarray); i++){ |
---|
329 | vertex = array_fetch(vertex_t *, dfsarray, i); |
---|
330 | node = Ntk_NetworkFindNodeByName(network, Part_VertexReadName(vertex)); |
---|
331 | if(!(Ntk_NodeTestIsCombInput(node) || Ntk_NodeTestIsCombOutput(node))){ |
---|
332 | array_insert_last(Ntk_Node_t *, internalPartitionArray, node); |
---|
333 | } |
---|
334 | } |
---|
335 | array_free(dfsarray); |
---|
336 | |
---|
337 | while (fgets(buffer, MAX_LINE_LENGTH -1, fp) != NULL) { |
---|
338 | int position = 0; |
---|
339 | lineNumber++; |
---|
340 | |
---|
341 | /* Every line must end by '\n' */ |
---|
342 | if (buffer[strlen(buffer) -1] != '\n') { |
---|
343 | SimAppendErrorMsg("Simulate: Line ", |
---|
344 | SimInteger2ASCII(lineNumber), "istoolong!\n"); |
---|
345 | FreeArrays(inputsArray, latchesArray, outputsArray, internalPartitionArray); |
---|
346 | return(sim); |
---|
347 | } |
---|
348 | |
---|
349 | |
---|
350 | /* Eliminate spaces */ |
---|
351 | BufferSkipWhiteSpace(buffer, &position); |
---|
352 | /* buffer2 will contain buffer without space in the begining */ |
---|
353 | buffer2 = buffer + position; |
---|
354 | /* Avoid comment and empty lines */ |
---|
355 | if (buffer[position] != '#' && buffer[position] != '\n') { |
---|
356 | if (!strncmp(buffer2, ".inputs", 7)) { |
---|
357 | inputsArray = BufferBuildInputsNodeArray(buffer2 + 7, network); |
---|
358 | if (inputsArray == NIL(array_t)) { |
---|
359 | SimAppendErrorMsg("Simulate: Error line ", |
---|
360 | SimInteger2ASCII(lineNumber), ".\n"); |
---|
361 | FreeArrays(inputsArray, latchesArray, outputsArray, internalPartitionArray); |
---|
362 | return(sim); |
---|
363 | } |
---|
364 | } |
---|
365 | else if (!strncmp(buffer2, ".latches", 8)) { |
---|
366 | latchesArray = BufferBuildLatchesNodeArray(buffer2 + 8, network); |
---|
367 | if (latchesArray == NIL(array_t)) { |
---|
368 | SimAppendErrorMsg("Simulate: Error line ", |
---|
369 | SimInteger2ASCII(lineNumber), ".\n"); |
---|
370 | FreeArrays(inputsArray, latchesArray, outputsArray, internalPartitionArray); |
---|
371 | return(sim); |
---|
372 | } |
---|
373 | } |
---|
374 | else if (!strncmp(buffer2, ".outputs", 8)) { |
---|
375 | outputsArray = BufferBuildOutputsNodeArray(buffer2 + 8, network); |
---|
376 | if (outputsArray == NIL(array_t)) { |
---|
377 | SimAppendErrorMsg("Simulate: Error line ", SimInteger2ASCII(lineNumber), |
---|
378 | ".\n"); |
---|
379 | FreeArrays(inputsArray, latchesArray, outputsArray, internalPartitionArray); |
---|
380 | return(sim); |
---|
381 | } |
---|
382 | } |
---|
383 | else if (!strncmp(buffer2, ".initial", 8)) { |
---|
384 | /* Error if latches are not already read before initial-state */ |
---|
385 | if (latchesArray == NIL(array_t)) { |
---|
386 | error_append("Simulate: Latches must be declared before initial state declaration.\n"); |
---|
387 | FreeArrays(inputsArray, latchesArray, outputsArray, internalPartitionArray); |
---|
388 | return(sim); |
---|
389 | } |
---|
390 | initState = BufferBuildValuesArray(buffer2 + 8, latchesArray); |
---|
391 | if (initState == NIL(array_t)) { |
---|
392 | SimAppendErrorMsg("Simulate: Error line ", |
---|
393 | SimInteger2ASCII(lineNumber), ".\n"); |
---|
394 | FreeArrays(inputsArray, latchesArray, outputsArray, internalPartitionArray); |
---|
395 | return(sim); |
---|
396 | } |
---|
397 | } |
---|
398 | else if (!strncmp(buffer2, ".start_vectors", 14)) { |
---|
399 | /* Verification of the declarations */ |
---|
400 | if (inputsArray == NIL(array_t)) { |
---|
401 | error_append("Simulate: Input file is missing inputs declaration.\n"); |
---|
402 | FreeArrays(inputsArray, latchesArray, outputsArray, internalPartitionArray); |
---|
403 | return(sim); |
---|
404 | } |
---|
405 | |
---|
406 | currentStateHead = array_n(inputsArray); |
---|
407 | |
---|
408 | nodesArray = array_dup(inputsArray); |
---|
409 | array_free(inputsArray); |
---|
410 | inputsArray = NIL(array_t); |
---|
411 | if(latchesArray == NIL(array_t)) { |
---|
412 | /* Verify if actually there is no latch in the network */ |
---|
413 | if (Ntk_NetworkReadNumLatches(network) > 0) { |
---|
414 | error_append("Simulate: Input file is missing latches declaration.\n"); |
---|
415 | FreeArrays(inputsArray, latchesArray, outputsArray, internalPartitionArray); |
---|
416 | return(0); |
---|
417 | } |
---|
418 | else { |
---|
419 | internalPartitionHead = currentStateHead; |
---|
420 | nextStateHead = internalPartitionHead + array_n(internalPartitionArray); |
---|
421 | outputHead = nextStateHead; |
---|
422 | } |
---|
423 | } |
---|
424 | else { |
---|
425 | internalPartitionHead = currentStateHead + array_n(latchesArray); |
---|
426 | nextStateHead = internalPartitionHead + array_n(internalPartitionArray); |
---|
427 | outputHead = nextStateHead + array_n(latchesArray); |
---|
428 | /* Add current states node */ |
---|
429 | array_append(nodesArray, latchesArray); |
---|
430 | array_append(nodesArray, internalPartitionArray); |
---|
431 | array_free(internalPartitionArray); |
---|
432 | /* Add next state node as data-input of current-state node */ |
---|
433 | for(i = 0; i < array_n(latchesArray); i++) { |
---|
434 | node = array_fetch(Ntk_Node_t *, latchesArray, i); |
---|
435 | node = Ntk_LatchReadDataInput(node); |
---|
436 | array_insert_last(Ntk_Node_t *, nodesArray, node); |
---|
437 | } |
---|
438 | array_free(latchesArray); |
---|
439 | } |
---|
440 | if (outputsArray != NIL(array_t)) { |
---|
441 | array_append(nodesArray, outputsArray); |
---|
442 | array_free(outputsArray); |
---|
443 | } |
---|
444 | /* Building nodeToMvfTable */ |
---|
445 | nodeToMvfTable = Sim_NetworkBuildNodeToMvfTable(network, nodesArray, |
---|
446 | internalPartitionHead, |
---|
447 | nextStateHead); |
---|
448 | sim = Sim_SimCreate(network, nodeToMvfTable, inputFile, lineNumber, |
---|
449 | nodesArray, currentStateHead, internalPartitionHead, |
---|
450 | nextStateHead, outputHead, initState, NULL, verbose); |
---|
451 | |
---|
452 | return(sim); /* Normal end */ |
---|
453 | } |
---|
454 | |
---|
455 | /* Unknown string in the declaration part */ |
---|
456 | else { |
---|
457 | SimAppendErrorMsg("Simulate: Syntax error in the declaration line: ", |
---|
458 | SimInteger2ASCII(lineNumber), |
---|
459 | " or missing .start_vectors statement.\n") ; |
---|
460 | FreeArrays(inputsArray, latchesArray, outputsArray, internalPartitionArray); |
---|
461 | return(sim); |
---|
462 | } |
---|
463 | } |
---|
464 | } |
---|
465 | array_free(internalPartitionArray); |
---|
466 | return(sim); |
---|
467 | } |
---|
468 | |
---|
469 | /**Function******************************************************************** |
---|
470 | |
---|
471 | Synopsis [Parses the vectors of a simulation vectors file.] |
---|
472 | |
---|
473 | Description [Parses the vectors of a simulation vectors file. This function |
---|
474 | should be called after Sim_FileParseDeclaration. Reads lines from first line |
---|
475 | after ".start_vectors" statement. Fills the vectorArray field of sim. If |
---|
476 | this field is already set, it will be lost. Only "num" vectors are read(even |
---|
477 | if the number of vectors in the file is greater than this number). If num is |
---|
478 | 0, then all vectors in the file are read. If value is found that does not |
---|
479 | belong to the domain of its specific variable, then an error message is |
---|
480 | written in error_string, and the function returns 0. The function returns 1 |
---|
481 | if it normally ends and no EOF is detected. It returns 2 otherwise(normal |
---|
482 | end and EOF).] |
---|
483 | |
---|
484 | SideEffects [] |
---|
485 | |
---|
486 | SeeAlso [Sim_FileParseDeclaration, Sim_SimReset] |
---|
487 | |
---|
488 | ******************************************************************************/ |
---|
489 | int |
---|
490 | Sim_FileParseVectors( |
---|
491 | FILE * fp, |
---|
492 | Sim_Sim_t * sim, |
---|
493 | int num) |
---|
494 | { |
---|
495 | char buffer[MAX_LINE_LENGTH]; |
---|
496 | char *buffer2; |
---|
497 | array_t *vectorArray; |
---|
498 | int numberVector = 0; |
---|
499 | array_t *inputsArray = SimObtainInputsArray(sim); |
---|
500 | |
---|
501 | sim->vectorArray = array_alloc(array_t *, 0); |
---|
502 | |
---|
503 | while (fgets(buffer, MAX_LINE_LENGTH -1, fp) != NULL) { |
---|
504 | int position = 0; |
---|
505 | (sim->lineNumber)++; |
---|
506 | |
---|
507 | /* Every line must end by '\n' */ |
---|
508 | if (buffer[strlen(buffer) -1] != '\n') { |
---|
509 | SimAppendErrorMsg("Simulate: Line ", SimInteger2ASCII(sim->lineNumber), |
---|
510 | " is too long!\n"); |
---|
511 | array_free(inputsArray); |
---|
512 | return(0); |
---|
513 | } |
---|
514 | |
---|
515 | /* Eliminate spaces */ |
---|
516 | BufferSkipWhiteSpace(buffer, &position); |
---|
517 | /* buffer2 will contain buffer without space in the begining */ |
---|
518 | buffer2 = buffer + position; |
---|
519 | /* Avoid comment and empty lines */ |
---|
520 | if (buffer[position] != '#' && buffer[position] != '\n') { |
---|
521 | /* Read only "num" vectors */ |
---|
522 | if (numberVector >= num && num != 0) { |
---|
523 | array_free(inputsArray); |
---|
524 | return(1); /* Normal end before EOF */ |
---|
525 | } |
---|
526 | vectorArray = BufferBuildValuesArray(buffer2, inputsArray); |
---|
527 | if (vectorArray == NIL(array_t)) { |
---|
528 | SimAppendErrorMsg("Simulate: Error line ", |
---|
529 | SimInteger2ASCII(sim->lineNumber), ".\n"); |
---|
530 | array_free(inputsArray); |
---|
531 | return(0); |
---|
532 | } |
---|
533 | numberVector++; |
---|
534 | SimAddVector(sim, vectorArray); |
---|
535 | } |
---|
536 | } |
---|
537 | array_free(inputsArray); |
---|
538 | return(2); /* End of file */ |
---|
539 | } |
---|
540 | |
---|
541 | /*---------------------------------------------------------------------------*/ |
---|
542 | /* Definition of internal functions */ |
---|
543 | /*---------------------------------------------------------------------------*/ |
---|
544 | |
---|
545 | /*---------------------------------------------------------------------------*/ |
---|
546 | /* Definition of static functions */ |
---|
547 | /*---------------------------------------------------------------------------*/ |
---|
548 | /**Function******************************************************************** |
---|
549 | |
---|
550 | Synopsis [Returns a new array containing the input nodes.] |
---|
551 | |
---|
552 | Description [Returns a new array containing the input nodes. If there is no |
---|
553 | inputs node in sim structure, then an empty array is returned.] |
---|
554 | |
---|
555 | SideEffects [] |
---|
556 | |
---|
557 | ******************************************************************************/ |
---|
558 | static array_t * |
---|
559 | SimObtainInputsArray( |
---|
560 | Sim_Sim_t * sim) |
---|
561 | { |
---|
562 | int i; |
---|
563 | Ntk_Node_t * node; |
---|
564 | array_t * inputsArray = array_alloc(Ntk_Node_t *, 0); |
---|
565 | |
---|
566 | for (i = 0; i < sim->currentStateHead; i++) { |
---|
567 | node = array_fetch(Ntk_Node_t *, sim->nodesArray, i); |
---|
568 | array_insert_last(Ntk_Node_t *, inputsArray, node); |
---|
569 | } |
---|
570 | return(inputsArray); |
---|
571 | } |
---|
572 | |
---|
573 | /**Function******************************************************************** |
---|
574 | |
---|
575 | Synopsis [Frees arrays.] |
---|
576 | |
---|
577 | Description [Frees array. Verifies if array is non NULL.] |
---|
578 | |
---|
579 | SideEffects [] |
---|
580 | |
---|
581 | ******************************************************************************/ |
---|
582 | static void |
---|
583 | FreeArrays( |
---|
584 | array_t *array1, |
---|
585 | array_t *array2, |
---|
586 | array_t *array3, |
---|
587 | array_t *array4) |
---|
588 | { |
---|
589 | if (array1 != NIL(array_t)) { |
---|
590 | array_free(array1); |
---|
591 | } |
---|
592 | if (array2 != NIL(array_t)) { |
---|
593 | array_free(array2); |
---|
594 | } |
---|
595 | if (array3 != NIL(array_t)) { |
---|
596 | array_free(array3); |
---|
597 | } |
---|
598 | if (array4 != NIL(array_t)) { |
---|
599 | array_free(array4); |
---|
600 | } |
---|
601 | } |
---|
602 | |
---|
603 | |
---|
604 | /**Function******************************************************************** |
---|
605 | |
---|
606 | Synopsis [Builds an array of nodes corresponding to the name of inputs |
---|
607 | read in the buffer.] |
---|
608 | |
---|
609 | Description [Builds an array of nodes corresponding to the name of inputs |
---|
610 | read in the buffer. If the name does not correspond to any input node in the |
---|
611 | network, or the number of values is not correct, then an error message is |
---|
612 | written in error_string, and NULL is returned.] |
---|
613 | |
---|
614 | SideEffects [] |
---|
615 | |
---|
616 | ******************************************************************************/ |
---|
617 | static array_t * |
---|
618 | BufferBuildInputsNodeArray( |
---|
619 | char * buffer, |
---|
620 | Ntk_Network_t * network) |
---|
621 | { |
---|
622 | char *str; |
---|
623 | Ntk_Node_t *node; |
---|
624 | int position = 0; |
---|
625 | array_t *array = array_alloc(Ntk_Node_t *, 0); |
---|
626 | |
---|
627 | while((str = BufferObtainStringAtPosition(buffer, &position)) != NULL) { |
---|
628 | node = Ntk_NetworkFindNodeByActualName(network, str); |
---|
629 | if (node == NIL(Ntk_Node_t) || !Ntk_NodeTestIsInput(node)) { |
---|
630 | SimAppendErrorMsg("Simulate: ", str, " is not a valid input name.\n"); |
---|
631 | array_free(array); |
---|
632 | FREE(str); |
---|
633 | return(NIL(array_t)); |
---|
634 | } |
---|
635 | FREE(str); |
---|
636 | array_insert_last(Ntk_Node_t *, array, node); |
---|
637 | } |
---|
638 | /* Verification of number of values */ |
---|
639 | if (array_n(array) != Ntk_NetworkReadNumInputs(network)) { |
---|
640 | error_append("Simulate: All inputs and pseudo-inputs must be specified.\n"); |
---|
641 | array_free(array); |
---|
642 | return(NIL(array_t)); |
---|
643 | } |
---|
644 | return(array); |
---|
645 | } |
---|
646 | |
---|
647 | |
---|
648 | /**Function******************************************************************** |
---|
649 | |
---|
650 | Synopsis [Builds an array of nodes corresponding to the name of latches |
---|
651 | read in the buffer.] |
---|
652 | |
---|
653 | Description [Builds an array of nodes corresponding to the name of latches |
---|
654 | read in the buffer. If the name does not correspond to any latch node in the |
---|
655 | network, or the number of values is not correct, then an error message is |
---|
656 | written in error_string, and NULL is returned.] |
---|
657 | |
---|
658 | SideEffects [] |
---|
659 | |
---|
660 | ******************************************************************************/ |
---|
661 | static array_t * |
---|
662 | BufferBuildLatchesNodeArray( |
---|
663 | char * buffer, |
---|
664 | Ntk_Network_t * network) |
---|
665 | { |
---|
666 | char *str; |
---|
667 | Ntk_Node_t *node; |
---|
668 | int position = 0; |
---|
669 | array_t *array = array_alloc(Ntk_Node_t *, 0); |
---|
670 | |
---|
671 | while ((str = BufferObtainStringAtPosition(buffer, &position)) != NULL) { |
---|
672 | node = Ntk_NetworkFindNodeByActualName(network, str); |
---|
673 | if (node == NIL(Ntk_Node_t) || !Ntk_NodeTestIsLatch(node)) { |
---|
674 | SimAppendErrorMsg("Simulate: ", str, " is not a valid latch name\n"); |
---|
675 | array_free(array); |
---|
676 | FREE(str); |
---|
677 | return(NIL(array_t)); |
---|
678 | } |
---|
679 | FREE(str); |
---|
680 | array_insert_last(Ntk_Node_t *, array, node); |
---|
681 | } |
---|
682 | /* Verification of number of items */ |
---|
683 | if (array_n(array) != Ntk_NetworkReadNumLatches(network)) { |
---|
684 | error_append("Simulate: All latches must be specified.\n"); |
---|
685 | array_free(array); |
---|
686 | return(NIL(array_t)); |
---|
687 | } |
---|
688 | return(array); |
---|
689 | } |
---|
690 | |
---|
691 | /**Function******************************************************************** |
---|
692 | |
---|
693 | Synopsis [Builds an array of nodes corresponding to the name of outputs |
---|
694 | read in the buffer.] |
---|
695 | |
---|
696 | Description [Builds an array of nodes corresponding to the name of outputs |
---|
697 | read in the buffer. If the name does not correspond to any output node in the |
---|
698 | network, then an error message is written in error_string, and NULL is |
---|
699 | returned. The number of outputs may be incomplete.] |
---|
700 | |
---|
701 | SideEffects [] |
---|
702 | |
---|
703 | ******************************************************************************/ |
---|
704 | static array_t * |
---|
705 | BufferBuildOutputsNodeArray( |
---|
706 | char * buffer, |
---|
707 | Ntk_Network_t * network) |
---|
708 | { |
---|
709 | char *str; |
---|
710 | Ntk_Node_t *node; |
---|
711 | int position = 0; |
---|
712 | array_t *array = array_alloc(Ntk_Node_t *, 0); |
---|
713 | |
---|
714 | while((str = BufferObtainStringAtPosition(buffer, &position)) != NULL) { |
---|
715 | node = Ntk_NetworkFindNodeByActualName(network, str); |
---|
716 | if (node == NIL(Ntk_Node_t) || !Ntk_NodeTestIsPrimaryOutput(node)) { |
---|
717 | SimAppendErrorMsg("Simulate: ", str, " is not a valid output name\n"); |
---|
718 | FREE(str); |
---|
719 | array_free(array); |
---|
720 | return(NIL(array_t)); |
---|
721 | } |
---|
722 | FREE(str); |
---|
723 | array_insert_last(Ntk_Node_t *, array, node); |
---|
724 | } |
---|
725 | return(array); |
---|
726 | } |
---|
727 | |
---|
728 | /**Function******************************************************************** |
---|
729 | |
---|
730 | Synopsis [Builds an array of integers representing the code of strings |
---|
731 | contained in the buffer.] |
---|
732 | |
---|
733 | Description [Builds an array of integers representing the code of strings |
---|
734 | contained in the buffer. The code is 1 or 0, if the value is equal "1" or |
---|
735 | "0" and the variable is a binary variable. For a symbolic variable it is |
---|
736 | equal to the index of the value of the variable. The code is equal to the |
---|
737 | value of a variable if the variable has an enumerative type. If a wrong |
---|
738 | value is detected, then an error message is written in error_string and NULL |
---|
739 | is returned. This function verifies also if the number of values is equal to |
---|
740 | the number of nodes in the nodesArray. If it is not, it returns NULL.] |
---|
741 | |
---|
742 | SideEffects [] |
---|
743 | |
---|
744 | ******************************************************************************/ |
---|
745 | static array_t * |
---|
746 | BufferBuildValuesArray( |
---|
747 | char * buffer, |
---|
748 | array_t * nodesArray) |
---|
749 | { |
---|
750 | char *str; |
---|
751 | Ntk_Node_t *node; |
---|
752 | int index; |
---|
753 | int i = 0; |
---|
754 | int arraySize = array_n(nodesArray); |
---|
755 | int position = 0; |
---|
756 | array_t *array = array_alloc(int, 0); |
---|
757 | |
---|
758 | while((str = BufferObtainStringAtPosition(buffer, &position)) != NULL) { |
---|
759 | if (i >= arraySize) { |
---|
760 | SimAppendErrorMsg("Simulate: Too many values(", str, " invalid value).\n"); |
---|
761 | array_free(array); |
---|
762 | FREE(str); |
---|
763 | return(NIL(array_t)); |
---|
764 | } |
---|
765 | node = array_fetch(Ntk_Node_t *, nodesArray, i); |
---|
766 | i++; |
---|
767 | index = SimNodeReadValueCode(node, str); |
---|
768 | if (index == -1) { |
---|
769 | SimAppendErrorMsg("Simulate: ", str, ": invalid value.\n"); |
---|
770 | array_free(array); |
---|
771 | FREE(str); |
---|
772 | return(NIL(array_t)); |
---|
773 | } |
---|
774 | |
---|
775 | FREE(str); |
---|
776 | array_insert_last(int, array, index); |
---|
777 | } |
---|
778 | |
---|
779 | /* Verification of number of items */ |
---|
780 | if (array_n(array) != array_n(nodesArray)) { |
---|
781 | error_append("Simulate: incomplete number of values.\n"); |
---|
782 | array_free(array); |
---|
783 | return(NIL(array_t)); |
---|
784 | } |
---|
785 | return(array); |
---|
786 | } |
---|
787 | |
---|
788 | |
---|
789 | /**Function******************************************************************** |
---|
790 | |
---|
791 | Synopsis [Add a vector to the array of vectors of a sim.] |
---|
792 | |
---|
793 | Description [Add a vector to the array of vectors of a sim. It is an error |
---|
794 | to call this function with a NULL sim or a sim that does not have a vectors |
---|
795 | array.] |
---|
796 | |
---|
797 | SideEffects [] |
---|
798 | |
---|
799 | ******************************************************************************/ |
---|
800 | static void |
---|
801 | SimAddVector( |
---|
802 | Sim_Sim_t * sim, |
---|
803 | array_t * vector) |
---|
804 | { |
---|
805 | array_insert_last(array_t *, sim->vectorArray, vector); |
---|
806 | } |
---|
807 | |
---|
808 | /**Function******************************************************************** |
---|
809 | |
---|
810 | Synopsis [skip over white space in a string.] |
---|
811 | |
---|
812 | Description [skip over white space in a string. set position to the first |
---|
813 | character different from ' ' and '\t'.] |
---|
814 | |
---|
815 | SideEffects [] |
---|
816 | |
---|
817 | ******************************************************************************/ |
---|
818 | static void |
---|
819 | BufferSkipWhiteSpace( |
---|
820 | char * buffer, |
---|
821 | int * position) |
---|
822 | { |
---|
823 | for (; buffer[*position] == ' ' || buffer[*position] == '\t'; (*position)++); |
---|
824 | } |
---|
825 | |
---|
826 | /**Function******************************************************************** |
---|
827 | |
---|
828 | Synopsis [Returns a string read in a buffer at the given position.] |
---|
829 | |
---|
830 | Description [Returns a string read in a buffer at the given position. The |
---|
831 | end of string is detected by ' ', '\t', ';' or '\n'. Eliminates the Space in |
---|
832 | the begining of the buffer. Returns NULL if an empty string has been found |
---|
833 | before ';' or '\n'.] |
---|
834 | |
---|
835 | SideEffects [] |
---|
836 | |
---|
837 | ******************************************************************************/ |
---|
838 | static char * |
---|
839 | BufferObtainStringAtPosition( |
---|
840 | char * buffer, |
---|
841 | int * position) |
---|
842 | { |
---|
843 | char *str; |
---|
844 | int strPosition; |
---|
845 | int len; |
---|
846 | |
---|
847 | /* Traverse Space */ |
---|
848 | BufferSkipWhiteSpace(buffer, position); |
---|
849 | |
---|
850 | strPosition = *position; |
---|
851 | for (;buffer[*position] != ' ' && buffer[*position] != '\t' && |
---|
852 | buffer[*position] != ';' && buffer[*position] != '\n'; (*position)++); |
---|
853 | |
---|
854 | if (strPosition == *position) { |
---|
855 | return(NIL(char)); |
---|
856 | } |
---|
857 | len = *position - strPosition + 1; |
---|
858 | str = ALLOC(char, len); |
---|
859 | strncpy(str, buffer + strPosition, len - 1); |
---|
860 | str[len-1] = '\0'; |
---|
861 | return(str); |
---|
862 | } |
---|
863 | |
---|
864 | /**Function******************************************************************** |
---|
865 | |
---|
866 | Synopsis [Prints the value of a particular variable for a given |
---|
867 | simulation vector.] |
---|
868 | |
---|
869 | Description [Prints the value of a particular variable for a given |
---|
870 | simulation vector. The variable is obtained from the node at the |
---|
871 | vectorIndex position of the nodesArray. The value is obtained from |
---|
872 | the vectorIndex position of the vector. strSize is used for |
---|
873 | formatting. If the number of elements in the vector is less than the |
---|
874 | vectorIndex, a * is printed instead.] |
---|
875 | |
---|
876 | SideEffects [] |
---|
877 | |
---|
878 | ******************************************************************************/ |
---|
879 | static void |
---|
880 | PrintValue(array_t *nodesArray, array_t *vector, int vectorIndex, |
---|
881 | int strSize, FILE *file) |
---|
882 | { |
---|
883 | int index; |
---|
884 | Var_Variable_t *var; |
---|
885 | char *str; |
---|
886 | Ntk_Node_t *node; |
---|
887 | |
---|
888 | if (array_n(vector) > vectorIndex) { |
---|
889 | node = array_fetch(Ntk_Node_t *, nodesArray, vectorIndex); |
---|
890 | var = Ntk_NodeReadVariable(node); |
---|
891 | index = array_fetch(int, vector, vectorIndex); |
---|
892 | if (Var_VariableTestIsSymbolic(var)) { |
---|
893 | SimStringPrint(file, Var_VariableReadSymbolicValueFromIndex(var, index), |
---|
894 | strSize); |
---|
895 | } |
---|
896 | else { /* Binary or enumerative type */ |
---|
897 | str = SimInteger2ASCII(index); |
---|
898 | SimStringPrint(file, str, strSize); |
---|
899 | FREE(str); |
---|
900 | } |
---|
901 | } |
---|
902 | else { |
---|
903 | error_append("Warning: Value is missing in vector.\n"); |
---|
904 | SimStringPrint(file, "*", strSize); |
---|
905 | } |
---|
906 | } |
---|