1 | /**CFile*********************************************************************** |
---|
2 | |
---|
3 | FileName [simMain.c] |
---|
4 | |
---|
5 | PackageName [sim] |
---|
6 | |
---|
7 | Synopsis [simulation of a Network.] |
---|
8 | |
---|
9 | Description [simulation of a Network. This file contains simulate command and |
---|
10 | main simulation functions.] |
---|
11 | |
---|
12 | Author [Shaker Sarwary, Tom Shiple and Rajeev Ranjan] |
---|
13 | |
---|
14 | Copyright [Copyright (c) 1994-1996 The Regents of the Univ. of California. |
---|
15 | All rights reserved. |
---|
16 | |
---|
17 | Permission is hereby granted, without written agreement and without license |
---|
18 | or royalty fees, to use, copy, modify, and distribute this software and its |
---|
19 | documentation for any purpose, provided that the above copyright notice and |
---|
20 | the following two paragraphs appear in all copies of this software. |
---|
21 | |
---|
22 | IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR |
---|
23 | DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT |
---|
24 | OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF |
---|
25 | CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
---|
26 | |
---|
27 | THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, |
---|
28 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
---|
29 | FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN |
---|
30 | "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE |
---|
31 | MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.] |
---|
32 | |
---|
33 | ******************************************************************************/ |
---|
34 | #include "simInt.h" |
---|
35 | |
---|
36 | static char rcsid[] UNUSED = "$Id: simMain.c,v 1.19 2005/04/23 14:31:51 jinh Exp $"; |
---|
37 | |
---|
38 | /**AutomaticStart*************************************************************/ |
---|
39 | |
---|
40 | /*---------------------------------------------------------------------------*/ |
---|
41 | /* Static function prototypes */ |
---|
42 | /*---------------------------------------------------------------------------*/ |
---|
43 | |
---|
44 | static int CommandSimulate(Hrc_Manager_t ** hmgr, int argc, char ** argv); |
---|
45 | static int EvaluateBinaryFunction(mdd_t * functionMdd, mdd_t * vectorMdd); |
---|
46 | static int NodeLexCmp(const void *node1, const void *node2); |
---|
47 | static mdd_t * StatesMddFromVector(Sim_Sim_t * sim, mdd_manager *mddManager); |
---|
48 | static void GenerateInitState(Sim_Sim_t * sim, boolean random); |
---|
49 | |
---|
50 | /**AutomaticEnd***************************************************************/ |
---|
51 | |
---|
52 | |
---|
53 | /*---------------------------------------------------------------------------*/ |
---|
54 | /* Definition of exported functions */ |
---|
55 | /*---------------------------------------------------------------------------*/ |
---|
56 | |
---|
57 | /**Function******************************************************************** |
---|
58 | |
---|
59 | Synopsis [Initializes the sim package.] |
---|
60 | |
---|
61 | SideEffects [] |
---|
62 | |
---|
63 | SeeAlso [Sim_End] |
---|
64 | |
---|
65 | ******************************************************************************/ |
---|
66 | void |
---|
67 | Sim_Init(void) |
---|
68 | { |
---|
69 | Cmd_CommandAdd("simulate", CommandSimulate, /* doesn't changes_network */ 0); |
---|
70 | } |
---|
71 | |
---|
72 | |
---|
73 | /**Function******************************************************************** |
---|
74 | |
---|
75 | Synopsis [Ends the sim package.] |
---|
76 | |
---|
77 | SideEffects [] |
---|
78 | |
---|
79 | SeeAlso [Sim_Init] |
---|
80 | |
---|
81 | ******************************************************************************/ |
---|
82 | void |
---|
83 | Sim_End(void) |
---|
84 | { |
---|
85 | } |
---|
86 | |
---|
87 | /**Function******************************************************************** |
---|
88 | |
---|
89 | Synopsis [Allocates and initializes the SimSimStruct struct.] |
---|
90 | |
---|
91 | Description [Allocates and initializes the SimSimStruct struct. Internally, |
---|
92 | sim deals with nodes of a network instead the name(string) of a variable, |
---|
93 | and with integers representing the value of a variable instead the value as |
---|
94 | a string. nodeToMvfTable provides MDDs of primary outputs and next-state |
---|
95 | functions. External function is provided by sim package that builds |
---|
96 | nodeToMvfTable from network and nodesArray. inputFile is the name of the file |
---|
97 | containing the simulation vectors. lineNumber is the current line number |
---|
98 | while parsing inputFile, it is used to print error messages. nodesArray is |
---|
99 | an array of network nodes of every inputs, current and next state, and |
---|
100 | partial outputs. Only outputs contained in nodesArray are |
---|
101 | simulated. currentStateHead, nextStateHead, outputHead are the index of |
---|
102 | first current state, next state, and output, in nodesArray. initState is an |
---|
103 | array of values representing initial state according to the current state |
---|
104 | order in nodesArray. vectorArray is an array of array of values representing |
---|
105 | vectors to be simulated. if verbose is TRUE, then messages like begin of |
---|
106 | simulation procedure and printing procedure as well as the cpu-time spent |
---|
107 | while simulation are directed to vis_stdout.] |
---|
108 | |
---|
109 | SideEffects [] |
---|
110 | |
---|
111 | ******************************************************************************/ |
---|
112 | Sim_Sim_t * |
---|
113 | Sim_SimCreate( |
---|
114 | Ntk_Network_t * network, |
---|
115 | st_table * nodeToMvfTable, |
---|
116 | char * inputFile, |
---|
117 | int lineNumber, |
---|
118 | array_t * nodesArray, |
---|
119 | int currentStateHead, |
---|
120 | int internalPartitionHead, |
---|
121 | int nextStateHead, |
---|
122 | int outputHead, |
---|
123 | array_t * initState, |
---|
124 | array_t * vectorArray, |
---|
125 | boolean verbose) |
---|
126 | { |
---|
127 | Sim_Sim_t *sim = ALLOC(Sim_Sim_t, 1); |
---|
128 | |
---|
129 | sim->network = network; |
---|
130 | sim->nodeToMvfTable = nodeToMvfTable; |
---|
131 | sim->inputFile = inputFile; |
---|
132 | sim->lineNumber = lineNumber; |
---|
133 | sim->nodesArray = nodesArray; |
---|
134 | sim->currentStateHead = currentStateHead; |
---|
135 | sim->internalPartitionHead = internalPartitionHead, |
---|
136 | sim->nextStateHead = nextStateHead; |
---|
137 | sim->outputHead = outputHead; |
---|
138 | sim->initState = initState; |
---|
139 | sim->vectorArray = vectorArray; |
---|
140 | sim->verbose = verbose; |
---|
141 | |
---|
142 | return(sim); |
---|
143 | } |
---|
144 | |
---|
145 | /**Function******************************************************************** |
---|
146 | |
---|
147 | Synopsis [Resets the sim structure.] |
---|
148 | |
---|
149 | Description [Resets the sim structure. Frees the vectors, and makes it equal |
---|
150 | to NULL. Sets also the initState as the nextState of last vector in |
---|
151 | vectorArray. sim->vectorArray must be != NULL, and contain valid vectors.] |
---|
152 | |
---|
153 | SideEffects [] |
---|
154 | |
---|
155 | ******************************************************************************/ |
---|
156 | void |
---|
157 | Sim_SimReset( |
---|
158 | Sim_Sim_t * sim) |
---|
159 | { |
---|
160 | int i, value; |
---|
161 | array_t *lastVector; |
---|
162 | |
---|
163 | assert(sim->initState != NIL(array_t)); |
---|
164 | |
---|
165 | /* Reset initState */ |
---|
166 | |
---|
167 | if (sim->initState != NIL(array_t)) { |
---|
168 | array_free(sim->initState); |
---|
169 | } |
---|
170 | |
---|
171 | sim->initState = array_alloc(int, 0); |
---|
172 | lastVector = array_fetch_last(array_t *,sim->vectorArray); |
---|
173 | for (i = sim->nextStateHead; i < sim->outputHead; i++) { |
---|
174 | value = array_fetch(int, lastVector, i); |
---|
175 | array_insert_last(int, sim->initState, value); |
---|
176 | } |
---|
177 | |
---|
178 | /* Free vectorArray */ |
---|
179 | for (i = 0; i < array_n(sim->vectorArray); i++) {/* Free Vectors */ |
---|
180 | array_t *vector = array_fetch(array_t *, sim->vectorArray, i); |
---|
181 | array_free(vector); |
---|
182 | } |
---|
183 | array_free(sim->vectorArray); |
---|
184 | sim->vectorArray = NIL(array_t); |
---|
185 | } |
---|
186 | |
---|
187 | /**Function******************************************************************** |
---|
188 | |
---|
189 | Synopsis [Frees a sim Structure.] |
---|
190 | |
---|
191 | SideEffects [] |
---|
192 | |
---|
193 | ******************************************************************************/ |
---|
194 | void |
---|
195 | Sim_SimFree( |
---|
196 | Sim_Sim_t * sim) |
---|
197 | { |
---|
198 | int i; |
---|
199 | array_t *vector; |
---|
200 | Ntk_Node_t *node; |
---|
201 | Mvf_Function_t *mvFunction; |
---|
202 | st_generator *stGen; |
---|
203 | |
---|
204 | if (sim->nodesArray != NULL) { |
---|
205 | array_free(sim->nodesArray); |
---|
206 | } |
---|
207 | if (sim->initState != NIL(array_t)) { |
---|
208 | array_free(sim->initState); |
---|
209 | } |
---|
210 | |
---|
211 | if (sim->vectorArray != NIL(array_t)) { |
---|
212 | for (i = 0; i < array_n(sim->vectorArray); i++) { |
---|
213 | vector = array_fetch(array_t *, sim->vectorArray, i); |
---|
214 | array_free(vector); |
---|
215 | } |
---|
216 | array_free(sim->vectorArray); |
---|
217 | } |
---|
218 | if(sim->nodeToMvfTable != NIL(st_table)) { |
---|
219 | st_foreach_item(sim->nodeToMvfTable, stGen, &node, &mvFunction) { |
---|
220 | Mvf_FunctionFree(mvFunction); |
---|
221 | } |
---|
222 | } |
---|
223 | st_free_table(sim->nodeToMvfTable); |
---|
224 | FREE(sim); |
---|
225 | } |
---|
226 | |
---|
227 | /**Function******************************************************************** |
---|
228 | |
---|
229 | Synopsis [Allocates and initializes an array of nodes of every input, |
---|
230 | current-state, next-state, output.] |
---|
231 | |
---|
232 | SideEffects [] |
---|
233 | |
---|
234 | ******************************************************************************/ |
---|
235 | array_t * |
---|
236 | Sim_NetworkCreateNodesArray( |
---|
237 | Ntk_Network_t * network, |
---|
238 | int * currentStateHead, |
---|
239 | int * internalPartitionHead, |
---|
240 | int * nextStateHead, |
---|
241 | int * outputHead) |
---|
242 | { |
---|
243 | int i; |
---|
244 | lsGen inputGen; |
---|
245 | lsGen latchGen; |
---|
246 | lsGen outputGen; |
---|
247 | Ntk_Node_t *node; |
---|
248 | array_t *nodesArray = array_alloc(Ntk_Node_t *, 0); |
---|
249 | graph_t *partition; |
---|
250 | vertex_t *vertex; |
---|
251 | array_t *dfsarray; |
---|
252 | |
---|
253 | /* Input Nodes */ |
---|
254 | |
---|
255 | { |
---|
256 | array_t *tmpArray= array_alloc(Ntk_Node_t *, 0); |
---|
257 | Ntk_NetworkForEachInput(network, inputGen, node) { |
---|
258 | array_insert_last(Ntk_Node_t *, tmpArray, node); |
---|
259 | } |
---|
260 | array_sort(tmpArray, NodeLexCmp); |
---|
261 | array_append(nodesArray, tmpArray); |
---|
262 | array_free(tmpArray); |
---|
263 | } |
---|
264 | |
---|
265 | |
---|
266 | *currentStateHead = array_n(nodesArray); /* Initialize currentStateHead */ |
---|
267 | |
---|
268 | /* Adding latches */ |
---|
269 | |
---|
270 | { |
---|
271 | array_t *tmpArray= array_alloc(Ntk_Node_t *, 0); |
---|
272 | Ntk_NetworkForEachLatch(network, latchGen, node) { |
---|
273 | array_insert_last(Ntk_Node_t *, tmpArray, node); |
---|
274 | } |
---|
275 | array_sort(tmpArray, NodeLexCmp); |
---|
276 | array_append(nodesArray, tmpArray); |
---|
277 | array_free(tmpArray); |
---|
278 | } |
---|
279 | |
---|
280 | *internalPartitionHead = array_n(nodesArray); /* Initialize internalPartitionHead */ |
---|
281 | |
---|
282 | /* Add internal partition nodes */ |
---|
283 | |
---|
284 | partition = Part_NetworkReadPartition(network); |
---|
285 | dfsarray = g_dfs(partition); |
---|
286 | for(i=0; i< array_n(dfsarray); i++){ |
---|
287 | vertex = array_fetch(vertex_t *, dfsarray, i); |
---|
288 | node = Ntk_NetworkFindNodeByName(network, Part_VertexReadName(vertex)); |
---|
289 | if(!(Ntk_NodeTestIsCombInput(node) || Ntk_NodeTestIsCombOutput(node))){ |
---|
290 | array_insert_last(Ntk_Node_t *, nodesArray, node); |
---|
291 | } |
---|
292 | } |
---|
293 | array_free(dfsarray); |
---|
294 | |
---|
295 | *nextStateHead = array_n(nodesArray); /* Initialize nextStateHead */ |
---|
296 | |
---|
297 | /* Add data-input of latches as next state node */ |
---|
298 | |
---|
299 | for (i = *currentStateHead; i < *internalPartitionHead; i++) { |
---|
300 | node = array_fetch(Ntk_Node_t *, nodesArray, i); |
---|
301 | node = Ntk_LatchReadDataInput(node); |
---|
302 | array_insert_last(Ntk_Node_t *, nodesArray, node); |
---|
303 | } |
---|
304 | |
---|
305 | *outputHead = array_n(nodesArray); /* Initialize outputHead */ |
---|
306 | |
---|
307 | |
---|
308 | /* Adding outputs */ |
---|
309 | |
---|
310 | { |
---|
311 | array_t *tmpArray= array_alloc(Ntk_Node_t *, 0); |
---|
312 | Ntk_NetworkForEachPrimaryOutput(network, outputGen, node) { |
---|
313 | array_insert_last(Ntk_Node_t *, tmpArray, node); |
---|
314 | } |
---|
315 | array_sort(tmpArray, NodeLexCmp); |
---|
316 | array_append(nodesArray, tmpArray); |
---|
317 | array_free(tmpArray); |
---|
318 | } |
---|
319 | |
---|
320 | return(nodesArray); |
---|
321 | } |
---|
322 | |
---|
323 | /**Function******************************************************************** |
---|
324 | |
---|
325 | Synopsis [Generates random simulation vectors.] |
---|
326 | |
---|
327 | Description [Generates numberVector random simulation vectors. |
---|
328 | sim->vectorArray is re-initialized by this function. If sim->vectorArray |
---|
329 | already contains vectors, they will be lost and cause a memory leak.] |
---|
330 | |
---|
331 | SideEffects [] |
---|
332 | |
---|
333 | ******************************************************************************/ |
---|
334 | void |
---|
335 | Sim_SimGenerateRandomVectors( |
---|
336 | Sim_Sim_t * sim, |
---|
337 | int numberVector, |
---|
338 | Sim_PseudoSrc pseudoInputSource) |
---|
339 | { |
---|
340 | int i; |
---|
341 | int j; |
---|
342 | array_t *vector; |
---|
343 | array_t *vectorArray = array_alloc(array_t *, 0); |
---|
344 | array_t *nodesArray = sim->nodesArray; |
---|
345 | |
---|
346 | |
---|
347 | /* Initialization with empty vectors */ |
---|
348 | for (j = 0; j < numberVector; j++) { |
---|
349 | vector = array_alloc(int, 0); |
---|
350 | array_insert_last(array_t *, vectorArray, vector); |
---|
351 | } |
---|
352 | |
---|
353 | /* For every input node */ |
---|
354 | for (i = 0; i < sim->currentStateHead; i++) { |
---|
355 | Ntk_Node_t *node = array_fetch(Ntk_Node_t *, nodesArray, i); |
---|
356 | |
---|
357 | /* For every vector */ |
---|
358 | for (j = 0; j < numberVector; j++) { |
---|
359 | int value = SimNodeComputeRandomValue(node, pseudoInputSource); |
---|
360 | |
---|
361 | vector = array_fetch(array_t *, vectorArray, j); |
---|
362 | /* vector is empty => array_insert_last is convenient */ |
---|
363 | array_insert_last(int, vector, value); |
---|
364 | } |
---|
365 | } |
---|
366 | |
---|
367 | sim->vectorArray = vectorArray; |
---|
368 | } |
---|
369 | |
---|
370 | /**Function******************************************************************** |
---|
371 | |
---|
372 | Synopsis [Generates a random initial state.] |
---|
373 | |
---|
374 | Description [Generates a random initial state, using the primary and pseudo |
---|
375 | input values in the first input vector of the sim structure. sim->initState |
---|
376 | is reset by this function.] |
---|
377 | |
---|
378 | SideEffects [] |
---|
379 | |
---|
380 | ******************************************************************************/ |
---|
381 | void |
---|
382 | Sim_SimGenerateRandomInitState( |
---|
383 | Sim_Sim_t * sim) |
---|
384 | { |
---|
385 | GenerateInitState(sim, TRUE); |
---|
386 | } |
---|
387 | |
---|
388 | |
---|
389 | /**Function******************************************************************** |
---|
390 | |
---|
391 | Synopsis [Does a simulation on a sim structure.] |
---|
392 | |
---|
393 | Description [Does a simulation on a sim structure. The sim structure must |
---|
394 | previously be initialized by valid vectors. If vectors are not valid, bad |
---|
395 | evaluations should be expected. There are two kinds of invalid vectors : |
---|
396 | <p> |
---|
397 | 1- The vector is incomplete : f = a+b+c, and vector = not(a) (a = 0) |
---|
398 | <p> |
---|
399 | 2- The vector is not in the domain of the function : F_red = a.b, F_blue = |
---|
400 | a.c, vector = not(a).] |
---|
401 | |
---|
402 | SideEffects [] |
---|
403 | |
---|
404 | ******************************************************************************/ |
---|
405 | void |
---|
406 | Sim_SimSimulate( |
---|
407 | Sim_Sim_t * sim) |
---|
408 | { |
---|
409 | Ntk_Node_t *node; |
---|
410 | array_t *vector; |
---|
411 | array_t *partitionVector; |
---|
412 | int i, j; |
---|
413 | int value; |
---|
414 | mdd_t *vectorMdd; |
---|
415 | int numberVector = array_n(sim->vectorArray); |
---|
416 | |
---|
417 | if(sim->verbose) { |
---|
418 | (void) fprintf(vis_stdout, "Simulating %d vectors ...\n", numberVector); |
---|
419 | fflush(vis_stdout); |
---|
420 | } |
---|
421 | |
---|
422 | /* Initialization with initState */ |
---|
423 | SimSimInitializeCurrentState(sim); |
---|
424 | |
---|
425 | /* |
---|
426 | for (j = sim->internalPartitionHead; j < sim->nextStateHead; j++) { |
---|
427 | node = array_fetch(Ntk_Node_t *, sim->nodesArray, j); |
---|
428 | fprintf(stdout, "%s \t", Ntk_NodeReadName(node)); |
---|
429 | } |
---|
430 | if(sim->internalPartitionHead < sim->nextStateHead){ |
---|
431 | fprintf(stdout, "\n"); |
---|
432 | } |
---|
433 | */ |
---|
434 | |
---|
435 | for (i = 0; i < numberVector; i++) { /* For every vector */ |
---|
436 | if (i > 0) { /* Put the current-state = last-next-state */ |
---|
437 | SimSimVectorFillCurrentState(sim, i); |
---|
438 | } |
---|
439 | else { |
---|
440 | SimSimInitializeCurrentState(sim); |
---|
441 | } |
---|
442 | |
---|
443 | vector = array_fetch(array_t *, sim->vectorArray, i); |
---|
444 | |
---|
445 | /* partitionVector represents the values of the internal nodes |
---|
446 | of the partition, induced by the values of the vector array. |
---|
447 | */ |
---|
448 | |
---|
449 | partitionVector = array_alloc(int, 0); |
---|
450 | |
---|
451 | /* simulate internal nodes first. As these internal nodes are |
---|
452 | simulated, the vectorMdd is updated to reflect the newly computed |
---|
453 | values |
---|
454 | */ |
---|
455 | |
---|
456 | for (j = sim->internalPartitionHead; j < sim->nextStateHead; j++) { |
---|
457 | vectorMdd = SimSimVectorBuildMdd(sim, vector, partitionVector); |
---|
458 | node = array_fetch(Ntk_Node_t *, sim->nodesArray, j); |
---|
459 | value = Sim_nodeToMvfTableEvaluateNode(sim->nodeToMvfTable, node, vectorMdd); |
---|
460 | array_insert(int, partitionVector, j - sim->internalPartitionHead, value); |
---|
461 | mdd_free(vectorMdd); |
---|
462 | } |
---|
463 | /* |
---|
464 | if(sim->internalPartitionHead < sim->nextStateHead){ |
---|
465 | fprintf(stdout, "\n"); |
---|
466 | } |
---|
467 | */ |
---|
468 | /* simulate the rest of the nodes */ |
---|
469 | vectorMdd = SimSimVectorBuildMdd(sim, vector, partitionVector); |
---|
470 | array_free(partitionVector); |
---|
471 | |
---|
472 | for (j = sim->nextStateHead; j < array_n(sim->nodesArray); j++) { |
---|
473 | node = array_fetch(Ntk_Node_t *, sim->nodesArray, j); |
---|
474 | value = Sim_nodeToMvfTableEvaluateNode(sim->nodeToMvfTable, node, vectorMdd); |
---|
475 | array_insert(int, vector, j, value); |
---|
476 | } |
---|
477 | |
---|
478 | mdd_free(vectorMdd); |
---|
479 | } |
---|
480 | } |
---|
481 | |
---|
482 | /**Function******************************************************************** |
---|
483 | |
---|
484 | Synopsis [Evaluates the function of a node on a minterm.] |
---|
485 | |
---|
486 | Description [Evaluates the function of a node on a minterm. This node must |
---|
487 | have an entry in nodeToMvfTable. The node may represent a binary or |
---|
488 | multi-valued function. The result is returned as an integer. If the node |
---|
489 | represents a binary function, 0 or 1 will be returned. |
---|
490 | <p> |
---|
491 | NOTE : WE ASSUME THAT THE FUNCTION IS COMPLETELY SPECIFIED. WE ASSUME ALSO |
---|
492 | THAT THE VECTOR IS "COMPLETE". AS A CONSEQUENCE, IF THE VECTOR IS NOT IN THE |
---|
493 | ONSET OF ONE OF THE FIRST n-1 VALUES OF THE FUNCTION, THEN IT IS ASSUMED |
---|
494 | THAT THE FUNCTION TAKES ITS LAST VALUE ON THIS VECTOR.] |
---|
495 | |
---|
496 | SideEffects [] |
---|
497 | |
---|
498 | SeeAlso [Sim_nodeToMvfTableEvaluateNodesArray] |
---|
499 | |
---|
500 | ******************************************************************************/ |
---|
501 | int |
---|
502 | Sim_nodeToMvfTableEvaluateNode( |
---|
503 | st_table * nodeToMvfTable, |
---|
504 | Ntk_Node_t * node, |
---|
505 | mdd_t * vectorMdd) |
---|
506 | { |
---|
507 | int i; |
---|
508 | Mvf_Function_t *mvFunction = NIL(Mvf_Function_t); |
---|
509 | |
---|
510 | (void) st_lookup(nodeToMvfTable, (char *) node, &mvFunction); |
---|
511 | |
---|
512 | /* |
---|
513 | * For a binary function the array contains 2 MDDs for off-set and |
---|
514 | * on-set, with the indices 0 or 1. |
---|
515 | */ |
---|
516 | |
---|
517 | for (i = 0; i < Mvf_FunctionReadNumComponents(mvFunction) - 1; i++) { |
---|
518 | if (EvaluateBinaryFunction(Mvf_FunctionReadComponent(mvFunction, i), |
---|
519 | vectorMdd) == 1) { |
---|
520 | return(i); |
---|
521 | } |
---|
522 | } |
---|
523 | /* Return last value without evaluation */ |
---|
524 | return(i); |
---|
525 | } |
---|
526 | |
---|
527 | /**Function******************************************************************** |
---|
528 | |
---|
529 | Synopsis [Evaluates every node of an array on a minterm.] |
---|
530 | |
---|
531 | Description [Evaluates every node of an array on a minterm. The input values |
---|
532 | are given by an MDD. Nodes, to be evaluated, must have an entry in |
---|
533 | nodeToMvfTable. The nodes may represent a binary or multi-valued |
---|
534 | function. The result is returned as an array of integers. If a node |
---|
535 | represents a binary function, the integer is equal to either 0 or 1. |
---|
536 | <p> |
---|
537 | NOTE : WE ASSUME THAT THE FUNCTION IS COMPLETELY SPECIFIED. WE ASSUME ALSO |
---|
538 | THAT THE VECTOR IS "COMPLETE". AS A CONSEQUENCE, IF THE VECTOR IS NOT IN THE |
---|
539 | ONSET OF ONE OF THE FIRST n-1 VALUES OF THE FUNCTION, THEN IT IS ASSUMED |
---|
540 | THAT THE FUNCTION TAKES ITS LAST VALUE ON THIS VECTOR.] |
---|
541 | |
---|
542 | SideEffects [] |
---|
543 | |
---|
544 | SeeAlso [Sim_nodeToMvfTableEvaluateNode] |
---|
545 | |
---|
546 | ******************************************************************************/ |
---|
547 | array_t * |
---|
548 | Sim_nodeToMvfTableEvaluateNodesArray( |
---|
549 | st_table * nodeToMvfTable, |
---|
550 | array_t * nodesArray, |
---|
551 | mdd_t * vectorMdd) |
---|
552 | { |
---|
553 | int i, value; |
---|
554 | Ntk_Node_t *node; |
---|
555 | array_t *resultArray = array_alloc(int, 0); |
---|
556 | |
---|
557 | for (i = 0; i < array_n(nodesArray); i++) { |
---|
558 | node = array_fetch(Ntk_Node_t *, nodesArray, i); |
---|
559 | value = Sim_nodeToMvfTableEvaluateNode(nodeToMvfTable, node, vectorMdd); |
---|
560 | array_insert(int, resultArray, i, value); |
---|
561 | } |
---|
562 | return(resultArray); |
---|
563 | } |
---|
564 | |
---|
565 | /**Function******************************************************************** |
---|
566 | |
---|
567 | Synopsis [Generates random vectors, performs simulation.] |
---|
568 | |
---|
569 | Devscription [Generates num random vectors, performs |
---|
570 | simulation. These vectors form only one thread of |
---|
571 | simulation. Returns an mdd_t of simulated states.] |
---|
572 | |
---|
573 | SideEffects [] |
---|
574 | |
---|
575 | ******************************************************************************/ |
---|
576 | mdd_t * |
---|
577 | Sim_RandomSimulate( |
---|
578 | Ntk_Network_t * network, |
---|
579 | int num, |
---|
580 | boolean verbose) |
---|
581 | { |
---|
582 | int numRemainingVector; |
---|
583 | st_table *nodeToMvfTable; |
---|
584 | Sim_Sim_t *sim; |
---|
585 | int currentStateHead = 0; |
---|
586 | int internalPartitionHead = 0; |
---|
587 | int nextStateHead = 0; |
---|
588 | int outputHead = 0; |
---|
589 | int firstTime = 1; |
---|
590 | mdd_t *states, *simStates; |
---|
591 | mdd_manager *mddManager = Ntk_NetworkReadMddManager(network); |
---|
592 | Sim_PseudoSrc pseudoInputSource = Sim_Random_c; |
---|
593 | array_t *nodesArray = Sim_NetworkCreateNodesArray(network, |
---|
594 | ¤tStateHead, &internalPartitionHead, |
---|
595 | &nextStateHead, &outputHead); |
---|
596 | |
---|
597 | /* Building nodeToMvfTable */ |
---|
598 | nodeToMvfTable = Sim_NetworkBuildNodeToMvfTable(network, nodesArray, |
---|
599 | internalPartitionHead, |
---|
600 | nextStateHead); |
---|
601 | |
---|
602 | sim = Sim_SimCreate(network, nodeToMvfTable, NULL, 0, nodesArray, |
---|
603 | currentStateHead, internalPartitionHead, nextStateHead, outputHead, |
---|
604 | NULL, NULL, verbose); |
---|
605 | |
---|
606 | /* If partition method was partial/boundary, and -i was used, then dont simulate*/ |
---|
607 | if(SimTestPartInTermsOfCI(sim)){ |
---|
608 | fprintf(stdout, "The partition contains internal nodes, and all partition functions are \n"); |
---|
609 | fprintf(stdout, "in terms of combinational inputs - quitting. Re-create the partition \n"); |
---|
610 | fprintf(stdout, "without the -i option and then re-run simulatate.\n"); |
---|
611 | Sim_SimFree(sim); |
---|
612 | return(0); |
---|
613 | } |
---|
614 | |
---|
615 | /* Simulation by packet */ |
---|
616 | simStates = mdd_zero(mddManager); |
---|
617 | numRemainingVector = num; |
---|
618 | do { |
---|
619 | mdd_t *tmp; |
---|
620 | /* Number of vectors to be simulated in current pass. */ |
---|
621 | num = (numRemainingVector > SIMPACKET_SIZE) |
---|
622 | ? SIMPACKET_SIZE |
---|
623 | : numRemainingVector; |
---|
624 | |
---|
625 | Sim_SimGenerateRandomVectors(sim, num, pseudoInputSource); |
---|
626 | |
---|
627 | /* |
---|
628 | * Random init state generation. This must follow generation of input |
---|
629 | * vectors, because init state depends on inputs. |
---|
630 | */ |
---|
631 | if (firstTime) { |
---|
632 | GenerateInitState(sim, FALSE); |
---|
633 | } |
---|
634 | |
---|
635 | /* SIMULATION */ |
---|
636 | Sim_SimSimulate(sim); |
---|
637 | |
---|
638 | /* Print simulation vectors. On first pass, file must be created. */ |
---|
639 | states = StatesMddFromVector(sim, mddManager); |
---|
640 | tmp = mdd_or(states, simStates, 1, 1); |
---|
641 | mdd_free(states); |
---|
642 | mdd_free(simStates); |
---|
643 | simStates = tmp; |
---|
644 | firstTime = 0; |
---|
645 | |
---|
646 | /* Reset Vectors */ |
---|
647 | Sim_SimReset(sim); |
---|
648 | |
---|
649 | numRemainingVector -= num; |
---|
650 | } while(numRemainingVector > 0); |
---|
651 | |
---|
652 | Sim_SimFree(sim); |
---|
653 | return(simStates); |
---|
654 | } /* end of Sim_RandomSimulate */ |
---|
655 | |
---|
656 | |
---|
657 | |
---|
658 | /*---------------------------------------------------------------------------*/ |
---|
659 | /* Definition of internal functions */ |
---|
660 | /*---------------------------------------------------------------------------*/ |
---|
661 | |
---|
662 | /**Function******************************************************************** |
---|
663 | |
---|
664 | Synopsis [Sets the current state of the first vector in vectorArray using |
---|
665 | initState.] |
---|
666 | |
---|
667 | Description [Sets the current state of the first vector in vectorArray using |
---|
668 | initState. vectorArray must contain already the inputs value(AND only the |
---|
669 | inputs value). It is an error to call this function with a sim structure |
---|
670 | that contains a wrong vectorArray or a wrong initState.] |
---|
671 | |
---|
672 | SideEffects [] |
---|
673 | |
---|
674 | ******************************************************************************/ |
---|
675 | void |
---|
676 | SimSimInitializeCurrentState( |
---|
677 | Sim_Sim_t * sim) |
---|
678 | { |
---|
679 | int i, value; |
---|
680 | |
---|
681 | /* Get the first vector from vectorArray */ |
---|
682 | array_t *vector = array_fetch(array_t *, sim->vectorArray, 0); |
---|
683 | |
---|
684 | for (i = 0; i < array_n(sim->initState); i++) { |
---|
685 | value = array_fetch(int, sim->initState, i); |
---|
686 | array_insert_last(int, vector, value); |
---|
687 | } |
---|
688 | } |
---|
689 | |
---|
690 | /**Function******************************************************************** |
---|
691 | |
---|
692 | Synopsis [Generates random vectors, performs simulation, and prints the |
---|
693 | result.] |
---|
694 | |
---|
695 | Devscription [Generates num random vectors, performs simulation, and prints |
---|
696 | the result. Returns 1 if function ends normally, else returns 0. If |
---|
697 | statesPrint is 1, then current and next state are also printed, else it is |
---|
698 | not. See Sim_SimInitialize for further information about arguments.] |
---|
699 | |
---|
700 | SideEffects [] |
---|
701 | |
---|
702 | ******************************************************************************/ |
---|
703 | boolean |
---|
704 | SimRandomSimulateAndPrint( |
---|
705 | Ntk_Network_t * network, |
---|
706 | int num, |
---|
707 | char * outputFile, |
---|
708 | Sim_PseudoSrc pseudoInputSource, |
---|
709 | int printInputsFlag, |
---|
710 | int printOutputsFlag, |
---|
711 | int printPseudoInputsFlag, |
---|
712 | int printStatesFlag, |
---|
713 | boolean verbose) |
---|
714 | { |
---|
715 | int numRemainingVector; |
---|
716 | FILE *outFile; |
---|
717 | st_table *nodeToMvfTable; |
---|
718 | Sim_Sim_t *sim; |
---|
719 | int firstTime = 1; |
---|
720 | int currentStateHead = 0; |
---|
721 | int internalPartitionHead = 0; |
---|
722 | int nextStateHead = 0; |
---|
723 | int outputHead = 0; |
---|
724 | array_t *nodesArray = Sim_NetworkCreateNodesArray(network, |
---|
725 | ¤tStateHead, &internalPartitionHead, |
---|
726 | &nextStateHead, &outputHead); |
---|
727 | |
---|
728 | /* Building nodeToMvfTable */ |
---|
729 | nodeToMvfTable = Sim_NetworkBuildNodeToMvfTable(network, nodesArray, |
---|
730 | internalPartitionHead, |
---|
731 | nextStateHead); |
---|
732 | |
---|
733 | sim = Sim_SimCreate(network, nodeToMvfTable, NULL, 0, nodesArray, |
---|
734 | currentStateHead, internalPartitionHead, nextStateHead, outputHead, |
---|
735 | NULL, NULL, verbose); |
---|
736 | |
---|
737 | /* If partition method was partial/boundary, and -i was used, then dont simulate*/ |
---|
738 | if(SimTestPartInTermsOfCI(sim)){ |
---|
739 | fprintf(stdout, "The partition contains internal nodes, and all partition functions are \n"); |
---|
740 | fprintf(stdout, "in terms of combinational inputs - quitting. Re-create the partition \n"); |
---|
741 | fprintf(stdout, "without the -i option and then re-run simulatate.\n"); |
---|
742 | Sim_SimFree(sim); |
---|
743 | return(0); |
---|
744 | } |
---|
745 | |
---|
746 | if (outputFile == NIL(char)) { |
---|
747 | outFile = vis_stdout; |
---|
748 | } |
---|
749 | else { |
---|
750 | outFile = Cmd_FileOpen(outputFile, "w", NIL(char *), 0); |
---|
751 | if (outFile == NIL(FILE)){ |
---|
752 | return(0); |
---|
753 | } |
---|
754 | } |
---|
755 | |
---|
756 | /* Simulation by packet */ |
---|
757 | numRemainingVector = num; |
---|
758 | do { |
---|
759 | |
---|
760 | /* Number of vectors to be simulated in current pass. */ |
---|
761 | num = (numRemainingVector > SIMPACKET_SIZE) |
---|
762 | ? SIMPACKET_SIZE |
---|
763 | : numRemainingVector; |
---|
764 | |
---|
765 | Sim_SimGenerateRandomVectors(sim, num, pseudoInputSource); |
---|
766 | |
---|
767 | /* |
---|
768 | * Random init state generation. This must follow generation of input |
---|
769 | * vectors, because init state depends on inputs. |
---|
770 | */ |
---|
771 | if (firstTime) { |
---|
772 | Sim_SimGenerateRandomInitState(sim); |
---|
773 | } |
---|
774 | |
---|
775 | /* SIMULATION */ |
---|
776 | Sim_SimSimulate(sim); |
---|
777 | |
---|
778 | /* Print simulation vectors. On first pass, file must be created. */ |
---|
779 | Sim_SimPrint(sim, outFile, firstTime, printInputsFlag, |
---|
780 | printOutputsFlag, printPseudoInputsFlag, |
---|
781 | printStatesFlag); |
---|
782 | firstTime = 0; |
---|
783 | |
---|
784 | /* Reset Vectors */ |
---|
785 | Sim_SimReset(sim); |
---|
786 | |
---|
787 | numRemainingVector -= num; |
---|
788 | } while(numRemainingVector > 0); |
---|
789 | |
---|
790 | if (outputFile != NIL(char)) { |
---|
791 | fclose(outFile); |
---|
792 | } |
---|
793 | Sim_SimFree(sim); |
---|
794 | return(1); |
---|
795 | } |
---|
796 | |
---|
797 | /**Function******************************************************************** |
---|
798 | |
---|
799 | Synopsis [Parses the simulation vectors file, builds a SimSimStruct, |
---|
800 | simulate and prints the result into the output file.] |
---|
801 | |
---|
802 | Description [Parses the simulation vectors file, builds a SimSimStruct, |
---|
803 | simulate and prints the result into the output file. The header of a |
---|
804 | simulation-vectors file contains .inputs, .pseudo-inputs, .latches, |
---|
805 | .outputs, and .initial fields and ends with .start_vectors. If a variable is |
---|
806 | found for which there doesn't exist a corresponding node in the network, or |
---|
807 | a value is found that does not belong to the domain of its specific |
---|
808 | variable, then an error message is writen in error_string, the partial |
---|
809 | simStruct is freed, and the function returns 0. The simulation file must |
---|
810 | contain each category of declaration in a line(Two ".inputs" is not allowed |
---|
811 | in the same file). initial-state declaration must be writen after the |
---|
812 | latches declaration. Vectors are simulated by "packet": When SIMPACKET_SIZE |
---|
813 | vectors are read, they are simulated and the result is printed. Only "num" |
---|
814 | vectors are read and simulated(even if the number of vectors in the file is |
---|
815 | greater than this number). If num is 0, then all vectors in the file are |
---|
816 | simulated. The function returns 1 if it ends normally, else returns 0.] |
---|
817 | |
---|
818 | SideEffects [] |
---|
819 | |
---|
820 | ******************************************************************************/ |
---|
821 | boolean |
---|
822 | SimFileSimulateAndPrint( |
---|
823 | Ntk_Network_t * network, |
---|
824 | int num, |
---|
825 | char * inputFile, |
---|
826 | char * outputFile, |
---|
827 | Sim_PseudoSrc pseudoInputSource, |
---|
828 | int printInputsFlag, |
---|
829 | int printOutputsFlag, |
---|
830 | int printPseudoInputsFlag, |
---|
831 | int printStatesFlag, |
---|
832 | boolean verbose) |
---|
833 | { |
---|
834 | int numRemainingVector, packet; |
---|
835 | int ioStatus; |
---|
836 | FILE *outFile; |
---|
837 | int printFlag = 1; |
---|
838 | FILE *inFile = Cmd_FileOpen(inputFile, "r", NIL(char *), 0); |
---|
839 | Sim_Sim_t *sim = Sim_FileParseDeclaration(network, inFile, inputFile, verbose); |
---|
840 | |
---|
841 | if (sim == NIL(Sim_Sim_t)) { |
---|
842 | return(0); |
---|
843 | } |
---|
844 | |
---|
845 | /* If partition method was partial/boundary, and -i was used, then dont simulate*/ |
---|
846 | if(SimTestPartInTermsOfCI(sim)){ |
---|
847 | fprintf(stdout, "The partition contains internal nodes, and all partition functions are \n"); |
---|
848 | fprintf(stdout, "in terms of combinational inputs - quitting. Re-create the partition \n"); |
---|
849 | fprintf(stdout, "without the -i option and then re-run simulatate.\n"); |
---|
850 | Sim_SimFree(sim); |
---|
851 | return(0); |
---|
852 | } |
---|
853 | |
---|
854 | if (outputFile == NIL(char)) { |
---|
855 | outFile = vis_stdout; |
---|
856 | } |
---|
857 | else { |
---|
858 | outFile = Cmd_FileOpen(outputFile, "w", NIL(char *), 0); |
---|
859 | if (outFile == NIL(FILE)){ |
---|
860 | return(0); |
---|
861 | } |
---|
862 | } |
---|
863 | |
---|
864 | /* Simulation by packet */ |
---|
865 | numRemainingVector = num; |
---|
866 | do { |
---|
867 | |
---|
868 | /********** Number of vectors to be simulated in current pass **********/ |
---|
869 | /* num == 0 => simulate all vectors of the file => packet = SIMPACKET_SIZE */ |
---|
870 | if (numRemainingVector > SIMPACKET_SIZE || num == 0) { |
---|
871 | packet = SIMPACKET_SIZE; |
---|
872 | } |
---|
873 | else { |
---|
874 | packet = numRemainingVector; |
---|
875 | } |
---|
876 | |
---|
877 | ioStatus = Sim_FileParseVectors(inFile, sim, numRemainingVector); |
---|
878 | if (ioStatus == 0) { /* Error case */ |
---|
879 | Sim_SimFree(sim); |
---|
880 | fclose(inFile); |
---|
881 | if (outputFile != NIL(char)) { |
---|
882 | fclose(outFile); |
---|
883 | } |
---|
884 | return(0); |
---|
885 | } |
---|
886 | |
---|
887 | |
---|
888 | /*************************** SIMULATION ****************************/ |
---|
889 | |
---|
890 | Sim_SimSimulate(sim); |
---|
891 | |
---|
892 | /******************* Print Simulation Vectors **********************/ |
---|
893 | |
---|
894 | Sim_SimPrint(sim, outFile, printFlag, printInputsFlag, |
---|
895 | printOutputsFlag, printPseudoInputsFlag, |
---|
896 | printStatesFlag); |
---|
897 | printFlag = 0; |
---|
898 | |
---|
899 | Sim_SimReset(sim); |
---|
900 | numRemainingVector -= packet; |
---|
901 | } while(ioStatus != 2 && (num == 0 || numRemainingVector > 0)); |
---|
902 | |
---|
903 | Sim_SimFree(sim); |
---|
904 | fclose(inFile); |
---|
905 | if (outputFile != NIL(char)) { |
---|
906 | fclose(outFile); |
---|
907 | } |
---|
908 | return(1); |
---|
909 | } |
---|
910 | |
---|
911 | /*---------------------------------------------------------------------------*/ |
---|
912 | /* Definition of static functions */ |
---|
913 | /*---------------------------------------------------------------------------*/ |
---|
914 | |
---|
915 | /**Function******************************************************************** |
---|
916 | |
---|
917 | Synopsis [implement the simulate command.] |
---|
918 | |
---|
919 | CommandName [simulate] |
---|
920 | |
---|
921 | CommandSynopsis [simulate the flattened network] |
---|
922 | |
---|
923 | CommandArguments [\[ -I <0/1> \] \[ -O <0/1> \] \[ -P |
---|
924 | <0/1> \] \[ -S <0/1> \] \[ -h \] \[ -i <vectors_file> \] \[ -n <vectors_number> \] \[ -o |
---|
925 | <output_file> \] \[ -p <0|1> \] |
---|
926 | \[ -v \]] |
---|
927 | |
---|
928 | CommandDescription [Simulates a network with a set of input |
---|
929 | vectors. Before calling this command, the user should create a partition |
---|
930 | (using the command <tt>build_partition_mdds</tt>). The simulation |
---|
931 | vectors can be provided by the user (using -i vectors_file), or |
---|
932 | generated randomly. <p> |
---|
933 | |
---|
934 | Command options:<p> |
---|
935 | |
---|
936 | <dl> |
---|
937 | <dt>-I <0/1> |
---|
938 | |
---|
939 | <dd>This option controls the printing the |
---|
940 | primary input variables. 0 implies printing is disabled, enabled |
---|
941 | otherwise. The default value is 1. The output file generated with |
---|
942 | this flag set to 0 may not be used as input file for simulation (if |
---|
943 | there are some primary inputs to the system). |
---|
944 | |
---|
945 | <dt>-O <0/1> |
---|
946 | |
---|
947 | <dd>This option controls the printing the |
---|
948 | primary output variables. 0 implies printing is disabled, enabled |
---|
949 | otherwise. The default value is 1. |
---|
950 | |
---|
951 | <dt>-P <0/1> |
---|
952 | <dd> This option controls the printing the |
---|
953 | pseudo input variables. 0 implies printing is disabled, enabled |
---|
954 | otherwise. The default value is 1. The output file generated with |
---|
955 | this flag set to 0 may not be used as input file for simulation (if |
---|
956 | there are some pseudo-inputs to the system). |
---|
957 | |
---|
958 | |
---|
959 | <dt>-S <0/1> |
---|
960 | <dd> This option controls the printing the |
---|
961 | state variables. 0 implies printing is disabled, enabled |
---|
962 | otherwise. The default value is 1. |
---|
963 | |
---|
964 | <dt>-h |
---|
965 | <dd>Print a help message that details all options. |
---|
966 | |
---|
967 | |
---|
968 | <dt> -i <vectors_file> |
---|
969 | <dd>Give the simulation vector file name. If this option |
---|
970 | is not used, vectors are generated randomly. |
---|
971 | |
---|
972 | <dt>-n <N> |
---|
973 | <dd> Simulate N vectors. This option should be used if vectors_file |
---|
974 | is not specified. If a vectors_file is given, and if there are more than N |
---|
975 | vectors in the file, only the first N vectors are simulated. |
---|
976 | |
---|
977 | <dt>-o <output_file> |
---|
978 | <dd> Give the name of a file where the simulation result |
---|
979 | should be written. If this option is not used, the simulation result is |
---|
980 | directed to standard output. |
---|
981 | |
---|
982 | <dt>-p <0|1|2> |
---|
983 | <dd> This option is available only with random vector |
---|
984 | generation mode, and affects how values for pseudo-inputs (non-deterministic |
---|
985 | constants) are generated. |
---|
986 | |
---|
987 | 0: pseudo-inputs are treated by user. |
---|
988 | |
---|
989 | 1: pseudo-inputs are treated randomly. |
---|
990 | |
---|
991 | 2: pseudo-inputs are treated by choosing the first possibility. |
---|
992 | |
---|
993 | <dt>-v |
---|
994 | <dd> Enable verbose mode. Prints CPU time usage. |
---|
995 | </dl> |
---|
996 | |
---|
997 | The vectors_file has two main parts: |
---|
998 | <dl> |
---|
999 | <dt>Declarations: |
---|
1000 | <dd> |
---|
1001 | |
---|
1002 | <dl> |
---|
1003 | <dt>Inputs list: |
---|
1004 | <dd> Gives an ordering of the primary and pseudo |
---|
1005 | inputs. Every input must be reported in this field. |
---|
1006 | |
---|
1007 | <dt>Latches list: |
---|
1008 | <dd> Gives an ordering of the latches. Every latch must |
---|
1009 | be reported in this field. |
---|
1010 | |
---|
1011 | <dt>Outputs list: |
---|
1012 | <dd> Gives an ordering of the outputs. This list may be |
---|
1013 | incomplete. Simulation is performed only on outputs present in this list. |
---|
1014 | |
---|
1015 | <dt>Initial state: |
---|
1016 | <dd> Value of an initial state. This value is given |
---|
1017 | with respect to the latch ordering. |
---|
1018 | |
---|
1019 | </dl> |
---|
1020 | |
---|
1021 | <dt>Simulation Vectors: |
---|
1022 | <dd>One vector per line according to the given |
---|
1023 | order of inputs. |
---|
1024 | |
---|
1025 | <dt>Final State: |
---|
1026 | <dd>Prints the value of state variables after the last simulation |
---|
1027 | vector is applied. |
---|
1028 | </dl> |
---|
1029 | |
---|
1030 | An example of a simulation vectors file is: |
---|
1031 | |
---|
1032 | <ul> |
---|
1033 | |
---|
1034 | # ----> Declarations<p> |
---|
1035 | .inputs X1 X2 <br> |
---|
1036 | .latches L1 L2 <br> |
---|
1037 | .outputs O <br> |
---|
1038 | .initial green 0 <br> |
---|
1039 | .start_vectors <br> |
---|
1040 | # ----> Vectors <br> |
---|
1041 | 0 1 <br> |
---|
1042 | 1 0 <br> |
---|
1043 | 1 1 <br> |
---|
1044 | |
---|
1045 | </ul> |
---|
1046 | |
---|
1047 | Note the keywords: .inputs, .latches, .outputs, .initial, .start_vectors. A |
---|
1048 | line started by a '#' is a comment line.<p> The simulation result is printed |
---|
1049 | either in a file (using -o output_file) or to standard output. It has |
---|
1050 | the same format as vectors_file with additional fields for latches and |
---|
1051 | outputs. Here is the result of simulation on last vectors_file example: |
---|
1052 | |
---|
1053 | <ul> |
---|
1054 | |
---|
1055 | .inputs X1 X2 <br> |
---|
1056 | .latches L1 L2 <br> |
---|
1057 | .outputs O <br> |
---|
1058 | .initial green 0 <br> |
---|
1059 | .start_vectors <br> |
---|
1060 | #input; current_state; output <br> |
---|
1061 | 0 1 ; green 0 ; 0 <br> |
---|
1062 | 1 0 ; blue 0 ; 1 <br> |
---|
1063 | 1 1 ; red 1 ; 1 <br> |
---|
1064 | #Final State : green 1 |
---|
1065 | </ul> |
---|
1066 | |
---|
1067 | Note that each input line has been extended by its simulation result with |
---|
1068 | current states and outputs listed in order. |
---|
1069 | The output_file can be read by simulate as vectors_file (latches and |
---|
1070 | outputs values are ignored). When starting simulation a good trick |
---|
1071 | is to run simulate with random vectors generation mode; the resulting |
---|
1072 | can be used as a template to write a vectors_file. For example, executing "simulate -n 1 |
---|
1073 | -o foo.output" will generate a representative file.<p>] |
---|
1074 | |
---|
1075 | SideEffects [] |
---|
1076 | |
---|
1077 | ******************************************************************************/ |
---|
1078 | static int |
---|
1079 | CommandSimulate( |
---|
1080 | Hrc_Manager_t ** hmgr, |
---|
1081 | int argc, |
---|
1082 | char ** argv) |
---|
1083 | { |
---|
1084 | int c; |
---|
1085 | unsigned int i; |
---|
1086 | long startTime = 0; |
---|
1087 | long endTime = 0; |
---|
1088 | long cpuTime = 0; |
---|
1089 | int numberVector = 0; |
---|
1090 | FILE *inputFp = NIL(FILE); |
---|
1091 | Sim_PseudoSrc pseudoInputSource = Sim_Undef_c; /* default */ |
---|
1092 | boolean verbose = FALSE; /* default */ |
---|
1093 | char *inputFile = NIL(char); |
---|
1094 | char *outputFile = NIL(char); |
---|
1095 | Ntk_Network_t *network = Ntk_HrcManagerReadCurrentNetwork(*hmgr); |
---|
1096 | int printInputsFlag = 1; /*default*/ |
---|
1097 | int printOutputsFlag = 1;/*default*/ |
---|
1098 | int printPseudoInputsFlag = 1;/*default*/ |
---|
1099 | int printStatesFlag = 1;/*default*/ |
---|
1100 | |
---|
1101 | /* |
---|
1102 | * Parse command line options. |
---|
1103 | */ |
---|
1104 | |
---|
1105 | util_getopt_reset(); |
---|
1106 | while ((c = util_getopt(argc, argv, "I:O:P:S:hvi:o:n:p:s")) != EOF) { |
---|
1107 | switch(c) { |
---|
1108 | case 'I': |
---|
1109 | printInputsFlag = atoi(util_optarg); |
---|
1110 | break; |
---|
1111 | case 'O': |
---|
1112 | printOutputsFlag = atoi(util_optarg); |
---|
1113 | break; |
---|
1114 | case 'P': |
---|
1115 | printPseudoInputsFlag = atoi(util_optarg); |
---|
1116 | break; |
---|
1117 | case 'S': |
---|
1118 | printStatesFlag = atoi(util_optarg); |
---|
1119 | break; |
---|
1120 | case 'h': |
---|
1121 | goto usage; |
---|
1122 | case 'i': |
---|
1123 | inputFile = util_optarg; |
---|
1124 | break; |
---|
1125 | case 'n': |
---|
1126 | for (i = 0; i < strlen(util_optarg); i++) { |
---|
1127 | if (!isdigit((int)util_optarg[i])) { |
---|
1128 | goto usage; |
---|
1129 | } |
---|
1130 | } |
---|
1131 | numberVector = atoi(util_optarg); |
---|
1132 | break; |
---|
1133 | case 'o': |
---|
1134 | outputFile = util_optarg; |
---|
1135 | break; |
---|
1136 | case 'p': |
---|
1137 | if (!strcmp("0", util_optarg)) { |
---|
1138 | pseudoInputSource = Sim_User_c; |
---|
1139 | } |
---|
1140 | else if (!strcmp("1", util_optarg)) { |
---|
1141 | pseudoInputSource = Sim_Random_c; |
---|
1142 | } |
---|
1143 | else if (!strcmp("2", util_optarg)) { |
---|
1144 | pseudoInputSource = Sim_First_c; |
---|
1145 | } |
---|
1146 | else { |
---|
1147 | goto usage; |
---|
1148 | } |
---|
1149 | break; |
---|
1150 | case 'v': |
---|
1151 | verbose = 1; |
---|
1152 | break; |
---|
1153 | default: |
---|
1154 | goto usage; |
---|
1155 | } |
---|
1156 | } |
---|
1157 | |
---|
1158 | if (network == NIL(Ntk_Network_t)) { |
---|
1159 | return 1; |
---|
1160 | } |
---|
1161 | |
---|
1162 | if (Ord_NetworkTestAreVariablesOrdered(network,Ord_InputAndLatch_c) == FALSE){ |
---|
1163 | (void) fprintf(vis_stdout, "The MDD variables have not been ordered. Use static_order.\n"); |
---|
1164 | return 1; |
---|
1165 | } |
---|
1166 | |
---|
1167 | if (Part_NetworkReadPartition(network) == NIL(graph_t)) { |
---|
1168 | (void) fprintf(vis_stderr, "Network has not been partitioned. Use build_partition_mdds.\n"); |
---|
1169 | return 1; |
---|
1170 | } |
---|
1171 | |
---|
1172 | /** Initialization for random values generation **/ |
---|
1173 | util_srandom(SimComputeRandomInteger()); |
---|
1174 | |
---|
1175 | /* Parameters verification */ |
---|
1176 | |
---|
1177 | if (numberVector <= 0 && inputFile == NIL(char)) { |
---|
1178 | (void) fprintf(vis_stderr, "Simulate: specify an input file with -i or use -n option to set\n"); |
---|
1179 | (void) fprintf(vis_stderr, "the number of vectors randomly generated\n"); |
---|
1180 | return(1); |
---|
1181 | } |
---|
1182 | if (pseudoInputSource == Sim_User_c && inputFile == NIL(char)) { |
---|
1183 | (void) fprintf(vis_stderr, "Simulate: '-p 0' option and random vectors\n"); |
---|
1184 | (void) fprintf(vis_stderr, " generation are incompatible\n"); |
---|
1185 | return(1); |
---|
1186 | } |
---|
1187 | if ((pseudoInputSource != Sim_Undef_c) && inputFile != NIL(char)) { |
---|
1188 | (void) fprintf(vis_stderr, "Simulate: '-p' option is available only if vectors\n"); |
---|
1189 | (void) fprintf(vis_stderr, " are generated randomly.\n"); |
---|
1190 | return(1); |
---|
1191 | } |
---|
1192 | |
---|
1193 | if (numberVector == 0 && inputFile == NIL(char)) { |
---|
1194 | (void) fprintf(vis_stderr, "Simulate: number of vectors not specified.\nUsing 10 random vectors\n"); |
---|
1195 | numberVector = 10; |
---|
1196 | } |
---|
1197 | if (inputFile != NIL(char)) { |
---|
1198 | inputFp = Cmd_FileOpen(inputFile, "r", NIL(char *), 0); |
---|
1199 | if (inputFp == NIL(FILE)) { |
---|
1200 | return (1); |
---|
1201 | } |
---|
1202 | } |
---|
1203 | |
---|
1204 | /* CPU-Time print with verbose option */ |
---|
1205 | if (verbose) { |
---|
1206 | startTime = util_cpu_time(); |
---|
1207 | } |
---|
1208 | |
---|
1209 | |
---|
1210 | /************** Random Vectors generation **************/ |
---|
1211 | error_init(); |
---|
1212 | |
---|
1213 | if (inputFile == NIL(char)) { |
---|
1214 | if (SimRandomSimulateAndPrint(network, numberVector, outputFile, |
---|
1215 | pseudoInputSource, printInputsFlag, |
---|
1216 | printOutputsFlag, |
---|
1217 | printPseudoInputsFlag, |
---|
1218 | printStatesFlag, |
---|
1219 | verbose) == 0) { |
---|
1220 | (void) fprintf(vis_stdout, "%s", error_string()); |
---|
1221 | return (1); |
---|
1222 | } |
---|
1223 | } |
---|
1224 | |
---|
1225 | /************* Read vectors from a file ***************/ |
---|
1226 | |
---|
1227 | else { |
---|
1228 | if (SimFileSimulateAndPrint(network, numberVector, inputFile, outputFile, |
---|
1229 | pseudoInputSource, printInputsFlag, |
---|
1230 | printOutputsFlag, printPseudoInputsFlag, |
---|
1231 | printStatesFlag, verbose) == 0) { |
---|
1232 | (void) fprintf(vis_stdout, "%s", error_string()); |
---|
1233 | return(1); |
---|
1234 | } |
---|
1235 | } |
---|
1236 | |
---|
1237 | if (verbose) { |
---|
1238 | endTime = util_cpu_time(); |
---|
1239 | cpuTime = endTime - startTime; |
---|
1240 | (void) fprintf(vis_stdout, "====> Simulation time: %d ms\n", (int)cpuTime); |
---|
1241 | } |
---|
1242 | |
---|
1243 | return 0; /* normal exit */ |
---|
1244 | |
---|
1245 | usage: |
---|
1246 | (void) fprintf(vis_stderr, "usage: simulate [-I <0/1>][-O <0/1>][-P <0/1>][-S <0/1>][-h][-i vectors_file]\n"); |
---|
1247 | (void) fprintf(vis_stderr, " [-n number-vectors][-o output_file][-p <0/1/2>] [-v]\n"); |
---|
1248 | |
---|
1249 | (void) fprintf(vis_stderr, " -I <0/1>\t\tControls printing of primary input variables\n"); |
---|
1250 | (void) fprintf(vis_stderr, " \t\t(0:no print, 1:print, default is 1)\n"); |
---|
1251 | (void) fprintf(vis_stderr, " -O <0/1>\t\tControls printing of output variables\n"); |
---|
1252 | (void) fprintf(vis_stderr, " \t\t(0:no print, 1:print, default is 1)\n"); |
---|
1253 | (void) fprintf(vis_stderr, " -P <0/1>\t\tControls printing of pseudo input variables\n"); |
---|
1254 | (void) fprintf(vis_stderr, " \t\t(0:no print, 1:print, default is 1)\n"); |
---|
1255 | (void) fprintf(vis_stderr, " -S <0/1>\t\tControls printing of state variables\n"); |
---|
1256 | (void) fprintf(vis_stderr, " \t\t(0:no print, 1:print, default is 1)\n"); |
---|
1257 | (void) fprintf(vis_stderr, " -h \tPrints this usage message.\n"); |
---|
1258 | (void) fprintf(vis_stderr, " -i <vectors_file>\tThe input file containing simulation vectors.\n"); |
---|
1259 | (void) fprintf(vis_stderr, " \tIf not specified, N vectors are generated randomly.\n"); |
---|
1260 | (void) fprintf(vis_stderr, " \tN is given by the option '-n'.\n"); |
---|
1261 | (void) fprintf(vis_stderr, " -n <N>\t\tWith this option, only the first N vectors\n"); |
---|
1262 | (void) fprintf(vis_stderr, " \t\twill be simulated. If '-i' option is not used,\n"); |
---|
1263 | (void) fprintf(vis_stderr, " \t\tN is the number of random vectors.\n"); |
---|
1264 | (void) fprintf(vis_stderr, " -o <output_file>\tThe output file. If not specified, the output\n"); |
---|
1265 | (void) fprintf(vis_stderr, " \twill be directed to stdout.\n"); |
---|
1266 | (void) fprintf(vis_stderr, " -p <0|1|2>\t\tIf 0 : non-deterministic cases are treated\n"); |
---|
1267 | (void) fprintf(vis_stderr, " \t\tas specified by user.\n"); |
---|
1268 | (void) fprintf(vis_stderr, " \t\tIf 1: non-deterministic cases are treated randomly.\n"); |
---|
1269 | (void) fprintf(vis_stderr, " \t\tIf 2: non-deterministic cases are treated by\n"); |
---|
1270 | (void) fprintf(vis_stderr, " \t\tchoosing the first possibility.\n"); |
---|
1271 | (void) fprintf(vis_stderr, " -v \tVerbose. Print CPU time usage.\n"); |
---|
1272 | |
---|
1273 | return 1; /* error exit */ |
---|
1274 | } |
---|
1275 | |
---|
1276 | |
---|
1277 | /**Function******************************************************************** |
---|
1278 | |
---|
1279 | Synopsis [Evaluates a binary-valued function.] |
---|
1280 | |
---|
1281 | Description [Evaluates a binary-valued function on a vector given by its MDD |
---|
1282 | representation. Returns 1 (0) if the result of the evaluation is equal to |
---|
1283 | one (zero), otherwise returns -1.] |
---|
1284 | |
---|
1285 | SideEffects [] |
---|
1286 | |
---|
1287 | SeeAlso [Sim_nodeToMvfTableEvaluateNode] |
---|
1288 | |
---|
1289 | ******************************************************************************/ |
---|
1290 | static int |
---|
1291 | EvaluateBinaryFunction( |
---|
1292 | mdd_t * functionMdd, |
---|
1293 | mdd_t * vectorMdd) |
---|
1294 | { |
---|
1295 | mdd_t * result = mdd_cofactor_minterm(functionMdd, vectorMdd); |
---|
1296 | |
---|
1297 | if (mdd_is_tautology(result, 1)) { |
---|
1298 | mdd_free(result); |
---|
1299 | return (1); |
---|
1300 | } |
---|
1301 | else if (mdd_is_tautology(result, 0)) { |
---|
1302 | mdd_free(result); |
---|
1303 | return (0); |
---|
1304 | } |
---|
1305 | else { |
---|
1306 | mdd_free(result); |
---|
1307 | return (-1); |
---|
1308 | } |
---|
1309 | } |
---|
1310 | |
---|
1311 | |
---|
1312 | /**Function******************************************************************** |
---|
1313 | |
---|
1314 | Synopsis [Compare two nodes based on the lexigraphic order of their names.] |
---|
1315 | |
---|
1316 | SeeAlso [] |
---|
1317 | |
---|
1318 | SideEffects [] |
---|
1319 | |
---|
1320 | ******************************************************************************/ |
---|
1321 | static int |
---|
1322 | NodeLexCmp( |
---|
1323 | const void *node1, |
---|
1324 | const void *node2) |
---|
1325 | { |
---|
1326 | char *name1 = Ntk_NodeReadName(*(Ntk_Node_t **)node1); |
---|
1327 | char *name2 = Ntk_NodeReadName(*(Ntk_Node_t **)node2); |
---|
1328 | |
---|
1329 | return strcmp(name1, name2); |
---|
1330 | } |
---|
1331 | |
---|
1332 | /**Function******************************************************************** |
---|
1333 | |
---|
1334 | Synopsis [Builds an mdd of simulated states from the array of values.] |
---|
1335 | |
---|
1336 | Description [Builds an mdd of simulated states from the array of values in the sim structure.] |
---|
1337 | |
---|
1338 | SideEffects [] |
---|
1339 | |
---|
1340 | ******************************************************************************/ |
---|
1341 | static mdd_t * |
---|
1342 | StatesMddFromVector( |
---|
1343 | Sim_Sim_t * sim, |
---|
1344 | mdd_manager *mddManager |
---|
1345 | ) |
---|
1346 | |
---|
1347 | { |
---|
1348 | int i, j; |
---|
1349 | array_t *vector; |
---|
1350 | Ntk_Node_t *node; |
---|
1351 | mdd_t *state, *simStates, *tmp, *mddLiteral; |
---|
1352 | int value; |
---|
1353 | array_t *valueArray; |
---|
1354 | int mddId; |
---|
1355 | |
---|
1356 | /* start with zero */ |
---|
1357 | simStates = mdd_zero(mddManager); |
---|
1358 | valueArray = array_alloc(int, 1); |
---|
1359 | for (i = 0; i < array_n(sim->vectorArray); i++) { |
---|
1360 | /* add every state in the vector */ |
---|
1361 | vector = array_fetch(array_t *, sim->vectorArray, i); |
---|
1362 | state = mdd_one(mddManager); |
---|
1363 | for (j = sim->currentStateHead; j < sim->internalPartitionHead; j++){ |
---|
1364 | /* Build the state */ |
---|
1365 | node = array_fetch(Ntk_Node_t *, sim->nodesArray, j); |
---|
1366 | mddId = Ntk_NodeReadMddId(node); |
---|
1367 | value = array_fetch(int, vector, j); |
---|
1368 | array_insert(int, valueArray, 0, value); |
---|
1369 | mddLiteral = mdd_literal(mddManager, mddId, valueArray); |
---|
1370 | |
---|
1371 | tmp = mdd_and(state, mddLiteral, 1, 1); |
---|
1372 | mdd_free(state); |
---|
1373 | mdd_free(mddLiteral); |
---|
1374 | state = tmp; |
---|
1375 | } |
---|
1376 | |
---|
1377 | tmp = mdd_or(simStates, state, 1, 1); |
---|
1378 | mdd_free(simStates); |
---|
1379 | mdd_free(state); |
---|
1380 | simStates = tmp; |
---|
1381 | |
---|
1382 | } |
---|
1383 | array_free(valueArray); |
---|
1384 | return simStates; |
---|
1385 | } /* end of StatesMddFromVector */ |
---|
1386 | |
---|
1387 | |
---|
1388 | /**Function******************************************************************** |
---|
1389 | |
---|
1390 | Synopsis [Generates the initial state.] |
---|
1391 | |
---|
1392 | Description [Generates the initial state, input values in the first |
---|
1393 | input vector of the sim structure. sim->initState is reset by this |
---|
1394 | function.] |
---|
1395 | |
---|
1396 | SideEffects [] |
---|
1397 | |
---|
1398 | ******************************************************************************/ |
---|
1399 | static void |
---|
1400 | GenerateInitState( |
---|
1401 | Sim_Sim_t * sim, boolean random) |
---|
1402 | { |
---|
1403 | int i; |
---|
1404 | array_t *mvfArray; |
---|
1405 | array_t *initState = array_alloc(int, 0); |
---|
1406 | array_t *nodesArray = sim->nodesArray; |
---|
1407 | array_t *vectorArray = sim->vectorArray; |
---|
1408 | array_t *firstVector = array_fetch(array_t *, vectorArray, 0); |
---|
1409 | st_table *leaves = st_init_table(st_ptrcmp, st_ptrhash); |
---|
1410 | int numLatches = sim->internalPartitionHead - sim->currentStateHead; |
---|
1411 | array_t *rootArray = array_alloc(Ntk_Node_t *, numLatches); |
---|
1412 | |
---|
1413 | /* Free old initState */ |
---|
1414 | if (sim->initState != NIL(array_t)) { |
---|
1415 | array_free(sim->initState); |
---|
1416 | } |
---|
1417 | sim->initState = initState; |
---|
1418 | |
---|
1419 | /* |
---|
1420 | * Load a symbol table with the initial values of the primary and pseudo |
---|
1421 | * inputs. |
---|
1422 | */ |
---|
1423 | for (i = 0; i < sim->currentStateHead; i++) { |
---|
1424 | Ntk_Node_t *node = array_fetch(Ntk_Node_t *, nodesArray, i); |
---|
1425 | if (random) { |
---|
1426 | int value = array_fetch(int, firstVector, i); |
---|
1427 | st_insert(leaves, (char *) node, (char *) (long) value); |
---|
1428 | } else { |
---|
1429 | st_insert(leaves, (char *) node, (char *) (long) NTM_UNUSED); |
---|
1430 | } |
---|
1431 | } |
---|
1432 | |
---|
1433 | /* |
---|
1434 | * Create an array containing the initialization function for all the |
---|
1435 | * latches. This array has the same order as the simulation vector. |
---|
1436 | */ |
---|
1437 | for (i = sim->currentStateHead; i < sim->internalPartitionHead; i++) { |
---|
1438 | Ntk_Node_t *latch = array_fetch(Ntk_Node_t *, nodesArray, i); |
---|
1439 | Ntk_Node_t *initNode = Ntk_LatchReadInitialInput(latch); |
---|
1440 | |
---|
1441 | array_insert_last(Ntk_Node_t *, rootArray, initNode); |
---|
1442 | } |
---|
1443 | |
---|
1444 | /* |
---|
1445 | * Build the MVFs for the initialization functions, using the initial input |
---|
1446 | * values. |
---|
1447 | */ |
---|
1448 | mvfArray = Ntm_NetworkBuildMvfs(sim->network, rootArray, leaves, NIL(mdd_t)); |
---|
1449 | array_free(rootArray); |
---|
1450 | st_free_table(leaves); |
---|
1451 | |
---|
1452 | /* |
---|
1453 | * Get the initial value of each latch from the MVF of the corresponding |
---|
1454 | * initialization function. Since the initialization functions are in terms |
---|
1455 | * of primary and pseudo input values, and we have completely specified |
---|
1456 | * values for all inputs, each initialization function should have evaluated |
---|
1457 | * to a constant (i.e. exactly one non-zero component, and that component is |
---|
1458 | * the tautology. |
---|
1459 | */ |
---|
1460 | for (i = 0; i < numLatches; i++) { |
---|
1461 | int j; |
---|
1462 | int value = 0; /* initialized to avoid lint complaint */ |
---|
1463 | Mvf_Function_t *initMvf; |
---|
1464 | mdd_t *component; |
---|
1465 | int numNonZero = 0; |
---|
1466 | |
---|
1467 | initMvf = array_fetch(Mvf_Function_t *, mvfArray, i); |
---|
1468 | Mvf_FunctionForEachComponent(initMvf, j, component) { |
---|
1469 | if (!mdd_is_tautology(component, 0)) { |
---|
1470 | assert(mdd_is_tautology(component, 1)); |
---|
1471 | numNonZero++; |
---|
1472 | value = j; |
---|
1473 | } |
---|
1474 | } |
---|
1475 | |
---|
1476 | assert(numNonZero == 1); |
---|
1477 | array_insert_last(int, initState, value); |
---|
1478 | } |
---|
1479 | |
---|
1480 | Mvf_FunctionArrayFree(mvfArray); |
---|
1481 | return; |
---|
1482 | } /* end of GenerateInitState */ |
---|
1483 | |
---|