1 | /**CFile*********************************************************************** |
---|
2 | |
---|
3 | FileName [synthOpt.c] |
---|
4 | |
---|
5 | PackageName [synth] |
---|
6 | |
---|
7 | Synopsis [Multilevel optimization functions.] |
---|
8 | |
---|
9 | Author [In-Ho Moon, Balakrishna Kumthekar] |
---|
10 | |
---|
11 | Copyright [This file was created at the University of Colorado at Boulder. |
---|
12 | The University of Colorado at Boulder makes no warranty about the suitability |
---|
13 | of this software for any purpose. It is presented on an AS IS basis.] |
---|
14 | |
---|
15 | ******************************************************************************/ |
---|
16 | |
---|
17 | #include "synthInt.h" |
---|
18 | |
---|
19 | static char rcsid[] UNUSED = "$Id: synthOpt.c,v 1.53 2005/05/11 20:18:25 hhhan Exp $"; |
---|
20 | |
---|
21 | /*---------------------------------------------------------------------------*/ |
---|
22 | /* Constant declarations */ |
---|
23 | /*---------------------------------------------------------------------------*/ |
---|
24 | |
---|
25 | |
---|
26 | /*---------------------------------------------------------------------------*/ |
---|
27 | /* Type declarations */ |
---|
28 | /*---------------------------------------------------------------------------*/ |
---|
29 | |
---|
30 | |
---|
31 | /*---------------------------------------------------------------------------*/ |
---|
32 | /* Structure declarations */ |
---|
33 | /*---------------------------------------------------------------------------*/ |
---|
34 | |
---|
35 | |
---|
36 | /*---------------------------------------------------------------------------*/ |
---|
37 | /* Variable declarations */ |
---|
38 | /*---------------------------------------------------------------------------*/ |
---|
39 | |
---|
40 | int OutputOrdering = 1; /* |
---|
41 | ** 0 : just use VIS's order |
---|
42 | ** 1 : smaller first in terms of support |
---|
43 | ** 2 : smaller first in terms of bdd size |
---|
44 | */ |
---|
45 | |
---|
46 | static int UseFuncDivisor = 1; |
---|
47 | static float SuppFactor = 10.0; |
---|
48 | static float ProbFactor = 10.0; |
---|
49 | static int *SupportCount; |
---|
50 | static float *Probability; |
---|
51 | static char **outputNames; |
---|
52 | |
---|
53 | extern int TryNodeSharing; |
---|
54 | extern int noMemoryFlag; |
---|
55 | extern int VerifyTreeMode; |
---|
56 | |
---|
57 | /**AutomaticStart*************************************************************/ |
---|
58 | |
---|
59 | /*---------------------------------------------------------------------------*/ |
---|
60 | /* Static function prototypes */ |
---|
61 | /*---------------------------------------------------------------------------*/ |
---|
62 | |
---|
63 | static void GetOutputOrder(bdd_manager *dd, bdd_node **ofuncs, int no, int *order, int verbosity); |
---|
64 | static int IsSubsetOfSupportForOneWord(unsigned int mask1, unsigned int mask2); |
---|
65 | static int IsNullSupport(int size, unsigned int *mask); |
---|
66 | static void PrintSupportMask(int n, int size, unsigned int *mask); |
---|
67 | static int GetNumberOfSupport(int n, int size, unsigned int *mask); |
---|
68 | static int factorizeNetwork(Ntk_Network_t *net, bdd_manager *dd, bdd_node **ofuncs, MlTree **tree, int no, int *out_order, st_table *table, char **combOutNames, int divisor, MlTree *(* factoring_func)(bdd_manager *, st_table *, bdd_node *, int, int *, MlTree *, int, MlTree *, int), int verbosity); |
---|
69 | |
---|
70 | /**AutomaticEnd***************************************************************/ |
---|
71 | |
---|
72 | |
---|
73 | /*---------------------------------------------------------------------------*/ |
---|
74 | /* Definition of exported functions */ |
---|
75 | /*---------------------------------------------------------------------------*/ |
---|
76 | |
---|
77 | |
---|
78 | /*---------------------------------------------------------------------------*/ |
---|
79 | /* Definition of internal functions */ |
---|
80 | /*---------------------------------------------------------------------------*/ |
---|
81 | |
---|
82 | /**Function******************************************************************** |
---|
83 | |
---|
84 | Synopsis [Optimizes a network by factorizing.] |
---|
85 | |
---|
86 | Description [Optimizes a network by factorizing.] |
---|
87 | |
---|
88 | SideEffects [] |
---|
89 | |
---|
90 | SeeAlso [] |
---|
91 | |
---|
92 | ******************************************************************************/ |
---|
93 | void |
---|
94 | SynthMultiLevelOptimize(Ntk_Network_t *network, |
---|
95 | bdd_node **combOutBdds, |
---|
96 | bdd_node **combUpperBdds, |
---|
97 | char **combOutNames, |
---|
98 | int *initStates, |
---|
99 | Synth_InfoData_t *synthInfo, |
---|
100 | int verbosity) |
---|
101 | { |
---|
102 | bdd_manager *dd = (bdd_manager *)Ntk_NetworkReadMddManager(network); |
---|
103 | bdd_node *top; |
---|
104 | bdd_node **ofuncs; |
---|
105 | int i, no; |
---|
106 | int factoring, divisor; |
---|
107 | char *filename; |
---|
108 | char *filehead; |
---|
109 | MlTree **tree; |
---|
110 | bdd_node *zdd_I; |
---|
111 | st_table *table; |
---|
112 | int nml, tml; |
---|
113 | int *out_order; |
---|
114 | FILE *feqn; |
---|
115 | MlTree *(* factoring_func)(bdd_manager *, st_table *, |
---|
116 | bdd_node *, int, int *, MlTree *, |
---|
117 | int, MlTree *, int); |
---|
118 | int autoDyn, autoDynZ; |
---|
119 | bdd_reorder_type_t method, methodZ; |
---|
120 | int error; |
---|
121 | |
---|
122 | factoring = synthInfo->factoring; |
---|
123 | divisor = synthInfo->divisor; |
---|
124 | filehead = synthInfo->filehead; |
---|
125 | TryNodeSharing = synthInfo->trySharing; |
---|
126 | SynthSetInternalNodePrefix(synthInfo->prefix); |
---|
127 | |
---|
128 | /* Save reordering status and set reordering mode specific to |
---|
129 | * synthesis. |
---|
130 | */ |
---|
131 | autoDyn = bdd_reordering_status(dd, &method); |
---|
132 | autoDynZ = bdd_reordering_zdd_status(dd, &methodZ); |
---|
133 | |
---|
134 | switch (synthInfo->reordering) { |
---|
135 | case 0 : |
---|
136 | bdd_dynamic_reordering_disable(dd); |
---|
137 | bdd_dynamic_reordering_zdd_disable(dd); |
---|
138 | break; |
---|
139 | case 1 : |
---|
140 | bdd_dynamic_reordering(dd, method, BDD_REORDER_VERBOSITY_DEFAULT); |
---|
141 | bdd_dynamic_reordering_zdd_disable(dd); |
---|
142 | break; |
---|
143 | case 2 : |
---|
144 | bdd_dynamic_reordering_disable(dd); |
---|
145 | bdd_dynamic_reordering_zdd(dd, methodZ, BDD_REORDER_VERBOSITY_DEFAULT); |
---|
146 | break; |
---|
147 | case 3 : |
---|
148 | bdd_dynamic_reordering(dd, method, BDD_REORDER_VERBOSITY_DEFAULT); |
---|
149 | bdd_dynamic_reordering_zdd(dd, methodZ, BDD_REORDER_VERBOSITY_DEFAULT); |
---|
150 | break; |
---|
151 | default : |
---|
152 | bdd_dynamic_reordering_disable(dd); |
---|
153 | bdd_dynamic_reordering_zdd_disable(dd); |
---|
154 | break; |
---|
155 | } |
---|
156 | |
---|
157 | if (factoring == 0) |
---|
158 | factoring_func = SynthSimpleFactorTree; |
---|
159 | else |
---|
160 | factoring_func = SynthGenericFactorTree; |
---|
161 | |
---|
162 | /* outputNames is a static global variable for this file. */ |
---|
163 | outputNames = combOutNames; |
---|
164 | |
---|
165 | /* Initialize the node-tree table and other factoring-related variables. |
---|
166 | * The table contains pairs of a ZDD node and the corresponding multi-level |
---|
167 | * tree. |
---|
168 | */ |
---|
169 | table = st_init_table(st_ptrcmp, st_ptrhash); |
---|
170 | SynthInitMlTable(); |
---|
171 | |
---|
172 | /* Create ZDD variables for the positive and negative literals. */ |
---|
173 | bdd_zdd_vars_from_bdd_vars(dd, 2); |
---|
174 | |
---|
175 | /* Since we currently support only blif files, the number of |
---|
176 | * functions to synthesize should not include the initial |
---|
177 | * inputs of latches in case of sequential ckts. |
---|
178 | */ |
---|
179 | no = Ntk_NetworkReadNumCombOutputs(network) - |
---|
180 | Ntk_NetworkReadNumLatches(network); |
---|
181 | |
---|
182 | /* Compute two-level covers for all the functions to be synthesized. */ |
---|
183 | ofuncs = ALLOC(bdd_node *, no); |
---|
184 | for (i = 0; i < no; i++) { |
---|
185 | if (verbosity) { |
---|
186 | (void)fprintf(vis_stdout, "** synth info: Synthesizing output [%d(%s)]\n", |
---|
187 | i, combOutNames[i]); |
---|
188 | } |
---|
189 | bdd_ref(top = bdd_zdd_isop(dd, combOutBdds[i], combUpperBdds[i], |
---|
190 | &zdd_I)); |
---|
191 | bdd_ref(zdd_I); |
---|
192 | bdd_recursive_deref(dd, top); |
---|
193 | ofuncs[i] = zdd_I; |
---|
194 | } |
---|
195 | |
---|
196 | if (VerifyTreeMode == 2) |
---|
197 | SynthDumpBlif(network, dd, no, ofuncs, combOutNames, initStates, filehead); |
---|
198 | |
---|
199 | /* Initialize array of factoring trees and determine the order in |
---|
200 | * which the functions will be processed. Then proceed to factor. |
---|
201 | */ |
---|
202 | tree = ALLOC(MlTree *, no); |
---|
203 | (void)memset((void *)tree, 0, no * sizeof(MlTree *)); |
---|
204 | out_order = ALLOC(int, no); |
---|
205 | GetOutputOrder(dd, ofuncs, no, out_order, verbosity); |
---|
206 | error = factorizeNetwork(network, dd, ofuncs, tree, no, out_order, |
---|
207 | table, combOutNames, divisor, factoring_func, verbosity); |
---|
208 | FREE(out_order); |
---|
209 | |
---|
210 | if (error) { |
---|
211 | (void)fprintf(vis_stderr, |
---|
212 | "** synth error: synthesize_network has finished abnormally"); |
---|
213 | if (noMemoryFlag) |
---|
214 | (void)fprintf(vis_stderr, " due to lack of memory\n"); |
---|
215 | else |
---|
216 | (void)fprintf(vis_stderr, " for some reason\n"); |
---|
217 | goto cleanup; |
---|
218 | } |
---|
219 | |
---|
220 | /* Count total number of literals in multi-level network. */ |
---|
221 | tml = 0; |
---|
222 | for (i = 0; i < no; i++) { |
---|
223 | if (tree[i]) { |
---|
224 | nml = SynthCountMlLiteral(dd, tree[i], 1); |
---|
225 | tml += nml; |
---|
226 | } |
---|
227 | } |
---|
228 | (void)fprintf(vis_stdout, |
---|
229 | "** synth info: Total number of literals = %d\n", tml); |
---|
230 | |
---|
231 | /* Write network in eqn and blif formats. */ |
---|
232 | SynthSetupNodeNameTable(network); |
---|
233 | filename = ALLOC(char, strlen(filehead) + 9); |
---|
234 | if (synthInfo->eqn) { |
---|
235 | sprintf(filename, "%s.eqn", filehead); |
---|
236 | feqn = Cmd_FileOpen(filename, "w", NIL(char *), 0); |
---|
237 | if (feqn) { |
---|
238 | fprintf(feqn, "** synth info: Total number of literals = %d\n", tml); |
---|
239 | SynthWriteEqnHeader(feqn, network, dd); |
---|
240 | for (i = 0; i < no; i++) { |
---|
241 | if (tree[i]) |
---|
242 | SynthWriteEqn(feqn, network, dd, tree[i], ofuncs, combOutNames[i], 1); |
---|
243 | } |
---|
244 | fclose(feqn); |
---|
245 | } else { |
---|
246 | (void)fprintf(vis_stdout, |
---|
247 | "** synth error: Error in opening file [%s]\n", filename); |
---|
248 | } |
---|
249 | } |
---|
250 | sprintf(filename, "%s.ml.blif", filehead); |
---|
251 | SynthWriteBlifFile(network, dd, tree, filename, no, ofuncs, initStates, |
---|
252 | 0, verbosity); |
---|
253 | FREE(filename); |
---|
254 | SynthFreeNodeNameTable(); |
---|
255 | |
---|
256 | cleanup: |
---|
257 | /* Clean up. */ |
---|
258 | for (i = 0; i < no; i++) { |
---|
259 | if (!tree[i]) |
---|
260 | continue; |
---|
261 | bdd_recursive_deref_zdd(dd, tree[i]->node); |
---|
262 | /* frees some trees not in node-tree table */ |
---|
263 | if (tree[i]->ref) |
---|
264 | SynthFreeMlTree(tree[i], 0); |
---|
265 | } |
---|
266 | |
---|
267 | SynthClearMlTable(dd, table); |
---|
268 | st_free_table(table); |
---|
269 | FREE(tree); |
---|
270 | |
---|
271 | for (i = 0; i < no; i++) { |
---|
272 | if (!ofuncs[i]) |
---|
273 | continue; |
---|
274 | bdd_recursive_deref_zdd(dd, ofuncs[i]); |
---|
275 | } |
---|
276 | |
---|
277 | FREE(ofuncs); |
---|
278 | |
---|
279 | /* Restore reordering status. */ |
---|
280 | if (autoDyn) |
---|
281 | bdd_dynamic_reordering(dd, method, BDD_REORDER_VERBOSITY_DEFAULT); |
---|
282 | else |
---|
283 | bdd_dynamic_reordering_disable(dd); |
---|
284 | if (autoDynZ) |
---|
285 | bdd_dynamic_reordering_zdd(dd, methodZ, BDD_REORDER_VERBOSITY_DEFAULT); |
---|
286 | else |
---|
287 | bdd_dynamic_reordering_zdd_disable(dd); |
---|
288 | } |
---|
289 | |
---|
290 | |
---|
291 | /**Function******************************************************************** |
---|
292 | |
---|
293 | Synopsis [Sets the optional variable UseFuncDivisor.] |
---|
294 | |
---|
295 | Description [Sets the optional variable UseFuncDivisor. Currently |
---|
296 | UseFuncDivisor has always the initial value of 1, this is because it |
---|
297 | seems does better almost always than 0.] |
---|
298 | |
---|
299 | SideEffects [] |
---|
300 | |
---|
301 | SeeAlso [] |
---|
302 | |
---|
303 | ******************************************************************************/ |
---|
304 | void |
---|
305 | SynthSetUseFuncDivisor(int mode) |
---|
306 | { |
---|
307 | UseFuncDivisor = mode; |
---|
308 | } |
---|
309 | |
---|
310 | |
---|
311 | /**Function******************************************************************** |
---|
312 | |
---|
313 | Synopsis [Sets the optional variable OutputOrdering.] |
---|
314 | |
---|
315 | Description [Sets the optional variable OutputOrdering.] |
---|
316 | |
---|
317 | SideEffects [] |
---|
318 | |
---|
319 | SeeAlso [] |
---|
320 | |
---|
321 | ******************************************************************************/ |
---|
322 | void |
---|
323 | SynthSetOutputOrdering(int mode) |
---|
324 | { |
---|
325 | OutputOrdering = mode; |
---|
326 | } |
---|
327 | |
---|
328 | |
---|
329 | /**Function******************************************************************** |
---|
330 | |
---|
331 | Synopsis [Sets the cost factors to get a divisor for low power.] |
---|
332 | |
---|
333 | Description [Sets the cost factors to get a divisor for low power.] |
---|
334 | |
---|
335 | SideEffects [] |
---|
336 | |
---|
337 | SeeAlso [] |
---|
338 | |
---|
339 | ******************************************************************************/ |
---|
340 | void |
---|
341 | SynthSetCostFactors(float supp, |
---|
342 | float prob) |
---|
343 | { |
---|
344 | SuppFactor = supp; |
---|
345 | ProbFactor = prob; |
---|
346 | } |
---|
347 | |
---|
348 | |
---|
349 | /**Function******************************************************************** |
---|
350 | |
---|
351 | Synopsis [Sets the variable SupportCount.] |
---|
352 | |
---|
353 | Description [Sets the variable SupportCount.] |
---|
354 | |
---|
355 | SideEffects [] |
---|
356 | |
---|
357 | SeeAlso [] |
---|
358 | |
---|
359 | ******************************************************************************/ |
---|
360 | void |
---|
361 | SynthSetSupportCount(int *count) |
---|
362 | { |
---|
363 | SupportCount = count; |
---|
364 | } |
---|
365 | |
---|
366 | |
---|
367 | /**Function******************************************************************** |
---|
368 | |
---|
369 | Synopsis [Sets the variable Probability.] |
---|
370 | |
---|
371 | Description [Sets the variable Probability.] |
---|
372 | |
---|
373 | SideEffects [] |
---|
374 | |
---|
375 | SeeAlso [] |
---|
376 | |
---|
377 | ******************************************************************************/ |
---|
378 | void |
---|
379 | SynthSetProbability(float *prob) |
---|
380 | { |
---|
381 | Probability = prob; |
---|
382 | } |
---|
383 | |
---|
384 | |
---|
385 | /**Function******************************************************************** |
---|
386 | |
---|
387 | Synopsis [Finds a good divisor for low power.] |
---|
388 | |
---|
389 | Description [Finds a good divisor for low power.] |
---|
390 | |
---|
391 | SideEffects [] |
---|
392 | |
---|
393 | SeeAlso [] |
---|
394 | |
---|
395 | ******************************************************************************/ |
---|
396 | int |
---|
397 | SynthFindDivisorForLowPower(int *count, |
---|
398 | int nvars, |
---|
399 | int min_count, |
---|
400 | int min_pos) |
---|
401 | { |
---|
402 | int i, v; |
---|
403 | float cost, best; |
---|
404 | |
---|
405 | if ((!SupportCount) || (!Probability)) |
---|
406 | return(-1); |
---|
407 | |
---|
408 | v = min_pos; |
---|
409 | if (SuppFactor == 0.0 && ProbFactor == 0.0) |
---|
410 | best = (float)SupportCount[min_pos] * Probability[min_pos]; |
---|
411 | else { |
---|
412 | best = (float)SupportCount[min_pos] * SuppFactor + |
---|
413 | Probability[min_pos] * ProbFactor; |
---|
414 | } |
---|
415 | |
---|
416 | for (i = min_pos + 1; i < nvars; i++) { |
---|
417 | if (count[i] == min_count) { |
---|
418 | if (SuppFactor == 0.0 && ProbFactor == 0.0) |
---|
419 | cost = (float)SupportCount[i] * Probability[i]; |
---|
420 | else { |
---|
421 | cost = (float)SupportCount[i] * SuppFactor + |
---|
422 | Probability[i] * ProbFactor; |
---|
423 | } |
---|
424 | if (cost > best) { |
---|
425 | best = cost; |
---|
426 | v = i; |
---|
427 | } |
---|
428 | } |
---|
429 | } |
---|
430 | |
---|
431 | return(v); |
---|
432 | } |
---|
433 | |
---|
434 | |
---|
435 | /**Function******************************************************************** |
---|
436 | |
---|
437 | Synopsis [Returns the i-th output name.] |
---|
438 | |
---|
439 | Description [Returns the i-th output name.] |
---|
440 | |
---|
441 | SideEffects [] |
---|
442 | |
---|
443 | SeeAlso [] |
---|
444 | |
---|
445 | ******************************************************************************/ |
---|
446 | char * |
---|
447 | SynthGetIthOutputName(int i) |
---|
448 | { |
---|
449 | return outputNames[i]; |
---|
450 | } |
---|
451 | |
---|
452 | |
---|
453 | /**Function******************************************************************** |
---|
454 | |
---|
455 | Synopsis [Checks whether one support set is a subset of the other |
---|
456 | support set.] |
---|
457 | |
---|
458 | Description [Checks whether one support set is a subset of the other |
---|
459 | support set. A support set is represented by a bit-vector. If the |
---|
460 | index 0 variable of a unique table is in the support of a function, |
---|
461 | then the MSB bit is set to 1. In general, for the variable of index |
---|
462 | i, the i-th bit from the MSB is set to 1. The argument size means |
---|
463 | the number of words (word = sizeof(int)). If the sets are the same, |
---|
464 | SynthIsSubsetOfSupport returns 2. If the first set is a subset of |
---|
465 | the second, it returns 1, otherwise it returns 0.] |
---|
466 | |
---|
467 | SideEffects [] |
---|
468 | |
---|
469 | SeeAlso [IsSubsetOfSupportForOneWord IsNullSupport] |
---|
470 | |
---|
471 | ******************************************************************************/ |
---|
472 | int |
---|
473 | SynthIsSubsetOfSupport(int size, |
---|
474 | unsigned int *mask1, |
---|
475 | unsigned int *mask2) |
---|
476 | { |
---|
477 | int i, tmp, flag = 0; |
---|
478 | |
---|
479 | if (!mask2) |
---|
480 | return(1); |
---|
481 | |
---|
482 | if (IsNullSupport(size, mask1) && IsNullSupport(size, mask2)) |
---|
483 | return(0); |
---|
484 | else if (IsNullSupport(size, mask1)) |
---|
485 | return(0); |
---|
486 | else if (IsNullSupport(size, mask2)) |
---|
487 | return(1); |
---|
488 | |
---|
489 | for (i = 0; i < size; i++) { |
---|
490 | tmp = IsSubsetOfSupportForOneWord(mask1[i], mask2[i]); |
---|
491 | if (tmp == 0) |
---|
492 | return(0); |
---|
493 | flag |= tmp; |
---|
494 | } |
---|
495 | |
---|
496 | return(flag); |
---|
497 | } |
---|
498 | |
---|
499 | |
---|
500 | /*---------------------------------------------------------------------------*/ |
---|
501 | /* Definition of static functions */ |
---|
502 | /*---------------------------------------------------------------------------*/ |
---|
503 | |
---|
504 | /**Function******************************************************************** |
---|
505 | |
---|
506 | Synopsis [This function orders the output functions. With this |
---|
507 | output ordering, the lowest indexed output function is factorized |
---|
508 | first.] |
---|
509 | |
---|
510 | Description [This function orders the output functions. With this |
---|
511 | output ordering, the lowest indexed output function is factorized |
---|
512 | first. If OutputOrder is 0, the output order is just the same as the |
---|
513 | order VIS has. If OutputOrder is 1, the smallest function (in terms |
---|
514 | of the number of support variables) will be placed first in the |
---|
515 | order. In case of tie, the function with the smaller BDD is placed |
---|
516 | before the other in the order. If OutputOrder is 2, the smallest |
---|
517 | function in terms of BDD size is first.] |
---|
518 | |
---|
519 | SideEffects [] |
---|
520 | |
---|
521 | SeeAlso [SynthMultiLevelOptimize] |
---|
522 | |
---|
523 | ******************************************************************************/ |
---|
524 | static void |
---|
525 | GetOutputOrder(bdd_manager *dd, |
---|
526 | bdd_node **ofuncs, |
---|
527 | int no, |
---|
528 | int *order, |
---|
529 | int verbosity) |
---|
530 | { |
---|
531 | int i, j, k, flag; |
---|
532 | int *support, *bddsize; |
---|
533 | int size; |
---|
534 | unsigned int **mask; |
---|
535 | int word, sizeZ; |
---|
536 | int pos, bit, bit_mask; |
---|
537 | int insert_flag, s1, s2; |
---|
538 | |
---|
539 | if (no == 1) { |
---|
540 | order[0] = 0; |
---|
541 | return; |
---|
542 | } |
---|
543 | |
---|
544 | if (OutputOrdering == 0) { |
---|
545 | for (i = 0; i < no; i++) |
---|
546 | order[i] = i; |
---|
547 | return; |
---|
548 | } |
---|
549 | |
---|
550 | bddsize = ALLOC(int, no); |
---|
551 | if (OutputOrdering == 2) { |
---|
552 | for (i = 0; i < no; i++) { |
---|
553 | if (!ofuncs[i]) { |
---|
554 | order[i] = i; |
---|
555 | bddsize[i] = 0; |
---|
556 | continue; |
---|
557 | } |
---|
558 | |
---|
559 | bddsize[i] = bdd_node_size(ofuncs[i]); |
---|
560 | |
---|
561 | /* Insert i-th output at the right place in the order. */ |
---|
562 | for (j = 0; j < i; j++) { |
---|
563 | if (bddsize[i] < bddsize[order[j]]) { |
---|
564 | for (k = i; k > j; k--) |
---|
565 | order[k] = order[k - 1]; |
---|
566 | order[j] = i; |
---|
567 | break; |
---|
568 | } |
---|
569 | } |
---|
570 | |
---|
571 | if (j == i) |
---|
572 | order[i] = i; |
---|
573 | } |
---|
574 | |
---|
575 | if (verbosity) { |
---|
576 | fprintf(vis_stdout, "output order :"); |
---|
577 | for (i = 0; i < no; i++) |
---|
578 | fprintf(vis_stdout, " %d", order[i]); |
---|
579 | fprintf(vis_stdout, "\n"); |
---|
580 | if (verbosity > 1) { |
---|
581 | for (i = 0; i < no; i++) |
---|
582 | fprintf(vis_stdout, "%d - %d", i, bddsize[i]); |
---|
583 | } |
---|
584 | } |
---|
585 | |
---|
586 | FREE(bddsize); |
---|
587 | return; |
---|
588 | } |
---|
589 | |
---|
590 | /* Here OutputOrdering should be 1. */ |
---|
591 | mask = ALLOC(unsigned int *, no); |
---|
592 | sizeZ = bdd_num_zdd_vars(dd); |
---|
593 | support = ALLOC(int, sizeZ); |
---|
594 | word = sizeof(int) * 8; |
---|
595 | size = sizeZ / word + 1; |
---|
596 | |
---|
597 | for (i = 0; i < no; i++) { |
---|
598 | if (!ofuncs[i]) { |
---|
599 | mask[i] = (unsigned int *)NULL; |
---|
600 | order[i] = i; |
---|
601 | bddsize[i] = 0; |
---|
602 | continue; |
---|
603 | } |
---|
604 | |
---|
605 | mask[i] = ALLOC(unsigned int, size); |
---|
606 | (void)memset((void *)mask[i], 0, size * sizeof(int)); |
---|
607 | (void)memset((void *)support, 0, sizeof(int) * sizeZ); |
---|
608 | SynthZddSupportStep(bdd_regular(ofuncs[i]), support); |
---|
609 | SynthZddClearFlag(bdd_regular(ofuncs[i])); |
---|
610 | /* Pack the support array into a bit vector. */ |
---|
611 | for (j = 0; j < sizeZ; j++) { |
---|
612 | if (support[j]) { |
---|
613 | pos = j / word; |
---|
614 | bit = j % word; |
---|
615 | bit_mask = 01 << bit; |
---|
616 | mask[i][pos] |= bit_mask; |
---|
617 | } |
---|
618 | } |
---|
619 | bddsize[i] = bdd_node_size(ofuncs[i]); |
---|
620 | |
---|
621 | for (j = 0; j < i; j++) { |
---|
622 | insert_flag = 0; |
---|
623 | flag = SynthIsSubsetOfSupport(size, mask[i], mask[order[j]]); |
---|
624 | if (flag == 1) |
---|
625 | insert_flag = 1; |
---|
626 | else if (flag == 2) { |
---|
627 | s1 = GetNumberOfSupport(sizeZ, size, mask[i]); |
---|
628 | s2 = GetNumberOfSupport(sizeZ, size, mask[order[j]]); |
---|
629 | if (s1 < s2 || (s1 == s2 && bddsize[i] < bddsize[order[j]])) |
---|
630 | insert_flag = 1; |
---|
631 | } |
---|
632 | if (insert_flag) { |
---|
633 | for (k = i; k > j; k--) |
---|
634 | order[k] = order[k - 1]; |
---|
635 | order[j] = i; |
---|
636 | break; |
---|
637 | } |
---|
638 | } |
---|
639 | |
---|
640 | if (j == i) |
---|
641 | order[i] = i; |
---|
642 | } |
---|
643 | FREE(support); |
---|
644 | FREE(bddsize); |
---|
645 | |
---|
646 | if (verbosity) { |
---|
647 | fprintf(vis_stdout, "output order :"); |
---|
648 | for (i = 0; i < no; i++) |
---|
649 | fprintf(vis_stdout, " %d", order[i]); |
---|
650 | fprintf(vis_stdout, "\n"); |
---|
651 | if (verbosity > 1) { |
---|
652 | for (i = 0; i < no; i++) { |
---|
653 | if (mask[i]) |
---|
654 | PrintSupportMask(sizeZ, size, mask[i]); |
---|
655 | } |
---|
656 | } |
---|
657 | } |
---|
658 | |
---|
659 | for (i = 0; i < no; i++) { |
---|
660 | if (mask[i]) |
---|
661 | FREE(mask[i]); |
---|
662 | } |
---|
663 | FREE(mask); |
---|
664 | } |
---|
665 | |
---|
666 | |
---|
667 | /**Function******************************************************************** |
---|
668 | |
---|
669 | Synopsis [Checks whether a set of support for one word is subset of the |
---|
670 | other set of support for one word.] |
---|
671 | |
---|
672 | Description [Checks whether a set of support for one word is subset of |
---|
673 | the other set of support for one word. SynthIsSubsetOfSupport() calls |
---|
674 | this function for each word.] |
---|
675 | |
---|
676 | SideEffects [] |
---|
677 | |
---|
678 | SeeAlso [SynthIsSubsetOfSupport] |
---|
679 | |
---|
680 | ******************************************************************************/ |
---|
681 | static int |
---|
682 | IsSubsetOfSupportForOneWord(unsigned int mask1, |
---|
683 | unsigned int mask2) |
---|
684 | { |
---|
685 | unsigned int tmp; |
---|
686 | |
---|
687 | if (mask1 == mask2) |
---|
688 | return(2); |
---|
689 | |
---|
690 | tmp = mask1 | mask2; |
---|
691 | if (tmp != mask2) |
---|
692 | return(0); |
---|
693 | return(1); |
---|
694 | } |
---|
695 | |
---|
696 | |
---|
697 | /**Function******************************************************************** |
---|
698 | |
---|
699 | Synopsis [Checks if a support set is empty.] |
---|
700 | |
---|
701 | Description [Checks if a support set is empty.] |
---|
702 | |
---|
703 | SideEffects [] |
---|
704 | |
---|
705 | SeeAlso [] |
---|
706 | |
---|
707 | ******************************************************************************/ |
---|
708 | static int |
---|
709 | IsNullSupport(int size, |
---|
710 | unsigned int *mask) |
---|
711 | { |
---|
712 | int i; |
---|
713 | |
---|
714 | for (i = 0; i < size; i++) { |
---|
715 | if (mask[i] != 0) |
---|
716 | return(0); |
---|
717 | } |
---|
718 | return(1); |
---|
719 | } |
---|
720 | |
---|
721 | |
---|
722 | /**Function******************************************************************** |
---|
723 | |
---|
724 | Synopsis [Prints the support of a function.] |
---|
725 | |
---|
726 | Description [Prints the support of a function. The argument n is the |
---|
727 | number of variables and size is the number of word and mask is the |
---|
728 | array of support mask. The first line shows column index by modulo 10 |
---|
729 | and the next line shows which variables are support by printing 1.] |
---|
730 | |
---|
731 | SideEffects [] |
---|
732 | |
---|
733 | SeeAlso [] |
---|
734 | |
---|
735 | ******************************************************************************/ |
---|
736 | static void |
---|
737 | PrintSupportMask(int n, |
---|
738 | int size, |
---|
739 | unsigned int *mask) |
---|
740 | { |
---|
741 | int i, j, pos, last; |
---|
742 | char *support; |
---|
743 | char *mark; |
---|
744 | int bit; |
---|
745 | |
---|
746 | support = ALLOC(char,n); |
---|
747 | mark = ALLOC(char,n); |
---|
748 | |
---|
749 | pos = 0; |
---|
750 | for (i = 0; i < size; i++) { |
---|
751 | if (i == (size - 1)) |
---|
752 | last = n % 32; |
---|
753 | else |
---|
754 | last = 32; |
---|
755 | bit = 01; |
---|
756 | for (j = 0; j < last; j++) { |
---|
757 | sprintf(&mark[pos], "%d", pos % 10); |
---|
758 | if (mask[i] & bit) |
---|
759 | support[pos] = '1'; |
---|
760 | else |
---|
761 | support[pos] = '0'; |
---|
762 | pos++; |
---|
763 | bit = bit << 1; |
---|
764 | } |
---|
765 | } |
---|
766 | mark[pos] = support[pos] = '\0'; |
---|
767 | |
---|
768 | fprintf(vis_stdout, "%s\n", mark); |
---|
769 | fprintf(vis_stdout, "%s\n", support); |
---|
770 | |
---|
771 | FREE(support); |
---|
772 | FREE(mark); |
---|
773 | } |
---|
774 | |
---|
775 | |
---|
776 | /**Function******************************************************************** |
---|
777 | |
---|
778 | Synopsis [Returns the number of support variables of a function.] |
---|
779 | |
---|
780 | Description [Returns the number of support variables of a function.] |
---|
781 | |
---|
782 | SideEffects [none] |
---|
783 | |
---|
784 | SeeAlso [] |
---|
785 | |
---|
786 | ******************************************************************************/ |
---|
787 | static int |
---|
788 | GetNumberOfSupport(int n, |
---|
789 | int size, |
---|
790 | unsigned int *mask) |
---|
791 | { |
---|
792 | int i, j, last; |
---|
793 | int bit; |
---|
794 | int count; |
---|
795 | |
---|
796 | count = 0; |
---|
797 | for (i = 0; i < size; i++) { |
---|
798 | if (i == (size - 1)) |
---|
799 | last = n % 32; |
---|
800 | else |
---|
801 | last = 32; |
---|
802 | bit = 01; |
---|
803 | for (j = 0; j < last; j++) { |
---|
804 | if (mask[i] & bit) |
---|
805 | count++; |
---|
806 | bit = bit << 1; |
---|
807 | } |
---|
808 | } |
---|
809 | return(count); |
---|
810 | } |
---|
811 | |
---|
812 | |
---|
813 | /**Function******************************************************************** |
---|
814 | |
---|
815 | Synopsis [Factorizes a network.] |
---|
816 | |
---|
817 | Description [Factorizes a network. If successful, it returns 0, |
---|
818 | otherwise it returns 1 due to lack of memory.] |
---|
819 | |
---|
820 | SideEffects [] |
---|
821 | |
---|
822 | SeeAlso [SynthMultiLevelOptimize] |
---|
823 | |
---|
824 | ******************************************************************************/ |
---|
825 | static int |
---|
826 | factorizeNetwork(Ntk_Network_t *net, |
---|
827 | bdd_manager *dd, |
---|
828 | bdd_node **ofuncs, |
---|
829 | MlTree **tree, |
---|
830 | int no, |
---|
831 | int *out_order, |
---|
832 | st_table *table, |
---|
833 | char **combOutNames, |
---|
834 | int divisor, |
---|
835 | MlTree *(* factoring_func)(bdd_manager *, st_table *, |
---|
836 | bdd_node *, int, int *, MlTree *, |
---|
837 | int, MlTree *, int), |
---|
838 | int verbosity) |
---|
839 | { |
---|
840 | int i, j, k; |
---|
841 | int ref; |
---|
842 | int nml; |
---|
843 | MlTree *tmp_tree; |
---|
844 | int flag; |
---|
845 | int comp_flag; |
---|
846 | |
---|
847 | SynthSetZddDivisorFunc(divisor); /* set static variable in synthFactor.c */ |
---|
848 | |
---|
849 | for (k = 0; k < no; k++) { |
---|
850 | i = out_order[k]; |
---|
851 | if (!ofuncs[i]) { |
---|
852 | tree[i] = NULL; |
---|
853 | continue; |
---|
854 | } |
---|
855 | if (verbosity) |
---|
856 | SynthPrintZddCoverWithName(net, dd, ofuncs[i]); |
---|
857 | |
---|
858 | tree[i] = (MlTree *)NULL; |
---|
859 | ref = 0; |
---|
860 | if (ofuncs[i] == bdd_read_one(dd) || ofuncs[i] == bdd_read_zero(dd)) { |
---|
861 | tree[i] = SynthFindOrCreateMlTree(table, dd, ofuncs[i], 1, 0, |
---|
862 | &ref, verbosity); |
---|
863 | if (!tree[i]) |
---|
864 | return(1); |
---|
865 | } else { |
---|
866 | tree[i] = SynthLookupMlTable(table, dd, ofuncs[i], 1, verbosity); |
---|
867 | if (tree[i]) { |
---|
868 | if (MlTree_IsComplement(tree[i]) || tree[i]->top) |
---|
869 | ref = 1; |
---|
870 | else |
---|
871 | SynthUpdateRefOfParent(tree[i]); |
---|
872 | } |
---|
873 | else if (UseFuncDivisor) { |
---|
874 | /* Try to divide by existing functions. The smaller |
---|
875 | * functions are factored first to increase the probability |
---|
876 | * of success of this step. Both phases of the divisor are |
---|
877 | * tried. |
---|
878 | */ |
---|
879 | for (j = k - 1; j >= 0; j--) { |
---|
880 | tree[i] = (* factoring_func)(dd, table, ofuncs[i], 0, &ref, |
---|
881 | tree[out_order[j]], 0, NULL, verbosity); |
---|
882 | if (tree[i]) { |
---|
883 | SynthSetSharedFlag(dd, tree[out_order[j]]); |
---|
884 | break; |
---|
885 | } else if (noMemoryFlag == 1) |
---|
886 | return(1); |
---|
887 | else { |
---|
888 | tree[i] = (* factoring_func)(dd, table, ofuncs[i], 0, |
---|
889 | &ref, tree[out_order[j]], 1, NULL, verbosity); |
---|
890 | if (tree[i]) { |
---|
891 | SynthSetSharedFlag(dd, tree[out_order[j]]); |
---|
892 | break; |
---|
893 | } else if (noMemoryFlag == 1) |
---|
894 | return(1); |
---|
895 | } |
---|
896 | } |
---|
897 | } |
---|
898 | } |
---|
899 | /* Division by other functions did not work. Find a brand-new |
---|
900 | * factorization. |
---|
901 | */ |
---|
902 | if (!tree[i]) { |
---|
903 | tree[i] = (* factoring_func)(dd, table, ofuncs[i], 0, |
---|
904 | &ref, NULL, 0, NULL, verbosity); |
---|
905 | if (!tree[i]) |
---|
906 | return(1); |
---|
907 | } |
---|
908 | /* Compute the complement ZDD node of ofuncs[i], if not exist. |
---|
909 | * This is to increase sharing. |
---|
910 | */ |
---|
911 | tmp_tree = tree[i]; |
---|
912 | tree[i] = SynthCheckAndMakeComplement(dd, table, tree[i], &comp_flag, |
---|
913 | verbosity); |
---|
914 | if (!tree[i]) |
---|
915 | return(1); |
---|
916 | else if (tree[i] != tmp_tree) { |
---|
917 | ref = 1; |
---|
918 | if (comp_flag) |
---|
919 | tree[i] = MlTree_Not(tree[i]); |
---|
920 | } |
---|
921 | |
---|
922 | /* When the tree already exists, create a new tree and copy all |
---|
923 | * contents, and set the field 'ref' to 1. This is for the |
---|
924 | * purpose of avoiding duplicate literal counting. |
---|
925 | */ |
---|
926 | if (ref) { |
---|
927 | int comp_flag; |
---|
928 | |
---|
929 | comp_flag = 0; |
---|
930 | if (MlTree_IsComplement(tree[i])) { |
---|
931 | tree[i] = MlTree_Not(tree[i]); |
---|
932 | comp_flag = 1; |
---|
933 | } |
---|
934 | tmp_tree = ALLOC(MlTree, sizeof(MlTree)); |
---|
935 | memcpy((void *)tmp_tree, (void *)tree[i], sizeof(MlTree)); |
---|
936 | tree[i] = tmp_tree; |
---|
937 | tree[i]->ref = 1; |
---|
938 | tree[i]->comp = comp_flag; |
---|
939 | } |
---|
940 | tree[i]->top = 1; |
---|
941 | bdd_ref(tree[i]->node); |
---|
942 | |
---|
943 | nml = SynthCountMlLiteral(dd, tree[i], 1); |
---|
944 | |
---|
945 | if (verbosity) { |
---|
946 | SynthPrintMlTreeWithName(net, dd, tree[i], "result : "); |
---|
947 | fprintf(vis_stdout, "**** %d (#literal = %d) ****\n", i, nml); |
---|
948 | if (verbosity > 1) |
---|
949 | SynthWriteEqn(stdout, net, dd, tree[i], ofuncs, combOutNames[i], 1); |
---|
950 | } |
---|
951 | |
---|
952 | if (VerifyTreeMode) { |
---|
953 | SynthVerifyTree(dd, tree[i], 1); |
---|
954 | SynthVerifyMlTable(dd, table); |
---|
955 | } |
---|
956 | } |
---|
957 | |
---|
958 | flag = SynthPostFactoring(dd, table, factoring_func, verbosity); |
---|
959 | |
---|
960 | if (VerifyTreeMode) { |
---|
961 | bdd_node *tmp; |
---|
962 | |
---|
963 | for (i = 0; i < no; i++) { |
---|
964 | if (tree[i]->comp) |
---|
965 | tmp = tree[i]->complement; |
---|
966 | else |
---|
967 | tmp = tree[i]->node; |
---|
968 | if (tmp != ofuncs[i]) { |
---|
969 | (void) fprintf(vis_stdout, |
---|
970 | "** synth error: Different zdds in [%s].\n", |
---|
971 | combOutNames[i]); |
---|
972 | } |
---|
973 | SynthVerifyTree(dd, tree[i], 1); |
---|
974 | } |
---|
975 | } |
---|
976 | |
---|
977 | return(flag); |
---|
978 | } |
---|