00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "espresso.h"
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 static int opo_no_make_sparse;
00060 static int opo_repeated;
00061 static int opo_exact;
00062 static void minimize();
00063
00064 void phase_assignment(PLA, opo_strategy)
00065 pPLA PLA;
00066 int opo_strategy;
00067 {
00068 opo_no_make_sparse = opo_strategy % 2;
00069 skip_make_sparse = opo_no_make_sparse;
00070 opo_repeated = (opo_strategy / 2) % 2;
00071 opo_exact = (opo_strategy / 4) % 2;
00072
00073
00074 if (PLA->phase != NULL) {
00075 FREE(PLA->phase);
00076 }
00077
00078 if (opo_repeated) {
00079 PLA->phase = set_save(cube.fullset);
00080 repeated_phase_assignment(PLA);
00081 } else {
00082 PLA->phase = find_phase(PLA, 0, (pcube) NULL);
00083 }
00084
00085
00086 skip_make_sparse = FALSE;
00087 (void) set_phase(PLA);
00088 minimize(PLA);
00089 }
00090
00091
00092
00093
00094
00095
00096 void repeated_phase_assignment(PLA)
00097 pPLA PLA;
00098 {
00099 int i;
00100 pcube phase;
00101
00102 for(i = 0; i < cube.part_size[cube.output]; i++) {
00103
00104
00105 phase = find_phase(PLA, i, PLA->phase);
00106
00107
00108 if (! is_in_set(phase, cube.first_part[cube.output] + i)) {
00109 set_remove(PLA->phase, cube.first_part[cube.output] + i);
00110 }
00111
00112 if (trace || summary) {
00113 printf("\nOPO loop for output #%d\n", i);
00114 printf("PLA->phase is %s\n", pc1(PLA->phase));
00115 printf("phase is %s\n", pc1(phase));
00116 }
00117 set_free(phase);
00118 }
00119 }
00120
00121
00122
00123
00124
00125
00126 pcube find_phase(PLA, first_output, phase1)
00127 pPLA PLA;
00128 int first_output;
00129 pcube phase1;
00130 {
00131 pcube phase;
00132 pPLA PLA1;
00133
00134 phase = set_save(cube.fullset);
00135
00136
00137 PLA1 = new_PLA();
00138 PLA1->F = sf_save(PLA->F);
00139 PLA1->R = sf_save(PLA->R);
00140 PLA1->D = sf_save(PLA->D);
00141 if (phase1 != NULL) {
00142 PLA1->phase = set_save(phase1);
00143 (void) set_phase(PLA1);
00144 }
00145 EXEC_S(output_phase_setup(PLA1, first_output), "OPO-SETUP ", PLA1->F);
00146
00147
00148 minimize(PLA1);
00149
00150
00151 EXEC_S(PLA1->F = opo(phase, PLA1->F, PLA1->D, PLA1->R, first_output),
00152 "OPO ", PLA1->F);
00153 free_PLA(PLA1);
00154
00155
00156 setdown_cube();
00157 cube.part_size[cube.output] -=
00158 (cube.part_size[cube.output] - first_output) / 2;
00159 cube_setup();
00160
00161 return phase;
00162 }
00163
00164
00165
00166
00167
00168
00169
00170 pcover opo(phase, T, D, R, first_output)
00171 pcube phase;
00172 pcover T, D, R;
00173 int first_output;
00174 {
00175 int offset, output, i, last_output, ind;
00176 pset pdest, select, p, p1, last, last1, not_covered, tmp;
00177 pset_family temp, T1, T2;
00178
00179
00180 select = set_full(T->count);
00181 for(output = 0; output < first_output; output++) {
00182 ind = cube.first_part[cube.output] + output;
00183 foreachi_set(T, i, p) {
00184 if (is_in_set(p, ind)) {
00185 set_remove(select, i);
00186 }
00187 }
00188 }
00189
00190
00191 offset = (cube.part_size[cube.output] - first_output) / 2;
00192 last_output = first_output + offset - 1;
00193 temp = opo_recur(T, D, select, offset, first_output, last_output);
00194
00195
00196 pdest = temp->data;
00197 T1 = new_cover(T->count);
00198 foreachi_set(T, i, p) {
00199 if (! is_in_set(pdest, i)) {
00200 T1 = sf_addset(T1, p);
00201 }
00202 }
00203
00204 set_free(select);
00205 sf_free(temp);
00206
00207
00208 T2 = complement(cube1list(T1));
00209 not_covered = new_cube();
00210 tmp = new_cube();
00211 foreach_set(T, last, p) {
00212 foreach_set(T2, last1, p1) {
00213 if (cdist0(p, p1)) {
00214 (void) set_or(not_covered, not_covered, set_and(tmp, p, p1));
00215 }
00216 }
00217 }
00218 free_cover(T);
00219 free_cover(T2);
00220 set_free(tmp);
00221
00222
00223 for(output = first_output; output <= last_output; output++) {
00224 ind = cube.first_part[cube.output] + output;
00225 if (is_in_set(not_covered, ind)) {
00226 if (is_in_set(not_covered, ind + offset)) {
00227 fatal("error in output phase assignment");
00228 } else {
00229 set_remove(phase, ind);
00230 }
00231 }
00232 }
00233 set_free(not_covered);
00234 return T1;
00235 }
00236
00237 pset_family opo_recur(T, D, select, offset, first, last)
00238 pcover T, D;
00239 pcube select;
00240 int offset, first, last;
00241 {
00242 static int level = 0;
00243 int middle;
00244 pset_family sl, sr, temp;
00245
00246 level++;
00247 if (first == last) {
00248 #if 0
00249 if (opo_no_make_sparse) {
00250 temp = form_cover_table(T, D, select, first, first + offset);
00251 } else {
00252 temp = opo_leaf(T, select, first, first + offset);
00253 }
00254 #else
00255 temp = opo_leaf(T, select, first, first + offset);
00256 #endif
00257 } else {
00258 middle = (first + last) / 2;
00259 sl = opo_recur(T, D, select, offset, first, middle);
00260 sr = opo_recur(T, D, select, offset, middle+1, last);
00261 temp = unate_intersect(sl, sr, level == 1);
00262 if (trace) {
00263 printf("# OPO[%d]: %4d = %4d x %4d, time = %s\n", level - 1,
00264 temp->count, sl->count, sr->count, print_time(ptime()));
00265 (void) fflush(stdout);
00266 }
00267 free_cover(sl);
00268 free_cover(sr);
00269 }
00270 level--;
00271 return temp;
00272 }
00273
00274
00275 pset_family opo_leaf(T, select, out1, out2)
00276 register pcover T;
00277 pset select;
00278 int out1, out2;
00279 {
00280 register pset_family temp;
00281 register pset p, pdest;
00282 register int i;
00283
00284 out1 += cube.first_part[cube.output];
00285 out2 += cube.first_part[cube.output];
00286
00287
00288 temp = sf_new(2, T->count);
00289
00290
00291 pdest = GETSET(temp, temp->count++);
00292 (void) set_copy(pdest, select);
00293 foreachi_set(T, i, p) {
00294 if (is_in_set(p, out1)) {
00295 set_remove(pdest, i);
00296 }
00297 }
00298
00299
00300 pdest = GETSET(temp, temp->count++);
00301 (void) set_copy(pdest, select);
00302 foreachi_set(T, i, p) {
00303 if (is_in_set(p, out2)) {
00304 set_remove(pdest, i);
00305 }
00306 }
00307
00308 return temp;
00309 }
00310
00311 #if 0
00312 pset_family form_cover_table(F, D, select, f, fbar)
00313 pcover F, D;
00314 pset select;
00315 int f, fbar;
00316 {
00317 register int i;
00318 register pcube p;
00319 pset_family f_table, fbar_table;
00320
00321
00322 Rp_size = F->count;
00323 Rp_start = set_new(Rp_size);
00324 foreachi_set(F, i, p) {
00325 PUTSIZE(p, i);
00326 }
00327 foreachi_set(D, i, p) {
00328 RESET(p, REDUND);
00329 }
00330
00331 f_table = find_covers(F, D, select, f);
00332 fbar_table = find_covers(F, D, select, fbar);
00333 f_table = sf_append(f_table, fbar_table);
00334
00335 set_free(Rp_start);
00336 return f_table;
00337 }
00338
00339
00340 pset_family find_covers(F, D, select, n)
00341 pcover F, D;
00342 register pset select;
00343 int n;
00344 {
00345 register pset p, last, new;
00346 pcover F1;
00347 pcube *Flist;
00348 pset_family f_table, table;
00349 int i;
00350
00351 n += cube.first_part[cube.output];
00352
00353
00354 F1 = new_cover(F->count);
00355 foreach_set(F, last, p)
00356 if (is_in_set(p, n)) {
00357 new = GETSET(F1, F1->count++);
00358 set_or(new, p, cube.var_mask[cube.output]);
00359 PUTSIZE(new, SIZE(p));
00360 SET(new, REDUND);
00361 }
00362
00363
00364 Flist = cube2list(F1, D);
00365 table = sf_new(10, Rp_size);
00366 foreach_set(F1, last, p) {
00367 set_fill(Rp_start, Rp_size);
00368 set_remove(Rp_start, SIZE(p));
00369 table = sf_append(table, fcube_is_covered(Flist, p));
00370 RESET(p, REDUND);
00371 }
00372 set_fill(Rp_start, Rp_size);
00373 foreach_set(table, last, p) {
00374 set_diff(p, Rp_start, p);
00375 }
00376
00377
00378 for(i = 0; i < Rp_size; i++) {
00379 if (! is_in_set(select, i)) {
00380 p = set_new(Rp_size);
00381 set_insert(p, i);
00382 table = sf_addset(table, p);
00383 set_free(p);
00384 }
00385 }
00386 f_table = unate_compl(table);
00387
00388
00389 set_fill(Rp_start, Rp_size);
00390 foreach_set(f_table, last, p) {
00391 set_diff(p, Rp_start, p);
00392 }
00393
00394 free_cubelist(Flist);
00395 sf_free(F1);
00396 return f_table;
00397 }
00398 #endif
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414 output_phase_setup(PLA, first_output)
00415 INOUT pPLA PLA;
00416 int first_output;
00417 {
00418 pcover F, R, D;
00419 pcube mask, mask1, last;
00420 int first_part, offset;
00421 bool save;
00422 register pcube p, pr, pf;
00423 register int i, last_part;
00424
00425 if (cube.output == -1)
00426 fatal("output_phase_setup: must have an output");
00427
00428 F = PLA->F;
00429 D = PLA->D;
00430 R = PLA->R;
00431 first_part = cube.first_part[cube.output] + first_output;
00432 last_part = cube.last_part[cube.output];
00433 offset = cube.part_size[cube.output] - first_output;
00434
00435
00436 setdown_cube();
00437 cube.part_size[cube.output] += offset;
00438 cube_setup();
00439
00440
00441 mask = set_save(cube.fullset);
00442 for(i = first_part; i < cube.size; i++)
00443 set_remove(mask, i);
00444 mask1 = set_save(mask);
00445 for(i = cube.first_part[cube.output]; i < first_part; i++) {
00446 set_remove(mask1, i);
00447 }
00448
00449 PLA->F = new_cover(F->count + R->count);
00450 PLA->R = new_cover(F->count + R->count);
00451 PLA->D = new_cover(D->count);
00452
00453 foreach_set(F, last, p) {
00454 pf = GETSET(PLA->F, (PLA->F)->count++);
00455 pr = GETSET(PLA->R, (PLA->R)->count++);
00456 INLINEset_and(pf, mask, p);
00457 INLINEset_and(pr, mask1, p);
00458 for(i = first_part; i <= last_part; i++)
00459 if (is_in_set(p, i))
00460 set_insert(pf, i);
00461 save = FALSE;
00462 for(i = first_part; i <= last_part; i++)
00463 if (is_in_set(p, i))
00464 save = TRUE, set_insert(pr, i+offset);
00465 if (! save) PLA->R->count--;
00466 }
00467
00468 foreach_set(R, last, p) {
00469 pf = GETSET(PLA->F, (PLA->F)->count++);
00470 pr = GETSET(PLA->R, (PLA->R)->count++);
00471 INLINEset_and(pf, mask1, p);
00472 INLINEset_and(pr, mask, p);
00473 save = FALSE;
00474 for(i = first_part; i <= last_part; i++)
00475 if (is_in_set(p, i))
00476 save = TRUE, set_insert(pf, i+offset);
00477 if (! save) PLA->F->count--;
00478 for(i = first_part; i <= last_part; i++)
00479 if (is_in_set(p, i))
00480 set_insert(pr, i);
00481 }
00482
00483 foreach_set(D, last, p) {
00484 pf = GETSET(PLA->D, (PLA->D)->count++);
00485 INLINEset_and(pf, mask, p);
00486 for(i = first_part; i <= last_part; i++)
00487 if (is_in_set(p, i)) {
00488 set_insert(pf, i);
00489 set_insert(pf, i+offset);
00490 }
00491 }
00492
00493 free_cover(F);
00494 free_cover(D);
00495 free_cover(R);
00496 set_free(mask);
00497 set_free(mask1);
00498 }
00499
00500
00501
00502
00503
00504 pPLA set_phase(PLA)
00505 INOUT pPLA PLA;
00506 {
00507 pcover F1, R1;
00508 register pcube last, p, outmask;
00509 register pcube temp=cube.temp[0], phase=PLA->phase, phase1=cube.temp[1];
00510
00511 outmask = cube.var_mask[cube.num_vars - 1];
00512 set_diff(phase1, outmask, phase);
00513 set_or(phase1, set_diff(temp, cube.fullset, outmask), phase1);
00514 F1 = new_cover((PLA->F)->count + (PLA->R)->count);
00515 R1 = new_cover((PLA->F)->count + (PLA->R)->count);
00516
00517 foreach_set(PLA->F, last, p) {
00518 if (! setp_disjoint(set_and(temp, p, phase), outmask))
00519 set_copy(GETSET(F1, F1->count++), temp);
00520 if (! setp_disjoint(set_and(temp, p, phase1), outmask))
00521 set_copy(GETSET(R1, R1->count++), temp);
00522 }
00523 foreach_set(PLA->R, last, p) {
00524 if (! setp_disjoint(set_and(temp, p, phase), outmask))
00525 set_copy(GETSET(R1, R1->count++), temp);
00526 if (! setp_disjoint(set_and(temp, p, phase1), outmask))
00527 set_copy(GETSET(F1, F1->count++), temp);
00528 }
00529 free_cover(PLA->F);
00530 free_cover(PLA->R);
00531 PLA->F = F1;
00532 PLA->R = R1;
00533 return PLA;
00534 }
00535
00536 #define POW2(x) (1 << (x))
00537
00538 void opoall(PLA, first_output, last_output, opo_strategy)
00539 pPLA PLA;
00540 int first_output, last_output;
00541 int opo_strategy;
00542 {
00543 pcover F, D, R, best_F, best_D, best_R;
00544 int i, j, ind, num;
00545 pcube bestphase;
00546
00547 opo_exact = opo_strategy;
00548
00549 if (PLA->phase != NULL) {
00550 set_free(PLA->phase);
00551 }
00552
00553 bestphase = set_save(cube.fullset);
00554 best_F = sf_save(PLA->F);
00555 best_D = sf_save(PLA->D);
00556 best_R = sf_save(PLA->R);
00557
00558 for(i = 0; i < POW2(last_output - first_output + 1); i++) {
00559
00560
00561 F = sf_save(PLA->F);
00562 D = sf_save(PLA->D);
00563 R = sf_save(PLA->R);
00564
00565
00566 PLA->phase = set_save(cube.fullset);
00567 num = i;
00568 for(j = last_output; j >= first_output; j--) {
00569 if (num % 2 == 0) {
00570 ind = cube.first_part[cube.output] + j;
00571 set_remove(PLA->phase, ind);
00572 }
00573 num /= 2;
00574 }
00575
00576
00577 (void) set_phase(PLA);
00578 printf("# phase is %s\n", pc1(PLA->phase));
00579 summary = TRUE;
00580 minimize(PLA);
00581
00582
00583 if (PLA->F->count < best_F->count) {
00584
00585 set_copy(bestphase, PLA->phase);
00586 sf_free(best_F);
00587 sf_free(best_D);
00588 sf_free(best_R);
00589 best_F = PLA->F;
00590 best_D = PLA->D;
00591 best_R = PLA->R;
00592 } else {
00593
00594 free_cover(PLA->F);
00595 free_cover(PLA->D);
00596 free_cover(PLA->R);
00597 }
00598 set_free(PLA->phase);
00599
00600
00601 PLA->F = F;
00602 PLA->D = D;
00603 PLA->R = R;
00604 }
00605
00606
00607 PLA->phase = bestphase;
00608 sf_free(PLA->F);
00609 sf_free(PLA->D);
00610 sf_free(PLA->R);
00611 PLA->F = best_F;
00612 PLA->D = best_D;
00613 PLA->R = best_R;
00614 }
00615
00616 static void minimize(PLA)
00617 pPLA PLA;
00618 {
00619 if (opo_exact) {
00620 EXEC_S(PLA->F = minimize_exact(PLA->F,PLA->D,PLA->R,1), "EXACT", PLA->F);
00621 } else {
00622 EXEC_S(PLA->F = espresso(PLA->F, PLA->D, PLA->R), "ESPRESSO ",PLA->F);
00623 }
00624 }